Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 8 additions & 0 deletions llvm/include/llvm/CodeGen/MachineInstr.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class AAResults;
template <typename T> class ArrayRef;
class DIExpression;
class DILocalVariable;
class LiveRegUnits;
class MachineBasicBlock;
class MachineFunction;
class MachineRegisterInfo;
Expand Down Expand Up @@ -1786,6 +1787,13 @@ class MachineInstr
/// Return true if all the implicit defs of this instruction are dead.
bool allImplicitDefsAreDead() 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.
bool isDead(const MachineRegisterInfo *MRI,
LiveRegUnits *LivePhysRegs = nullptr) const;

/// Return a valid size if the instruction is a spill instruction.
std::optional<LocationSize> getSpillSize(const TargetInstrInfo *TII) const;

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 @@ -1592,6 +1593,43 @@ bool MachineInstr::allImplicitDefsAreDead() const {
return true;
}

bool MachineInstr::isDead(const MachineRegisterInfo *MRI,
LiveRegUnits *LivePhysRegs) 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 : 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;
}
}
}

// 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;

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

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

/// copyImplicitOps - Copy implicit register operands from specified
/// instruction to this instruction.
void MachineInstr::copyImplicitOps(MachineFunction &MF,
Expand Down
Loading