Implement LiveRangeCalc::extendToUses() and createDeadDefs().

These LiveRangeCalc methods are to be used when computing a live range
from scratch.

llvm-svn: 158027
This commit is contained in:
Jakob Stoklund Olesen 2012-06-05 21:54:09 +00:00
parent 4b037005d2
commit 989b3b1516
4 changed files with 108 additions and 2 deletions

View File

@ -274,6 +274,11 @@ namespace llvm {
return VNI;
}
/// createDeadDef - Make sure the interval has a value defined at Def.
/// If one already exists, return it. Otherwise allocate a new value and
/// add liveness for a dead def.
VNInfo *createDeadDef(SlotIndex Def, VNInfo::Allocator &VNInfoAllocator);
/// Create a copy of the given value. The new value will be identical except
/// for the Value number.
VNInfo *createValueCopy(const VNInfo *orig,

View File

@ -48,6 +48,26 @@ LiveInterval::iterator LiveInterval::find(SlotIndex Pos) {
return I;
}
VNInfo *LiveInterval::createDeadDef(SlotIndex Def,
VNInfo::Allocator &VNInfoAllocator) {
assert(!Def.isDead() && "Cannot define a value at the dead slot");
iterator I = find(Def);
if (I == end()) {
VNInfo *VNI = getNextValue(Def, VNInfoAllocator);
ranges.push_back(LiveRange(Def, Def.getDeadSlot(), VNI));
return VNI;
}
if (SlotIndex::isSameInstr(Def, I->start)) {
assert(I->start == Def && "Cannot insert def, already live");
assert(I->valno->def == Def && "Inconsistent existing value def");
return I->valno;
}
assert(SlotIndex::isEarlierInstr(Def, I->start) && "Already live at def");
VNInfo *VNI = getNextValue(Def, VNInfoAllocator);
ranges.insert(I, LiveRange(Def, Def.getDeadSlot(), VNI));
return VNI;
}
/// killedInRange - Return true if the interval has kills in [Start,End).
bool LiveInterval::killedInRange(SlotIndex Start, SlotIndex End) const {
Ranges::const_iterator r =

View File

@ -14,6 +14,7 @@
#define DEBUG_TYPE "regalloc"
#include "LiveRangeCalc.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
using namespace llvm;
@ -34,6 +35,71 @@ void LiveRangeCalc::reset(const MachineFunction *MF,
}
void LiveRangeCalc::createDeadDefs(LiveInterval *LI, unsigned Reg) {
assert(MRI && Indexes && "call reset() first");
// Visit all def operands. If the same instruction has multiple defs of Reg,
// LI->createDeadDef() will deduplicate.
for (MachineRegisterInfo::def_iterator
I = MRI->def_begin(Reg), E = MRI->def_end(); I != E; ++I) {
const MachineInstr *MI = &*I;
// Find the corresponding slot index.
SlotIndex Idx;
if (MI->isPHI())
// PHI defs begin at the basic block start index.
Idx = Indexes->getMBBStartIdx(MI->getParent());
else
// Instructions are either normal 'r', or early clobber 'e'.
Idx = Indexes->getInstructionIndex(MI)
.getRegSlot(I.getOperand().isEarlyClobber());
// Create the def in LI. This may find an existing def.
VNInfo *VNI = LI->createDeadDef(Idx, *Alloc);
VNI->setIsPHIDef(MI->isPHI());
}
}
void LiveRangeCalc::extendToUses(LiveInterval *LI, unsigned Reg) {
assert(MRI && Indexes && "call reset() first");
// Visit all operands that read Reg. This may include partial defs.
for (MachineRegisterInfo::reg_nodbg_iterator I = MRI->reg_nodbg_begin(Reg),
E = MRI->reg_nodbg_end(); I != E; ++I) {
const MachineOperand &MO = I.getOperand();
if (!MO.readsReg())
continue;
// MI is reading Reg. We may have visited MI before if it happens to be
// reading Reg multiple times. That is OK, extend() is idempotent.
const MachineInstr *MI = &*I;
// Find the SlotIndex being read.
SlotIndex Idx;
if (MI->isPHI()) {
assert(!MO.isDef() && "Cannot handle PHI def of partial register.");
// PHI operands are paired: (Reg, PredMBB).
// Extend the live range to be live-out from PredMBB.
Idx = Indexes->getMBBEndIdx(MI->getOperand(I.getOperandNo()+1).getMBB());
} else {
// This is a normal instruction.
Idx = Indexes->getInstructionIndex(MI).getRegSlot();
// Check for early-clobber redefs.
unsigned DefIdx;
if (MO.isDef()) {
if (MO.isEarlyClobber())
Idx = Idx.getRegSlot(true);
} else if (MI->isRegTiedToDefOperand(I.getOperandNo(), &DefIdx)) {
// FIXME: This would be a lot easier if tied early-clobber uses also
// had an early-clobber flag.
if (MI->getOperand(DefIdx).isEarlyClobber())
Idx = Idx.getRegSlot(true);
}
}
extend(LI, Idx);
}
}
// Transfer information from the LiveIn vector to the live ranges.
void LiveRangeCalc::updateLiveIns(VNInfo *OverrideVNI) {
for (SmallVectorImpl<LiveInBlock>::iterator I = LiveIn.begin(),

View File

@ -159,11 +159,26 @@ public:
/// single existing value, Alloc may be null.
void extend(LiveInterval *LI, SlotIndex Kill);
/// extendToUses - Extend the live range of LI to reach all uses.
/// createDeadDefs - Create a dead def in LI for every def operand of Reg.
/// Each instruction defining Reg gets a new VNInfo with a corresponding
/// minimal live range.
void createDeadDefs(LiveInterval *LI, unsigned Reg);
/// createDeadDefs - Create a dead def in LI for every def of LI->reg.
void createDeadDefs(LiveInterval *LI) {
createDeadDefs(LI, LI->reg);
}
/// extendToUses - Extend the live range of LI to reach all uses of Reg.
///
/// All uses must be jointly dominated by existing liveness. PHI-defs are
/// inserted as needed to preserve SSA form.
void extendToUses(LiveInterval *LI);
void extendToUses(LiveInterval *LI, unsigned Reg);
/// extendToUses - Extend the live range of LI to reach all uses of LI->reg.
void extendToUses(LiveInterval *LI) {
extendToUses(LI, LI->reg);
}
//===--------------------------------------------------------------------===//
// Low-level interface.