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