From 96dcd95a45968de6cb05864cf91aae33169cf179 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Sat, 5 Mar 2011 01:10:31 +0000 Subject: [PATCH] Compute the constraints for global live range splitting from an interference pattern. This simplifies the code and makes it faster too. The interference patterns are saved for each candidate register. It will be reused for actually executing the split. Work in progress. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127054 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegAllocGreedy.cpp | 230 ++++++++++----------------------- 1 file changed, 67 insertions(+), 163 deletions(-) diff --git a/lib/CodeGen/RegAllocGreedy.cpp b/lib/CodeGen/RegAllocGreedy.cpp index 201fa93cc77..061e38640b6 100644 --- a/lib/CodeGen/RegAllocGreedy.cpp +++ b/lib/CodeGen/RegAllocGreedy.cpp @@ -114,10 +114,22 @@ class RAGreedy : public MachineFunctionPass, public RegAllocBase { std::auto_ptr SE; /// All basic blocks where the current register is live. - SmallVector SpillConstraints; + SmallVector SplitConstraints; typedef std::pair IndexPair; + /// Global live range splitting candidate info. + struct GlobalSplitCandidate { + unsigned PhysReg; + SmallVector Interference; + BitVector LiveBundles; + }; + + /// Candidate info for for each PhysReg in AllocationOrder. + /// This vector never shrinks, but grows to the size of the largest register + /// class. + SmallVector GlobalCand; + /// For every instruction in SA->UseSlots, store the previous non-copy /// instruction. SmallVector PrevSlot; @@ -148,8 +160,10 @@ private: bool checkUncachedInterference(LiveInterval&, unsigned); LiveInterval *getSingleInterference(LiveInterval&, unsigned); bool reassignVReg(LiveInterval &InterferingVReg, unsigned OldPhysReg); + void mapGlobalInterference(unsigned, SmallVectorImpl&); - float calcInterferenceInfo(LiveInterval&, unsigned); + float calcSplitConstraints(const SmallVectorImpl&); + float calcGlobalSplitCost(const BitVector&); void splitAroundRegion(LiveInterval&, unsigned, const BitVector&, SmallVectorImpl&); @@ -485,185 +499,67 @@ void RAGreedy::mapGlobalInterference(unsigned PhysReg, } } -/// calcInterferenceInfo - Compute per-block outgoing and ingoing constraints -/// when considering interference from PhysReg. Also compute an optimistic local -/// cost of this interference pattern. -/// -/// The final cost of a split is the local cost + global cost of preferences -/// broken by SpillPlacement. -/// -float RAGreedy::calcInterferenceInfo(LiveInterval &VirtReg, unsigned PhysReg) { +/// 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) { // Reset interference dependent info. - SpillConstraints.resize(SA->LiveBlocks.size()); + 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 = SpillConstraints[i]; + SpillPlacement::BlockConstraint &BC = SplitConstraints[i]; + IndexPair IP = Intf[i]; + BC.Number = BI.MBB->getNumber(); BC.Entry = (BI.Uses && BI.LiveIn) ? SpillPlacement::PrefReg : SpillPlacement::DontCare; BC.Exit = (BI.Uses && BI.LiveOut) ? SpillPlacement::PrefReg : SpillPlacement::DontCare; - BI.OverlapEntry = BI.OverlapExit = false; - } - - // Add interference info from each PhysReg alias. - 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; - // Determine which blocks have interference live in or after the last split - // point. - for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) { - SplitAnalysis::BlockInfo &BI = SA->LiveBlocks[i]; - SpillPlacement::BlockConstraint &BC = SpillConstraints[i]; - - // Skip interference-free blocks. - if (IntI.start() >= BI.Stop) - continue; - - // Is the interference live-in? - if (BI.LiveIn) { - IntI.advanceTo(BI.Start); - if (!IntI.valid()) - break; - if (IntI.start() <= BI.Start) - BC.Entry = SpillPlacement::MustSpill; - } - - // Is the interference overlapping the last split point? - if (BI.LiveOut) { - if (IntI.stop() < BI.LastSplitPoint) - IntI.advanceTo(BI.LastSplitPoint.getPrevSlot()); - if (!IntI.valid()) - break; - if (IntI.start() < BI.Stop) - BC.Exit = SpillPlacement::MustSpill; - } + // 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) + BC.Entry = SpillPlacement::MustSpill, Ins += BI.Uses; + else if (!BI.Uses) + BC.Entry = SpillPlacement::PrefSpill; + else if (IP.first < BI.FirstUse) + BC.Entry = SpillPlacement::PrefSpill, ++Ins; + else if (IP.first < (BI.LiveThrough ? BI.LastUse : BI.Kill)) + ++Ins; } - // Rewind iterator and check other interferences. - IntI.find(VirtReg.beginIndex()); - for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) { - SplitAnalysis::BlockInfo &BI = SA->LiveBlocks[i]; - SpillPlacement::BlockConstraint &BC = SpillConstraints[i]; - - // Skip interference-free blocks. - if (IntI.start() >= BI.Stop) - continue; - - // Handle transparent blocks with interference separately. - // Transparent blocks never incur any fixed cost. - if (BI.LiveThrough && !BI.Uses) { - IntI.advanceTo(BI.Start); - if (!IntI.valid()) - break; - if (IntI.start() >= BI.Stop) - continue; - - if (BC.Entry != SpillPlacement::MustSpill) - BC.Entry = SpillPlacement::PrefSpill; - if (BC.Exit != SpillPlacement::MustSpill) - BC.Exit = SpillPlacement::PrefSpill; - continue; - } - - // Now we only have blocks with uses left. - // Check if the interference overlaps the uses. - assert(BI.Uses && "Non-transparent block without any uses"); - - // Check interference on entry. - if (BI.LiveIn && BC.Entry != SpillPlacement::MustSpill) { - IntI.advanceTo(BI.Start); - if (!IntI.valid()) - break; - // Not live in, but before the first use. - if (IntI.start() < BI.FirstUse) { - BC.Entry = SpillPlacement::PrefSpill; - // If the block contains a kill from an earlier split, never split - // again in the same block. - if (!BI.LiveThrough && !SA->isOriginalEndpoint(BI.Kill)) - BC.Entry = SpillPlacement::MustSpill; - } - } - - // Does interference overlap the uses in the entry segment - // [FirstUse;Kill)? - if (BI.LiveIn && !BI.OverlapEntry) { - IntI.advanceTo(BI.FirstUse); - if (!IntI.valid()) - break; - // A live-through interval has no kill. - // Check [FirstUse;LastUse) instead. - if (IntI.start() < (BI.LiveThrough ? BI.LastUse : BI.Kill)) - BI.OverlapEntry = true; - } - - // Does interference overlap the uses in the exit segment [Def;LastUse)? - if (BI.LiveOut && !BI.LiveThrough && !BI.OverlapExit) { - IntI.advanceTo(BI.Def); - if (!IntI.valid()) - break; - if (IntI.start() < BI.LastUse) - BI.OverlapExit = true; - } - - // Check interference on exit. - if (BI.LiveOut && BC.Exit != SpillPlacement::MustSpill) { - // Check interference between LastUse and Stop. - if (BC.Exit != SpillPlacement::PrefSpill) { - IntI.advanceTo(BI.LastUse); - if (!IntI.valid()) - break; - if (IntI.start() < BI.Stop) { - BC.Exit = SpillPlacement::PrefSpill; - // Avoid splitting twice in the same block. - if (!BI.LiveThrough && !SA->isOriginalEndpoint(BI.Def)) - BC.Exit = SpillPlacement::MustSpill; - } - } - } + // Interference for the live-out value. + if (IP.second.isValid()) { + if (IP.second >= BI.LastSplitPoint) + BC.Exit = SpillPlacement::MustSpill, Ins += BI.Uses; + else if (!BI.Uses) + BC.Exit = SpillPlacement::PrefSpill; + else if (IP.second > BI.LastUse) + BC.Exit = SpillPlacement::PrefSpill, ++Ins; + else if (IP.second > (BI.LiveThrough ? BI.FirstUse : BI.Def)) + ++Ins; } - } - // Accumulate a local cost of this interference pattern. - float LocalCost = 0; - for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) { - SplitAnalysis::BlockInfo &BI = SA->LiveBlocks[i]; - if (!BI.Uses) - continue; - SpillPlacement::BlockConstraint &BC = SpillConstraints[i]; - unsigned Inserts = 0; - - // Do we need spill code for the entry segment? - if (BI.LiveIn) - Inserts += BI.OverlapEntry || BC.Entry != SpillPlacement::PrefReg; - - // For the exit segment? - if (BI.LiveOut) - Inserts += BI.OverlapExit || BC.Exit != SpillPlacement::PrefReg; - - // The local cost of spill code in this block is the block frequency times - // the number of spill instructions inserted. - if (Inserts) - LocalCost += Inserts * SpillPlacer->getBlockFrequency(BC.Number); + // Accumulate the total frequency of inserted spill code. + if (Ins) + StaticCost += Ins * SpillPlacer->getBlockFrequency(BC.Number); } - DEBUG(dbgs() << "Local cost of " << PrintReg(PhysReg, TRI) << " = " - << LocalCost << '\n'); - return LocalCost; + return StaticCost; } + /// calcGlobalSplitCost - Return the global split cost of following the split /// pattern in LiveBundles. This cost should be added to the local cost of the -/// interference pattern in SpillConstraints. +/// interference pattern in SplitConstraints. /// float RAGreedy::calcGlobalSplitCost(const BitVector &LiveBundles) { float GlobalCost = 0; - for (unsigned i = 0, e = SpillConstraints.size(); i != e; ++i) { - SpillPlacement::BlockConstraint &BC = SpillConstraints[i]; + for (unsigned i = 0, e = SplitConstraints.size(); i != e; ++i) { + SpillPlacement::BlockConstraint &BC = SplitConstraints[i]; unsigned Inserts = 0; // Broken entry preference? Inserts += LiveBundles[Bundles->getBundle(BC.Number, 0)] != @@ -938,13 +834,21 @@ unsigned RAGreedy::tryRegionSplit(LiveInterval &VirtReg, AllocationOrder &Order, BitVector LiveBundles, BestBundles; float BestCost = 0; unsigned BestReg = 0; + Order.rewind(); - while (unsigned PhysReg = Order.next()) { - float Cost = calcInterferenceInfo(VirtReg, PhysReg); + for (unsigned Cand = 0; unsigned PhysReg = Order.next(); ++Cand) { + if (GlobalCand.size() <= Cand) + GlobalCand.resize(Cand+1); + GlobalCand[Cand].PhysReg = PhysReg; + + mapGlobalInterference(PhysReg, GlobalCand[Cand].Interference); + float Cost = calcSplitConstraints(GlobalCand[Cand].Interference); + DEBUG(dbgs() << PrintReg(PhysReg, TRI) << " static split cost = " << Cost + << '\n'); if (BestReg && Cost >= BestCost) continue; - SpillPlacer->placeSpills(SpillConstraints, LiveBundles); + SpillPlacer->placeSpills(SplitConstraints, LiveBundles); // No live bundles, defer to splitSingleBlocks(). if (!LiveBundles.any()) continue; -- 2.34.1