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