Skip to content

Commit 1f283a6

Browse files
committed
Reapply "RegisterCoalescer: Add implicit-def of super register when coalescing SUBREG_TO_REG"
This reverts commit 9e50c6e. A few assertion and verifier errors have been fixed in the coalescer and allocator, so hopefully this sticks this time.
1 parent c7b3ae5 commit 1f283a6

6 files changed

+670
-57
lines changed

llvm/lib/CodeGen/RegisterCoalescer.cpp

+42-9
Original file line numberDiff line numberDiff line change
@@ -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.
@@ -1328,8 +1332,7 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
13281332
if (DstReg.isPhysical()) {
13291333
Register NewDstReg = DstReg;
13301334

1331-
unsigned NewDstIdx = TRI->composeSubRegIndices(CP.getSrcIdx(),
1332-
DefMI->getOperand(0).getSubReg());
1335+
unsigned NewDstIdx = TRI->composeSubRegIndices(CP.getSrcIdx(), DefSubIdx);
13331336
if (NewDstIdx)
13341337
NewDstReg = TRI->getSubReg(DstReg, NewDstIdx);
13351338

@@ -1478,7 +1481,7 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
14781481
MRI->setRegClass(DstReg, NewRC);
14791482

14801483
// Update machine operands and add flags.
1481-
updateRegDefsUses(DstReg, DstReg, DstIdx);
1484+
updateRegDefsUses(DstReg, DstReg, DstIdx, false);
14821485
NewMI.getOperand(0).setSubReg(NewIdx);
14831486
// updateRegDefUses can add an "undef" flag to the definition, since
14841487
// it will replace DstReg with DstReg.DstIdx. If NewIdx is 0, make
@@ -1800,7 +1803,7 @@ void RegisterCoalescer::addUndefFlag(const LiveInterval &Int, SlotIndex UseIdx,
18001803
}
18011804

18021805
void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
1803-
unsigned SubIdx) {
1806+
unsigned SubIdx, bool IsSubregToReg) {
18041807
bool DstIsPhys = DstReg.isPhysical();
18051808
LiveInterval *DstInt = DstIsPhys ? nullptr : &LIS->getInterval(DstReg);
18061809

@@ -1840,16 +1843,22 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
18401843
if (DstInt && !Reads && SubIdx && !UseMI->isDebugInstr())
18411844
Reads = DstInt->liveAt(LIS->getInstructionIndex(*UseMI));
18421845

1846+
bool FullDef = true;
1847+
18431848
// Replace SrcReg with DstReg in all UseMI operands.
18441849
for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
18451850
MachineOperand &MO = UseMI->getOperand(Ops[i]);
18461851

18471852
// Adjust <undef> flags in case of sub-register joins. We don't want to
18481853
// turn a full def into a read-modify-write sub-register def and vice
18491854
// versa.
1850-
if (SubIdx && MO.isDef())
1855+
if (SubIdx && MO.isDef()) {
18511856
MO.setIsUndef(!Reads);
18521857

1858+
if (!Reads)
1859+
FullDef = false;
1860+
}
1861+
18531862
// A subreg use of a partially undef (super) register may be a complete
18541863
// undef use now and then has to be marked that way.
18551864
if (MO.isUse() && !DstIsPhys) {
@@ -1881,6 +1890,25 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
18811890
MO.substVirtReg(DstReg, SubIdx, *TRI);
18821891
}
18831892

1893+
if (IsSubregToReg && !FullDef) {
1894+
// If the coalesed instruction doesn't fully define the register, we need
1895+
// to preserve the original super register liveness for SUBREG_TO_REG.
1896+
//
1897+
// We pretended SUBREG_TO_REG was a regular copy for coalescing purposes,
1898+
// but it introduces liveness for other subregisters. Downstream users may
1899+
// have been relying on those bits, so we need to ensure their liveness is
1900+
// captured with a def of other lanes.
1901+
1902+
// FIXME: Need to add new subrange if tracking subranges. We could also
1903+
// skip adding this if we knew the other lanes are dead, and only for
1904+
// other lanes.
1905+
1906+
assert(!MRI->shouldTrackSubRegLiveness(DstReg) &&
1907+
"this should update subranges");
1908+
MachineInstrBuilder MIB(*MF, UseMI);
1909+
MIB.addReg(DstReg, RegState::ImplicitDefine);
1910+
}
1911+
18841912
LLVM_DEBUG({
18851913
dbgs() << "\t\tupdated: ";
18861914
if (!UseMI->isDebugInstr())
@@ -2080,6 +2108,8 @@ bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) {
20802108
});
20812109
}
20822110

2111+
const bool IsSubregToReg = CopyMI->isSubregToReg();
2112+
20832113
ShrinkMask = LaneBitmask::getNone();
20842114
ShrinkMainRange = false;
20852115

@@ -2147,9 +2177,12 @@ bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) {
21472177

21482178
// Rewrite all SrcReg operands to DstReg.
21492179
// Also update DstReg operands to include DstIdx if it is set.
2150-
if (CP.getDstIdx())
2151-
updateRegDefsUses(CP.getDstReg(), CP.getDstReg(), CP.getDstIdx());
2152-
updateRegDefsUses(CP.getSrcReg(), CP.getDstReg(), CP.getSrcIdx());
2180+
if (CP.getDstIdx()) {
2181+
assert(!IsSubregToReg && "can this happen?");
2182+
updateRegDefsUses(CP.getDstReg(), CP.getDstReg(), CP.getDstIdx(), false);
2183+
}
2184+
updateRegDefsUses(CP.getSrcReg(), CP.getDstReg(), CP.getSrcIdx(),
2185+
IsSubregToReg);
21532186

21542187
// Shrink subregister ranges if necessary.
21552188
if (ShrinkMask.any()) {

0 commit comments

Comments
 (0)