Update LiveDebugVariables after live range splitting.

After a virtual register is split, update any debug user variables that resided
in the old register. This ensures that the LiveDebugVariables are still correct
after register allocation.

This may create DBG_VALUE instructions that place a user variable in a register
in parts of the function and in a stack slot in other parts. DwarfDebug
currently doesn't support that.

llvm-svn: 130998
This commit is contained in:
Jakob Stoklund Olesen 2011-05-06 18:00:02 +00:00
parent c86fe05923
commit f8da028895
4 changed files with 165 additions and 3 deletions

View File

@ -101,9 +101,13 @@ class UserValue {
void insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx, unsigned LocNo,
LiveIntervals &LIS, const TargetInstrInfo &TII);
/// splitLocation - Replace OldLocNo ranges with NewRegs ranges where NewRegs
/// is live. Returns true if any changes were made.
bool splitLocation(unsigned OldLocNo, ArrayRef<LiveInterval*> NewRegs);
public:
/// UserValue - Create a new UserValue.
UserValue(const MDNode *var, unsigned o, DebugLoc L,
UserValue(const MDNode *var, unsigned o, DebugLoc L,
LocMap::Allocator &alloc)
: variable(var), offset(o), dl(L), leader(this), next(0), locInts(alloc)
{}
@ -215,6 +219,10 @@ public:
void renameRegister(unsigned OldReg, unsigned NewReg, unsigned SubIdx,
const TargetRegisterInfo *TRI);
/// splitRegister - Replace OldReg ranges with NewRegs ranges where NewRegs is
/// live. Returns true if any changes were made.
bool splitRegister(unsigned OldLocNo, ArrayRef<LiveInterval*> NewRegs);
/// rewriteLocations - Rewrite virtual register locations according to the
/// provided virtual register map.
void rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI);
@ -293,6 +301,9 @@ public:
/// renameRegister - Replace all references to OldReg with NewReg:SubIdx.
void renameRegister(unsigned OldReg, unsigned NewReg, unsigned SubIdx);
/// splitRegister - Replace all references to OldReg with NewRegs.
void splitRegister(unsigned OldReg, ArrayRef<LiveInterval*> NewRegs);
/// emitDebugVariables - Recreate DBG_VALUE instruction from data structures.
void emitDebugValues(VirtRegMap *VRM);
@ -679,6 +690,140 @@ renameRegister(unsigned OldReg, unsigned NewReg, unsigned SubIdx) {
static_cast<LDVImpl*>(pImpl)->renameRegister(OldReg, NewReg, SubIdx);
}
//===----------------------------------------------------------------------===//
// Live Range Splitting
//===----------------------------------------------------------------------===//
bool
UserValue::splitLocation(unsigned OldLocNo, ArrayRef<LiveInterval*> NewRegs) {
DEBUG({
dbgs() << "Splitting Loc" << OldLocNo << '\t';
print(dbgs(), 0);
});
bool DidChange = false;
LocMap::iterator LocMapI;
LocMapI.setMap(locInts);
for (unsigned i = 0; i != NewRegs.size(); ++i) {
LiveInterval *LI = NewRegs[i];
if (LI->empty())
continue;
// Don't allocate the new LocNo until it is needed.
unsigned NewLocNo = ~0u;
// Iterate over the overlaps between locInts and LI.
LocMapI.find(LI->beginIndex());
if (!LocMapI.valid())
continue;
LiveInterval::iterator LII = LI->advanceTo(LI->begin(), LocMapI.start());
LiveInterval::iterator LIE = LI->end();
while (LocMapI.valid() && LII != LIE) {
// At this point, we know that LocMapI.stop() > LII->start.
LII = LI->advanceTo(LII, LocMapI.start());
if (LII == LIE)
break;
// Now LII->end > LocMapI.start(). Do we have an overlap?
if (LocMapI.value() == OldLocNo && LII->start < LocMapI.stop()) {
// Overlapping correct location. Allocate NewLocNo now.
if (NewLocNo == ~0u) {
MachineOperand MO = MachineOperand::CreateReg(LI->reg, false);
MO.setSubReg(locations[OldLocNo].getSubReg());
NewLocNo = getLocationNo(MO);
DidChange = true;
}
SlotIndex LStart = LocMapI.start();
SlotIndex LStop = LocMapI.stop();
// Trim LocMapI down to the LII overlap.
if (LStart < LII->start)
LocMapI.setStartUnchecked(LII->start);
if (LStop > LII->end)
LocMapI.setStopUnchecked(LII->end);
// Change the value in the overlap. This may trigger coalescing.
LocMapI.setValue(NewLocNo);
// Re-insert any removed OldLocNo ranges.
if (LStart < LocMapI.start()) {
LocMapI.insert(LStart, LocMapI.start(), OldLocNo);
++LocMapI;
assert(LocMapI.valid() && "Unexpected coalescing");
}
if (LStop > LocMapI.stop()) {
++LocMapI;
LocMapI.insert(LII->end, LStop, OldLocNo);
--LocMapI;
}
}
// Advance to the next overlap.
if (LII->end < LocMapI.stop()) {
if (++LII == LIE)
break;
LocMapI.advanceTo(LII->start);
} else {
++LocMapI;
if (!LocMapI.valid())
break;
LII = LI->advanceTo(LII, LocMapI.start());
}
}
}
// Finally, remove any remaining OldLocNo intervals and OldLocNo itself.
locations.erase(locations.begin() + OldLocNo);
LocMapI.goToBegin();
while (LocMapI.valid()) {
unsigned v = LocMapI.value();
if (v == OldLocNo) {
DEBUG(dbgs() << "Erasing [" << LocMapI.start() << ';'
<< LocMapI.stop() << ")\n");
LocMapI.erase();
} else {
if (v > OldLocNo)
LocMapI.setValueUnchecked(v-1);
++LocMapI;
}
}
DEBUG({dbgs() << "Split result: \t"; print(dbgs(), 0);});
return DidChange;
}
bool
UserValue::splitRegister(unsigned OldReg, ArrayRef<LiveInterval*> NewRegs) {
bool DidChange = false;
for (unsigned LocNo = 0, E = locations.size(); LocNo != E; ++LocNo) {
const MachineOperand *Loc = &locations[LocNo];
if (!Loc->isReg() || Loc->getReg() != OldReg)
continue;
DidChange |= splitLocation(LocNo, NewRegs);
}
return DidChange;
}
void LDVImpl::splitRegister(unsigned OldReg, ArrayRef<LiveInterval*> NewRegs) {
bool DidChange = false;
for (UserValue *UV = lookupVirtReg(OldReg); UV; UV = UV->getNext())
DidChange |= UV->splitRegister(OldReg, NewRegs);
if (!DidChange)
return;
// Map all of the new virtual registers.
UserValue *UV = lookupVirtReg(OldReg);
for (unsigned i = 0; i != NewRegs.size(); ++i)
mapVirtReg(NewRegs[i]->reg, UV);
}
void LiveDebugVariables::
splitRegister(unsigned OldReg, ArrayRef<LiveInterval*> NewRegs) {
if (pImpl)
static_cast<LDVImpl*>(pImpl)->splitRegister(OldReg, NewRegs);
}
void
UserValue::rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI) {
// Iterate over locations in reverse makes it easier to handle coalescing.

View File

@ -21,10 +21,12 @@
#ifndef LLVM_CODEGEN_LIVEDEBUGVARIABLES_H
#define LLVM_CODEGEN_LIVEDEBUGVARIABLES_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
namespace llvm {
class LiveInterval;
class VirtRegMap;
class LiveDebugVariables : public MachineFunctionPass {
@ -42,6 +44,11 @@ public:
/// register.
void renameRegister(unsigned OldReg, unsigned NewReg, unsigned SubIdx);
/// splitRegister - Move any user variables in OldReg to the live ranges in
/// NewRegs where they are live. Mark the values as unavailable where no new
/// register is live.
void splitRegister(unsigned OldReg, ArrayRef<LiveInterval*> NewRegs);
/// emitDebugValues - Emit new DBG_VALUE instructions reflecting the changes
/// that happened during register allocation.
/// @param VRM Rename virtual registers according to map.

View File

@ -18,8 +18,9 @@
#ifndef LLVM_CODEGEN_LIVERANGEEDIT_H
#define LLVM_CODEGEN_LIVERANGEEDIT_H
#include "llvm/CodeGen/LiveInterval.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/CodeGen/LiveInterval.h"
namespace llvm {
@ -113,6 +114,10 @@ public:
bool empty() const { return size() == 0; }
LiveInterval *get(unsigned idx) const { return newRegs_[idx+firstNew_]; }
ArrayRef<LiveInterval*> regs() const {
return ArrayRef<LiveInterval*>(newRegs_).slice(firstNew_);
}
/// FIXME: Temporary accessors until we can get rid of
/// LiveIntervals::AddIntervalsForSpills
SmallVectorImpl<LiveInterval*> *getNewVRegs() { return &newRegs_; }

View File

@ -72,6 +72,7 @@ class RAGreedy : public MachineFunctionPass,
MachineLoopRanges *LoopRanges;
EdgeBundles *Bundles;
SpillPlacement *SpillPlacer;
LiveDebugVariables *DebugVars;
// state
std::auto_ptr<Spiller> SpillerInstance;
@ -920,6 +921,8 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg,
SmallVector<unsigned, 8> IntvMap;
SE->finish(&IntvMap);
DebugVars->splitRegister(VirtReg.reg, LREdit.regs());
LRStage.resize(MRI->getNumVirtRegs());
unsigned OrigBlocks = SA->getNumThroughBlocks() + SA->getUseBlocks().size();
@ -1284,6 +1287,7 @@ unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order,
SlotIndex SegStop = SE->leaveIntvAfter(Uses[BestAfter]);
SE->useIntv(SegStart, SegStop);
SE->finish();
DebugVars->splitRegister(VirtReg.reg, LREdit.regs());
setStage(NewVRegs.begin(), NewVRegs.end(), RS_Local);
++NumLocalSplits;
@ -1415,6 +1419,7 @@ bool RAGreedy::runOnMachineFunction(MachineFunction &mf) {
LoopRanges = &getAnalysis<MachineLoopRanges>();
Bundles = &getAnalysis<EdgeBundles>();
SpillPlacer = &getAnalysis<SpillPlacement>();
DebugVars = &getAnalysis<LiveDebugVariables>();
SA.reset(new SplitAnalysis(*VRM, *LIS, *Loops));
SE.reset(new SplitEditor(*SA, *LIS, *VRM, *DomTree));
@ -1433,7 +1438,7 @@ bool RAGreedy::runOnMachineFunction(MachineFunction &mf) {
}
// Write out new DBG_VALUE instructions.
getAnalysis<LiveDebugVariables>().emitDebugValues(VRM);
DebugVars->emitDebugValues(VRM);
// The pass output is in VirtRegMap. Release all the transient data.
releaseMemory();