@@ -305,7 +305,11 @@ namespace {
305305 // / number if it is not zero. If DstReg is a physical register and the
306306 // / existing subregister number of the def / use being updated is not zero,
307307 // / make sure to set it to the correct physical subregister.
308- void updateRegDefsUses (Register SrcReg, Register DstReg, unsigned SubIdx);
308+ // /
309+ // / If \p IsSubregToReg, we are coalescing a DstReg = SUBREG_TO_REG
310+ // / SrcReg. This introduces an implicit-def of DstReg on coalesced users.
311+ void updateRegDefsUses (Register SrcReg, Register DstReg, unsigned SubIdx,
312+ bool IsSubregToReg);
309313
310314 // / If the given machine operand reads only undefined lanes add an undef
311315 // / flag.
@@ -1343,8 +1347,7 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
13431347 if (DstReg.isPhysical ()) {
13441348 Register NewDstReg = DstReg;
13451349
1346- unsigned NewDstIdx = TRI->composeSubRegIndices (CP.getSrcIdx (),
1347- DefMI->getOperand (0 ).getSubReg ());
1350+ unsigned NewDstIdx = TRI->composeSubRegIndices (CP.getSrcIdx (), DefSubIdx);
13481351 if (NewDstIdx)
13491352 NewDstReg = TRI->getSubReg (DstReg, NewDstIdx);
13501353
@@ -1493,7 +1496,7 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
14931496 MRI->setRegClass (DstReg, NewRC);
14941497
14951498 // Update machine operands and add flags.
1496- updateRegDefsUses (DstReg, DstReg, DstIdx);
1499+ updateRegDefsUses (DstReg, DstReg, DstIdx, false );
14971500 NewMI.getOperand (0 ).setSubReg (NewIdx);
14981501 // updateRegDefUses can add an "undef" flag to the definition, since
14991502 // it will replace DstReg with DstReg.DstIdx. If NewIdx is 0, make
@@ -1814,7 +1817,7 @@ void RegisterCoalescer::addUndefFlag(const LiveInterval &Int, SlotIndex UseIdx,
18141817}
18151818
18161819void RegisterCoalescer::updateRegDefsUses (Register SrcReg, Register DstReg,
1817- unsigned SubIdx) {
1820+ unsigned SubIdx, bool IsSubregToReg ) {
18181821 bool DstIsPhys = DstReg.isPhysical ();
18191822 LiveInterval *DstInt = DstIsPhys ? nullptr : &LIS->getInterval (DstReg);
18201823
@@ -1854,16 +1857,22 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
18541857 if (DstInt && !Reads && SubIdx && !UseMI->isDebugInstr ())
18551858 Reads = DstInt->liveAt (LIS->getInstructionIndex (*UseMI));
18561859
1860+ bool FullDef = true ;
1861+
18571862 // Replace SrcReg with DstReg in all UseMI operands.
18581863 for (unsigned i = 0 , e = Ops.size (); i != e; ++i) {
18591864 MachineOperand &MO = UseMI->getOperand (Ops[i]);
18601865
18611866 // Adjust <undef> flags in case of sub-register joins. We don't want to
18621867 // turn a full def into a read-modify-write sub-register def and vice
18631868 // versa.
1864- if (SubIdx && MO.isDef ())
1869+ if (SubIdx && MO.isDef ()) {
18651870 MO.setIsUndef (!Reads);
18661871
1872+ if (!Reads)
1873+ FullDef = false ;
1874+ }
1875+
18671876 // A subreg use of a partially undef (super) register may be a complete
18681877 // undef use now and then has to be marked that way.
18691878 if (MO.isUse () && !DstIsPhys) {
@@ -1895,6 +1904,25 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
18951904 MO.substVirtReg (DstReg, SubIdx, *TRI);
18961905 }
18971906
1907+ if (IsSubregToReg && !FullDef) {
1908+ // If the coalesed instruction doesn't fully define the register, we need
1909+ // to preserve the original super register liveness for SUBREG_TO_REG.
1910+ //
1911+ // We pretended SUBREG_TO_REG was a regular copy for coalescing purposes,
1912+ // but it introduces liveness for other subregisters. Downstream users may
1913+ // have been relying on those bits, so we need to ensure their liveness is
1914+ // captured with a def of other lanes.
1915+
1916+ // FIXME: Need to add new subrange if tracking subranges. We could also
1917+ // skip adding this if we knew the other lanes are dead, and only for
1918+ // other lanes.
1919+
1920+ assert (!MRI->shouldTrackSubRegLiveness (DstReg) &&
1921+ " this should update subranges" );
1922+ MachineInstrBuilder MIB (*MF, UseMI);
1923+ MIB.addReg (DstReg, RegState::ImplicitDefine);
1924+ }
1925+
18981926 LLVM_DEBUG ({
18991927 dbgs () << " \t\t updated: " ;
19001928 if (!UseMI->isDebugInstr ())
@@ -2094,6 +2122,8 @@ bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) {
20942122 });
20952123 }
20962124
2125+ const bool IsSubregToReg = CopyMI->isSubregToReg ();
2126+
20972127 ShrinkMask = LaneBitmask::getNone ();
20982128 ShrinkMainRange = false ;
20992129
@@ -2161,9 +2191,12 @@ bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) {
21612191
21622192 // Rewrite all SrcReg operands to DstReg.
21632193 // Also update DstReg operands to include DstIdx if it is set.
2164- if (CP.getDstIdx ())
2165- updateRegDefsUses (CP.getDstReg (), CP.getDstReg (), CP.getDstIdx ());
2166- updateRegDefsUses (CP.getSrcReg (), CP.getDstReg (), CP.getSrcIdx ());
2194+ if (CP.getDstIdx ()) {
2195+ assert (!IsSubregToReg && " can this happen?" );
2196+ updateRegDefsUses (CP.getDstReg (), CP.getDstReg (), CP.getDstIdx (), false );
2197+ }
2198+ updateRegDefsUses (CP.getSrcReg (), CP.getDstReg (), CP.getSrcIdx (),
2199+ IsSubregToReg);
21672200
21682201 // Shrink subregister ranges if necessary.
21692202 if (ShrinkMask.any ()) {
0 commit comments