Skip to content

Commit 2d338be

Browse files
[CodeGen] Refactor DeadMIElim isDead and GISel isTriviallyDead (#105956)
Merge GlobalISel's isTriviallyDead and DeadMachineInstructionElim's isDead code and remove all unnecessary checks from the hot path by looping over the operands before doing any other checks. See #105950 for why DeadMIElim needs to remove LIFETIME markers even though they probably shouldn't generally be considered dead. x86 CTMark O3: -0.1% AArch64 GlobalISel CTMark O0: -0.6%, O2: -0.2%
1 parent a2f659c commit 2d338be

File tree

4 files changed

+50
-42
lines changed

4 files changed

+50
-42
lines changed

llvm/include/llvm/CodeGen/MachineInstr.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,6 +1323,11 @@ class MachineInstr
13231323
return getOpcode() == TargetOpcode::ANNOTATION_LABEL;
13241324
}
13251325

1326+
bool isLifetimeMarker() const {
1327+
return getOpcode() == TargetOpcode::LIFETIME_START ||
1328+
getOpcode() == TargetOpcode::LIFETIME_END;
1329+
}
1330+
13261331
/// Returns true if the MachineInstr represents a label.
13271332
bool isLabel() const {
13281333
return isEHLabel() || isGCLabel() || isAnnotationLabel();
@@ -1727,6 +1732,10 @@ class MachineInstr
17271732
/// the instruction's location and its intended destination.
17281733
bool isSafeToMove(bool &SawStore) const;
17291734

1735+
/// Return true if this instruction would be trivially dead if all of its
1736+
/// defined registers were dead.
1737+
bool wouldBeTriviallyDead() const;
1738+
17301739
/// Returns true if this instruction's memory access aliases the memory
17311740
/// access of Other.
17321741
//

llvm/lib/CodeGen/DeadMachineInstructionElim.cpp

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -80,23 +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-
MI->getOpcode() == TargetOpcode::FAKE_USE)
92-
return false;
93-
94-
// Don't delete instructions with side effects.
95-
bool SawStore = false;
96-
if (!MI->isSafeToMove(SawStore) && !MI->isPHI())
97-
return false;
98-
99-
// Examine each operand.
83+
// Instructions without side-effects are dead iff they only define dead regs.
84+
// This function is hot and this loop returns early in the common case,
85+
// so only perform additional checks before this if absolutely necessary.
10086
for (const MachineOperand &MO : MI->all_defs()) {
10187
Register Reg = MO.getReg();
10288
if (Reg.isPhysical()) {
@@ -120,8 +106,18 @@ bool DeadMachineInstructionElimImpl::isDead(const MachineInstr *MI) const {
120106
}
121107
}
122108

123-
// If there are no defs with uses, the instruction is dead.
124-
return true;
109+
// Technically speaking inline asm without side effects and no defs can still
110+
// be deleted. But there is so much bad inline asm code out there, we should
111+
// let them be.
112+
if (MI->isInlineAsm())
113+
return false;
114+
115+
// FIXME: See issue #105950 for why LIFETIME markers are considered dead here.
116+
if (MI->isLifetimeMarker())
117+
return true;
118+
119+
// If there are no defs with uses, the instruction might be dead.
120+
return MI->wouldBeTriviallyDead();
125121
}
126122

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

llvm/lib/CodeGen/GlobalISel/Utils.cpp

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -221,34 +221,15 @@ 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?
227-
228-
// Don't delete frame allocation labels.
229-
if (MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE)
230-
return false;
231-
// Don't delete fake uses.
232-
if (MI.getOpcode() == TargetOpcode::FAKE_USE)
233-
return false;
234-
// LIFETIME markers should be preserved even if they seem dead.
235-
if (MI.getOpcode() == TargetOpcode::LIFETIME_START ||
236-
MI.getOpcode() == TargetOpcode::LIFETIME_END)
237-
return false;
238-
239-
// If we can move an instruction, we can remove it. Otherwise, it has
240-
// a side-effect of some sort.
241-
bool SawStore = false;
242-
if (!MI.isSafeToMove(SawStore) && !MI.isPHI())
243-
return false;
244-
245-
// Instructions without side-effects are dead iff they only define dead vregs.
224+
// Instructions without side-effects are dead iff they only define dead regs.
225+
// This function is hot and this loop returns early in the common case,
226+
// so only perform additional checks before this if absolutely necessary.
246227
for (const auto &MO : MI.all_defs()) {
247228
Register Reg = MO.getReg();
248229
if (Reg.isPhysical() || !MRI.use_nodbg_empty(Reg))
249230
return false;
250231
}
251-
return true;
232+
return MI.wouldBeTriviallyDead();
252233
}
253234

254235
static void reportGISelDiagnostic(DiagnosticSeverity Severity,

llvm/lib/CodeGen/MachineInstr.cpp

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

1326+
bool MachineInstr::wouldBeTriviallyDead() const {
1327+
// Don't delete frame allocation labels.
1328+
// FIXME: Why is LOCAL_ESCAPE not considered in MachineInstr::isLabel?
1329+
if (getOpcode() == TargetOpcode::LOCAL_ESCAPE)
1330+
return false;
1331+
1332+
// Don't delete FAKE_USE.
1333+
// FIXME: Why is FAKE_USE not considered in MachineInstr::isPosition?
1334+
if (isFakeUse())
1335+
return false;
1336+
1337+
// LIFETIME markers should be preserved.
1338+
// FIXME: Why are LIFETIME markers not considered in MachineInstr::isPosition?
1339+
if (isLifetimeMarker())
1340+
return false;
1341+
1342+
// If we can move an instruction, we can remove it. Otherwise, it has
1343+
// a side-effect of some sort.
1344+
bool SawStore = false;
1345+
return isPHI() || isSafeToMove(SawStore);
1346+
}
1347+
13261348
static bool MemOperandsHaveAlias(const MachineFrameInfo &MFI, AAResults *AA,
13271349
bool UseTBAA, const MachineMemOperand *MMOa,
13281350
const MachineMemOperand *MMOb) {

0 commit comments

Comments
 (0)