forked from OSchip/llvm-project
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:
parent
c86fe05923
commit
f8da028895
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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_; }
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue