Skip to content

Commit 9559f62

Browse files
committed
Revert "Revert "Reland "RegisterCoalescer: Add implicit-def of super register when coalescing SUBREG_TO_REG" (#123632)""
This reverts commit 6b1db79.
1 parent 808ebbd commit 9559f62

25 files changed

+1250
-140
lines changed

llvm/lib/CodeGen/RegisterCoalescer.cpp

Lines changed: 65 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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

18741880
void 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\tupdated: ";
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

Comments
 (0)