Skip to content

[CodeGen] NFC: Move isDead to MachineInstr #123531

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions llvm/include/llvm/CodeGen/MachineInstr.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class BatchAAResults;
template <typename T> class ArrayRef;
class DIExpression;
class DILocalVariable;
class LiveRegUnits;
class MachineBasicBlock;
class MachineFunction;
class MachineRegisterInfo;
Expand Down Expand Up @@ -1744,6 +1745,18 @@ class MachineInstr
/// defined registers were dead.
bool wouldBeTriviallyDead() const;

/// Check whether an MI is dead. If \p LivePhysRegs is provided, it is assumed
/// to be at the position of MI and will be used to check the Liveness of
/// physical register defs. If \p LivePhysRegs is not provided, this will
/// pessimistically assume any PhysReg def is live.
/// For trivially dead instructions (i.e. those without hard to model effects
/// / wouldBeTriviallyDead), this checks deadness by analyzing defs of the
/// MachineInstr. If the instruction wouldBeTriviallyDead, and all the defs
/// either have dead flags or have no uses, then the instruction is said to be
/// dead.
bool isDead(const MachineRegisterInfo &MRI,
LiveRegUnits *LivePhysRegs = nullptr) const;

/// Returns true if this instruction's memory access aliases the memory
/// access of Other.
//
Expand Down
46 changes: 1 addition & 45 deletions llvm/lib/CodeGen/DeadMachineInstructionElim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ class DeadMachineInstructionElimImpl {
bool runImpl(MachineFunction &MF);

private:
bool isDead(const MachineInstr *MI) const;
bool eliminateDeadMI(MachineFunction &MF);
};

Expand Down Expand Up @@ -79,47 +78,6 @@ char &llvm::DeadMachineInstructionElimID = DeadMachineInstructionElim::ID;
INITIALIZE_PASS(DeadMachineInstructionElim, DEBUG_TYPE,
"Remove dead machine instructions", false, false)

bool DeadMachineInstructionElimImpl::isDead(const MachineInstr *MI) const {
// Instructions without side-effects are dead iff they only define dead regs.
// This function is hot and this loop returns early in the common case,
// so only perform additional checks before this if absolutely necessary.
for (const MachineOperand &MO : MI->all_defs()) {
Register Reg = MO.getReg();
if (Reg.isPhysical()) {
// Don't delete live physreg defs, or any reserved register defs.
if (!LivePhysRegs.available(Reg) || MRI->isReserved(Reg))
return false;
} else {
if (MO.isDead()) {
#ifndef NDEBUG
// Basic check on the register. All of them should be 'undef'.
for (auto &U : MRI->use_nodbg_operands(Reg))
assert(U.isUndef() && "'Undef' use on a 'dead' register is found!");
#endif
continue;
}
for (const MachineInstr &Use : MRI->use_nodbg_instructions(Reg)) {
if (&Use != MI)
// This def has a non-debug use. Don't delete the instruction!
return false;
}
}
}

// Technically speaking inline asm without side effects and no defs can still
// be deleted. But there is so much bad inline asm code out there, we should
// let them be.
if (MI->isInlineAsm())
return false;

// FIXME: See issue #105950 for why LIFETIME markers are considered dead here.
if (MI->isLifetimeMarker())
return true;

// If there are no defs with uses, the instruction might be dead.
return MI->wouldBeTriviallyDead();
}

bool DeadMachineInstructionElimImpl::runImpl(MachineFunction &MF) {
MRI = &MF.getRegInfo();

Expand All @@ -146,7 +104,7 @@ bool DeadMachineInstructionElimImpl::eliminateDeadMI(MachineFunction &MF) {
// liveness as we go.
for (MachineInstr &MI : make_early_inc_range(reverse(*MBB))) {
// If the instruction is dead, delete it!
if (isDead(&MI)) {
if (MI.isDead(*MRI, &LivePhysRegs)) {
LLVM_DEBUG(dbgs() << "DeadMachineInstructionElim: DELETING: " << MI);
// It is possible that some DBG_VALUE instructions refer to this
// instruction. They will be deleted in the live debug variable
Expand All @@ -156,11 +114,9 @@ bool DeadMachineInstructionElimImpl::eliminateDeadMI(MachineFunction &MF) {
++NumDeletes;
continue;
}

LivePhysRegs.stepBackward(MI);
}
}

LivePhysRegs.clear();
return AnyChanges;
}
38 changes: 38 additions & 0 deletions llvm/lib/CodeGen/MachineInstr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/CodeGen/LiveRegUnits.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
Expand Down Expand Up @@ -1350,6 +1351,43 @@ bool MachineInstr::wouldBeTriviallyDead() const {
return isPHI() || isSafeToMove(SawStore);
}

bool MachineInstr::isDead(const MachineRegisterInfo &MRI,
LiveRegUnits *LivePhysRegs) const {
// Technically speaking inline asm without side effects and no defs can still
// be deleted. But there is so much bad inline asm code out there, we should
// let them be.
if (isInlineAsm())
return false;

// If we suspect this instruction may have some side-effects, then we say
// this instruction cannot be dead.
// FIXME: See issue #105950 for why LIFETIME markers are considered dead here.
if (!isLifetimeMarker() && !wouldBeTriviallyDead())
return false;

// Instructions without side-effects are dead iff they only define dead regs.
// This function is hot and this loop returns early in the common case,
// so only perform additional checks before this if absolutely necessary.
for (const MachineOperand &MO : all_defs()) {
Register Reg = MO.getReg();
if (Reg.isPhysical()) {
// Don't delete live physreg defs, or any reserved register defs.
if (!LivePhysRegs || !LivePhysRegs->available(Reg) || MRI.isReserved(Reg))
return false;
} else {
if (MO.isDead())
continue;
for (const MachineInstr &Use : MRI.use_nodbg_instructions(Reg)) {
if (&Use != this)
// This def has a non-debug use. Don't delete the instruction!
return false;
}
}
}

return true;
}

static bool MemOperandsHaveAlias(const MachineFrameInfo &MFI,
BatchAAResults *AA, bool UseTBAA,
const MachineMemOperand *MMOa,
Expand Down
Loading