Skip to content

Commit 9b21b02

Browse files
committed
[LRE] Adjust order of cases in eliminateDeadDefs
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 2512611 commit 9b21b02

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
@@ -303,14 +303,45 @@ void LiveRangeEdit::eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink) {
303303
}
304304
}
305305

306+
// If the dest of MI is an original reg and MI is reMaterializable,
307+
// don't delete the inst. Replace the dest with a new reg, and keep
308+
// the inst for remat of other siblings. The inst is saved in
309+
// LiveRangeEdit::DeadRemats and will be deleted after all the
310+
// allocations of the func are done. Note that if we keep the
311+
// instruction with the original operands, that handles the physreg
312+
// operand case (described just below) as well.
313+
// However, immediately delete instructions which have unshrunk virtual
314+
// register uses. That may provoke RA to split an interval at the KILL
315+
// and later result in an invalid live segment end.
316+
if (isOrigDef && DeadRemats && !HasLiveVRegUses &&
317+
TII.isReMaterializable(*MI)) {
318+
LiveInterval &NewLI = createEmptyIntervalFrom(Dest, false);
319+
VNInfo::Allocator &Alloc = LIS.getVNInfoAllocator();
320+
VNInfo *VNI = NewLI.getNextValue(Idx, Alloc);
321+
NewLI.addSegment(LiveInterval::Segment(Idx, Idx.getDeadSlot(), VNI));
322+
323+
if (DestSubReg) {
324+
const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
325+
auto *SR = NewLI.createSubRange(
326+
Alloc, TRI->getSubRegIndexLaneMask(DestSubReg));
327+
SR->addSegment(LiveInterval::Segment(Idx, Idx.getDeadSlot(),
328+
SR->getNextValue(Idx, Alloc)));
329+
}
330+
331+
pop_back();
332+
DeadRemats->insert(MI);
333+
const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
334+
MI->substituteRegister(Dest, NewLI.reg(), 0, TRI);
335+
assert(MI->registerDefIsDead(NewLI.reg(), &TRI));
336+
}
306337
// Currently, we don't support DCE of physreg live ranges. If MI reads
307338
// any unreserved physregs, don't erase the instruction, but turn it into
308339
// a KILL instead. This way, the physreg live ranges don't end up
309340
// dangling.
310341
// FIXME: It would be better to have something like shrinkToUses() for
311342
// physregs. That could potentially enable more DCE and it would free up
312343
// the physreg. It would not happen often, though.
313-
if (ReadsPhysRegs) {
344+
else if (ReadsPhysRegs) {
314345
MI->setDesc(TII.get(TargetOpcode::KILL));
315346
// Remove all operands that aren't physregs.
316347
for (unsigned i = MI->getNumOperands(); i; --i) {
@@ -322,41 +353,11 @@ void LiveRangeEdit::eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink) {
322353
MI->dropMemRefs(*MI->getMF());
323354
LLVM_DEBUG(dbgs() << "Converted physregs to:\t" << *MI);
324355
} else {
325-
// If the dest of MI is an original reg and MI is reMaterializable,
326-
// don't delete the inst. Replace the dest with a new reg, and keep
327-
// the inst for remat of other siblings. The inst is saved in
328-
// LiveRangeEdit::DeadRemats and will be deleted after all the
329-
// allocations of the func are done.
330-
// However, immediately delete instructions which have unshrunk virtual
331-
// register uses. That may provoke RA to split an interval at the KILL
332-
// and later result in an invalid live segment end.
333-
if (isOrigDef && DeadRemats && !HasLiveVRegUses &&
334-
TII.isReMaterializable(*MI)) {
335-
LiveInterval &NewLI = createEmptyIntervalFrom(Dest, false);
336-
VNInfo::Allocator &Alloc = LIS.getVNInfoAllocator();
337-
VNInfo *VNI = NewLI.getNextValue(Idx, Alloc);
338-
NewLI.addSegment(LiveInterval::Segment(Idx, Idx.getDeadSlot(), VNI));
339-
340-
if (DestSubReg) {
341-
const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
342-
auto *SR = NewLI.createSubRange(
343-
Alloc, TRI->getSubRegIndexLaneMask(DestSubReg));
344-
SR->addSegment(LiveInterval::Segment(Idx, Idx.getDeadSlot(),
345-
SR->getNextValue(Idx, Alloc)));
346-
}
347-
348-
pop_back();
349-
DeadRemats->insert(MI);
350-
const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
351-
MI->substituteRegister(Dest, NewLI.reg(), 0, TRI);
352-
assert(MI->registerDefIsDead(NewLI.reg(), &TRI));
353-
} else {
354-
if (TheDelegate)
355-
TheDelegate->LRE_WillEraseInstruction(MI);
356-
LIS.RemoveMachineInstrFromMaps(*MI);
357-
MI->eraseFromParent();
358-
++NumDCEDeleted;
359-
}
356+
if (TheDelegate)
357+
TheDelegate->LRE_WillEraseInstruction(MI);
358+
LIS.RemoveMachineInstrFromMaps(*MI);
359+
MI->eraseFromParent();
360+
++NumDCEDeleted;
360361
}
361362

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

0 commit comments

Comments
 (0)