@@ -306,7 +306,11 @@ namespace {
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.
@@ -1430,6 +1434,7 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
1430
1434
1431
1435
// CopyMI may have implicit operands, save them so that we can transfer them
1432
1436
// over to the newly materialized instruction after CopyMI is removed.
1437
+ LaneBitmask NewMIImplicitOpsMask;
1433
1438
SmallVector<MachineOperand, 4 > ImplicitOps;
1434
1439
ImplicitOps.reserve (CopyMI->getNumOperands () -
1435
1440
CopyMI->getDesc ().getNumOperands ());
@@ -1443,6 +1448,9 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
1443
1448
(MO.getSubReg () == 0 && MO.getReg () == DstOperand.getReg ())) &&
1444
1449
" unexpected implicit virtual register def" );
1445
1450
ImplicitOps.push_back (MO);
1451
+ if (MO.isDef () && MO.getReg ().isVirtual () &&
1452
+ MRI->shouldTrackSubRegLiveness (DstReg))
1453
+ NewMIImplicitOpsMask |= MRI->getMaxLaneMaskForVReg (MO.getReg ());
1446
1454
}
1447
1455
}
1448
1456
@@ -1485,14 +1493,11 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
1485
1493
} else {
1486
1494
assert (MO.getReg () == NewMI.getOperand (0 ).getReg ());
1487
1495
1488
- // We're only expecting another def of the main output, so the range
1489
- // should get updated with the regular output range.
1490
- //
1491
- // FIXME: The range updating below probably needs updating to look at
1492
- // the super register if subranges are tracked.
1493
- assert (!MRI->shouldTrackSubRegLiveness (DstReg) &&
1494
- " subrange update for implicit-def of super register may not be "
1495
- " properly handled" );
1496
+ // If lanemasks need to be tracked, compile the lanemask of the NewMI
1497
+ // implicit def operands to avoid subranges for the super-regs from
1498
+ // being removed by code later on in this function.
1499
+ if (MRI->shouldTrackSubRegLiveness (MO.getReg ()))
1500
+ NewMIImplicitOpsMask |= MRI->getMaxLaneMaskForVReg (MO.getReg ());
1496
1501
}
1497
1502
}
1498
1503
}
@@ -1516,7 +1521,7 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
1516
1521
MRI->setRegClass (DstReg, NewRC);
1517
1522
1518
1523
// Update machine operands and add flags.
1519
- updateRegDefsUses (DstReg, DstReg, DstIdx);
1524
+ updateRegDefsUses (DstReg, DstReg, DstIdx, false );
1520
1525
NewMI.getOperand (0 ).setSubReg (NewIdx);
1521
1526
// updateRegDefUses can add an "undef" flag to the definition, since
1522
1527
// it will replace DstReg with DstReg.DstIdx. If NewIdx is 0, make
@@ -1592,7 +1597,8 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
1592
1597
CurrIdx.getRegSlot (NewMI.getOperand (0 ).isEarlyClobber ());
1593
1598
VNInfo::Allocator &Alloc = LIS->getVNInfoAllocator ();
1594
1599
for (LiveInterval::SubRange &SR : DstInt.subranges ()) {
1595
- if ((SR.LaneMask & DstMask).none ()) {
1600
+ if ((SR.LaneMask & DstMask).none () &&
1601
+ (SR.LaneMask & NewMIImplicitOpsMask).none ()) {
1596
1602
LLVM_DEBUG (dbgs ()
1597
1603
<< " Removing undefined SubRange "
1598
1604
<< PrintLaneMask (SR.LaneMask ) << " : " << SR << " \n " );
@@ -1857,7 +1863,7 @@ void RegisterCoalescer::addUndefFlag(const LiveInterval &Int, SlotIndex UseIdx,
1857
1863
}
1858
1864
1859
1865
void RegisterCoalescer::updateRegDefsUses (Register SrcReg, Register DstReg,
1860
- unsigned SubIdx) {
1866
+ unsigned SubIdx, bool IsSubregToReg ) {
1861
1867
bool DstIsPhys = DstReg.isPhysical ();
1862
1868
LiveInterval *DstInt = DstIsPhys ? nullptr : &LIS->getInterval (DstReg);
1863
1869
@@ -1877,6 +1883,14 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
1877
1883
}
1878
1884
}
1879
1885
1886
+ // If DstInt already has a subrange for the unused lanes, then we shouldn't
1887
+ // create duplicate subranges when we update the interval for unused lanes.
1888
+ LaneBitmask DefinedLanes;
1889
+ if (DstInt && MRI->shouldTrackSubRegLiveness (DstReg)) {
1890
+ for (LiveInterval::SubRange &SR : DstInt->subranges ())
1891
+ DefinedLanes |= SR.LaneMask ;
1892
+ }
1893
+
1880
1894
SmallPtrSet<MachineInstr*, 8 > Visited;
1881
1895
for (MachineRegisterInfo::reg_instr_iterator
1882
1896
I = MRI->reg_instr_begin (SrcReg), E = MRI->reg_instr_end ();
@@ -1900,15 +1914,19 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
1900
1914
if (DstInt && !Reads && SubIdx && !UseMI->isDebugInstr ())
1901
1915
Reads = DstInt->liveAt (LIS->getInstructionIndex (*UseMI));
1902
1916
1917
+ bool FullDef = true ;
1918
+
1903
1919
// Replace SrcReg with DstReg in all UseMI operands.
1904
1920
for (unsigned Op : Ops) {
1905
1921
MachineOperand &MO = UseMI->getOperand (Op);
1906
1922
1907
1923
// Adjust <undef> flags in case of sub-register joins. We don't want to
1908
1924
// turn a full def into a read-modify-write sub-register def and vice
1909
1925
// versa.
1910
- if (SubIdx && MO.isDef ())
1926
+ if (SubIdx && MO.isDef ()) {
1911
1927
MO.setIsUndef (!Reads);
1928
+ FullDef = false ;
1929
+ }
1912
1930
1913
1931
// A subreg use of a partially undef (super) register may be a complete
1914
1932
// undef use now and then has to be marked that way.
@@ -1941,6 +1959,32 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
1941
1959
MO.substVirtReg (DstReg, SubIdx, *TRI);
1942
1960
}
1943
1961
1962
+ if (IsSubregToReg && !FullDef) {
1963
+ // If the coalesed instruction doesn't fully define the register, we need
1964
+ // to preserve the original super register liveness for SUBREG_TO_REG.
1965
+ //
1966
+ // We pretended SUBREG_TO_REG was a regular copy for coalescing purposes,
1967
+ // but it introduces liveness for other subregisters. Downstream users may
1968
+ // have been relying on those bits, so we need to ensure their liveness is
1969
+ // captured with a def of other lanes.
1970
+
1971
+ if (DstInt && MRI->shouldTrackSubRegLiveness (DstReg)) {
1972
+ assert (DstInt->hasSubRanges () &&
1973
+ " SUBREG_TO_REG should have resulted in subrange" );
1974
+ LaneBitmask DstMask = MRI->getMaxLaneMaskForVReg (DstInt->reg ());
1975
+ LaneBitmask UsedLanes = TRI->getSubRegIndexLaneMask (SubIdx);
1976
+ LaneBitmask UnusedLanes = DstMask & ~UsedLanes & ~DefinedLanes;
1977
+ if ((UnusedLanes).any ()) {
1978
+ BumpPtrAllocator &Allocator = LIS->getVNInfoAllocator ();
1979
+ DstInt->createSubRangeFrom (Allocator, UnusedLanes, *DstInt);
1980
+ DefinedLanes |= UnusedLanes;
1981
+ }
1982
+ }
1983
+
1984
+ MachineInstrBuilder MIB (*MF, UseMI);
1985
+ MIB.addReg (DstReg, RegState::ImplicitDefine);
1986
+ }
1987
+
1944
1988
LLVM_DEBUG ({
1945
1989
dbgs () << " \t\t updated: " ;
1946
1990
if (!UseMI->isDebugInstr ())
@@ -2142,6 +2186,8 @@ bool RegisterCoalescer::joinCopy(
2142
2186
});
2143
2187
}
2144
2188
2189
+ const bool IsSubregToReg = CopyMI->isSubregToReg ();
2190
+
2145
2191
ShrinkMask = LaneBitmask::getNone ();
2146
2192
ShrinkMainRange = false ;
2147
2193
@@ -2211,9 +2257,12 @@ bool RegisterCoalescer::joinCopy(
2211
2257
2212
2258
// Rewrite all SrcReg operands to DstReg.
2213
2259
// 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 ());
2260
+ if (CP.getDstIdx ()) {
2261
+ assert (!IsSubregToReg && " can this happen?" );
2262
+ updateRegDefsUses (CP.getDstReg (), CP.getDstReg (), CP.getDstIdx (), false );
2263
+ }
2264
+ updateRegDefsUses (CP.getSrcReg (), CP.getDstReg (), CP.getSrcIdx (),
2265
+ IsSubregToReg);
2217
2266
2218
2267
// Shrink subregister ranges if necessary.
2219
2268
if (ShrinkMask.any ()) {
0 commit comments