From eda0fe8d58b0aaff5f18e7f13edfda3022384e70 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Sat, 2 Apr 2011 06:03:38 +0000 Subject: [PATCH] Use InterferenceCache in RegAllocGreedy. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128765 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegAllocGreedy.cpp | 140 +++++++++++---------------------- 1 file changed, 46 insertions(+), 94 deletions(-) diff --git a/lib/CodeGen/RegAllocGreedy.cpp b/lib/CodeGen/RegAllocGreedy.cpp index e2cf71a6504..e64deafc219 100644 --- a/lib/CodeGen/RegAllocGreedy.cpp +++ b/lib/CodeGen/RegAllocGreedy.cpp @@ -119,15 +119,15 @@ class RAGreedy : public MachineFunctionPass, std::auto_ptr SA; std::auto_ptr SE; + /// Cached per-block interference maps + InterferenceCache IntfCache; + /// All basic blocks where the current register is live. SmallVector SplitConstraints; - typedef std::pair IndexPair; - /// Global live range splitting candidate info. struct GlobalSplitCandidate { unsigned PhysReg; - SmallVector Interference; BitVector LiveBundles; }; @@ -168,9 +168,7 @@ private: void LRE_WillShrinkVirtReg(unsigned); void LRE_DidCloneVirtReg(unsigned, unsigned); - void mapGlobalInterference(unsigned, SmallVectorImpl&); - float calcSplitConstraints(const SmallVectorImpl&); - + float calcSplitConstraints(unsigned); float calcGlobalSplitCost(const BitVector&); void splitAroundRegion(LiveInterval&, unsigned, const BitVector&, SmallVectorImpl&); @@ -407,96 +405,53 @@ unsigned RAGreedy::tryEvict(LiveInterval &VirtReg, // 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 &Ranges) { - Ranges.assign(SA->LiveBlocks.size(), IndexPair()); - LiveInterval &VirtReg = const_cast(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 -/// interference pattern in Intf. Return the static cost of this split, -/// assuming that all preferences in SplitConstraints are met. -float RAGreedy::calcSplitConstraints(const SmallVectorImpl &Intf) { +/// interference pattern in Physreg and its aliases. Return the static cost of +/// this split, assuming that all preferences in SplitConstraints are met. +float RAGreedy::calcSplitConstraints(unsigned PhysReg) { + InterferenceCache::Cursor Intf(IntfCache, PhysReg); + // Reset interference dependent info. SplitConstraints.resize(SA->LiveBlocks.size()); float StaticCost = 0; for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) { SplitAnalysis::BlockInfo &BI = SA->LiveBlocks[i]; SpillPlacement::BlockConstraint &BC = SplitConstraints[i]; - IndexPair IP = Intf[i]; BC.Number = BI.MBB->getNumber(); + Intf.moveToBlock(BC.Number); BC.Entry = (BI.Uses && BI.LiveIn) ? SpillPlacement::PrefReg : SpillPlacement::DontCare; BC.Exit = (BI.Uses && BI.LiveOut) ? SpillPlacement::PrefReg : SpillPlacement::DontCare; + if (!Intf.hasInterference()) + continue; + // Number of spill code instructions to insert. unsigned Ins = 0; // Interference for the live-in value. - if (IP.first.isValid()) { - if (IP.first <= BI.Start) + if (BI.LiveIn) { + if (Intf.first() <= BI.Start) BC.Entry = SpillPlacement::MustSpill, Ins += BI.Uses; else if (!BI.Uses) BC.Entry = SpillPlacement::PrefSpill; - else if (IP.first < BI.FirstUse) + else if (Intf.first() < BI.FirstUse) 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; } // Interference for the live-out value. - if (IP.second.isValid()) { - if (IP.second >= BI.LastSplitPoint) + if (BI.LiveOut) { + if (Intf.last() >= BI.LastSplitPoint) BC.Exit = SpillPlacement::MustSpill, Ins += BI.Uses; else if (!BI.Uses) BC.Exit = SpillPlacement::PrefSpill; - else if (IP.second > BI.LastUse) + else if (Intf.last() > BI.LastUse) 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; } @@ -553,10 +508,7 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg, dbgs() << ".\n"; }); - // First compute interference ranges in the live blocks. - SmallVector InterferenceRanges; - mapGlobalInterference(PhysReg, InterferenceRanges); - + InterferenceCache::Cursor Intf(IntfCache, PhysReg); LiveRangeEdit LREdit(VirtReg, NewVRegs, this); SE->reset(LREdit); @@ -573,20 +525,21 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg, if (!BI.LiveOut || !RegOut) continue; - IndexPair &IP = InterferenceRanges[i]; + Intf.moveToBlock(BI.MBB->getNumber()); DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " -> EB#" << Bundles->getBundle(BI.MBB->getNumber(), 1) << " [" << 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. - assert((!IP.first.isValid() || IP.first < BI.Stop) && "Bad interference"); - assert((!IP.second.isValid() || IP.second > BI.Start) + assert((!Intf.hasInterference() || Intf.first() < BI.Stop) + && "Bad interference"); + assert((!Intf.hasInterference() || Intf.last() > BI.Start) && "Bad interference"); // Check interference leaving the block. - if (!IP.second.isValid()) { + if (!Intf.hasInterference()) { // Block is interference-free. DEBUG(dbgs() << ", no interference"); if (!BI.Uses) { @@ -615,9 +568,9 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg, } // 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. DEBUG(dbgs() << " doesn't affect def from " << BI.Def << '\n'); 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. DEBUG(dbgs() << ", no uses.\n"); SlotIndex SegStart = SE->enterIntvAtEnd(*BI.MBB); - assert(SegStart >= IP.second && "Couldn't avoid interference"); + assert(SegStart >= Intf.last() && "Couldn't avoid interference"); continue; } - if (IP.second.getBoundaryIndex() < BI.LastUse) { + if (Intf.last().getBoundaryIndex() < BI.LastUse) { // There are interference-free uses at the end of the block. // Find the first use that can get the live-out register. SmallVectorImpl::const_iterator UI = 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"); SlotIndex Use = *UI; 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) { DEBUG(dbgs() << ", free use at " << Use << ".\n"); 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"); SE->useIntv(SegStart, BI.Stop); continue; @@ -656,7 +609,7 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg, // Interference is after the last use. DEBUG(dbgs() << " after last use.\n"); 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. @@ -670,14 +623,13 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg, continue; // 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) << " -> BB#" << BI.MBB->getNumber() << " [" << BI.Start << ';' << BI.LastSplitPoint << '-' << BI.Stop << ')'); // Check interference entering the block. - if (!IP.first.isValid()) { + if (!Intf.hasInterference()) { // Block is interference-free. DEBUG(dbgs() << ", no interference"); if (!BI.Uses) { @@ -724,9 +676,9 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg, } // 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. DEBUG(dbgs() << " doesn't affect kill at " << BI.Kill << '\n'); 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. DEBUG(dbgs() << ", no uses.\n"); SlotIndex SegEnd = SE->leaveIntvAtTop(*BI.MBB); - assert(SegEnd <= IP.first && "Couldn't avoid interference"); + assert(SegEnd <= Intf.first() && "Couldn't avoid interference"); continue; } - if (IP.first.getBaseIndex() > BI.FirstUse) { + if (Intf.first().getBaseIndex() > BI.FirstUse) { // There are interference-free uses at the beginning of the block. // Find the last use that can get the register. SmallVectorImpl::const_iterator UI = 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"); SlotIndex Use = (--UI)->getBoundaryIndex(); DEBUG(dbgs() << ", free use at " << *UI << ".\n"); 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); continue; } @@ -758,7 +710,7 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg, // Interference is before the first use. DEBUG(dbgs() << " before first use.\n"); SlotIndex SegEnd = SE->leaveIntvAtTop(*BI.MBB); - assert(SegEnd <= IP.first && "Couldn't avoid interference"); + assert(SegEnd <= Intf.first() && "Couldn't avoid interference"); } SE->closeIntv(); @@ -785,8 +737,7 @@ unsigned RAGreedy::tryRegionSplit(LiveInterval &VirtReg, AllocationOrder &Order, GlobalCand.resize(Cand+1); GlobalCand[Cand].PhysReg = PhysReg; - mapGlobalInterference(PhysReg, GlobalCand[Cand].Interference); - float Cost = calcSplitConstraints(GlobalCand[Cand].Interference); + float Cost = calcSplitConstraints(PhysReg); DEBUG(dbgs() << PrintReg(PhysReg, TRI) << "\tstatic = " << Cost); if (BestReg && Cost >= BestCost) { DEBUG(dbgs() << " higher.\n"); @@ -1213,6 +1164,7 @@ bool RAGreedy::runOnMachineFunction(MachineFunction &mf) { SE.reset(new SplitEditor(*SA, *LIS, *VRM, *DomTree)); LRStage.clear(); LRStage.resize(MRI->getNumVirtRegs()); + IntfCache.init(MF, &PhysReg2LiveUnion[0], Indexes, TRI); allocatePhysRegs(); addMBBLiveIns(MF);