Skip to content

Commit 459472e

Browse files
authored
[LRE] Adjust order of cases in eliminateDeadDefs (#162108)
If we have a rematerializable instruction without live virtual register uses (that we didn't heuristically decide to shrink), but with a physreg use, we were creating a kill to keep the physreg operand liveness unchanged. This meant we *weren't* keeping around the remat instruction, and thus inhibiting future remat within the original live interval. If we keep the remat instruction, that *also* keeps the physreg use, and thus we can achieve both objectives at once. Noticed this via inspection, and we don't currently seem to have any rematerializable instructions which could observe the difference. This could in theory happen for both trivial and non-trivial remat, but requires the rematerialization of an instruction with a physreg use.
1 parent 6ae6583 commit 459472e

File tree

1 file changed

+37
-36
lines changed

1 file changed

+37
-36
lines changed

llvm/lib/CodeGen/LiveRangeEdit.cpp

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -274,14 +274,45 @@ void LiveRangeEdit::eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink) {
274274
}
275275
}
276276

277+
// If the dest of MI is an original reg and MI is reMaterializable,
278+
// don't delete the inst. Replace the dest with a new reg, and keep
279+
// the inst for remat of other siblings. The inst is saved in
280+
// LiveRangeEdit::DeadRemats and will be deleted after all the
281+
// allocations of the func are done. Note that if we keep the
282+
// instruction with the original operands, that handles the physreg
283+
// operand case (described just below) as well.
284+
// However, immediately delete instructions which have unshrunk virtual
285+
// register uses. That may provoke RA to split an interval at the KILL
286+
// and later result in an invalid live segment end.
287+
if (isOrigDef && DeadRemats && !HasLiveVRegUses &&
288+
TII.isReMaterializable(*MI)) {
289+
LiveInterval &NewLI = createEmptyIntervalFrom(Dest, false);
290+
VNInfo::Allocator &Alloc = LIS.getVNInfoAllocator();
291+
VNInfo *VNI = NewLI.getNextValue(Idx, Alloc);
292+
NewLI.addSegment(LiveInterval::Segment(Idx, Idx.getDeadSlot(), VNI));
293+
294+
if (DestSubReg) {
295+
const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
296+
auto *SR =
297+
NewLI.createSubRange(Alloc, TRI->getSubRegIndexLaneMask(DestSubReg));
298+
SR->addSegment(LiveInterval::Segment(Idx, Idx.getDeadSlot(),
299+
SR->getNextValue(Idx, Alloc)));
300+
}
301+
302+
pop_back();
303+
DeadRemats->insert(MI);
304+
const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
305+
MI->substituteRegister(Dest, NewLI.reg(), 0, TRI);
306+
assert(MI->registerDefIsDead(NewLI.reg(), &TRI));
307+
}
277308
// Currently, we don't support DCE of physreg live ranges. If MI reads
278309
// any unreserved physregs, don't erase the instruction, but turn it into
279310
// a KILL instead. This way, the physreg live ranges don't end up
280311
// dangling.
281312
// FIXME: It would be better to have something like shrinkToUses() for
282313
// physregs. That could potentially enable more DCE and it would free up
283314
// the physreg. It would not happen often, though.
284-
if (ReadsPhysRegs) {
315+
else if (ReadsPhysRegs) {
285316
MI->setDesc(TII.get(TargetOpcode::KILL));
286317
// Remove all operands that aren't physregs.
287318
for (unsigned i = MI->getNumOperands(); i; --i) {
@@ -293,41 +324,11 @@ void LiveRangeEdit::eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink) {
293324
MI->dropMemRefs(*MI->getMF());
294325
LLVM_DEBUG(dbgs() << "Converted physregs to:\t" << *MI);
295326
} else {
296-
// If the dest of MI is an original reg and MI is reMaterializable,
297-
// don't delete the inst. Replace the dest with a new reg, and keep
298-
// the inst for remat of other siblings. The inst is saved in
299-
// LiveRangeEdit::DeadRemats and will be deleted after all the
300-
// allocations of the func are done.
301-
// However, immediately delete instructions which have unshrunk virtual
302-
// register uses. That may provoke RA to split an interval at the KILL
303-
// and later result in an invalid live segment end.
304-
if (isOrigDef && DeadRemats && !HasLiveVRegUses &&
305-
TII.isReMaterializable(*MI)) {
306-
LiveInterval &NewLI = createEmptyIntervalFrom(Dest, false);
307-
VNInfo::Allocator &Alloc = LIS.getVNInfoAllocator();
308-
VNInfo *VNI = NewLI.getNextValue(Idx, Alloc);
309-
NewLI.addSegment(LiveInterval::Segment(Idx, Idx.getDeadSlot(), VNI));
310-
311-
if (DestSubReg) {
312-
const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
313-
auto *SR = NewLI.createSubRange(
314-
Alloc, TRI->getSubRegIndexLaneMask(DestSubReg));
315-
SR->addSegment(LiveInterval::Segment(Idx, Idx.getDeadSlot(),
316-
SR->getNextValue(Idx, Alloc)));
317-
}
318-
319-
pop_back();
320-
DeadRemats->insert(MI);
321-
const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
322-
MI->substituteRegister(Dest, NewLI.reg(), 0, TRI);
323-
assert(MI->registerDefIsDead(NewLI.reg(), &TRI));
324-
} else {
325-
if (TheDelegate)
326-
TheDelegate->LRE_WillEraseInstruction(MI);
327-
LIS.RemoveMachineInstrFromMaps(*MI);
328-
MI->eraseFromParent();
329-
++NumDCEDeleted;
330-
}
327+
if (TheDelegate)
328+
TheDelegate->LRE_WillEraseInstruction(MI);
329+
LIS.RemoveMachineInstrFromMaps(*MI);
330+
MI->eraseFromParent();
331+
++NumDCEDeleted;
331332
}
332333

333334
// Erase any virtregs that are now empty and unused. There may be <undef>

0 commit comments

Comments
 (0)