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" 1804eeddc0SDimitry Andric #include "SpillPlacement.h" 1904eeddc0SDimitry Andric #include "SplitKit.h" 2004eeddc0SDimitry Andric #include "llvm/ADT/ArrayRef.h" 2104eeddc0SDimitry Andric #include "llvm/ADT/BitVector.h" 2204eeddc0SDimitry Andric #include "llvm/ADT/DenseMap.h" 2304eeddc0SDimitry Andric #include "llvm/ADT/IndexedMap.h" 2404eeddc0SDimitry Andric #include "llvm/ADT/SetVector.h" 2504eeddc0SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 2604eeddc0SDimitry Andric #include "llvm/ADT/SmallVector.h" 2704eeddc0SDimitry Andric #include "llvm/ADT/StringRef.h" 2804eeddc0SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 2904eeddc0SDimitry Andric #include "llvm/CodeGen/CalcSpillWeights.h" 3004eeddc0SDimitry Andric #include "llvm/CodeGen/LiveInterval.h" 3104eeddc0SDimitry Andric #include "llvm/CodeGen/LiveRangeEdit.h" 3204eeddc0SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 3304eeddc0SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 3404eeddc0SDimitry Andric #include "llvm/CodeGen/RegisterClassInfo.h" 3504eeddc0SDimitry Andric #include "llvm/CodeGen/Spiller.h" 3604eeddc0SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 3704eeddc0SDimitry Andric #include <algorithm> 3804eeddc0SDimitry Andric #include <cstdint> 3904eeddc0SDimitry Andric #include <memory> 4004eeddc0SDimitry Andric #include <queue> 4104eeddc0SDimitry Andric #include <utility> 4204eeddc0SDimitry Andric 4304eeddc0SDimitry Andric namespace llvm { 44*81ad6265SDimitry Andric class AllocationOrder; 45*81ad6265SDimitry Andric class AnalysisUsage; 46*81ad6265SDimitry Andric class EdgeBundles; 47*81ad6265SDimitry Andric class LiveDebugVariables; 48*81ad6265SDimitry Andric class LiveIntervals; 49*81ad6265SDimitry Andric class LiveRegMatrix; 50*81ad6265SDimitry Andric class MachineBasicBlock; 51*81ad6265SDimitry Andric class MachineBlockFrequencyInfo; 52*81ad6265SDimitry Andric class MachineDominatorTree; 53*81ad6265SDimitry Andric class MachineLoop; 54*81ad6265SDimitry Andric class MachineLoopInfo; 55*81ad6265SDimitry Andric class MachineOptimizationRemarkEmitter; 56*81ad6265SDimitry Andric class MachineOptimizationRemarkMissed; 57*81ad6265SDimitry Andric class SlotIndex; 58*81ad6265SDimitry Andric class SlotIndexes; 59*81ad6265SDimitry Andric class TargetInstrInfo; 60*81ad6265SDimitry Andric class VirtRegMap; 61*81ad6265SDimitry Andric 6204eeddc0SDimitry Andric class LLVM_LIBRARY_VISIBILITY RAGreedy : public MachineFunctionPass, 6304eeddc0SDimitry Andric public RegAllocBase, 6404eeddc0SDimitry Andric private LiveRangeEdit::Delegate { 6504eeddc0SDimitry Andric // Interface to eviction advisers 6604eeddc0SDimitry Andric public: 6704eeddc0SDimitry Andric /// Track allocation stage and eviction loop prevention during allocation. 6804eeddc0SDimitry Andric class ExtraRegInfo final { 6904eeddc0SDimitry Andric // RegInfo - Keep additional information about each live range. 7004eeddc0SDimitry Andric struct RegInfo { 7104eeddc0SDimitry Andric LiveRangeStage Stage = RS_New; 7204eeddc0SDimitry Andric 7304eeddc0SDimitry Andric // Cascade - Eviction loop prevention. See 7404eeddc0SDimitry Andric // canEvictInterferenceBasedOnCost(). 7504eeddc0SDimitry Andric unsigned Cascade = 0; 7604eeddc0SDimitry Andric 7704eeddc0SDimitry Andric RegInfo() = default; 7804eeddc0SDimitry Andric }; 7904eeddc0SDimitry Andric 8004eeddc0SDimitry Andric IndexedMap<RegInfo, VirtReg2IndexFunctor> Info; 8104eeddc0SDimitry Andric unsigned NextCascade = 1; 8204eeddc0SDimitry Andric 8304eeddc0SDimitry Andric public: 8404eeddc0SDimitry Andric ExtraRegInfo() = default; 8504eeddc0SDimitry Andric ExtraRegInfo(const ExtraRegInfo &) = delete; 8604eeddc0SDimitry Andric 8704eeddc0SDimitry Andric LiveRangeStage getStage(Register Reg) const { return Info[Reg].Stage; } 8804eeddc0SDimitry Andric 8904eeddc0SDimitry Andric LiveRangeStage getStage(const LiveInterval &VirtReg) const { 9004eeddc0SDimitry Andric return getStage(VirtReg.reg()); 9104eeddc0SDimitry Andric } 9204eeddc0SDimitry Andric 9304eeddc0SDimitry Andric void setStage(Register Reg, LiveRangeStage Stage) { 9404eeddc0SDimitry Andric Info.grow(Reg.id()); 9504eeddc0SDimitry Andric Info[Reg].Stage = Stage; 9604eeddc0SDimitry Andric } 9704eeddc0SDimitry Andric 9804eeddc0SDimitry Andric void setStage(const LiveInterval &VirtReg, LiveRangeStage Stage) { 9904eeddc0SDimitry Andric setStage(VirtReg.reg(), Stage); 10004eeddc0SDimitry Andric } 10104eeddc0SDimitry Andric 10204eeddc0SDimitry Andric /// Return the current stage of the register, if present, otherwise 10304eeddc0SDimitry Andric /// initialize it and return that. 10404eeddc0SDimitry Andric LiveRangeStage getOrInitStage(Register Reg) { 10504eeddc0SDimitry Andric Info.grow(Reg.id()); 10604eeddc0SDimitry Andric return getStage(Reg); 10704eeddc0SDimitry Andric } 10804eeddc0SDimitry Andric 10904eeddc0SDimitry Andric unsigned getCascade(Register Reg) const { return Info[Reg].Cascade; } 11004eeddc0SDimitry Andric 11104eeddc0SDimitry Andric void setCascade(Register Reg, unsigned Cascade) { 11204eeddc0SDimitry Andric Info.grow(Reg.id()); 11304eeddc0SDimitry Andric Info[Reg].Cascade = Cascade; 11404eeddc0SDimitry Andric } 11504eeddc0SDimitry Andric 11604eeddc0SDimitry Andric unsigned getOrAssignNewCascade(Register Reg) { 11704eeddc0SDimitry Andric unsigned Cascade = getCascade(Reg); 11804eeddc0SDimitry Andric if (!Cascade) { 11904eeddc0SDimitry Andric Cascade = NextCascade++; 12004eeddc0SDimitry Andric setCascade(Reg, Cascade); 12104eeddc0SDimitry Andric } 12204eeddc0SDimitry Andric return Cascade; 12304eeddc0SDimitry Andric } 12404eeddc0SDimitry Andric 12504eeddc0SDimitry Andric unsigned getCascadeOrCurrentNext(Register Reg) const { 12604eeddc0SDimitry Andric unsigned Cascade = getCascade(Reg); 12704eeddc0SDimitry Andric if (!Cascade) 12804eeddc0SDimitry Andric Cascade = NextCascade; 12904eeddc0SDimitry Andric return Cascade; 13004eeddc0SDimitry Andric } 13104eeddc0SDimitry Andric 13204eeddc0SDimitry Andric template <typename Iterator> 13304eeddc0SDimitry Andric void setStage(Iterator Begin, Iterator End, LiveRangeStage NewStage) { 13404eeddc0SDimitry Andric for (; Begin != End; ++Begin) { 13504eeddc0SDimitry Andric Register Reg = *Begin; 13604eeddc0SDimitry Andric Info.grow(Reg.id()); 13704eeddc0SDimitry Andric if (Info[Reg].Stage == RS_New) 13804eeddc0SDimitry Andric Info[Reg].Stage = NewStage; 13904eeddc0SDimitry Andric } 14004eeddc0SDimitry Andric } 14104eeddc0SDimitry Andric void LRE_DidCloneVirtReg(Register New, Register Old); 14204eeddc0SDimitry Andric }; 14304eeddc0SDimitry Andric 14404eeddc0SDimitry Andric LiveRegMatrix *getInterferenceMatrix() const { return Matrix; } 14504eeddc0SDimitry Andric LiveIntervals *getLiveIntervals() const { return LIS; } 14604eeddc0SDimitry Andric VirtRegMap *getVirtRegMap() const { return VRM; } 14704eeddc0SDimitry Andric const RegisterClassInfo &getRegClassInfo() const { return RegClassInfo; } 14804eeddc0SDimitry Andric const ExtraRegInfo &getExtraInfo() const { return *ExtraInfo; } 14904eeddc0SDimitry Andric size_t getQueueSize() const { return Queue.size(); } 15004eeddc0SDimitry Andric // end (interface to eviction advisers) 15104eeddc0SDimitry Andric 15204eeddc0SDimitry Andric private: 15304eeddc0SDimitry Andric // Convenient shortcuts. 15404eeddc0SDimitry Andric using PQueue = std::priority_queue<std::pair<unsigned, unsigned>>; 155*81ad6265SDimitry Andric using SmallLISet = SmallPtrSet<const LiveInterval *, 4>; 156*81ad6265SDimitry Andric 157*81ad6265SDimitry Andric // We need to track all tentative recolorings so we can roll back any 158*81ad6265SDimitry Andric // successful and unsuccessful recoloring attempts. 159*81ad6265SDimitry Andric using RecoloringStack = 160*81ad6265SDimitry Andric SmallVector<std::pair<const LiveInterval *, MCRegister>, 8>; 16104eeddc0SDimitry Andric 16204eeddc0SDimitry Andric // context 16304eeddc0SDimitry Andric MachineFunction *MF; 16404eeddc0SDimitry Andric 16504eeddc0SDimitry Andric // Shortcuts to some useful interface. 16604eeddc0SDimitry Andric const TargetInstrInfo *TII; 16704eeddc0SDimitry Andric 16804eeddc0SDimitry Andric // analyses 16904eeddc0SDimitry Andric SlotIndexes *Indexes; 17004eeddc0SDimitry Andric MachineBlockFrequencyInfo *MBFI; 17104eeddc0SDimitry Andric MachineDominatorTree *DomTree; 17204eeddc0SDimitry Andric MachineLoopInfo *Loops; 17304eeddc0SDimitry Andric MachineOptimizationRemarkEmitter *ORE; 17404eeddc0SDimitry Andric EdgeBundles *Bundles; 17504eeddc0SDimitry Andric SpillPlacement *SpillPlacer; 17604eeddc0SDimitry Andric LiveDebugVariables *DebugVars; 17704eeddc0SDimitry Andric AliasAnalysis *AA; 17804eeddc0SDimitry Andric 17904eeddc0SDimitry Andric // state 18004eeddc0SDimitry Andric std::unique_ptr<Spiller> SpillerInstance; 18104eeddc0SDimitry Andric PQueue Queue; 18204eeddc0SDimitry Andric std::unique_ptr<VirtRegAuxInfo> VRAI; 18304eeddc0SDimitry Andric Optional<ExtraRegInfo> ExtraInfo; 18404eeddc0SDimitry Andric std::unique_ptr<RegAllocEvictionAdvisor> EvictAdvisor; 18504eeddc0SDimitry Andric 18604eeddc0SDimitry Andric // Enum CutOffStage to keep a track whether the register allocation failed 18704eeddc0SDimitry Andric // because of the cutoffs encountered in last chance recoloring. 18804eeddc0SDimitry Andric // Note: This is used as bitmask. New value should be next power of 2. 18904eeddc0SDimitry Andric enum CutOffStage { 19004eeddc0SDimitry Andric // No cutoffs encountered 19104eeddc0SDimitry Andric CO_None = 0, 19204eeddc0SDimitry Andric 19304eeddc0SDimitry Andric // lcr-max-depth cutoff encountered 19404eeddc0SDimitry Andric CO_Depth = 1, 19504eeddc0SDimitry Andric 19604eeddc0SDimitry Andric // lcr-max-interf cutoff encountered 19704eeddc0SDimitry Andric CO_Interf = 2 19804eeddc0SDimitry Andric }; 19904eeddc0SDimitry Andric 20004eeddc0SDimitry Andric uint8_t CutOffInfo; 20104eeddc0SDimitry Andric 20204eeddc0SDimitry Andric #ifndef NDEBUG 20304eeddc0SDimitry Andric static const char *const StageName[]; 20404eeddc0SDimitry Andric #endif 20504eeddc0SDimitry Andric 20604eeddc0SDimitry Andric // splitting state. 20704eeddc0SDimitry Andric std::unique_ptr<SplitAnalysis> SA; 20804eeddc0SDimitry Andric std::unique_ptr<SplitEditor> SE; 20904eeddc0SDimitry Andric 21004eeddc0SDimitry Andric /// Cached per-block interference maps 21104eeddc0SDimitry Andric InterferenceCache IntfCache; 21204eeddc0SDimitry Andric 21304eeddc0SDimitry Andric /// All basic blocks where the current register has uses. 21404eeddc0SDimitry Andric SmallVector<SpillPlacement::BlockConstraint, 8> SplitConstraints; 21504eeddc0SDimitry Andric 21604eeddc0SDimitry Andric /// Global live range splitting candidate info. 21704eeddc0SDimitry Andric struct GlobalSplitCandidate { 21804eeddc0SDimitry Andric // Register intended for assignment, or 0. 21904eeddc0SDimitry Andric MCRegister PhysReg; 22004eeddc0SDimitry Andric 22104eeddc0SDimitry Andric // SplitKit interval index for this candidate. 22204eeddc0SDimitry Andric unsigned IntvIdx; 22304eeddc0SDimitry Andric 22404eeddc0SDimitry Andric // Interference for PhysReg. 22504eeddc0SDimitry Andric InterferenceCache::Cursor Intf; 22604eeddc0SDimitry Andric 22704eeddc0SDimitry Andric // Bundles where this candidate should be live. 22804eeddc0SDimitry Andric BitVector LiveBundles; 22904eeddc0SDimitry Andric SmallVector<unsigned, 8> ActiveBlocks; 23004eeddc0SDimitry Andric 23104eeddc0SDimitry Andric void reset(InterferenceCache &Cache, MCRegister Reg) { 23204eeddc0SDimitry Andric PhysReg = Reg; 23304eeddc0SDimitry Andric IntvIdx = 0; 23404eeddc0SDimitry Andric Intf.setPhysReg(Cache, Reg); 23504eeddc0SDimitry Andric LiveBundles.clear(); 23604eeddc0SDimitry Andric ActiveBlocks.clear(); 23704eeddc0SDimitry Andric } 23804eeddc0SDimitry Andric 23904eeddc0SDimitry Andric // Set B[I] = C for every live bundle where B[I] was NoCand. 24004eeddc0SDimitry Andric unsigned getBundles(SmallVectorImpl<unsigned> &B, unsigned C) { 24104eeddc0SDimitry Andric unsigned Count = 0; 24204eeddc0SDimitry Andric for (unsigned I : LiveBundles.set_bits()) 24304eeddc0SDimitry Andric if (B[I] == NoCand) { 24404eeddc0SDimitry Andric B[I] = C; 24504eeddc0SDimitry Andric Count++; 24604eeddc0SDimitry Andric } 24704eeddc0SDimitry Andric return Count; 24804eeddc0SDimitry Andric } 24904eeddc0SDimitry Andric }; 25004eeddc0SDimitry Andric 25104eeddc0SDimitry Andric /// Candidate info for each PhysReg in AllocationOrder. 25204eeddc0SDimitry Andric /// This vector never shrinks, but grows to the size of the largest register 25304eeddc0SDimitry Andric /// class. 25404eeddc0SDimitry Andric SmallVector<GlobalSplitCandidate, 32> GlobalCand; 25504eeddc0SDimitry Andric 25604eeddc0SDimitry Andric enum : unsigned { NoCand = ~0u }; 25704eeddc0SDimitry Andric 25804eeddc0SDimitry Andric /// Candidate map. Each edge bundle is assigned to a GlobalCand entry, or to 25904eeddc0SDimitry Andric /// NoCand which indicates the stack interval. 26004eeddc0SDimitry Andric SmallVector<unsigned, 32> BundleCand; 26104eeddc0SDimitry Andric 26204eeddc0SDimitry Andric /// Callee-save register cost, calculated once per machine function. 26304eeddc0SDimitry Andric BlockFrequency CSRCost; 26404eeddc0SDimitry Andric 26504eeddc0SDimitry Andric /// Set of broken hints that may be reconciled later because of eviction. 266*81ad6265SDimitry Andric SmallSetVector<const LiveInterval *, 8> SetOfBrokenHints; 26704eeddc0SDimitry Andric 26804eeddc0SDimitry Andric /// The register cost values. This list will be recreated for each Machine 26904eeddc0SDimitry Andric /// Function 27004eeddc0SDimitry Andric ArrayRef<uint8_t> RegCosts; 27104eeddc0SDimitry Andric 272*81ad6265SDimitry Andric /// Flags for the live range priority calculation, determined once per 273*81ad6265SDimitry Andric /// machine function. 274*81ad6265SDimitry Andric bool RegClassPriorityTrumpsGlobalness; 275*81ad6265SDimitry Andric 27604eeddc0SDimitry Andric public: 27704eeddc0SDimitry Andric RAGreedy(const RegClassFilterFunc F = allocateAllRegClasses); 27804eeddc0SDimitry Andric 27904eeddc0SDimitry Andric /// Return the pass name. 28004eeddc0SDimitry Andric StringRef getPassName() const override { return "Greedy Register Allocator"; } 28104eeddc0SDimitry Andric 28204eeddc0SDimitry Andric /// RAGreedy analysis usage. 28304eeddc0SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 28404eeddc0SDimitry Andric void releaseMemory() override; 28504eeddc0SDimitry Andric Spiller &spiller() override { return *SpillerInstance; } 286*81ad6265SDimitry Andric void enqueueImpl(const LiveInterval *LI) override; 287*81ad6265SDimitry Andric const LiveInterval *dequeue() override; 288*81ad6265SDimitry Andric MCRegister selectOrSplit(const LiveInterval &, 28904eeddc0SDimitry Andric SmallVectorImpl<Register> &) override; 290*81ad6265SDimitry Andric void aboutToRemoveInterval(const LiveInterval &) override; 29104eeddc0SDimitry Andric 29204eeddc0SDimitry Andric /// Perform register allocation. 29304eeddc0SDimitry Andric bool runOnMachineFunction(MachineFunction &mf) override; 29404eeddc0SDimitry Andric 29504eeddc0SDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 29604eeddc0SDimitry Andric return MachineFunctionProperties().set( 29704eeddc0SDimitry Andric MachineFunctionProperties::Property::NoPHIs); 29804eeddc0SDimitry Andric } 29904eeddc0SDimitry Andric 30004eeddc0SDimitry Andric MachineFunctionProperties getClearedProperties() const override { 30104eeddc0SDimitry Andric return MachineFunctionProperties().set( 30204eeddc0SDimitry Andric MachineFunctionProperties::Property::IsSSA); 30304eeddc0SDimitry Andric } 30404eeddc0SDimitry Andric 30504eeddc0SDimitry Andric static char ID; 30604eeddc0SDimitry Andric 30704eeddc0SDimitry Andric private: 308*81ad6265SDimitry Andric MCRegister selectOrSplitImpl(const LiveInterval &, 309*81ad6265SDimitry Andric SmallVectorImpl<Register> &, SmallVirtRegSet &, 310*81ad6265SDimitry Andric RecoloringStack &, unsigned = 0); 31104eeddc0SDimitry Andric 31204eeddc0SDimitry Andric bool LRE_CanEraseVirtReg(Register) override; 31304eeddc0SDimitry Andric void LRE_WillShrinkVirtReg(Register) override; 31404eeddc0SDimitry Andric void LRE_DidCloneVirtReg(Register, Register) override; 315*81ad6265SDimitry Andric void enqueue(PQueue &CurQueue, const LiveInterval *LI); 316*81ad6265SDimitry Andric const LiveInterval *dequeue(PQueue &CurQueue); 31704eeddc0SDimitry Andric 318*81ad6265SDimitry Andric bool hasVirtRegAlloc(); 31904eeddc0SDimitry Andric BlockFrequency calcSpillCost(); 32004eeddc0SDimitry Andric bool addSplitConstraints(InterferenceCache::Cursor, BlockFrequency &); 32104eeddc0SDimitry Andric bool addThroughConstraints(InterferenceCache::Cursor, ArrayRef<unsigned>); 32204eeddc0SDimitry Andric bool growRegion(GlobalSplitCandidate &Cand); 32304eeddc0SDimitry Andric BlockFrequency calcGlobalSplitCost(GlobalSplitCandidate &, 324*81ad6265SDimitry Andric const AllocationOrder &Order); 32504eeddc0SDimitry Andric bool calcCompactRegion(GlobalSplitCandidate &); 32604eeddc0SDimitry Andric void splitAroundRegion(LiveRangeEdit &, ArrayRef<unsigned>); 32704eeddc0SDimitry Andric void calcGapWeights(MCRegister, SmallVectorImpl<float> &); 328*81ad6265SDimitry Andric void evictInterference(const LiveInterval &, MCRegister, 32904eeddc0SDimitry Andric SmallVectorImpl<Register> &); 330*81ad6265SDimitry Andric bool mayRecolorAllInterferences(MCRegister PhysReg, 331*81ad6265SDimitry Andric const LiveInterval &VirtReg, 33204eeddc0SDimitry Andric SmallLISet &RecoloringCandidates, 33304eeddc0SDimitry Andric const SmallVirtRegSet &FixedRegisters); 33404eeddc0SDimitry Andric 335*81ad6265SDimitry Andric MCRegister tryAssign(const LiveInterval &, AllocationOrder &, 33604eeddc0SDimitry Andric SmallVectorImpl<Register> &, const SmallVirtRegSet &); 337*81ad6265SDimitry Andric MCRegister tryEvict(const LiveInterval &, AllocationOrder &, 33804eeddc0SDimitry Andric SmallVectorImpl<Register> &, uint8_t, 33904eeddc0SDimitry Andric const SmallVirtRegSet &); 340*81ad6265SDimitry Andric MCRegister tryRegionSplit(const LiveInterval &, AllocationOrder &, 34104eeddc0SDimitry Andric SmallVectorImpl<Register> &); 34204eeddc0SDimitry Andric /// Calculate cost of region splitting. 343*81ad6265SDimitry Andric unsigned calculateRegionSplitCost(const LiveInterval &VirtReg, 34404eeddc0SDimitry Andric AllocationOrder &Order, 34504eeddc0SDimitry Andric BlockFrequency &BestCost, 346*81ad6265SDimitry Andric unsigned &NumCands, bool IgnoreCSR); 34704eeddc0SDimitry Andric /// Perform region splitting. 348*81ad6265SDimitry Andric unsigned doRegionSplit(const LiveInterval &VirtReg, unsigned BestCand, 34904eeddc0SDimitry Andric bool HasCompact, SmallVectorImpl<Register> &NewVRegs); 35004eeddc0SDimitry Andric /// Check other options before using a callee-saved register for the first 35104eeddc0SDimitry Andric /// time. 352*81ad6265SDimitry Andric MCRegister tryAssignCSRFirstTime(const LiveInterval &VirtReg, 35304eeddc0SDimitry Andric AllocationOrder &Order, MCRegister PhysReg, 35404eeddc0SDimitry Andric uint8_t &CostPerUseLimit, 35504eeddc0SDimitry Andric SmallVectorImpl<Register> &NewVRegs); 35604eeddc0SDimitry Andric void initializeCSRCost(); 357*81ad6265SDimitry Andric unsigned tryBlockSplit(const LiveInterval &, AllocationOrder &, 35804eeddc0SDimitry Andric SmallVectorImpl<Register> &); 359*81ad6265SDimitry Andric unsigned tryInstructionSplit(const LiveInterval &, AllocationOrder &, 36004eeddc0SDimitry Andric SmallVectorImpl<Register> &); 361*81ad6265SDimitry Andric unsigned tryLocalSplit(const LiveInterval &, AllocationOrder &, 36204eeddc0SDimitry Andric SmallVectorImpl<Register> &); 363*81ad6265SDimitry Andric unsigned trySplit(const LiveInterval &, AllocationOrder &, 36404eeddc0SDimitry Andric SmallVectorImpl<Register> &, const SmallVirtRegSet &); 365*81ad6265SDimitry Andric unsigned tryLastChanceRecoloring(const LiveInterval &, AllocationOrder &, 36604eeddc0SDimitry Andric SmallVectorImpl<Register> &, 367*81ad6265SDimitry Andric SmallVirtRegSet &, RecoloringStack &, 368*81ad6265SDimitry Andric unsigned); 36904eeddc0SDimitry Andric bool tryRecoloringCandidates(PQueue &, SmallVectorImpl<Register> &, 370*81ad6265SDimitry Andric SmallVirtRegSet &, RecoloringStack &, unsigned); 371*81ad6265SDimitry Andric void tryHintRecoloring(const LiveInterval &); 37204eeddc0SDimitry Andric void tryHintsRecoloring(); 37304eeddc0SDimitry Andric 37404eeddc0SDimitry Andric /// Model the information carried by one end of a copy. 37504eeddc0SDimitry Andric struct HintInfo { 37604eeddc0SDimitry Andric /// The frequency of the copy. 37704eeddc0SDimitry Andric BlockFrequency Freq; 37804eeddc0SDimitry Andric /// The virtual register or physical register. 37904eeddc0SDimitry Andric Register Reg; 38004eeddc0SDimitry Andric /// Its currently assigned register. 38104eeddc0SDimitry Andric /// In case of a physical register Reg == PhysReg. 38204eeddc0SDimitry Andric MCRegister PhysReg; 38304eeddc0SDimitry Andric 38404eeddc0SDimitry Andric HintInfo(BlockFrequency Freq, Register Reg, MCRegister PhysReg) 38504eeddc0SDimitry Andric : Freq(Freq), Reg(Reg), PhysReg(PhysReg) {} 38604eeddc0SDimitry Andric }; 38704eeddc0SDimitry Andric using HintsInfo = SmallVector<HintInfo, 4>; 38804eeddc0SDimitry Andric 38904eeddc0SDimitry Andric BlockFrequency getBrokenHintFreq(const HintsInfo &, MCRegister); 39004eeddc0SDimitry Andric void collectHintInfo(Register, HintsInfo &); 39104eeddc0SDimitry Andric 39204eeddc0SDimitry Andric /// Greedy RA statistic to remark. 39304eeddc0SDimitry Andric struct RAGreedyStats { 39404eeddc0SDimitry Andric unsigned Reloads = 0; 39504eeddc0SDimitry Andric unsigned FoldedReloads = 0; 39604eeddc0SDimitry Andric unsigned ZeroCostFoldedReloads = 0; 39704eeddc0SDimitry Andric unsigned Spills = 0; 39804eeddc0SDimitry Andric unsigned FoldedSpills = 0; 39904eeddc0SDimitry Andric unsigned Copies = 0; 40004eeddc0SDimitry Andric float ReloadsCost = 0.0f; 40104eeddc0SDimitry Andric float FoldedReloadsCost = 0.0f; 40204eeddc0SDimitry Andric float SpillsCost = 0.0f; 40304eeddc0SDimitry Andric float FoldedSpillsCost = 0.0f; 40404eeddc0SDimitry Andric float CopiesCost = 0.0f; 40504eeddc0SDimitry Andric 40604eeddc0SDimitry Andric bool isEmpty() { 40704eeddc0SDimitry Andric return !(Reloads || FoldedReloads || Spills || FoldedSpills || 40804eeddc0SDimitry Andric ZeroCostFoldedReloads || Copies); 40904eeddc0SDimitry Andric } 41004eeddc0SDimitry Andric 41104eeddc0SDimitry Andric void add(RAGreedyStats other) { 41204eeddc0SDimitry Andric Reloads += other.Reloads; 41304eeddc0SDimitry Andric FoldedReloads += other.FoldedReloads; 41404eeddc0SDimitry Andric ZeroCostFoldedReloads += other.ZeroCostFoldedReloads; 41504eeddc0SDimitry Andric Spills += other.Spills; 41604eeddc0SDimitry Andric FoldedSpills += other.FoldedSpills; 41704eeddc0SDimitry Andric Copies += other.Copies; 41804eeddc0SDimitry Andric ReloadsCost += other.ReloadsCost; 41904eeddc0SDimitry Andric FoldedReloadsCost += other.FoldedReloadsCost; 42004eeddc0SDimitry Andric SpillsCost += other.SpillsCost; 42104eeddc0SDimitry Andric FoldedSpillsCost += other.FoldedSpillsCost; 42204eeddc0SDimitry Andric CopiesCost += other.CopiesCost; 42304eeddc0SDimitry Andric } 42404eeddc0SDimitry Andric 42504eeddc0SDimitry Andric void report(MachineOptimizationRemarkMissed &R); 42604eeddc0SDimitry Andric }; 42704eeddc0SDimitry Andric 42804eeddc0SDimitry Andric /// Compute statistic for a basic block. 42904eeddc0SDimitry Andric RAGreedyStats computeStats(MachineBasicBlock &MBB); 43004eeddc0SDimitry Andric 43104eeddc0SDimitry Andric /// Compute and report statistic through a remark. 43204eeddc0SDimitry Andric RAGreedyStats reportStats(MachineLoop *L); 43304eeddc0SDimitry Andric 43404eeddc0SDimitry Andric /// Report the statistic for each loop. 43504eeddc0SDimitry Andric void reportStats(); 43604eeddc0SDimitry Andric }; 43704eeddc0SDimitry Andric } // namespace llvm 43804eeddc0SDimitry Andric #endif // #ifndef LLVM_CODEGEN_REGALLOCGREEDY_H_ 439