Nagurne, James via llvm-dev
2021-Jan-06 21:06 UTC
[llvm-dev] Question on PHI operands and register classes
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? J.B. Nagurne Code Generation Texas Instruments -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20210106/2d111e42/attachment.html>
Quentin Colombet via llvm-dev
2021-Jan-06 21:37 UTC
[llvm-dev] Question on PHI operands and register classes
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>