[llvm-dev] Question on PHI operands and register classes

Quentin Colombet via llvm-dev
2021-01-06T21:37:18Z

Hi James,

> On Jan 6, 2021, at 1:06 PM, Nagurne, James via llvm-dev <llvm-dev at
lists.llvm.org> wrote:
>
> I’m working on a downstream target and have a question about PHI nodes at
the MI level that I haven’t been able to find any explicit documentation for.
> Are there any expectations on the relationship between register classes of
PHI register operands?
>
> I’m seeing our compiler generate PHI nodes where the two source operands
are disjoint register sets. For example, let’s say we have an A and B class that
are disjoint (MRs A0-A8 and B0-B8, respectively).
>
> %2:A = PHI %0:B, %bb.1, %1:A, %bb.2
>
> This is actually handled well by the PHI elimination pass prior to
allocation. At the point that %0 is defined, a COPY is inserted that moves %0
into a new register with the A class. This makes it seem like the instruction is
legal. This does mean, however, that I believe I’ve found a bug in the
MachinePipeliner’s ModuloScheduleExpander.
>
> In the case that the PHI node feeds into an instruction that’s being placed
into the prolog of the pipelined loop, we end up in rewriteScheduledInstr with
OldReg as %2 and NewReg as %0. What follows is the following sequence of
operations:
>
> unsigned ReplaceReg = 0;
> …
> ReplaceReg = NewReg;
> …
> If (ReplaceReg) {
>       MRI.constrainRegClass(ReplaceReg, MRI.getRegClass(OldReg));
>       UseOp.setReg(ReplaceReg);
> }
>
> MRI.constrainRegClass seems to be the attempt to select a compatible class
for ReplaceReg with regard to OldReg. However, if the register sets are
disjoint, then this call does nothing, and we replace the operand regardless,
which leads to errors later.
>
> There’s code in multiple other modules that generates a COPY when
constrainRegClass fails:
> FastISel
> InstrEmitter
> TailDuplicator
> UnreachableMachineBlockElim
>
> But there’s just as many or more calls to constrainRegClass that do not
check the result. Thus, I’m left wondering which construct is in error: The PHI
of disjoint register sets, or the unconditional SetReg after a potentially
failed constrainRegClass?

In my opinion, the unconditional SetReg after a failed constrainRegClass is at
fault here.
There is nothing wrong with having disjoint register classes around copies/phis
as long as the target knows how to lower them.

Cheers,
-Quentin

>
> J.B. Nagurne
> Code Generation
> Texas Instruments
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
<https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20210106/613cc120/attachment.html>