Skip to content

Commit 79267ac

Browse files
[CodeGen] Refactor DeadMIElim isDead and GISel isTriviallyDead
Merge GlobalISel's isTriviallyDead and DeadMachineInstructionElim's isDead behavior and move all unnecessary checks out of the hot path. Functional changes to ponder over: 1. isTriviallyDead now never removes inlineasm like DeadMIElim. 2. We loop over the operands before doing any other checks. Please especially double-check if this fine for the loop in DeadMIElim. See #105950 for why the LIFETIME markers check can't be moved to wouldBeTriviallyDead().
1 parent 3e763db commit 79267ac

File tree

4 files changed

+40
-37
lines changed

4 files changed

+40
-37
lines changed

llvm/include/llvm/CodeGen/MachineInstr.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1725,6 +1725,10 @@ class MachineInstr
17251725
/// the instruction's location and its intended destination.
17261726
bool isSafeToMove(bool &SawStore) const;
17271727

1728+
/// Return true if this instruction would be trivially dead if all its defined
1729+
/// registers were dead.
1730+
bool wouldBeTriviallyDead() const;
1731+
17281732
/// Returns true if this instruction's memory access aliases the memory
17291733
/// access of Other.
17301734
//

llvm/lib/CodeGen/DeadMachineInstructionElim.cpp

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -80,22 +80,9 @@ INITIALIZE_PASS(DeadMachineInstructionElim, DEBUG_TYPE,
8080
"Remove dead machine instructions", false, false)
8181

8282
bool DeadMachineInstructionElimImpl::isDead(const MachineInstr *MI) const {
83-
// Technically speaking inline asm without side effects and no defs can still
84-
// be deleted. But there is so much bad inline asm code out there, we should
85-
// let them be.
86-
if (MI->isInlineAsm())
87-
return false;
88-
89-
// Don't delete frame allocation labels.
90-
if (MI->getOpcode() == TargetOpcode::LOCAL_ESCAPE)
91-
return false;
92-
93-
// Don't delete instructions with side effects.
94-
bool SawStore = false;
95-
if (!MI->isSafeToMove(SawStore) && !MI->isPHI())
96-
return false;
97-
98-
// Examine each operand.
83+
// Instructions without side-effects are dead iff they only define dead regs.
84+
// This function is very hot and this loop returns early in the common case,
85+
// so only perform additional checks before this if absolutely necessary.
9986
for (const MachineOperand &MO : MI->all_defs()) {
10087
Register Reg = MO.getReg();
10188
if (Reg.isPhysical()) {
@@ -119,8 +106,8 @@ bool DeadMachineInstructionElimImpl::isDead(const MachineInstr *MI) const {
119106
}
120107
}
121108

122-
// If there are no defs with uses, the instruction is dead.
123-
return true;
109+
// If there are no defs with uses, the instruction might be dead.
110+
return MI->wouldBeTriviallyDead();
124111
}
125112

126113
bool DeadMachineInstructionElimImpl::runImpl(MachineFunction &MF) {

llvm/lib/CodeGen/GlobalISel/Utils.cpp

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -221,31 +221,22 @@ bool llvm::canReplaceReg(Register DstReg, Register SrcReg,
221221

222222
bool llvm::isTriviallyDead(const MachineInstr &MI,
223223
const MachineRegisterInfo &MRI) {
224-
// FIXME: This logical is mostly duplicated with
225-
// DeadMachineInstructionElim::isDead. Why is LOCAL_ESCAPE not considered in
226-
// MachineInstr::isLabel?
224+
// Instructions without side-effects are dead iff they only define dead regs.
225+
// This function is very hot and this loop returns early in the common case,
226+
// so only perform additional checks before this if absolutely necessary.
227+
for (const auto &MO : MI.all_defs()) {
228+
Register Reg = MO.getReg();
229+
if (Reg.isPhysical() || !MRI.use_nodbg_empty(Reg))
230+
return false;
231+
}
227232

228-
// Don't delete frame allocation labels.
229-
if (MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE)
230-
return false;
231233
// LIFETIME markers should be preserved even if they seem dead.
234+
// FIXME: See issue #105950 for why this isn't in wouldBeTriviallyDead().
232235
if (MI.getOpcode() == TargetOpcode::LIFETIME_START ||
233236
MI.getOpcode() == TargetOpcode::LIFETIME_END)
234237
return false;
235238

236-
// If we can move an instruction, we can remove it. Otherwise, it has
237-
// a side-effect of some sort.
238-
bool SawStore = false;
239-
if (!MI.isSafeToMove(SawStore) && !MI.isPHI())
240-
return false;
241-
242-
// Instructions without side-effects are dead iff they only define dead vregs.
243-
for (const auto &MO : MI.all_defs()) {
244-
Register Reg = MO.getReg();
245-
if (Reg.isPhysical() || !MRI.use_nodbg_empty(Reg))
246-
return false;
247-
}
248-
return true;
239+
return MI.wouldBeTriviallyDead();
249240
}
250241

251242
static void reportGISelDiagnostic(DiagnosticSeverity Severity,

llvm/lib/CodeGen/MachineInstr.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,6 +1323,27 @@ bool MachineInstr::isSafeToMove(bool &SawStore) const {
13231323
return true;
13241324
}
13251325

1326+
bool MachineInstr::wouldBeTriviallyDead() const {
1327+
// Technically speaking inline asm without side effects and no defs can still
1328+
// be deleted. But there is so much bad inline asm code out there, we should
1329+
// let them be.
1330+
if (isInlineAsm())
1331+
return false;
1332+
1333+
// Don't delete frame allocation labels.
1334+
// FIXME: Why is LOCAL_ESCAPE not considered in MachineInstr::isLabel?
1335+
if (getOpcode() == TargetOpcode::LOCAL_ESCAPE)
1336+
return false;
1337+
1338+
// If we can move an instruction, we can remove it. Otherwise, it has
1339+
// a side-effect of some sort.
1340+
bool SawStore = false;
1341+
if (!isSafeToMove(SawStore) && !isPHI())
1342+
return false;
1343+
1344+
return true;
1345+
}
1346+
13261347
static bool MemOperandsHaveAlias(const MachineFrameInfo &MFI, AAResults *AA,
13271348
bool UseTBAA, const MachineMemOperand *MMOa,
13281349
const MachineMemOperand *MMOb) {

0 commit comments

Comments
 (0)