Change the SplitEditor interface to a single instance can be shared for multiple splits.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@126912 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen 2011-03-03 01:29:13 +00:00
parent 8701768ae2
commit bece06f0c6
3 changed files with 50 additions and 40 deletions

View File

@ -111,6 +111,7 @@ class RAGreedy : public MachineFunctionPass, public RegAllocBase {
// splitting state. // splitting state.
std::auto_ptr<SplitAnalysis> SA; std::auto_ptr<SplitAnalysis> SA;
std::auto_ptr<SplitEditor> SE;
/// All basic blocks where the current register is live. /// All basic blocks where the current register is live.
SmallVector<SpillPlacement::BlockConstraint, 8> SpillConstraints; SmallVector<SpillPlacement::BlockConstraint, 8> SpillConstraints;
@ -699,10 +700,10 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg,
SmallVector<LiveInterval*, 4> SpillRegs; SmallVector<LiveInterval*, 4> SpillRegs;
LiveRangeEdit LREdit(VirtReg, NewVRegs, SpillRegs); LiveRangeEdit LREdit(VirtReg, NewVRegs, SpillRegs);
SplitEditor SE(*SA, *LIS, *VRM, *DomTree, LREdit); SE->reset(LREdit);
// Create the main cross-block interval. // Create the main cross-block interval.
SE.openIntv(); SE->openIntv();
// First add all defs that are live out of a block. // First add all defs that are live out of a block.
for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) { for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) {
@ -736,19 +737,19 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg,
DEBUG(dbgs() << ", no uses" DEBUG(dbgs() << ", no uses"
<< (RegIn ? ", live-through.\n" : ", stack in.\n")); << (RegIn ? ", live-through.\n" : ", stack in.\n"));
if (!RegIn) if (!RegIn)
SE.enterIntvAtEnd(*BI.MBB); SE->enterIntvAtEnd(*BI.MBB);
continue; continue;
} }
if (!BI.LiveThrough) { if (!BI.LiveThrough) {
DEBUG(dbgs() << ", not live-through.\n"); DEBUG(dbgs() << ", not live-through.\n");
SE.useIntv(SE.enterIntvBefore(BI.Def), Stop); SE->useIntv(SE->enterIntvBefore(BI.Def), Stop);
continue; continue;
} }
if (!RegIn) { if (!RegIn) {
// Block is live-through, but entry bundle is on the stack. // Block is live-through, but entry bundle is on the stack.
// Reload just before the first use. // Reload just before the first use.
DEBUG(dbgs() << ", not live-in, enter before first use.\n"); DEBUG(dbgs() << ", not live-in, enter before first use.\n");
SE.useIntv(SE.enterIntvBefore(BI.FirstUse), Stop); SE->useIntv(SE->enterIntvBefore(BI.FirstUse), Stop);
continue; continue;
} }
DEBUG(dbgs() << ", live-through.\n"); DEBUG(dbgs() << ", live-through.\n");
@ -761,7 +762,7 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg,
if (!BI.LiveThrough && IP.second <= BI.Def) { if (!BI.LiveThrough && IP.second <= BI.Def) {
// The interference doesn't reach the outgoing segment. // The interference doesn't reach the outgoing segment.
DEBUG(dbgs() << " doesn't affect def from " << BI.Def << '\n'); DEBUG(dbgs() << " doesn't affect def from " << BI.Def << '\n');
SE.useIntv(BI.Def, Stop); SE->useIntv(BI.Def, Stop);
continue; continue;
} }
@ -769,7 +770,7 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg,
if (!BI.Uses) { if (!BI.Uses) {
// No uses in block, avoid interference by reloading as late as possible. // No uses in block, avoid interference by reloading as late as possible.
DEBUG(dbgs() << ", no uses.\n"); DEBUG(dbgs() << ", no uses.\n");
SlotIndex SegStart = SE.enterIntvAtEnd(*BI.MBB); SlotIndex SegStart = SE->enterIntvAtEnd(*BI.MBB);
assert(SegStart >= IP.second && "Couldn't avoid interference"); assert(SegStart >= IP.second && "Couldn't avoid interference");
continue; continue;
} }
@ -786,17 +787,17 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg,
// Only attempt a split befroe the last split point. // Only attempt a split befroe the last split point.
if (Use.getBaseIndex() <= BI.LastSplitPoint) { if (Use.getBaseIndex() <= BI.LastSplitPoint) {
DEBUG(dbgs() << ", free use at " << Use << ".\n"); DEBUG(dbgs() << ", free use at " << Use << ".\n");
SlotIndex SegStart = SE.enterIntvBefore(Use); SlotIndex SegStart = SE->enterIntvBefore(Use);
assert(SegStart >= IP.second && "Couldn't avoid interference"); assert(SegStart >= IP.second && "Couldn't avoid interference");
assert(SegStart < BI.LastSplitPoint && "Impossible split point"); assert(SegStart < BI.LastSplitPoint && "Impossible split point");
SE.useIntv(SegStart, Stop); SE->useIntv(SegStart, Stop);
continue; continue;
} }
} }
// Interference is after the last use. // Interference is after the last use.
DEBUG(dbgs() << " after last use.\n"); DEBUG(dbgs() << " after last use.\n");
SlotIndex SegStart = SE.enterIntvAtEnd(*BI.MBB); SlotIndex SegStart = SE->enterIntvAtEnd(*BI.MBB);
assert(SegStart >= IP.second && "Couldn't avoid interference"); assert(SegStart >= IP.second && "Couldn't avoid interference");
} }
@ -827,16 +828,16 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg,
// Block is live-through without interference. // Block is live-through without interference.
if (RegOut) { if (RegOut) {
DEBUG(dbgs() << ", no uses, live-through.\n"); DEBUG(dbgs() << ", no uses, live-through.\n");
SE.useIntv(Start, Stop); SE->useIntv(Start, Stop);
} else { } else {
DEBUG(dbgs() << ", no uses, stack-out.\n"); DEBUG(dbgs() << ", no uses, stack-out.\n");
SE.leaveIntvAtTop(*BI.MBB); SE->leaveIntvAtTop(*BI.MBB);
} }
continue; continue;
} }
if (!BI.LiveThrough) { if (!BI.LiveThrough) {
DEBUG(dbgs() << ", killed in block.\n"); DEBUG(dbgs() << ", killed in block.\n");
SE.useIntv(Start, SE.leaveIntvAfter(BI.Kill)); SE->useIntv(Start, SE->leaveIntvAfter(BI.Kill));
continue; continue;
} }
if (!RegOut) { if (!RegOut) {
@ -844,24 +845,24 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg,
// Spill immediately after the last use. // Spill immediately after the last use.
if (BI.LastUse < BI.LastSplitPoint) { if (BI.LastUse < BI.LastSplitPoint) {
DEBUG(dbgs() << ", uses, stack-out.\n"); DEBUG(dbgs() << ", uses, stack-out.\n");
SE.useIntv(Start, SE.leaveIntvAfter(BI.LastUse)); SE->useIntv(Start, SE->leaveIntvAfter(BI.LastUse));
continue; continue;
} }
// The last use is after the last split point, it is probably an // The last use is after the last split point, it is probably an
// indirect jump. // indirect jump.
DEBUG(dbgs() << ", uses at " << BI.LastUse << " after split point " DEBUG(dbgs() << ", uses at " << BI.LastUse << " after split point "
<< BI.LastSplitPoint << ", stack-out.\n"); << BI.LastSplitPoint << ", stack-out.\n");
SlotIndex SegEnd = SE.leaveIntvBefore(BI.LastSplitPoint); SlotIndex SegEnd = SE->leaveIntvBefore(BI.LastSplitPoint);
SE.useIntv(Start, SegEnd); SE->useIntv(Start, SegEnd);
// Run a double interval from the split to the last use. // Run a double interval from the split to the last use.
// This makes it possible to spill the complement without affecting the // This makes it possible to spill the complement without affecting the
// indirect branch. // indirect branch.
SE.overlapIntv(SegEnd, BI.LastUse); SE->overlapIntv(SegEnd, BI.LastUse);
continue; continue;
} }
// Register is live-through. // Register is live-through.
DEBUG(dbgs() << ", uses, live-through.\n"); DEBUG(dbgs() << ", uses, live-through.\n");
SE.useIntv(Start, Stop); SE->useIntv(Start, Stop);
continue; continue;
} }
@ -871,14 +872,14 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg,
if (!BI.LiveThrough && IP.first >= BI.Kill) { if (!BI.LiveThrough && IP.first >= BI.Kill) {
// The interference doesn't reach the outgoing segment. // The interference doesn't reach the outgoing segment.
DEBUG(dbgs() << " doesn't affect kill at " << BI.Kill << '\n'); DEBUG(dbgs() << " doesn't affect kill at " << BI.Kill << '\n');
SE.useIntv(Start, BI.Kill); SE->useIntv(Start, BI.Kill);
continue; continue;
} }
if (!BI.Uses) { if (!BI.Uses) {
// No uses in block, avoid interference by spilling as soon as possible. // No uses in block, avoid interference by spilling as soon as possible.
DEBUG(dbgs() << ", no uses.\n"); DEBUG(dbgs() << ", no uses.\n");
SlotIndex SegEnd = SE.leaveIntvAtTop(*BI.MBB); SlotIndex SegEnd = SE->leaveIntvAtTop(*BI.MBB);
assert(SegEnd <= IP.first && "Couldn't avoid interference"); assert(SegEnd <= IP.first && "Couldn't avoid interference");
continue; continue;
} }
@ -891,24 +892,24 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg,
assert(UI != SA->UseSlots.begin() && "Couldn't find first use"); assert(UI != SA->UseSlots.begin() && "Couldn't find first use");
SlotIndex Use = (--UI)->getBoundaryIndex(); SlotIndex Use = (--UI)->getBoundaryIndex();
DEBUG(dbgs() << ", free use at " << *UI << ".\n"); DEBUG(dbgs() << ", free use at " << *UI << ".\n");
SlotIndex SegEnd = SE.leaveIntvAfter(Use); SlotIndex SegEnd = SE->leaveIntvAfter(Use);
assert(SegEnd <= IP.first && "Couldn't avoid interference"); assert(SegEnd <= IP.first && "Couldn't avoid interference");
SE.useIntv(Start, SegEnd); SE->useIntv(Start, SegEnd);
continue; continue;
} }
// Interference is before the first use. // Interference is before the first use.
DEBUG(dbgs() << " before first use.\n"); DEBUG(dbgs() << " before first use.\n");
SlotIndex SegEnd = SE.leaveIntvAtTop(*BI.MBB); SlotIndex SegEnd = SE->leaveIntvAtTop(*BI.MBB);
assert(SegEnd <= IP.first && "Couldn't avoid interference"); assert(SegEnd <= IP.first && "Couldn't avoid interference");
} }
SE.closeIntv(); SE->closeIntv();
// FIXME: Should we be more aggressive about splitting the stack region into // FIXME: Should we be more aggressive about splitting the stack region into
// per-block segments? The current approach allows the stack region to // per-block segments? The current approach allows the stack region to
// separate into connected components. Some components may be allocatable. // separate into connected components. Some components may be allocatable.
SE.finish(); SE->finish();
++NumGlobalSplits; ++NumGlobalSplits;
if (VerifyEnabled) { if (VerifyEnabled) {
@ -1215,14 +1216,14 @@ unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order,
SmallVector<LiveInterval*, 4> SpillRegs; SmallVector<LiveInterval*, 4> SpillRegs;
LiveRangeEdit LREdit(VirtReg, NewVRegs, SpillRegs); LiveRangeEdit LREdit(VirtReg, NewVRegs, SpillRegs);
SplitEditor SE(*SA, *LIS, *VRM, *DomTree, LREdit); SE->reset(LREdit);
SE.openIntv(); SE->openIntv();
SlotIndex SegStart = SE.enterIntvBefore(Uses[BestBefore]); SlotIndex SegStart = SE->enterIntvBefore(Uses[BestBefore]);
SlotIndex SegStop = SE.leaveIntvAfter(Uses[BestAfter]); SlotIndex SegStop = SE->leaveIntvAfter(Uses[BestAfter]);
SE.useIntv(SegStart, SegStop); SE->useIntv(SegStart, SegStop);
SE.closeIntv(); SE->closeIntv();
SE.finish(); SE->finish();
setStage(NewVRegs.begin(), NewVRegs.end(), RS_Local); setStage(NewVRegs.begin(), NewVRegs.end(), RS_Local);
++NumLocalSplits; ++NumLocalSplits;
@ -1268,7 +1269,8 @@ unsigned RAGreedy::trySplit(LiveInterval &VirtReg, AllocationOrder &Order,
if (SA->getMultiUseBlocks(Blocks)) { if (SA->getMultiUseBlocks(Blocks)) {
SmallVector<LiveInterval*, 4> SpillRegs; SmallVector<LiveInterval*, 4> SpillRegs;
LiveRangeEdit LREdit(VirtReg, NewVRegs, SpillRegs); LiveRangeEdit LREdit(VirtReg, NewVRegs, SpillRegs);
SplitEditor(*SA, *LIS, *VRM, *DomTree, LREdit).splitSingleBlocks(Blocks); SE->reset(LREdit);
SE->splitSingleBlocks(Blocks);
setStage(NewVRegs.begin(), NewVRegs.end(), RS_Block); setStage(NewVRegs.begin(), NewVRegs.end(), RS_Block);
if (VerifyEnabled) if (VerifyEnabled)
MF->verify(this, "After splitting live range around basic blocks"); MF->verify(this, "After splitting live range around basic blocks");
@ -1350,6 +1352,7 @@ bool RAGreedy::runOnMachineFunction(MachineFunction &mf) {
SpillPlacer = &getAnalysis<SpillPlacement>(); SpillPlacer = &getAnalysis<SpillPlacement>();
SA.reset(new SplitAnalysis(*VRM, *LIS, *Loops)); SA.reset(new SplitAnalysis(*VRM, *LIS, *Loops));
SE.reset(new SplitEditor(*SA, *LIS, *VRM, *DomTree));
LRStage.clear(); LRStage.clear();
LRStage.resize(MRI->getNumVirtRegs()); LRStage.resize(MRI->getNumVirtRegs());

View File

@ -209,17 +209,24 @@ void SplitAnalysis::analyze(const LiveInterval *li) {
SplitEditor::SplitEditor(SplitAnalysis &sa, SplitEditor::SplitEditor(SplitAnalysis &sa,
LiveIntervals &lis, LiveIntervals &lis,
VirtRegMap &vrm, VirtRegMap &vrm,
MachineDominatorTree &mdt, MachineDominatorTree &mdt)
LiveRangeEdit &edit)
: SA(sa), LIS(lis), VRM(vrm), : SA(sa), LIS(lis), VRM(vrm),
MRI(vrm.getMachineFunction().getRegInfo()), MRI(vrm.getMachineFunction().getRegInfo()),
MDT(mdt), MDT(mdt),
TII(*vrm.getMachineFunction().getTarget().getInstrInfo()), TII(*vrm.getMachineFunction().getTarget().getInstrInfo()),
TRI(*vrm.getMachineFunction().getTarget().getRegisterInfo()), TRI(*vrm.getMachineFunction().getTarget().getRegisterInfo()),
Edit(&edit), Edit(0),
OpenIdx(0), OpenIdx(0),
RegAssign(Allocator) RegAssign(Allocator)
{ {}
void SplitEditor::reset(LiveRangeEdit &lre) {
Edit = &lre;
OpenIdx = 0;
RegAssign.clear();
Values.clear();
LiveOutCache.clear();
// We don't need an AliasAnalysis since we will only be performing // We don't need an AliasAnalysis since we will only be performing
// cheap-as-a-copy remats anyway. // cheap-as-a-copy remats anyway.
Edit->anyRematerializable(LIS, TII, 0); Edit->anyRematerializable(LIS, TII, 0);

View File

@ -268,10 +268,10 @@ public:
/// Create a new SplitEditor for editing the LiveInterval analyzed by SA. /// Create a new SplitEditor for editing the LiveInterval analyzed by SA.
/// Newly created intervals will be appended to newIntervals. /// Newly created intervals will be appended to newIntervals.
SplitEditor(SplitAnalysis &SA, LiveIntervals&, VirtRegMap&, SplitEditor(SplitAnalysis &SA, LiveIntervals&, VirtRegMap&,
MachineDominatorTree&, LiveRangeEdit&); MachineDominatorTree&);
/// getAnalysis - Get the corresponding analysis. /// reset - Prepare for a new split.
SplitAnalysis &getAnalysis() { return SA; } void reset(LiveRangeEdit&);
/// Create a new virtual register and live interval. /// Create a new virtual register and live interval.
void openIntv(); void openIntv();