@@ -306,7 +306,11 @@ namespace {
306306 // / number if it is not zero. If DstReg is a physical register and the
307307 // / existing subregister number of the def / use being updated is not zero,
308308 // / make sure to set it to the correct physical subregister.
309- void updateRegDefsUses (Register SrcReg, Register DstReg, unsigned SubIdx);
309+ // /
310+ // / If \p IsSubregToReg, we are coalescing a DstReg = SUBREG_TO_REG
311+ // / SrcReg. This introduces an implicit-def of DstReg on coalesced users.
312+ void updateRegDefsUses (Register SrcReg, Register DstReg, unsigned SubIdx,
313+ bool IsSubregToReg);
310314
311315 // / If the given machine operand reads only undefined lanes add an undef
312316 // / flag.
@@ -1516,7 +1520,7 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
15161520 MRI->setRegClass (DstReg, NewRC);
15171521
15181522 // Update machine operands and add flags.
1519- updateRegDefsUses (DstReg, DstReg, DstIdx);
1523+ updateRegDefsUses (DstReg, DstReg, DstIdx, false );
15201524 NewMI.getOperand (0 ).setSubReg (NewIdx);
15211525 // updateRegDefUses can add an "undef" flag to the definition, since
15221526 // it will replace DstReg with DstReg.DstIdx. If NewIdx is 0, make
@@ -1857,7 +1861,7 @@ void RegisterCoalescer::addUndefFlag(const LiveInterval &Int, SlotIndex UseIdx,
18571861}
18581862
18591863void RegisterCoalescer::updateRegDefsUses (Register SrcReg, Register DstReg,
1860- unsigned SubIdx) {
1864+ unsigned SubIdx, bool IsSubregToReg ) {
18611865 bool DstIsPhys = DstReg.isPhysical ();
18621866 LiveInterval *DstInt = DstIsPhys ? nullptr : &LIS->getInterval (DstReg);
18631867
@@ -1900,16 +1904,22 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
19001904 if (DstInt && !Reads && SubIdx && !UseMI->isDebugInstr ())
19011905 Reads = DstInt->liveAt (LIS->getInstructionIndex (*UseMI));
19021906
1907+ bool FullDef = true ;
1908+
19031909 // Replace SrcReg with DstReg in all UseMI operands.
19041910 for (unsigned Op : Ops) {
19051911 MachineOperand &MO = UseMI->getOperand (Op);
19061912
19071913 // Adjust <undef> flags in case of sub-register joins. We don't want to
19081914 // turn a full def into a read-modify-write sub-register def and vice
19091915 // versa.
1910- if (SubIdx && MO.isDef ())
1916+ if (SubIdx && MO.isDef ()) {
19111917 MO.setIsUndef (!Reads);
19121918
1919+ if (!Reads)
1920+ FullDef = false ;
1921+ }
1922+
19131923 // A subreg use of a partially undef (super) register may be a complete
19141924 // undef use now and then has to be marked that way.
19151925 if (MO.isUse () && !MO.isUndef () && !DstIsPhys) {
@@ -1941,6 +1951,25 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
19411951 MO.substVirtReg (DstReg, SubIdx, *TRI);
19421952 }
19431953
1954+ if (IsSubregToReg && !FullDef) {
1955+ // If the coalesed instruction doesn't fully define the register, we need
1956+ // to preserve the original super register liveness for SUBREG_TO_REG.
1957+ //
1958+ // We pretended SUBREG_TO_REG was a regular copy for coalescing purposes,
1959+ // but it introduces liveness for other subregisters. Downstream users may
1960+ // have been relying on those bits, so we need to ensure their liveness is
1961+ // captured with a def of other lanes.
1962+
1963+ // FIXME: Need to add new subrange if tracking subranges. We could also
1964+ // skip adding this if we knew the other lanes are dead, and only for
1965+ // other lanes.
1966+
1967+ assert (!MRI->shouldTrackSubRegLiveness (DstReg) &&
1968+ " this should update subranges" );
1969+ MachineInstrBuilder MIB (*MF, UseMI);
1970+ MIB.addReg (DstReg, RegState::ImplicitDefine);
1971+ }
1972+
19441973 LLVM_DEBUG ({
19451974 dbgs () << " \t\t updated: " ;
19461975 if (!UseMI->isDebugInstr ())
@@ -2142,6 +2171,8 @@ bool RegisterCoalescer::joinCopy(
21422171 });
21432172 }
21442173
2174+ const bool IsSubregToReg = CopyMI->isSubregToReg ();
2175+
21452176 ShrinkMask = LaneBitmask::getNone ();
21462177 ShrinkMainRange = false ;
21472178
@@ -2211,9 +2242,12 @@ bool RegisterCoalescer::joinCopy(
22112242
22122243 // Rewrite all SrcReg operands to DstReg.
22132244 // Also update DstReg operands to include DstIdx if it is set.
2214- if (CP.getDstIdx ())
2215- updateRegDefsUses (CP.getDstReg (), CP.getDstReg (), CP.getDstIdx ());
2216- updateRegDefsUses (CP.getSrcReg (), CP.getDstReg (), CP.getSrcIdx ());
2245+ if (CP.getDstIdx ()) {
2246+ assert (!IsSubregToReg && " can this happen?" );
2247+ updateRegDefsUses (CP.getDstReg (), CP.getDstReg (), CP.getDstIdx (), false );
2248+ }
2249+ updateRegDefsUses (CP.getSrcReg (), CP.getDstReg (), CP.getSrcIdx (),
2250+ IsSubregToReg);
22172251
22182252 // Shrink subregister ranges if necessary.
22192253 if (ShrinkMask.any ()) {
0 commit comments