mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-26 06:04:47 +00:00
Refactor LiveRangeEdit::eliminateDeadDefs.
I want to add logic to handle more cases. llvm-svn: 184571
This commit is contained in:
parent
8720e81dc3
commit
fdd89e475c
@ -19,6 +19,7 @@
|
||||
#define LLVM_CODEGEN_LIVERANGEEDIT_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/CodeGen/LiveInterval.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
@ -90,6 +91,12 @@ private:
|
||||
/// a load, eliminate the register by folding the def into the use.
|
||||
bool foldAsLoad(LiveInterval *LI, SmallVectorImpl<MachineInstr*> &Dead);
|
||||
|
||||
typedef SetVector<LiveInterval*,
|
||||
SmallVector<LiveInterval*, 8>,
|
||||
SmallPtrSet<LiveInterval*, 8> > ToShrinkSet;
|
||||
/// Helper for eliminateDeadDefs.
|
||||
void eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink);
|
||||
|
||||
public:
|
||||
/// Create a LiveRangeEdit for breaking down parent into smaller pieces.
|
||||
/// @param parent The register being spilled or split.
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
#define DEBUG_TYPE "regalloc"
|
||||
#include "llvm/CodeGen/LiveRangeEdit.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/CodeGen/CalcSpillWeights.h"
|
||||
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
|
||||
@ -216,108 +215,109 @@ bool LiveRangeEdit::foldAsLoad(LiveInterval *LI,
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Find all live intervals that need to shrink, then remove the instruction.
|
||||
void LiveRangeEdit::eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink) {
|
||||
assert(MI->allDefsAreDead() && "Def isn't really dead");
|
||||
SlotIndex Idx = LIS.getInstructionIndex(MI).getRegSlot();
|
||||
|
||||
// Never delete inline asm.
|
||||
if (MI->isInlineAsm()) {
|
||||
DEBUG(dbgs() << "Won't delete: " << Idx << '\t' << *MI);
|
||||
return;
|
||||
}
|
||||
|
||||
// Use the same criteria as DeadMachineInstructionElim.
|
||||
bool SawStore = false;
|
||||
if (!MI->isSafeToMove(&TII, 0, SawStore)) {
|
||||
DEBUG(dbgs() << "Can't delete: " << Idx << '\t' << *MI);
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG(dbgs() << "Deleting dead def " << Idx << '\t' << *MI);
|
||||
|
||||
// Collect virtual registers to be erased after MI is gone.
|
||||
SmallVector<unsigned, 8> RegsToErase;
|
||||
bool ReadsPhysRegs = false;
|
||||
|
||||
// Check for live intervals that may shrink
|
||||
for (MachineInstr::mop_iterator MOI = MI->operands_begin(),
|
||||
MOE = MI->operands_end(); MOI != MOE; ++MOI) {
|
||||
if (!MOI->isReg())
|
||||
continue;
|
||||
unsigned Reg = MOI->getReg();
|
||||
if (!TargetRegisterInfo::isVirtualRegister(Reg)) {
|
||||
// Check if MI reads any unreserved physregs.
|
||||
if (Reg && MOI->readsReg() && !MRI.isReserved(Reg))
|
||||
ReadsPhysRegs = true;
|
||||
continue;
|
||||
}
|
||||
LiveInterval &LI = LIS.getInterval(Reg);
|
||||
|
||||
// Shrink read registers, unless it is likely to be expensive and
|
||||
// unlikely to change anything. We typically don't want to shrink the
|
||||
// PIC base register that has lots of uses everywhere.
|
||||
// Always shrink COPY uses that probably come from live range splitting.
|
||||
if (MI->readsVirtualRegister(Reg) &&
|
||||
(MI->isCopy() || MOI->isDef() || MRI.hasOneNonDBGUse(Reg) ||
|
||||
LI.killedAt(Idx)))
|
||||
ToShrink.insert(&LI);
|
||||
|
||||
// Remove defined value.
|
||||
if (MOI->isDef()) {
|
||||
if (VNInfo *VNI = LI.getVNInfoAt(Idx)) {
|
||||
if (TheDelegate)
|
||||
TheDelegate->LRE_WillShrinkVirtReg(LI.reg);
|
||||
LI.removeValNo(VNI);
|
||||
if (LI.empty())
|
||||
RegsToErase.push_back(Reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Currently, we don't support DCE of physreg live ranges. If MI reads
|
||||
// any unreserved physregs, don't erase the instruction, but turn it into
|
||||
// a KILL instead. This way, the physreg live ranges don't end up
|
||||
// dangling.
|
||||
// FIXME: It would be better to have something like shrinkToUses() for
|
||||
// physregs. That could potentially enable more DCE and it would free up
|
||||
// the physreg. It would not happen often, though.
|
||||
if (ReadsPhysRegs) {
|
||||
MI->setDesc(TII.get(TargetOpcode::KILL));
|
||||
// Remove all operands that aren't physregs.
|
||||
for (unsigned i = MI->getNumOperands(); i; --i) {
|
||||
const MachineOperand &MO = MI->getOperand(i-1);
|
||||
if (MO.isReg() && TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
|
||||
continue;
|
||||
MI->RemoveOperand(i-1);
|
||||
}
|
||||
DEBUG(dbgs() << "Converted physregs to:\t" << *MI);
|
||||
} else {
|
||||
if (TheDelegate)
|
||||
TheDelegate->LRE_WillEraseInstruction(MI);
|
||||
LIS.RemoveMachineInstrFromMaps(MI);
|
||||
MI->eraseFromParent();
|
||||
++NumDCEDeleted;
|
||||
}
|
||||
|
||||
// Erase any virtregs that are now empty and unused. There may be <undef>
|
||||
// uses around. Keep the empty live range in that case.
|
||||
for (unsigned i = 0, e = RegsToErase.size(); i != e; ++i) {
|
||||
unsigned Reg = RegsToErase[i];
|
||||
if (LIS.hasInterval(Reg) && MRI.reg_nodbg_empty(Reg)) {
|
||||
ToShrink.remove(&LIS.getInterval(Reg));
|
||||
eraseVirtReg(Reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LiveRangeEdit::eliminateDeadDefs(SmallVectorImpl<MachineInstr*> &Dead,
|
||||
ArrayRef<unsigned> RegsBeingSpilled) {
|
||||
SetVector<LiveInterval*,
|
||||
SmallVector<LiveInterval*, 8>,
|
||||
SmallPtrSet<LiveInterval*, 8> > ToShrink;
|
||||
ToShrinkSet ToShrink;
|
||||
|
||||
for (;;) {
|
||||
// Erase all dead defs.
|
||||
while (!Dead.empty()) {
|
||||
MachineInstr *MI = Dead.pop_back_val();
|
||||
assert(MI->allDefsAreDead() && "Def isn't really dead");
|
||||
SlotIndex Idx = LIS.getInstructionIndex(MI).getRegSlot();
|
||||
|
||||
// Never delete inline asm.
|
||||
if (MI->isInlineAsm()) {
|
||||
DEBUG(dbgs() << "Won't delete: " << Idx << '\t' << *MI);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Use the same criteria as DeadMachineInstructionElim.
|
||||
bool SawStore = false;
|
||||
if (!MI->isSafeToMove(&TII, 0, SawStore)) {
|
||||
DEBUG(dbgs() << "Can't delete: " << Idx << '\t' << *MI);
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUG(dbgs() << "Deleting dead def " << Idx << '\t' << *MI);
|
||||
|
||||
// Collect virtual registers to be erased after MI is gone.
|
||||
SmallVector<unsigned, 8> RegsToErase;
|
||||
bool ReadsPhysRegs = false;
|
||||
|
||||
// Check for live intervals that may shrink
|
||||
for (MachineInstr::mop_iterator MOI = MI->operands_begin(),
|
||||
MOE = MI->operands_end(); MOI != MOE; ++MOI) {
|
||||
if (!MOI->isReg())
|
||||
continue;
|
||||
unsigned Reg = MOI->getReg();
|
||||
if (!TargetRegisterInfo::isVirtualRegister(Reg)) {
|
||||
// Check if MI reads any unreserved physregs.
|
||||
if (Reg && MOI->readsReg() && !MRI.isReserved(Reg))
|
||||
ReadsPhysRegs = true;
|
||||
continue;
|
||||
}
|
||||
LiveInterval &LI = LIS.getInterval(Reg);
|
||||
|
||||
// Shrink read registers, unless it is likely to be expensive and
|
||||
// unlikely to change anything. We typically don't want to shrink the
|
||||
// PIC base register that has lots of uses everywhere.
|
||||
// Always shrink COPY uses that probably come from live range splitting.
|
||||
if (MI->readsVirtualRegister(Reg) &&
|
||||
(MI->isCopy() || MOI->isDef() || MRI.hasOneNonDBGUse(Reg) ||
|
||||
LI.killedAt(Idx)))
|
||||
ToShrink.insert(&LI);
|
||||
|
||||
// Remove defined value.
|
||||
if (MOI->isDef()) {
|
||||
if (VNInfo *VNI = LI.getVNInfoAt(Idx)) {
|
||||
if (TheDelegate)
|
||||
TheDelegate->LRE_WillShrinkVirtReg(LI.reg);
|
||||
LI.removeValNo(VNI);
|
||||
if (LI.empty())
|
||||
RegsToErase.push_back(Reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Currently, we don't support DCE of physreg live ranges. If MI reads
|
||||
// any unreserved physregs, don't erase the instruction, but turn it into
|
||||
// a KILL instead. This way, the physreg live ranges don't end up
|
||||
// dangling.
|
||||
// FIXME: It would be better to have something like shrinkToUses() for
|
||||
// physregs. That could potentially enable more DCE and it would free up
|
||||
// the physreg. It would not happen often, though.
|
||||
if (ReadsPhysRegs) {
|
||||
MI->setDesc(TII.get(TargetOpcode::KILL));
|
||||
// Remove all operands that aren't physregs.
|
||||
for (unsigned i = MI->getNumOperands(); i; --i) {
|
||||
const MachineOperand &MO = MI->getOperand(i-1);
|
||||
if (MO.isReg() && TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
|
||||
continue;
|
||||
MI->RemoveOperand(i-1);
|
||||
}
|
||||
DEBUG(dbgs() << "Converted physregs to:\t" << *MI);
|
||||
} else {
|
||||
if (TheDelegate)
|
||||
TheDelegate->LRE_WillEraseInstruction(MI);
|
||||
LIS.RemoveMachineInstrFromMaps(MI);
|
||||
MI->eraseFromParent();
|
||||
++NumDCEDeleted;
|
||||
}
|
||||
|
||||
// Erase any virtregs that are now empty and unused. There may be <undef>
|
||||
// uses around. Keep the empty live range in that case.
|
||||
for (unsigned i = 0, e = RegsToErase.size(); i != e; ++i) {
|
||||
unsigned Reg = RegsToErase[i];
|
||||
if (LIS.hasInterval(Reg) && MRI.reg_nodbg_empty(Reg)) {
|
||||
ToShrink.remove(&LIS.getInterval(Reg));
|
||||
eraseVirtReg(Reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!Dead.empty())
|
||||
eliminateDeadDef(Dead.pop_back_val(), ToShrink);
|
||||
|
||||
if (ToShrink.empty())
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user