@@ -306,7 +306,11 @@ class RegisterCoalescer : private LiveRangeEdit::Delegate {
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.
@@ -1444,6 +1448,7 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
14441448
14451449 // CopyMI may have implicit operands, save them so that we can transfer them
14461450 // over to the newly materialized instruction after CopyMI is removed.
1451+ LaneBitmask NewMIImplicitOpsMask;
14471452 SmallVector<MachineOperand, 4 > ImplicitOps;
14481453 ImplicitOps.reserve (CopyMI->getNumOperands () -
14491454 CopyMI->getDesc ().getNumOperands ());
@@ -1458,6 +1463,9 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
14581463 (MO.getSubReg () == 0 && MO.getReg () == DstOperand.getReg ())) &&
14591464 " unexpected implicit virtual register def" );
14601465 ImplicitOps.push_back (MO);
1466+ if (MO.isDef () && MO.getReg ().isVirtual () &&
1467+ MRI->shouldTrackSubRegLiveness (DstReg))
1468+ NewMIImplicitOpsMask |= MRI->getMaxLaneMaskForVReg (MO.getReg ());
14611469 }
14621470 }
14631471
@@ -1500,14 +1508,11 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
15001508 } else {
15011509 assert (MO.getReg () == NewMI.getOperand (0 ).getReg ());
15021510
1503- // We're only expecting another def of the main output, so the range
1504- // should get updated with the regular output range.
1505- //
1506- // FIXME: The range updating below probably needs updating to look at
1507- // the super register if subranges are tracked.
1508- assert (!MRI->shouldTrackSubRegLiveness (DstReg) &&
1509- " subrange update for implicit-def of super register may not be "
1510- " properly handled" );
1511+ // If lanemasks need to be tracked, compile the lanemask of the NewMI
1512+ // implicit def operands to avoid subranges for the super-regs from
1513+ // being removed by code later on in this function.
1514+ if (MRI->shouldTrackSubRegLiveness (MO.getReg ()))
1515+ NewMIImplicitOpsMask |= MRI->getMaxLaneMaskForVReg (MO.getReg ());
15111516 }
15121517 }
15131518 }
@@ -1531,7 +1536,7 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
15311536 MRI->setRegClass (DstReg, NewRC);
15321537
15331538 // Update machine operands and add flags.
1534- updateRegDefsUses (DstReg, DstReg, DstIdx);
1539+ updateRegDefsUses (DstReg, DstReg, DstIdx, false );
15351540 NewMI.getOperand (0 ).setSubReg (NewIdx);
15361541 // updateRegDefUses can add an "undef" flag to the definition, since
15371542 // it will replace DstReg with DstReg.DstIdx. If NewIdx is 0, make
@@ -1607,7 +1612,8 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
16071612 CurrIdx.getRegSlot (NewMI.getOperand (0 ).isEarlyClobber ());
16081613 VNInfo::Allocator &Alloc = LIS->getVNInfoAllocator ();
16091614 for (LiveInterval::SubRange &SR : DstInt.subranges ()) {
1610- if ((SR.LaneMask & DstMask).none ()) {
1615+ if ((SR.LaneMask & DstMask).none () &&
1616+ (SR.LaneMask & NewMIImplicitOpsMask).none ()) {
16111617 LLVM_DEBUG (dbgs ()
16121618 << " Removing undefined SubRange "
16131619 << PrintLaneMask (SR.LaneMask ) << " : " << SR << " \n " );
@@ -1872,7 +1878,7 @@ void RegisterCoalescer::addUndefFlag(const LiveInterval &Int, SlotIndex UseIdx,
18721878}
18731879
18741880void RegisterCoalescer::updateRegDefsUses (Register SrcReg, Register DstReg,
1875- unsigned SubIdx) {
1881+ unsigned SubIdx, bool IsSubregToReg ) {
18761882 bool DstIsPhys = DstReg.isPhysical ();
18771883 LiveInterval *DstInt = DstIsPhys ? nullptr : &LIS->getInterval (DstReg);
18781884
@@ -1892,6 +1898,14 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
18921898 }
18931899 }
18941900
1901+ // If DstInt already has a subrange for the unused lanes, then we shouldn't
1902+ // create duplicate subranges when we update the interval for unused lanes.
1903+ LaneBitmask DefinedLanes;
1904+ if (DstInt && MRI->shouldTrackSubRegLiveness (DstReg)) {
1905+ for (LiveInterval::SubRange &SR : DstInt->subranges ())
1906+ DefinedLanes |= SR.LaneMask ;
1907+ }
1908+
18951909 SmallPtrSet<MachineInstr *, 8 > Visited;
18961910 for (MachineRegisterInfo::reg_instr_iterator I = MRI->reg_instr_begin (SrcReg),
18971911 E = MRI->reg_instr_end ();
@@ -1915,15 +1929,19 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
19151929 if (DstInt && !Reads && SubIdx && !UseMI->isDebugInstr ())
19161930 Reads = DstInt->liveAt (LIS->getInstructionIndex (*UseMI));
19171931
1932+ bool FullDef = true ;
1933+
19181934 // Replace SrcReg with DstReg in all UseMI operands.
19191935 for (unsigned Op : Ops) {
19201936 MachineOperand &MO = UseMI->getOperand (Op);
19211937
19221938 // Adjust <undef> flags in case of sub-register joins. We don't want to
19231939 // turn a full def into a read-modify-write sub-register def and vice
19241940 // versa.
1925- if (SubIdx && MO.isDef ())
1941+ if (SubIdx && MO.isDef ()) {
19261942 MO.setIsUndef (!Reads);
1943+ FullDef = false ;
1944+ }
19271945
19281946 // A subreg use of a partially undef (super) register may be a complete
19291947 // undef use now and then has to be marked that way.
@@ -1956,6 +1974,32 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
19561974 MO.substVirtReg (DstReg, SubIdx, *TRI);
19571975 }
19581976
1977+ if (IsSubregToReg && !FullDef) {
1978+ // If the coalesed instruction doesn't fully define the register, we need
1979+ // to preserve the original super register liveness for SUBREG_TO_REG.
1980+ //
1981+ // We pretended SUBREG_TO_REG was a regular copy for coalescing purposes,
1982+ // but it introduces liveness for other subregisters. Downstream users may
1983+ // have been relying on those bits, so we need to ensure their liveness is
1984+ // captured with a def of other lanes.
1985+
1986+ if (DstInt && MRI->shouldTrackSubRegLiveness (DstReg)) {
1987+ assert (DstInt->hasSubRanges () &&
1988+ " SUBREG_TO_REG should have resulted in subrange" );
1989+ LaneBitmask DstMask = MRI->getMaxLaneMaskForVReg (DstInt->reg ());
1990+ LaneBitmask UsedLanes = TRI->getSubRegIndexLaneMask (SubIdx);
1991+ LaneBitmask UnusedLanes = DstMask & ~UsedLanes & ~DefinedLanes;
1992+ if ((UnusedLanes).any ()) {
1993+ BumpPtrAllocator &Allocator = LIS->getVNInfoAllocator ();
1994+ DstInt->createSubRangeFrom (Allocator, UnusedLanes, *DstInt);
1995+ DefinedLanes |= UnusedLanes;
1996+ }
1997+ }
1998+
1999+ MachineInstrBuilder MIB (*MF, UseMI);
2000+ MIB.addReg (DstReg, RegState::ImplicitDefine);
2001+ }
2002+
19592003 LLVM_DEBUG ({
19602004 dbgs () << " \t\t updated: " ;
19612005 if (!UseMI->isDebugInstr ())
@@ -2157,6 +2201,8 @@ bool RegisterCoalescer::joinCopy(
21572201 });
21582202 }
21592203
2204+ const bool IsSubregToReg = CopyMI->isSubregToReg ();
2205+
21602206 ShrinkMask = LaneBitmask::getNone ();
21612207 ShrinkMainRange = false ;
21622208
@@ -2226,9 +2272,12 @@ bool RegisterCoalescer::joinCopy(
22262272
22272273 // Rewrite all SrcReg operands to DstReg.
22282274 // Also update DstReg operands to include DstIdx if it is set.
2229- if (CP.getDstIdx ())
2230- updateRegDefsUses (CP.getDstReg (), CP.getDstReg (), CP.getDstIdx ());
2231- updateRegDefsUses (CP.getSrcReg (), CP.getDstReg (), CP.getSrcIdx ());
2275+ if (CP.getDstIdx ()) {
2276+ assert (!IsSubregToReg && " can this happen?" );
2277+ updateRegDefsUses (CP.getDstReg (), CP.getDstReg (), CP.getDstIdx (), false );
2278+ }
2279+ updateRegDefsUses (CP.getSrcReg (), CP.getDstReg (), CP.getSrcIdx (),
2280+ IsSubregToReg);
22322281
22332282 // Shrink subregister ranges if necessary.
22342283 if (ShrinkMask.any ()) {
0 commit comments