@@ -306,7 +306,11 @@ class RegisterCoalescer : private LiveRangeEdit::Delegate {
306
306
// / number if it is not zero. If DstReg is a physical register and the
307
307
// / existing subregister number of the def / use being updated is not zero,
308
308
// / 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);
310
314
311
315
// / If the given machine operand reads only undefined lanes add an undef
312
316
// / flag.
@@ -1444,6 +1448,7 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
1444
1448
1445
1449
// CopyMI may have implicit operands, save them so that we can transfer them
1446
1450
// over to the newly materialized instruction after CopyMI is removed.
1451
+ LaneBitmask NewMIImplicitOpsMask;
1447
1452
SmallVector<MachineOperand, 4 > ImplicitOps;
1448
1453
ImplicitOps.reserve (CopyMI->getNumOperands () -
1449
1454
CopyMI->getDesc ().getNumOperands ());
@@ -1458,6 +1463,9 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
1458
1463
(MO.getSubReg () == 0 && MO.getReg () == DstOperand.getReg ())) &&
1459
1464
" unexpected implicit virtual register def" );
1460
1465
ImplicitOps.push_back (MO);
1466
+ if (MO.isDef () && MO.getReg ().isVirtual () &&
1467
+ MRI->shouldTrackSubRegLiveness (DstReg))
1468
+ NewMIImplicitOpsMask |= MRI->getMaxLaneMaskForVReg (MO.getReg ());
1461
1469
}
1462
1470
}
1463
1471
@@ -1500,14 +1508,11 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
1500
1508
} else {
1501
1509
assert (MO.getReg () == NewMI.getOperand (0 ).getReg ());
1502
1510
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 ());
1511
1516
}
1512
1517
}
1513
1518
}
@@ -1531,7 +1536,7 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
1531
1536
MRI->setRegClass (DstReg, NewRC);
1532
1537
1533
1538
// Update machine operands and add flags.
1534
- updateRegDefsUses (DstReg, DstReg, DstIdx);
1539
+ updateRegDefsUses (DstReg, DstReg, DstIdx, false );
1535
1540
NewMI.getOperand (0 ).setSubReg (NewIdx);
1536
1541
// updateRegDefUses can add an "undef" flag to the definition, since
1537
1542
// it will replace DstReg with DstReg.DstIdx. If NewIdx is 0, make
@@ -1607,7 +1612,8 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
1607
1612
CurrIdx.getRegSlot (NewMI.getOperand (0 ).isEarlyClobber ());
1608
1613
VNInfo::Allocator &Alloc = LIS->getVNInfoAllocator ();
1609
1614
for (LiveInterval::SubRange &SR : DstInt.subranges ()) {
1610
- if ((SR.LaneMask & DstMask).none ()) {
1615
+ if ((SR.LaneMask & DstMask).none () &&
1616
+ (SR.LaneMask & NewMIImplicitOpsMask).none ()) {
1611
1617
LLVM_DEBUG (dbgs ()
1612
1618
<< " Removing undefined SubRange "
1613
1619
<< PrintLaneMask (SR.LaneMask ) << " : " << SR << " \n " );
@@ -1872,7 +1878,7 @@ void RegisterCoalescer::addUndefFlag(const LiveInterval &Int, SlotIndex UseIdx,
1872
1878
}
1873
1879
1874
1880
void RegisterCoalescer::updateRegDefsUses (Register SrcReg, Register DstReg,
1875
- unsigned SubIdx) {
1881
+ unsigned SubIdx, bool IsSubregToReg ) {
1876
1882
bool DstIsPhys = DstReg.isPhysical ();
1877
1883
LiveInterval *DstInt = DstIsPhys ? nullptr : &LIS->getInterval (DstReg);
1878
1884
@@ -1892,6 +1898,14 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
1892
1898
}
1893
1899
}
1894
1900
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
+
1895
1909
SmallPtrSet<MachineInstr *, 8 > Visited;
1896
1910
for (MachineRegisterInfo::reg_instr_iterator I = MRI->reg_instr_begin (SrcReg),
1897
1911
E = MRI->reg_instr_end ();
@@ -1915,15 +1929,19 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
1915
1929
if (DstInt && !Reads && SubIdx && !UseMI->isDebugInstr ())
1916
1930
Reads = DstInt->liveAt (LIS->getInstructionIndex (*UseMI));
1917
1931
1932
+ bool FullDef = true ;
1933
+
1918
1934
// Replace SrcReg with DstReg in all UseMI operands.
1919
1935
for (unsigned Op : Ops) {
1920
1936
MachineOperand &MO = UseMI->getOperand (Op);
1921
1937
1922
1938
// Adjust <undef> flags in case of sub-register joins. We don't want to
1923
1939
// turn a full def into a read-modify-write sub-register def and vice
1924
1940
// versa.
1925
- if (SubIdx && MO.isDef ())
1941
+ if (SubIdx && MO.isDef ()) {
1926
1942
MO.setIsUndef (!Reads);
1943
+ FullDef = false ;
1944
+ }
1927
1945
1928
1946
// A subreg use of a partially undef (super) register may be a complete
1929
1947
// undef use now and then has to be marked that way.
@@ -1956,6 +1974,32 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
1956
1974
MO.substVirtReg (DstReg, SubIdx, *TRI);
1957
1975
}
1958
1976
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
+
1959
2003
LLVM_DEBUG ({
1960
2004
dbgs () << " \t\t updated: " ;
1961
2005
if (!UseMI->isDebugInstr ())
@@ -2157,6 +2201,8 @@ bool RegisterCoalescer::joinCopy(
2157
2201
});
2158
2202
}
2159
2203
2204
+ const bool IsSubregToReg = CopyMI->isSubregToReg ();
2205
+
2160
2206
ShrinkMask = LaneBitmask::getNone ();
2161
2207
ShrinkMainRange = false ;
2162
2208
@@ -2226,9 +2272,12 @@ bool RegisterCoalescer::joinCopy(
2226
2272
2227
2273
// Rewrite all SrcReg operands to DstReg.
2228
2274
// 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);
2232
2281
2233
2282
// Shrink subregister ranges if necessary.
2234
2283
if (ShrinkMask.any ()) {
0 commit comments