Use InterferenceCache in RegAllocGreedy.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128765 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen
2011-04-02 06:03:38 +00:00
parent 5907d86365
commit eda0fe8d58

View File

@ -119,15 +119,15 @@ class RAGreedy : public MachineFunctionPass,
std::auto_ptr<SplitAnalysis> SA; std::auto_ptr<SplitAnalysis> SA;
std::auto_ptr<SplitEditor> SE; std::auto_ptr<SplitEditor> SE;
/// Cached per-block interference maps
InterferenceCache IntfCache;
/// All basic blocks where the current register is live. /// All basic blocks where the current register is live.
SmallVector<SpillPlacement::BlockConstraint, 8> SplitConstraints; SmallVector<SpillPlacement::BlockConstraint, 8> SplitConstraints;
typedef std::pair<SlotIndex, SlotIndex> IndexPair;
/// Global live range splitting candidate info. /// Global live range splitting candidate info.
struct GlobalSplitCandidate { struct GlobalSplitCandidate {
unsigned PhysReg; unsigned PhysReg;
SmallVector<IndexPair, 8> Interference;
BitVector LiveBundles; BitVector LiveBundles;
}; };
@ -168,9 +168,7 @@ private:
void LRE_WillShrinkVirtReg(unsigned); void LRE_WillShrinkVirtReg(unsigned);
void LRE_DidCloneVirtReg(unsigned, unsigned); void LRE_DidCloneVirtReg(unsigned, unsigned);
void mapGlobalInterference(unsigned, SmallVectorImpl<IndexPair>&); float calcSplitConstraints(unsigned);
float calcSplitConstraints(const SmallVectorImpl<IndexPair>&);
float calcGlobalSplitCost(const BitVector&); float calcGlobalSplitCost(const BitVector&);
void splitAroundRegion(LiveInterval&, unsigned, const BitVector&, void splitAroundRegion(LiveInterval&, unsigned, const BitVector&,
SmallVectorImpl<LiveInterval*>&); SmallVectorImpl<LiveInterval*>&);
@ -407,96 +405,53 @@ unsigned RAGreedy::tryEvict(LiveInterval &VirtReg,
// Region Splitting // Region Splitting
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// mapGlobalInterference - Compute a map of the interference from PhysReg and
/// its aliases in each block in SA->LiveBlocks.
/// If LiveBlocks[i] is live-in, Ranges[i].first is the first interference.
/// If LiveBlocks[i] is live-out, Ranges[i].second is the last interference.
void RAGreedy::mapGlobalInterference(unsigned PhysReg,
SmallVectorImpl<IndexPair> &Ranges) {
Ranges.assign(SA->LiveBlocks.size(), IndexPair());
LiveInterval &VirtReg = const_cast<LiveInterval&>(SA->getParent());
for (const unsigned *AI = TRI->getOverlaps(PhysReg); *AI; ++AI) {
if (!query(VirtReg, *AI).checkInterference())
continue;
LiveIntervalUnion::SegmentIter IntI =
PhysReg2LiveUnion[*AI].find(VirtReg.beginIndex());
if (!IntI.valid())
continue;
for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) {
const SplitAnalysis::BlockInfo &BI = SA->LiveBlocks[i];
IndexPair &IP = Ranges[i];
// Skip interference-free blocks.
if (IntI.start() >= BI.Stop)
continue;
// First interference in block.
if (BI.LiveIn) {
IntI.advanceTo(BI.Start);
if (!IntI.valid())
break;
if (IntI.start() >= BI.Stop)
continue;
if (!IP.first.isValid() || IntI.start() < IP.first)
IP.first = IntI.start();
}
// Last interference in block.
if (BI.LiveOut) {
IntI.advanceTo(BI.Stop);
if (!IntI.valid() || IntI.start() >= BI.Stop)
--IntI;
if (IntI.stop() <= BI.Start)
continue;
if (!IP.second.isValid() || IntI.stop() > IP.second)
IP.second = IntI.stop();
}
}
}
}
/// calcSplitConstraints - Fill out the SplitConstraints vector based on the /// calcSplitConstraints - Fill out the SplitConstraints vector based on the
/// interference pattern in Intf. Return the static cost of this split, /// interference pattern in Physreg and its aliases. Return the static cost of
/// assuming that all preferences in SplitConstraints are met. /// this split, assuming that all preferences in SplitConstraints are met.
float RAGreedy::calcSplitConstraints(const SmallVectorImpl<IndexPair> &Intf) { float RAGreedy::calcSplitConstraints(unsigned PhysReg) {
InterferenceCache::Cursor Intf(IntfCache, PhysReg);
// Reset interference dependent info. // Reset interference dependent info.
SplitConstraints.resize(SA->LiveBlocks.size()); SplitConstraints.resize(SA->LiveBlocks.size());
float StaticCost = 0; float StaticCost = 0;
for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) { for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) {
SplitAnalysis::BlockInfo &BI = SA->LiveBlocks[i]; SplitAnalysis::BlockInfo &BI = SA->LiveBlocks[i];
SpillPlacement::BlockConstraint &BC = SplitConstraints[i]; SpillPlacement::BlockConstraint &BC = SplitConstraints[i];
IndexPair IP = Intf[i];
BC.Number = BI.MBB->getNumber(); BC.Number = BI.MBB->getNumber();
Intf.moveToBlock(BC.Number);
BC.Entry = (BI.Uses && BI.LiveIn) ? BC.Entry = (BI.Uses && BI.LiveIn) ?
SpillPlacement::PrefReg : SpillPlacement::DontCare; SpillPlacement::PrefReg : SpillPlacement::DontCare;
BC.Exit = (BI.Uses && BI.LiveOut) ? BC.Exit = (BI.Uses && BI.LiveOut) ?
SpillPlacement::PrefReg : SpillPlacement::DontCare; SpillPlacement::PrefReg : SpillPlacement::DontCare;
if (!Intf.hasInterference())
continue;
// Number of spill code instructions to insert. // Number of spill code instructions to insert.
unsigned Ins = 0; unsigned Ins = 0;
// Interference for the live-in value. // Interference for the live-in value.
if (IP.first.isValid()) { if (BI.LiveIn) {
if (IP.first <= BI.Start) if (Intf.first() <= BI.Start)
BC.Entry = SpillPlacement::MustSpill, Ins += BI.Uses; BC.Entry = SpillPlacement::MustSpill, Ins += BI.Uses;
else if (!BI.Uses) else if (!BI.Uses)
BC.Entry = SpillPlacement::PrefSpill; BC.Entry = SpillPlacement::PrefSpill;
else if (IP.first < BI.FirstUse) else if (Intf.first() < BI.FirstUse)
BC.Entry = SpillPlacement::PrefSpill, ++Ins; BC.Entry = SpillPlacement::PrefSpill, ++Ins;
else if (IP.first < (BI.LiveThrough ? BI.LastUse : BI.Kill)) else if (Intf.first() < (BI.LiveThrough ? BI.LastUse : BI.Kill))
++Ins; ++Ins;
} }
// Interference for the live-out value. // Interference for the live-out value.
if (IP.second.isValid()) { if (BI.LiveOut) {
if (IP.second >= BI.LastSplitPoint) if (Intf.last() >= BI.LastSplitPoint)
BC.Exit = SpillPlacement::MustSpill, Ins += BI.Uses; BC.Exit = SpillPlacement::MustSpill, Ins += BI.Uses;
else if (!BI.Uses) else if (!BI.Uses)
BC.Exit = SpillPlacement::PrefSpill; BC.Exit = SpillPlacement::PrefSpill;
else if (IP.second > BI.LastUse) else if (Intf.last() > BI.LastUse)
BC.Exit = SpillPlacement::PrefSpill, ++Ins; BC.Exit = SpillPlacement::PrefSpill, ++Ins;
else if (IP.second > (BI.LiveThrough ? BI.FirstUse : BI.Def)) else if (Intf.last() > (BI.LiveThrough ? BI.FirstUse : BI.Def))
++Ins; ++Ins;
} }
@ -553,10 +508,7 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg,
dbgs() << ".\n"; dbgs() << ".\n";
}); });
// First compute interference ranges in the live blocks. InterferenceCache::Cursor Intf(IntfCache, PhysReg);
SmallVector<IndexPair, 8> InterferenceRanges;
mapGlobalInterference(PhysReg, InterferenceRanges);
LiveRangeEdit LREdit(VirtReg, NewVRegs, this); LiveRangeEdit LREdit(VirtReg, NewVRegs, this);
SE->reset(LREdit); SE->reset(LREdit);
@ -573,20 +525,21 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg,
if (!BI.LiveOut || !RegOut) if (!BI.LiveOut || !RegOut)
continue; continue;
IndexPair &IP = InterferenceRanges[i]; Intf.moveToBlock(BI.MBB->getNumber());
DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " -> EB#" DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " -> EB#"
<< Bundles->getBundle(BI.MBB->getNumber(), 1) << Bundles->getBundle(BI.MBB->getNumber(), 1)
<< " [" << BI.Start << ';' << BI.LastSplitPoint << '-' << " [" << BI.Start << ';' << BI.LastSplitPoint << '-'
<< BI.Stop << ") intf [" << IP.first << ';' << IP.second << BI.Stop << ") intf [" << Intf.first() << ';' << Intf.last()
<< ')'); << ')');
// The interference interval should either be invalid or overlap MBB. // The interference interval should either be invalid or overlap MBB.
assert((!IP.first.isValid() || IP.first < BI.Stop) && "Bad interference"); assert((!Intf.hasInterference() || Intf.first() < BI.Stop)
assert((!IP.second.isValid() || IP.second > BI.Start) && "Bad interference");
assert((!Intf.hasInterference() || Intf.last() > BI.Start)
&& "Bad interference"); && "Bad interference");
// Check interference leaving the block. // Check interference leaving the block.
if (!IP.second.isValid()) { if (!Intf.hasInterference()) {
// Block is interference-free. // Block is interference-free.
DEBUG(dbgs() << ", no interference"); DEBUG(dbgs() << ", no interference");
if (!BI.Uses) { if (!BI.Uses) {
@ -615,9 +568,9 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg,
} }
// Block has interference. // Block has interference.
DEBUG(dbgs() << ", interference to " << IP.second); DEBUG(dbgs() << ", interference to " << Intf.last());
if (!BI.LiveThrough && IP.second <= BI.Def) { if (!BI.LiveThrough && Intf.last() <= 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, BI.Stop); SE->useIntv(BI.Def, BI.Stop);
@ -629,16 +582,16 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg,
// 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 >= Intf.last() && "Couldn't avoid interference");
continue; continue;
} }
if (IP.second.getBoundaryIndex() < BI.LastUse) { if (Intf.last().getBoundaryIndex() < BI.LastUse) {
// There are interference-free uses at the end of the block. // There are interference-free uses at the end of the block.
// Find the first use that can get the live-out register. // Find the first use that can get the live-out register.
SmallVectorImpl<SlotIndex>::const_iterator UI = SmallVectorImpl<SlotIndex>::const_iterator UI =
std::lower_bound(SA->UseSlots.begin(), SA->UseSlots.end(), std::lower_bound(SA->UseSlots.begin(), SA->UseSlots.end(),
IP.second.getBoundaryIndex()); Intf.last().getBoundaryIndex());
assert(UI != SA->UseSlots.end() && "Couldn't find last use"); assert(UI != SA->UseSlots.end() && "Couldn't find last use");
SlotIndex Use = *UI; SlotIndex Use = *UI;
assert(Use <= BI.LastUse && "Couldn't find last use"); assert(Use <= BI.LastUse && "Couldn't find last use");
@ -646,7 +599,7 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg,
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 >= Intf.last() && "Couldn't avoid interference");
assert(SegStart < BI.LastSplitPoint && "Impossible split point"); assert(SegStart < BI.LastSplitPoint && "Impossible split point");
SE->useIntv(SegStart, BI.Stop); SE->useIntv(SegStart, BI.Stop);
continue; continue;
@ -656,7 +609,7 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg,
// 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 >= Intf.last() && "Couldn't avoid interference");
} }
// Now all defs leading to live bundles are handled, do everything else. // Now all defs leading to live bundles are handled, do everything else.
@ -670,14 +623,13 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg,
continue; continue;
// We have an incoming register. Check for interference. // We have an incoming register. Check for interference.
IndexPair &IP = InterferenceRanges[i]; Intf.moveToBlock(BI.MBB->getNumber());
DEBUG(dbgs() << "EB#" << Bundles->getBundle(BI.MBB->getNumber(), 0) DEBUG(dbgs() << "EB#" << Bundles->getBundle(BI.MBB->getNumber(), 0)
<< " -> BB#" << BI.MBB->getNumber() << " [" << BI.Start << ';' << " -> BB#" << BI.MBB->getNumber() << " [" << BI.Start << ';'
<< BI.LastSplitPoint << '-' << BI.Stop << ')'); << BI.LastSplitPoint << '-' << BI.Stop << ')');
// Check interference entering the block. // Check interference entering the block.
if (!IP.first.isValid()) { if (!Intf.hasInterference()) {
// Block is interference-free. // Block is interference-free.
DEBUG(dbgs() << ", no interference"); DEBUG(dbgs() << ", no interference");
if (!BI.Uses) { if (!BI.Uses) {
@ -724,9 +676,9 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg,
} }
// Block has interference. // Block has interference.
DEBUG(dbgs() << ", interference from " << IP.first); DEBUG(dbgs() << ", interference from " << Intf.first());
if (!BI.LiveThrough && IP.first >= BI.Kill) { if (!BI.LiveThrough && Intf.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(BI.Start, BI.Kill); SE->useIntv(BI.Start, BI.Kill);
@ -737,20 +689,20 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg,
// 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 <= Intf.first() && "Couldn't avoid interference");
continue; continue;
} }
if (IP.first.getBaseIndex() > BI.FirstUse) { if (Intf.first().getBaseIndex() > BI.FirstUse) {
// There are interference-free uses at the beginning of the block. // There are interference-free uses at the beginning of the block.
// Find the last use that can get the register. // Find the last use that can get the register.
SmallVectorImpl<SlotIndex>::const_iterator UI = SmallVectorImpl<SlotIndex>::const_iterator UI =
std::lower_bound(SA->UseSlots.begin(), SA->UseSlots.end(), std::lower_bound(SA->UseSlots.begin(), SA->UseSlots.end(),
IP.first.getBaseIndex()); Intf.first().getBaseIndex());
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 <= Intf.first() && "Couldn't avoid interference");
SE->useIntv(BI.Start, SegEnd); SE->useIntv(BI.Start, SegEnd);
continue; continue;
} }
@ -758,7 +710,7 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg,
// 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 <= Intf.first() && "Couldn't avoid interference");
} }
SE->closeIntv(); SE->closeIntv();
@ -785,8 +737,7 @@ unsigned RAGreedy::tryRegionSplit(LiveInterval &VirtReg, AllocationOrder &Order,
GlobalCand.resize(Cand+1); GlobalCand.resize(Cand+1);
GlobalCand[Cand].PhysReg = PhysReg; GlobalCand[Cand].PhysReg = PhysReg;
mapGlobalInterference(PhysReg, GlobalCand[Cand].Interference); float Cost = calcSplitConstraints(PhysReg);
float Cost = calcSplitConstraints(GlobalCand[Cand].Interference);
DEBUG(dbgs() << PrintReg(PhysReg, TRI) << "\tstatic = " << Cost); DEBUG(dbgs() << PrintReg(PhysReg, TRI) << "\tstatic = " << Cost);
if (BestReg && Cost >= BestCost) { if (BestReg && Cost >= BestCost) {
DEBUG(dbgs() << " higher.\n"); DEBUG(dbgs() << " higher.\n");
@ -1213,6 +1164,7 @@ bool RAGreedy::runOnMachineFunction(MachineFunction &mf) {
SE.reset(new SplitEditor(*SA, *LIS, *VRM, *DomTree)); SE.reset(new SplitEditor(*SA, *LIS, *VRM, *DomTree));
LRStage.clear(); LRStage.clear();
LRStage.resize(MRI->getNumVirtRegs()); LRStage.resize(MRI->getNumVirtRegs());
IntfCache.init(MF, &PhysReg2LiveUnion[0], Indexes, TRI);
allocatePhysRegs(); allocatePhysRegs();
addMBBLiveIns(MF); addMBBLiveIns(MF);