[llvm-dev] PHI node to different register class vs TailDuplication
Mikael Holmén via llvm-dev
llvm-dev at lists.llvm.org
Fri Mar 4 04:44:45 PST 2016
Hi,
We're having an issue with TailDuplication in our out-of-tree target and
it's this PHI-node that seems to be the cause of the trouble:
%vreg2<def> = PHI %vreg0, <BB#2>, %vreg1, <BB#3>; rN:%vreg2
aNlh_0_7:%vreg0 aNlh_rN:%vreg1
Note that the defined %vreg2 has register class "rN" while the read
%vreg0 has register class "aNlh_0_7". "rN" and "aNlh_0_7" are disjoint.
Is such a PHI node ok?
If it is, then there is a bug in TailDuplication.
Before TailDuplication we have:
BB#2: derived from LLVM BB %bb2
Predecessors according to CFG: BB#1
%vreg12<def> = mv16Sym <ga:@a>; rN:%vreg12
%vreg13<def> = mv_nimm6_ar16 0; aNlh_rN:%vreg13
mv_ar16_r16_rmod1 %vreg13<kill>, %vreg12<kill>; aNlh_rN:%vreg13 rN:%vreg12
brr_uncond <BB#4>;
Successors according to CFG: BB#4(?%)
BB#4: derived from LLVM BB %bb4
Predecessors according to CFG: BB#2 BB#3
%vreg2<def> = PHI %vreg0, <BB#2>, %vreg1, <BB#3>; rN:%vreg2
aNlh_0_7:%vreg0 aNlh_rN:%vreg1
mv_a32_r16_rmod1 %vreg3, %vreg2; aN32_0_7:%vreg3 rN:%vreg2
brr_uncond <BB#6>;
Successors according to CFG: BB#6(?%)
Then TailDuplication runs
Tail-duplicating into PredBB: BB#2: derived from LLVM BB %bb2
[...]
From Succ: BB#4: derived from LLVM BB %bb4
and we get:
BB#2: derived from LLVM BB %bb2
Predecessors according to CFG: BB#1
%vreg12<def> = mv16Sym <ga:@a>; rN:%vreg12
%vreg13<def> = mv_nimm6_ar16 0; aNlh_rN:%vreg13
mv_ar16_r16_rmod1 %vreg13<kill>, %vreg12<kill>; aNlh_rN:%vreg13 rN:%vreg12
mv_a32_r16_rmod1 %vreg3, %vreg0; aN32_0_7:%vreg3 aNlh_0_7:%vreg0
%vreg18<def> = COPY %vreg0; rN:%vreg18 aNlh_0_7:%vreg0
brr_uncond <BB#6>;
Successors according to CFG: BB#6(0x80000000 / 0x80000000 = 100.00%)
The problem here is the duplicated instruction
mv_a32_r16_rmod1 %vreg3, %vreg0; aN32_0_7:%vreg3 aNlh_0_7:%vreg0
since %vreg0 has register class "aNlh_0_7" but the instruction expects a
disjoint register class, "rN".
During duplication TailDuplication copied the instruction and then
simply replaced %vreg2 with %vreg0 since they are connected through a
PHI, but since the register classes differ, the resulting code is wrong.
I've managed to get around this by inserting a COPY in TailDuplication
but I don't know what the proper fix is to this.
In TailDuplicatePass::ProcessPHI:
const TargetRegisterClass *RC = MRI->getRegClass(DefReg);
+ const TargetRegisterClass *SrcRC = MRI->getRegClass(SrcReg);
+
+ // If the register class of the PHI src is wider than the PHI def
+ // then we can't just use PHI src instead of PHI def in the cloned
+ // instruction. Instead we insert a copy, copying the PHI src to a
+ // register of the wanted register class.
+ if (!RC->hasSubClassEq(SrcRC)) {
+ unsigned NewDef = MRI->createVirtualRegister(RC);
+
+ BuildMI(*PredBB, PredBB->instr_end(), DebugLoc(),
+ TII->get(TargetOpcode::COPY), NewDef).addReg(SrcReg);
+ SrcReg = NewDef;
+ }
+
LocalVRMap.insert(std::make_pair(DefReg, SrcReg));
Any thoughts on this?
/Mikael
More information about the llvm-dev
mailing list