xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/RegAllocGreedy.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
104eeddc0SDimitry Andric //==- RegAllocGreedy.h ------- greedy register allocator  ----------*-C++-*-==//
204eeddc0SDimitry Andric //
304eeddc0SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
404eeddc0SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
504eeddc0SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
604eeddc0SDimitry Andric //
704eeddc0SDimitry Andric //===----------------------------------------------------------------------===//
804eeddc0SDimitry Andric // This file defines the RAGreedy function pass for register allocation in
904eeddc0SDimitry Andric // optimized builds.
1004eeddc0SDimitry Andric //===----------------------------------------------------------------------===//
1104eeddc0SDimitry Andric 
1204eeddc0SDimitry Andric #ifndef LLVM_CODEGEN_REGALLOCGREEDY_H_
1304eeddc0SDimitry Andric #define LLVM_CODEGEN_REGALLOCGREEDY_H_
1404eeddc0SDimitry Andric 
1504eeddc0SDimitry Andric #include "InterferenceCache.h"
1604eeddc0SDimitry Andric #include "RegAllocBase.h"
1704eeddc0SDimitry Andric #include "RegAllocEvictionAdvisor.h"
18bdd1243dSDimitry Andric #include "RegAllocPriorityAdvisor.h"
1904eeddc0SDimitry Andric #include "SpillPlacement.h"
2004eeddc0SDimitry Andric #include "SplitKit.h"
2104eeddc0SDimitry Andric #include "llvm/ADT/ArrayRef.h"
2204eeddc0SDimitry Andric #include "llvm/ADT/BitVector.h"
2304eeddc0SDimitry Andric #include "llvm/ADT/IndexedMap.h"
2404eeddc0SDimitry Andric #include "llvm/ADT/SetVector.h"
2504eeddc0SDimitry Andric #include "llvm/ADT/SmallVector.h"
2604eeddc0SDimitry Andric #include "llvm/ADT/StringRef.h"
2704eeddc0SDimitry Andric #include "llvm/CodeGen/CalcSpillWeights.h"
2804eeddc0SDimitry Andric #include "llvm/CodeGen/LiveInterval.h"
2904eeddc0SDimitry Andric #include "llvm/CodeGen/LiveRangeEdit.h"
3004eeddc0SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
3104eeddc0SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
3204eeddc0SDimitry Andric #include "llvm/CodeGen/RegisterClassInfo.h"
3304eeddc0SDimitry Andric #include "llvm/CodeGen/Spiller.h"
3404eeddc0SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
3504eeddc0SDimitry Andric #include <algorithm>
3604eeddc0SDimitry Andric #include <cstdint>
3704eeddc0SDimitry Andric #include <memory>
3804eeddc0SDimitry Andric #include <queue>
3904eeddc0SDimitry Andric #include <utility>
4004eeddc0SDimitry Andric 
4104eeddc0SDimitry Andric namespace llvm {
4281ad6265SDimitry Andric class AllocationOrder;
4381ad6265SDimitry Andric class AnalysisUsage;
4481ad6265SDimitry Andric class EdgeBundles;
4581ad6265SDimitry Andric class LiveDebugVariables;
4681ad6265SDimitry Andric class LiveIntervals;
4781ad6265SDimitry Andric class LiveRegMatrix;
4881ad6265SDimitry Andric class MachineBasicBlock;
4981ad6265SDimitry Andric class MachineBlockFrequencyInfo;
5081ad6265SDimitry Andric class MachineDominatorTree;
5181ad6265SDimitry Andric class MachineLoop;
5281ad6265SDimitry Andric class MachineLoopInfo;
5381ad6265SDimitry Andric class MachineOptimizationRemarkEmitter;
5481ad6265SDimitry Andric class MachineOptimizationRemarkMissed;
5581ad6265SDimitry Andric class SlotIndexes;
5681ad6265SDimitry Andric class TargetInstrInfo;
5781ad6265SDimitry Andric class VirtRegMap;
5881ad6265SDimitry Andric 
5904eeddc0SDimitry Andric class LLVM_LIBRARY_VISIBILITY RAGreedy : public MachineFunctionPass,
6004eeddc0SDimitry Andric                                          public RegAllocBase,
6104eeddc0SDimitry Andric                                          private LiveRangeEdit::Delegate {
6204eeddc0SDimitry Andric   // Interface to eviction advisers
6304eeddc0SDimitry Andric public:
6404eeddc0SDimitry Andric   /// Track allocation stage and eviction loop prevention during allocation.
6504eeddc0SDimitry Andric   class ExtraRegInfo final {
6604eeddc0SDimitry Andric     // RegInfo - Keep additional information about each live range.
6704eeddc0SDimitry Andric     struct RegInfo {
6804eeddc0SDimitry Andric       LiveRangeStage Stage = RS_New;
6904eeddc0SDimitry Andric 
7004eeddc0SDimitry Andric       // Cascade - Eviction loop prevention. See
7104eeddc0SDimitry Andric       // canEvictInterferenceBasedOnCost().
7204eeddc0SDimitry Andric       unsigned Cascade = 0;
7304eeddc0SDimitry Andric 
7404eeddc0SDimitry Andric       RegInfo() = default;
7504eeddc0SDimitry Andric     };
7604eeddc0SDimitry Andric 
7704eeddc0SDimitry Andric     IndexedMap<RegInfo, VirtReg2IndexFunctor> Info;
7804eeddc0SDimitry Andric     unsigned NextCascade = 1;
7904eeddc0SDimitry Andric 
8004eeddc0SDimitry Andric   public:
81bdd1243dSDimitry Andric     ExtraRegInfo() {}
8204eeddc0SDimitry Andric     ExtraRegInfo(const ExtraRegInfo &) = delete;
8304eeddc0SDimitry Andric 
8404eeddc0SDimitry Andric     LiveRangeStage getStage(Register Reg) const { return Info[Reg].Stage; }
8504eeddc0SDimitry Andric 
8604eeddc0SDimitry Andric     LiveRangeStage getStage(const LiveInterval &VirtReg) const {
8704eeddc0SDimitry Andric       return getStage(VirtReg.reg());
8804eeddc0SDimitry Andric     }
8904eeddc0SDimitry Andric 
9004eeddc0SDimitry Andric     void setStage(Register Reg, LiveRangeStage Stage) {
9104eeddc0SDimitry Andric       Info.grow(Reg.id());
9204eeddc0SDimitry Andric       Info[Reg].Stage = Stage;
9304eeddc0SDimitry Andric     }
9404eeddc0SDimitry Andric 
9504eeddc0SDimitry Andric     void setStage(const LiveInterval &VirtReg, LiveRangeStage Stage) {
9604eeddc0SDimitry Andric       setStage(VirtReg.reg(), Stage);
9704eeddc0SDimitry Andric     }
9804eeddc0SDimitry Andric 
9904eeddc0SDimitry Andric     /// Return the current stage of the register, if present, otherwise
10004eeddc0SDimitry Andric     /// initialize it and return that.
10104eeddc0SDimitry Andric     LiveRangeStage getOrInitStage(Register Reg) {
10204eeddc0SDimitry Andric       Info.grow(Reg.id());
10304eeddc0SDimitry Andric       return getStage(Reg);
10404eeddc0SDimitry Andric     }
10504eeddc0SDimitry Andric 
10604eeddc0SDimitry Andric     unsigned getCascade(Register Reg) const { return Info[Reg].Cascade; }
10704eeddc0SDimitry Andric 
10804eeddc0SDimitry Andric     void setCascade(Register Reg, unsigned Cascade) {
10904eeddc0SDimitry Andric       Info.grow(Reg.id());
11004eeddc0SDimitry Andric       Info[Reg].Cascade = Cascade;
11104eeddc0SDimitry Andric     }
11204eeddc0SDimitry Andric 
11304eeddc0SDimitry Andric     unsigned getOrAssignNewCascade(Register Reg) {
11404eeddc0SDimitry Andric       unsigned Cascade = getCascade(Reg);
11504eeddc0SDimitry Andric       if (!Cascade) {
11604eeddc0SDimitry Andric         Cascade = NextCascade++;
11704eeddc0SDimitry Andric         setCascade(Reg, Cascade);
11804eeddc0SDimitry Andric       }
11904eeddc0SDimitry Andric       return Cascade;
12004eeddc0SDimitry Andric     }
12104eeddc0SDimitry Andric 
12204eeddc0SDimitry Andric     unsigned getCascadeOrCurrentNext(Register Reg) const {
12304eeddc0SDimitry Andric       unsigned Cascade = getCascade(Reg);
12404eeddc0SDimitry Andric       if (!Cascade)
12504eeddc0SDimitry Andric         Cascade = NextCascade;
12604eeddc0SDimitry Andric       return Cascade;
12704eeddc0SDimitry Andric     }
12804eeddc0SDimitry Andric 
12904eeddc0SDimitry Andric     template <typename Iterator>
13004eeddc0SDimitry Andric     void setStage(Iterator Begin, Iterator End, LiveRangeStage NewStage) {
13104eeddc0SDimitry Andric       for (; Begin != End; ++Begin) {
13204eeddc0SDimitry Andric         Register Reg = *Begin;
13304eeddc0SDimitry Andric         Info.grow(Reg.id());
13404eeddc0SDimitry Andric         if (Info[Reg].Stage == RS_New)
13504eeddc0SDimitry Andric           Info[Reg].Stage = NewStage;
13604eeddc0SDimitry Andric       }
13704eeddc0SDimitry Andric     }
13804eeddc0SDimitry Andric     void LRE_DidCloneVirtReg(Register New, Register Old);
13904eeddc0SDimitry Andric   };
14004eeddc0SDimitry Andric 
14104eeddc0SDimitry Andric   LiveRegMatrix *getInterferenceMatrix() const { return Matrix; }
14204eeddc0SDimitry Andric   LiveIntervals *getLiveIntervals() const { return LIS; }
14304eeddc0SDimitry Andric   VirtRegMap *getVirtRegMap() const { return VRM; }
14404eeddc0SDimitry Andric   const RegisterClassInfo &getRegClassInfo() const { return RegClassInfo; }
14504eeddc0SDimitry Andric   const ExtraRegInfo &getExtraInfo() const { return *ExtraInfo; }
14604eeddc0SDimitry Andric   size_t getQueueSize() const { return Queue.size(); }
14704eeddc0SDimitry Andric   // end (interface to eviction advisers)
14804eeddc0SDimitry Andric 
149bdd1243dSDimitry Andric   // Interface to priority advisers
150bdd1243dSDimitry Andric   bool getRegClassPriorityTrumpsGlobalness() const {
151bdd1243dSDimitry Andric     return RegClassPriorityTrumpsGlobalness;
152bdd1243dSDimitry Andric   }
153bdd1243dSDimitry Andric   bool getReverseLocalAssignment() const { return ReverseLocalAssignment; }
154bdd1243dSDimitry Andric   // end (interface to priority advisers)
155bdd1243dSDimitry Andric 
15604eeddc0SDimitry Andric private:
15704eeddc0SDimitry Andric   // Convenient shortcuts.
15804eeddc0SDimitry Andric   using PQueue = std::priority_queue<std::pair<unsigned, unsigned>>;
159bdd1243dSDimitry Andric   using SmallLISet = SmallSetVector<const LiveInterval *, 4>;
16081ad6265SDimitry Andric 
16181ad6265SDimitry Andric   // We need to track all tentative recolorings so we can roll back any
16281ad6265SDimitry Andric   // successful and unsuccessful recoloring attempts.
16381ad6265SDimitry Andric   using RecoloringStack =
16481ad6265SDimitry Andric       SmallVector<std::pair<const LiveInterval *, MCRegister>, 8>;
16504eeddc0SDimitry Andric 
16604eeddc0SDimitry Andric   // context
16706c3fb27SDimitry Andric   MachineFunction *MF = nullptr;
16804eeddc0SDimitry Andric 
16904eeddc0SDimitry Andric   // Shortcuts to some useful interface.
17006c3fb27SDimitry Andric   const TargetInstrInfo *TII = nullptr;
17104eeddc0SDimitry Andric 
17204eeddc0SDimitry Andric   // analyses
17306c3fb27SDimitry Andric   SlotIndexes *Indexes = nullptr;
17406c3fb27SDimitry Andric   MachineBlockFrequencyInfo *MBFI = nullptr;
17506c3fb27SDimitry Andric   MachineDominatorTree *DomTree = nullptr;
17606c3fb27SDimitry Andric   MachineLoopInfo *Loops = nullptr;
17706c3fb27SDimitry Andric   MachineOptimizationRemarkEmitter *ORE = nullptr;
17806c3fb27SDimitry Andric   EdgeBundles *Bundles = nullptr;
17906c3fb27SDimitry Andric   SpillPlacement *SpillPlacer = nullptr;
18006c3fb27SDimitry Andric   LiveDebugVariables *DebugVars = nullptr;
18104eeddc0SDimitry Andric 
18204eeddc0SDimitry Andric   // state
18304eeddc0SDimitry Andric   std::unique_ptr<Spiller> SpillerInstance;
18404eeddc0SDimitry Andric   PQueue Queue;
18504eeddc0SDimitry Andric   std::unique_ptr<VirtRegAuxInfo> VRAI;
186bdd1243dSDimitry Andric   std::optional<ExtraRegInfo> ExtraInfo;
18704eeddc0SDimitry Andric   std::unique_ptr<RegAllocEvictionAdvisor> EvictAdvisor;
18804eeddc0SDimitry Andric 
189bdd1243dSDimitry Andric   std::unique_ptr<RegAllocPriorityAdvisor> PriorityAdvisor;
190bdd1243dSDimitry Andric 
19104eeddc0SDimitry Andric   // Enum CutOffStage to keep a track whether the register allocation failed
19204eeddc0SDimitry Andric   // because of the cutoffs encountered in last chance recoloring.
19304eeddc0SDimitry Andric   // Note: This is used as bitmask. New value should be next power of 2.
19404eeddc0SDimitry Andric   enum CutOffStage {
19504eeddc0SDimitry Andric     // No cutoffs encountered
19604eeddc0SDimitry Andric     CO_None = 0,
19704eeddc0SDimitry Andric 
19804eeddc0SDimitry Andric     // lcr-max-depth cutoff encountered
19904eeddc0SDimitry Andric     CO_Depth = 1,
20004eeddc0SDimitry Andric 
20104eeddc0SDimitry Andric     // lcr-max-interf cutoff encountered
20204eeddc0SDimitry Andric     CO_Interf = 2
20304eeddc0SDimitry Andric   };
20404eeddc0SDimitry Andric 
20506c3fb27SDimitry Andric   uint8_t CutOffInfo = CutOffStage::CO_None;
20604eeddc0SDimitry Andric 
20704eeddc0SDimitry Andric #ifndef NDEBUG
20804eeddc0SDimitry Andric   static const char *const StageName[];
20904eeddc0SDimitry Andric #endif
21004eeddc0SDimitry Andric 
21104eeddc0SDimitry Andric   // splitting state.
21204eeddc0SDimitry Andric   std::unique_ptr<SplitAnalysis> SA;
21304eeddc0SDimitry Andric   std::unique_ptr<SplitEditor> SE;
21404eeddc0SDimitry Andric 
21504eeddc0SDimitry Andric   /// Cached per-block interference maps
21604eeddc0SDimitry Andric   InterferenceCache IntfCache;
21704eeddc0SDimitry Andric 
21804eeddc0SDimitry Andric   /// All basic blocks where the current register has uses.
21904eeddc0SDimitry Andric   SmallVector<SpillPlacement::BlockConstraint, 8> SplitConstraints;
22004eeddc0SDimitry Andric 
22104eeddc0SDimitry Andric   /// Global live range splitting candidate info.
22204eeddc0SDimitry Andric   struct GlobalSplitCandidate {
22304eeddc0SDimitry Andric     // Register intended for assignment, or 0.
22404eeddc0SDimitry Andric     MCRegister PhysReg;
22504eeddc0SDimitry Andric 
22604eeddc0SDimitry Andric     // SplitKit interval index for this candidate.
22704eeddc0SDimitry Andric     unsigned IntvIdx;
22804eeddc0SDimitry Andric 
22904eeddc0SDimitry Andric     // Interference for PhysReg.
23004eeddc0SDimitry Andric     InterferenceCache::Cursor Intf;
23104eeddc0SDimitry Andric 
23204eeddc0SDimitry Andric     // Bundles where this candidate should be live.
23304eeddc0SDimitry Andric     BitVector LiveBundles;
23404eeddc0SDimitry Andric     SmallVector<unsigned, 8> ActiveBlocks;
23504eeddc0SDimitry Andric 
23604eeddc0SDimitry Andric     void reset(InterferenceCache &Cache, MCRegister Reg) {
23704eeddc0SDimitry Andric       PhysReg = Reg;
23804eeddc0SDimitry Andric       IntvIdx = 0;
23904eeddc0SDimitry Andric       Intf.setPhysReg(Cache, Reg);
24004eeddc0SDimitry Andric       LiveBundles.clear();
24104eeddc0SDimitry Andric       ActiveBlocks.clear();
24204eeddc0SDimitry Andric     }
24304eeddc0SDimitry Andric 
24404eeddc0SDimitry Andric     // Set B[I] = C for every live bundle where B[I] was NoCand.
24504eeddc0SDimitry Andric     unsigned getBundles(SmallVectorImpl<unsigned> &B, unsigned C) {
24604eeddc0SDimitry Andric       unsigned Count = 0;
24704eeddc0SDimitry Andric       for (unsigned I : LiveBundles.set_bits())
24804eeddc0SDimitry Andric         if (B[I] == NoCand) {
24904eeddc0SDimitry Andric           B[I] = C;
25004eeddc0SDimitry Andric           Count++;
25104eeddc0SDimitry Andric         }
25204eeddc0SDimitry Andric       return Count;
25304eeddc0SDimitry Andric     }
25404eeddc0SDimitry Andric   };
25504eeddc0SDimitry Andric 
25604eeddc0SDimitry Andric   /// Candidate info for each PhysReg in AllocationOrder.
25704eeddc0SDimitry Andric   /// This vector never shrinks, but grows to the size of the largest register
25804eeddc0SDimitry Andric   /// class.
25904eeddc0SDimitry Andric   SmallVector<GlobalSplitCandidate, 32> GlobalCand;
26004eeddc0SDimitry Andric 
26104eeddc0SDimitry Andric   enum : unsigned { NoCand = ~0u };
26204eeddc0SDimitry Andric 
26304eeddc0SDimitry Andric   /// Candidate map. Each edge bundle is assigned to a GlobalCand entry, or to
26404eeddc0SDimitry Andric   /// NoCand which indicates the stack interval.
26504eeddc0SDimitry Andric   SmallVector<unsigned, 32> BundleCand;
26604eeddc0SDimitry Andric 
26704eeddc0SDimitry Andric   /// Callee-save register cost, calculated once per machine function.
26804eeddc0SDimitry Andric   BlockFrequency CSRCost;
26904eeddc0SDimitry Andric 
27004eeddc0SDimitry Andric   /// Set of broken hints that may be reconciled later because of eviction.
27181ad6265SDimitry Andric   SmallSetVector<const LiveInterval *, 8> SetOfBrokenHints;
27204eeddc0SDimitry Andric 
27304eeddc0SDimitry Andric   /// The register cost values. This list will be recreated for each Machine
27404eeddc0SDimitry Andric   /// Function
27504eeddc0SDimitry Andric   ArrayRef<uint8_t> RegCosts;
27604eeddc0SDimitry Andric 
27781ad6265SDimitry Andric   /// Flags for the live range priority calculation, determined once per
27881ad6265SDimitry Andric   /// machine function.
27906c3fb27SDimitry Andric   bool RegClassPriorityTrumpsGlobalness = false;
28081ad6265SDimitry Andric 
28106c3fb27SDimitry Andric   bool ReverseLocalAssignment = false;
282972a253aSDimitry Andric 
28304eeddc0SDimitry Andric public:
284*0fca6ea1SDimitry Andric   RAGreedy(const RegAllocFilterFunc F = nullptr);
28504eeddc0SDimitry Andric 
28604eeddc0SDimitry Andric   /// Return the pass name.
28704eeddc0SDimitry Andric   StringRef getPassName() const override { return "Greedy Register Allocator"; }
28804eeddc0SDimitry Andric 
28904eeddc0SDimitry Andric   /// RAGreedy analysis usage.
29004eeddc0SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override;
29104eeddc0SDimitry Andric   void releaseMemory() override;
29204eeddc0SDimitry Andric   Spiller &spiller() override { return *SpillerInstance; }
29381ad6265SDimitry Andric   void enqueueImpl(const LiveInterval *LI) override;
29481ad6265SDimitry Andric   const LiveInterval *dequeue() override;
29581ad6265SDimitry Andric   MCRegister selectOrSplit(const LiveInterval &,
29604eeddc0SDimitry Andric                            SmallVectorImpl<Register> &) override;
29781ad6265SDimitry Andric   void aboutToRemoveInterval(const LiveInterval &) override;
29804eeddc0SDimitry Andric 
29904eeddc0SDimitry Andric   /// Perform register allocation.
30004eeddc0SDimitry Andric   bool runOnMachineFunction(MachineFunction &mf) override;
30104eeddc0SDimitry Andric 
30204eeddc0SDimitry Andric   MachineFunctionProperties getRequiredProperties() const override {
30304eeddc0SDimitry Andric     return MachineFunctionProperties().set(
30404eeddc0SDimitry Andric         MachineFunctionProperties::Property::NoPHIs);
30504eeddc0SDimitry Andric   }
30604eeddc0SDimitry Andric 
30704eeddc0SDimitry Andric   MachineFunctionProperties getClearedProperties() const override {
30804eeddc0SDimitry Andric     return MachineFunctionProperties().set(
30904eeddc0SDimitry Andric         MachineFunctionProperties::Property::IsSSA);
31004eeddc0SDimitry Andric   }
31104eeddc0SDimitry Andric 
31204eeddc0SDimitry Andric   static char ID;
31304eeddc0SDimitry Andric 
31404eeddc0SDimitry Andric private:
31581ad6265SDimitry Andric   MCRegister selectOrSplitImpl(const LiveInterval &,
31681ad6265SDimitry Andric                                SmallVectorImpl<Register> &, SmallVirtRegSet &,
31781ad6265SDimitry Andric                                RecoloringStack &, unsigned = 0);
31804eeddc0SDimitry Andric 
31904eeddc0SDimitry Andric   bool LRE_CanEraseVirtReg(Register) override;
32004eeddc0SDimitry Andric   void LRE_WillShrinkVirtReg(Register) override;
32104eeddc0SDimitry Andric   void LRE_DidCloneVirtReg(Register, Register) override;
32281ad6265SDimitry Andric   void enqueue(PQueue &CurQueue, const LiveInterval *LI);
32381ad6265SDimitry Andric   const LiveInterval *dequeue(PQueue &CurQueue);
32404eeddc0SDimitry Andric 
32581ad6265SDimitry Andric   bool hasVirtRegAlloc();
32604eeddc0SDimitry Andric   BlockFrequency calcSpillCost();
32704eeddc0SDimitry Andric   bool addSplitConstraints(InterferenceCache::Cursor, BlockFrequency &);
32804eeddc0SDimitry Andric   bool addThroughConstraints(InterferenceCache::Cursor, ArrayRef<unsigned>);
32904eeddc0SDimitry Andric   bool growRegion(GlobalSplitCandidate &Cand);
33004eeddc0SDimitry Andric   BlockFrequency calcGlobalSplitCost(GlobalSplitCandidate &,
33181ad6265SDimitry Andric                                      const AllocationOrder &Order);
33204eeddc0SDimitry Andric   bool calcCompactRegion(GlobalSplitCandidate &);
33304eeddc0SDimitry Andric   void splitAroundRegion(LiveRangeEdit &, ArrayRef<unsigned>);
33404eeddc0SDimitry Andric   void calcGapWeights(MCRegister, SmallVectorImpl<float> &);
33581ad6265SDimitry Andric   void evictInterference(const LiveInterval &, MCRegister,
33604eeddc0SDimitry Andric                          SmallVectorImpl<Register> &);
33781ad6265SDimitry Andric   bool mayRecolorAllInterferences(MCRegister PhysReg,
33881ad6265SDimitry Andric                                   const LiveInterval &VirtReg,
33904eeddc0SDimitry Andric                                   SmallLISet &RecoloringCandidates,
34004eeddc0SDimitry Andric                                   const SmallVirtRegSet &FixedRegisters);
34104eeddc0SDimitry Andric 
34281ad6265SDimitry Andric   MCRegister tryAssign(const LiveInterval &, AllocationOrder &,
34304eeddc0SDimitry Andric                        SmallVectorImpl<Register> &, const SmallVirtRegSet &);
34481ad6265SDimitry Andric   MCRegister tryEvict(const LiveInterval &, AllocationOrder &,
34504eeddc0SDimitry Andric                       SmallVectorImpl<Register> &, uint8_t,
34604eeddc0SDimitry Andric                       const SmallVirtRegSet &);
34781ad6265SDimitry Andric   MCRegister tryRegionSplit(const LiveInterval &, AllocationOrder &,
34804eeddc0SDimitry Andric                             SmallVectorImpl<Register> &);
3495f757f3fSDimitry Andric   /// Calculate cost of region splitting around the specified register.
3505f757f3fSDimitry Andric   unsigned calculateRegionSplitCostAroundReg(MCPhysReg PhysReg,
3515f757f3fSDimitry Andric                                              AllocationOrder &Order,
3525f757f3fSDimitry Andric                                              BlockFrequency &BestCost,
3535f757f3fSDimitry Andric                                              unsigned &NumCands,
3545f757f3fSDimitry Andric                                              unsigned &BestCand);
35504eeddc0SDimitry Andric   /// Calculate cost of region splitting.
35681ad6265SDimitry Andric   unsigned calculateRegionSplitCost(const LiveInterval &VirtReg,
35704eeddc0SDimitry Andric                                     AllocationOrder &Order,
35804eeddc0SDimitry Andric                                     BlockFrequency &BestCost,
35981ad6265SDimitry Andric                                     unsigned &NumCands, bool IgnoreCSR);
36004eeddc0SDimitry Andric   /// Perform region splitting.
36181ad6265SDimitry Andric   unsigned doRegionSplit(const LiveInterval &VirtReg, unsigned BestCand,
36204eeddc0SDimitry Andric                          bool HasCompact, SmallVectorImpl<Register> &NewVRegs);
3635f757f3fSDimitry Andric   /// Try to split VirtReg around physical Hint register.
3645f757f3fSDimitry Andric   bool trySplitAroundHintReg(MCPhysReg Hint, const LiveInterval &VirtReg,
3655f757f3fSDimitry Andric                              SmallVectorImpl<Register> &NewVRegs,
3665f757f3fSDimitry Andric                              AllocationOrder &Order);
36704eeddc0SDimitry Andric   /// Check other options before using a callee-saved register for the first
36804eeddc0SDimitry Andric   /// time.
36981ad6265SDimitry Andric   MCRegister tryAssignCSRFirstTime(const LiveInterval &VirtReg,
37004eeddc0SDimitry Andric                                    AllocationOrder &Order, MCRegister PhysReg,
37104eeddc0SDimitry Andric                                    uint8_t &CostPerUseLimit,
37204eeddc0SDimitry Andric                                    SmallVectorImpl<Register> &NewVRegs);
37304eeddc0SDimitry Andric   void initializeCSRCost();
37481ad6265SDimitry Andric   unsigned tryBlockSplit(const LiveInterval &, AllocationOrder &,
37504eeddc0SDimitry Andric                          SmallVectorImpl<Register> &);
37681ad6265SDimitry Andric   unsigned tryInstructionSplit(const LiveInterval &, AllocationOrder &,
37704eeddc0SDimitry Andric                                SmallVectorImpl<Register> &);
37881ad6265SDimitry Andric   unsigned tryLocalSplit(const LiveInterval &, AllocationOrder &,
37904eeddc0SDimitry Andric                          SmallVectorImpl<Register> &);
38081ad6265SDimitry Andric   unsigned trySplit(const LiveInterval &, AllocationOrder &,
38104eeddc0SDimitry Andric                     SmallVectorImpl<Register> &, const SmallVirtRegSet &);
38281ad6265SDimitry Andric   unsigned tryLastChanceRecoloring(const LiveInterval &, AllocationOrder &,
38304eeddc0SDimitry Andric                                    SmallVectorImpl<Register> &,
38481ad6265SDimitry Andric                                    SmallVirtRegSet &, RecoloringStack &,
38581ad6265SDimitry Andric                                    unsigned);
38604eeddc0SDimitry Andric   bool tryRecoloringCandidates(PQueue &, SmallVectorImpl<Register> &,
38781ad6265SDimitry Andric                                SmallVirtRegSet &, RecoloringStack &, unsigned);
38881ad6265SDimitry Andric   void tryHintRecoloring(const LiveInterval &);
38904eeddc0SDimitry Andric   void tryHintsRecoloring();
39004eeddc0SDimitry Andric 
39104eeddc0SDimitry Andric   /// Model the information carried by one end of a copy.
39204eeddc0SDimitry Andric   struct HintInfo {
39304eeddc0SDimitry Andric     /// The frequency of the copy.
39404eeddc0SDimitry Andric     BlockFrequency Freq;
39504eeddc0SDimitry Andric     /// The virtual register or physical register.
39604eeddc0SDimitry Andric     Register Reg;
39704eeddc0SDimitry Andric     /// Its currently assigned register.
39804eeddc0SDimitry Andric     /// In case of a physical register Reg == PhysReg.
39904eeddc0SDimitry Andric     MCRegister PhysReg;
40004eeddc0SDimitry Andric 
40104eeddc0SDimitry Andric     HintInfo(BlockFrequency Freq, Register Reg, MCRegister PhysReg)
40204eeddc0SDimitry Andric         : Freq(Freq), Reg(Reg), PhysReg(PhysReg) {}
40304eeddc0SDimitry Andric   };
40404eeddc0SDimitry Andric   using HintsInfo = SmallVector<HintInfo, 4>;
40504eeddc0SDimitry Andric 
40604eeddc0SDimitry Andric   BlockFrequency getBrokenHintFreq(const HintsInfo &, MCRegister);
40704eeddc0SDimitry Andric   void collectHintInfo(Register, HintsInfo &);
40804eeddc0SDimitry Andric 
40904eeddc0SDimitry Andric   /// Greedy RA statistic to remark.
41004eeddc0SDimitry Andric   struct RAGreedyStats {
41104eeddc0SDimitry Andric     unsigned Reloads = 0;
41204eeddc0SDimitry Andric     unsigned FoldedReloads = 0;
41304eeddc0SDimitry Andric     unsigned ZeroCostFoldedReloads = 0;
41404eeddc0SDimitry Andric     unsigned Spills = 0;
41504eeddc0SDimitry Andric     unsigned FoldedSpills = 0;
41604eeddc0SDimitry Andric     unsigned Copies = 0;
41704eeddc0SDimitry Andric     float ReloadsCost = 0.0f;
41804eeddc0SDimitry Andric     float FoldedReloadsCost = 0.0f;
41904eeddc0SDimitry Andric     float SpillsCost = 0.0f;
42004eeddc0SDimitry Andric     float FoldedSpillsCost = 0.0f;
42104eeddc0SDimitry Andric     float CopiesCost = 0.0f;
42204eeddc0SDimitry Andric 
42304eeddc0SDimitry Andric     bool isEmpty() {
42404eeddc0SDimitry Andric       return !(Reloads || FoldedReloads || Spills || FoldedSpills ||
42504eeddc0SDimitry Andric                ZeroCostFoldedReloads || Copies);
42604eeddc0SDimitry Andric     }
42704eeddc0SDimitry Andric 
428*0fca6ea1SDimitry Andric     void add(const RAGreedyStats &other) {
42904eeddc0SDimitry Andric       Reloads += other.Reloads;
43004eeddc0SDimitry Andric       FoldedReloads += other.FoldedReloads;
43104eeddc0SDimitry Andric       ZeroCostFoldedReloads += other.ZeroCostFoldedReloads;
43204eeddc0SDimitry Andric       Spills += other.Spills;
43304eeddc0SDimitry Andric       FoldedSpills += other.FoldedSpills;
43404eeddc0SDimitry Andric       Copies += other.Copies;
43504eeddc0SDimitry Andric       ReloadsCost += other.ReloadsCost;
43604eeddc0SDimitry Andric       FoldedReloadsCost += other.FoldedReloadsCost;
43704eeddc0SDimitry Andric       SpillsCost += other.SpillsCost;
43804eeddc0SDimitry Andric       FoldedSpillsCost += other.FoldedSpillsCost;
43904eeddc0SDimitry Andric       CopiesCost += other.CopiesCost;
44004eeddc0SDimitry Andric     }
44104eeddc0SDimitry Andric 
44204eeddc0SDimitry Andric     void report(MachineOptimizationRemarkMissed &R);
44304eeddc0SDimitry Andric   };
44404eeddc0SDimitry Andric 
44504eeddc0SDimitry Andric   /// Compute statistic for a basic block.
44604eeddc0SDimitry Andric   RAGreedyStats computeStats(MachineBasicBlock &MBB);
44704eeddc0SDimitry Andric 
44804eeddc0SDimitry Andric   /// Compute and report statistic through a remark.
44904eeddc0SDimitry Andric   RAGreedyStats reportStats(MachineLoop *L);
45004eeddc0SDimitry Andric 
45104eeddc0SDimitry Andric   /// Report the statistic for each loop.
45204eeddc0SDimitry Andric   void reportStats();
45304eeddc0SDimitry Andric };
45404eeddc0SDimitry Andric } // namespace llvm
45504eeddc0SDimitry Andric #endif // #ifndef LLVM_CODEGEN_REGALLOCGREEDY_H_
456