1*04eeddc0SDimitry Andric //==- RegAllocGreedy.h ------- greedy register allocator ----------*-C++-*-==// 2*04eeddc0SDimitry Andric // 3*04eeddc0SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*04eeddc0SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*04eeddc0SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*04eeddc0SDimitry Andric // 7*04eeddc0SDimitry Andric //===----------------------------------------------------------------------===// 8*04eeddc0SDimitry Andric // This file defines the RAGreedy function pass for register allocation in 9*04eeddc0SDimitry Andric // optimized builds. 10*04eeddc0SDimitry Andric //===----------------------------------------------------------------------===// 11*04eeddc0SDimitry Andric 12*04eeddc0SDimitry Andric #ifndef LLVM_CODEGEN_REGALLOCGREEDY_H_ 13*04eeddc0SDimitry Andric #define LLVM_CODEGEN_REGALLOCGREEDY_H_ 14*04eeddc0SDimitry Andric 15*04eeddc0SDimitry Andric #include "AllocationOrder.h" 16*04eeddc0SDimitry Andric #include "InterferenceCache.h" 17*04eeddc0SDimitry Andric #include "LiveDebugVariables.h" 18*04eeddc0SDimitry Andric #include "RegAllocBase.h" 19*04eeddc0SDimitry Andric #include "RegAllocEvictionAdvisor.h" 20*04eeddc0SDimitry Andric #include "SpillPlacement.h" 21*04eeddc0SDimitry Andric #include "SplitKit.h" 22*04eeddc0SDimitry Andric #include "llvm/ADT/ArrayRef.h" 23*04eeddc0SDimitry Andric #include "llvm/ADT/BitVector.h" 24*04eeddc0SDimitry Andric #include "llvm/ADT/DenseMap.h" 25*04eeddc0SDimitry Andric #include "llvm/ADT/IndexedMap.h" 26*04eeddc0SDimitry Andric #include "llvm/ADT/MapVector.h" 27*04eeddc0SDimitry Andric #include "llvm/ADT/SetVector.h" 28*04eeddc0SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 29*04eeddc0SDimitry Andric #include "llvm/ADT/SmallSet.h" 30*04eeddc0SDimitry Andric #include "llvm/ADT/SmallVector.h" 31*04eeddc0SDimitry Andric #include "llvm/ADT/StringRef.h" 32*04eeddc0SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 33*04eeddc0SDimitry Andric #include "llvm/CodeGen/CalcSpillWeights.h" 34*04eeddc0SDimitry Andric #include "llvm/CodeGen/EdgeBundles.h" 35*04eeddc0SDimitry Andric #include "llvm/CodeGen/LiveInterval.h" 36*04eeddc0SDimitry Andric #include "llvm/CodeGen/LiveIntervalUnion.h" 37*04eeddc0SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h" 38*04eeddc0SDimitry Andric #include "llvm/CodeGen/LiveRangeEdit.h" 39*04eeddc0SDimitry Andric #include "llvm/CodeGen/LiveRegMatrix.h" 40*04eeddc0SDimitry Andric #include "llvm/CodeGen/LiveStacks.h" 41*04eeddc0SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 42*04eeddc0SDimitry Andric #include "llvm/CodeGen/MachineBlockFrequencyInfo.h" 43*04eeddc0SDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 44*04eeddc0SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 45*04eeddc0SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 46*04eeddc0SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 47*04eeddc0SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h" 48*04eeddc0SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 49*04eeddc0SDimitry Andric #include "llvm/CodeGen/RegisterClassInfo.h" 50*04eeddc0SDimitry Andric #include "llvm/CodeGen/SlotIndexes.h" 51*04eeddc0SDimitry Andric #include "llvm/CodeGen/Spiller.h" 52*04eeddc0SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 53*04eeddc0SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 54*04eeddc0SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 55*04eeddc0SDimitry Andric #include "llvm/CodeGen/VirtRegMap.h" 56*04eeddc0SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h" 57*04eeddc0SDimitry Andric #include "llvm/IR/Function.h" 58*04eeddc0SDimitry Andric #include "llvm/IR/LLVMContext.h" 59*04eeddc0SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 60*04eeddc0SDimitry Andric #include "llvm/Pass.h" 61*04eeddc0SDimitry Andric #include "llvm/Support/BranchProbability.h" 62*04eeddc0SDimitry Andric #include "llvm/Target/TargetMachine.h" 63*04eeddc0SDimitry Andric #include <algorithm> 64*04eeddc0SDimitry Andric #include <cassert> 65*04eeddc0SDimitry Andric #include <cstdint> 66*04eeddc0SDimitry Andric #include <memory> 67*04eeddc0SDimitry Andric #include <queue> 68*04eeddc0SDimitry Andric #include <tuple> 69*04eeddc0SDimitry Andric #include <utility> 70*04eeddc0SDimitry Andric 71*04eeddc0SDimitry Andric namespace llvm { 72*04eeddc0SDimitry Andric class LLVM_LIBRARY_VISIBILITY RAGreedy : public MachineFunctionPass, 73*04eeddc0SDimitry Andric public RegAllocBase, 74*04eeddc0SDimitry Andric private LiveRangeEdit::Delegate { 75*04eeddc0SDimitry Andric // Interface to eviction advisers 76*04eeddc0SDimitry Andric public: 77*04eeddc0SDimitry Andric /// Track allocation stage and eviction loop prevention during allocation. 78*04eeddc0SDimitry Andric class ExtraRegInfo final { 79*04eeddc0SDimitry Andric // RegInfo - Keep additional information about each live range. 80*04eeddc0SDimitry Andric struct RegInfo { 81*04eeddc0SDimitry Andric LiveRangeStage Stage = RS_New; 82*04eeddc0SDimitry Andric 83*04eeddc0SDimitry Andric // Cascade - Eviction loop prevention. See 84*04eeddc0SDimitry Andric // canEvictInterferenceBasedOnCost(). 85*04eeddc0SDimitry Andric unsigned Cascade = 0; 86*04eeddc0SDimitry Andric 87*04eeddc0SDimitry Andric RegInfo() = default; 88*04eeddc0SDimitry Andric }; 89*04eeddc0SDimitry Andric 90*04eeddc0SDimitry Andric IndexedMap<RegInfo, VirtReg2IndexFunctor> Info; 91*04eeddc0SDimitry Andric unsigned NextCascade = 1; 92*04eeddc0SDimitry Andric 93*04eeddc0SDimitry Andric public: 94*04eeddc0SDimitry Andric ExtraRegInfo() = default; 95*04eeddc0SDimitry Andric ExtraRegInfo(const ExtraRegInfo &) = delete; 96*04eeddc0SDimitry Andric 97*04eeddc0SDimitry Andric LiveRangeStage getStage(Register Reg) const { return Info[Reg].Stage; } 98*04eeddc0SDimitry Andric 99*04eeddc0SDimitry Andric LiveRangeStage getStage(const LiveInterval &VirtReg) const { 100*04eeddc0SDimitry Andric return getStage(VirtReg.reg()); 101*04eeddc0SDimitry Andric } 102*04eeddc0SDimitry Andric 103*04eeddc0SDimitry Andric void setStage(Register Reg, LiveRangeStage Stage) { 104*04eeddc0SDimitry Andric Info.grow(Reg.id()); 105*04eeddc0SDimitry Andric Info[Reg].Stage = Stage; 106*04eeddc0SDimitry Andric } 107*04eeddc0SDimitry Andric 108*04eeddc0SDimitry Andric void setStage(const LiveInterval &VirtReg, LiveRangeStage Stage) { 109*04eeddc0SDimitry Andric setStage(VirtReg.reg(), Stage); 110*04eeddc0SDimitry Andric } 111*04eeddc0SDimitry Andric 112*04eeddc0SDimitry Andric /// Return the current stage of the register, if present, otherwise 113*04eeddc0SDimitry Andric /// initialize it and return that. 114*04eeddc0SDimitry Andric LiveRangeStage getOrInitStage(Register Reg) { 115*04eeddc0SDimitry Andric Info.grow(Reg.id()); 116*04eeddc0SDimitry Andric return getStage(Reg); 117*04eeddc0SDimitry Andric } 118*04eeddc0SDimitry Andric 119*04eeddc0SDimitry Andric unsigned getCascade(Register Reg) const { return Info[Reg].Cascade; } 120*04eeddc0SDimitry Andric 121*04eeddc0SDimitry Andric void setCascade(Register Reg, unsigned Cascade) { 122*04eeddc0SDimitry Andric Info.grow(Reg.id()); 123*04eeddc0SDimitry Andric Info[Reg].Cascade = Cascade; 124*04eeddc0SDimitry Andric } 125*04eeddc0SDimitry Andric 126*04eeddc0SDimitry Andric unsigned getOrAssignNewCascade(Register Reg) { 127*04eeddc0SDimitry Andric unsigned Cascade = getCascade(Reg); 128*04eeddc0SDimitry Andric if (!Cascade) { 129*04eeddc0SDimitry Andric Cascade = NextCascade++; 130*04eeddc0SDimitry Andric setCascade(Reg, Cascade); 131*04eeddc0SDimitry Andric } 132*04eeddc0SDimitry Andric return Cascade; 133*04eeddc0SDimitry Andric } 134*04eeddc0SDimitry Andric 135*04eeddc0SDimitry Andric unsigned getCascadeOrCurrentNext(Register Reg) const { 136*04eeddc0SDimitry Andric unsigned Cascade = getCascade(Reg); 137*04eeddc0SDimitry Andric if (!Cascade) 138*04eeddc0SDimitry Andric Cascade = NextCascade; 139*04eeddc0SDimitry Andric return Cascade; 140*04eeddc0SDimitry Andric } 141*04eeddc0SDimitry Andric 142*04eeddc0SDimitry Andric template <typename Iterator> 143*04eeddc0SDimitry Andric void setStage(Iterator Begin, Iterator End, LiveRangeStage NewStage) { 144*04eeddc0SDimitry Andric for (; Begin != End; ++Begin) { 145*04eeddc0SDimitry Andric Register Reg = *Begin; 146*04eeddc0SDimitry Andric Info.grow(Reg.id()); 147*04eeddc0SDimitry Andric if (Info[Reg].Stage == RS_New) 148*04eeddc0SDimitry Andric Info[Reg].Stage = NewStage; 149*04eeddc0SDimitry Andric } 150*04eeddc0SDimitry Andric } 151*04eeddc0SDimitry Andric void LRE_DidCloneVirtReg(Register New, Register Old); 152*04eeddc0SDimitry Andric }; 153*04eeddc0SDimitry Andric 154*04eeddc0SDimitry Andric LiveRegMatrix *getInterferenceMatrix() const { return Matrix; } 155*04eeddc0SDimitry Andric LiveIntervals *getLiveIntervals() const { return LIS; } 156*04eeddc0SDimitry Andric VirtRegMap *getVirtRegMap() const { return VRM; } 157*04eeddc0SDimitry Andric const RegisterClassInfo &getRegClassInfo() const { return RegClassInfo; } 158*04eeddc0SDimitry Andric const ExtraRegInfo &getExtraInfo() const { return *ExtraInfo; } 159*04eeddc0SDimitry Andric size_t getQueueSize() const { return Queue.size(); } 160*04eeddc0SDimitry Andric // end (interface to eviction advisers) 161*04eeddc0SDimitry Andric 162*04eeddc0SDimitry Andric private: 163*04eeddc0SDimitry Andric // Convenient shortcuts. 164*04eeddc0SDimitry Andric using PQueue = std::priority_queue<std::pair<unsigned, unsigned>>; 165*04eeddc0SDimitry Andric using SmallLISet = SmallPtrSet<LiveInterval *, 4>; 166*04eeddc0SDimitry Andric 167*04eeddc0SDimitry Andric // context 168*04eeddc0SDimitry Andric MachineFunction *MF; 169*04eeddc0SDimitry Andric 170*04eeddc0SDimitry Andric // Shortcuts to some useful interface. 171*04eeddc0SDimitry Andric const TargetInstrInfo *TII; 172*04eeddc0SDimitry Andric const TargetRegisterInfo *TRI; 173*04eeddc0SDimitry Andric RegisterClassInfo RCI; 174*04eeddc0SDimitry Andric 175*04eeddc0SDimitry Andric // analyses 176*04eeddc0SDimitry Andric SlotIndexes *Indexes; 177*04eeddc0SDimitry Andric MachineBlockFrequencyInfo *MBFI; 178*04eeddc0SDimitry Andric MachineDominatorTree *DomTree; 179*04eeddc0SDimitry Andric MachineLoopInfo *Loops; 180*04eeddc0SDimitry Andric MachineOptimizationRemarkEmitter *ORE; 181*04eeddc0SDimitry Andric EdgeBundles *Bundles; 182*04eeddc0SDimitry Andric SpillPlacement *SpillPlacer; 183*04eeddc0SDimitry Andric LiveDebugVariables *DebugVars; 184*04eeddc0SDimitry Andric AliasAnalysis *AA; 185*04eeddc0SDimitry Andric 186*04eeddc0SDimitry Andric // state 187*04eeddc0SDimitry Andric std::unique_ptr<Spiller> SpillerInstance; 188*04eeddc0SDimitry Andric PQueue Queue; 189*04eeddc0SDimitry Andric std::unique_ptr<VirtRegAuxInfo> VRAI; 190*04eeddc0SDimitry Andric Optional<ExtraRegInfo> ExtraInfo; 191*04eeddc0SDimitry Andric std::unique_ptr<RegAllocEvictionAdvisor> EvictAdvisor; 192*04eeddc0SDimitry Andric 193*04eeddc0SDimitry Andric // Enum CutOffStage to keep a track whether the register allocation failed 194*04eeddc0SDimitry Andric // because of the cutoffs encountered in last chance recoloring. 195*04eeddc0SDimitry Andric // Note: This is used as bitmask. New value should be next power of 2. 196*04eeddc0SDimitry Andric enum CutOffStage { 197*04eeddc0SDimitry Andric // No cutoffs encountered 198*04eeddc0SDimitry Andric CO_None = 0, 199*04eeddc0SDimitry Andric 200*04eeddc0SDimitry Andric // lcr-max-depth cutoff encountered 201*04eeddc0SDimitry Andric CO_Depth = 1, 202*04eeddc0SDimitry Andric 203*04eeddc0SDimitry Andric // lcr-max-interf cutoff encountered 204*04eeddc0SDimitry Andric CO_Interf = 2 205*04eeddc0SDimitry Andric }; 206*04eeddc0SDimitry Andric 207*04eeddc0SDimitry Andric uint8_t CutOffInfo; 208*04eeddc0SDimitry Andric 209*04eeddc0SDimitry Andric #ifndef NDEBUG 210*04eeddc0SDimitry Andric static const char *const StageName[]; 211*04eeddc0SDimitry Andric #endif 212*04eeddc0SDimitry Andric 213*04eeddc0SDimitry Andric /// EvictionTrack - Keeps track of past evictions in order to optimize region 214*04eeddc0SDimitry Andric /// split decision. 215*04eeddc0SDimitry Andric class EvictionTrack { 216*04eeddc0SDimitry Andric 217*04eeddc0SDimitry Andric public: 218*04eeddc0SDimitry Andric using EvictorInfo = 219*04eeddc0SDimitry Andric std::pair<Register /* evictor */, MCRegister /* physreg */>; 220*04eeddc0SDimitry Andric using EvicteeInfo = llvm::DenseMap<Register /* evictee */, EvictorInfo>; 221*04eeddc0SDimitry Andric 222*04eeddc0SDimitry Andric private: 223*04eeddc0SDimitry Andric /// Each Vreg that has been evicted in the last stage of selectOrSplit will 224*04eeddc0SDimitry Andric /// be mapped to the evictor Vreg and the PhysReg it was evicted from. 225*04eeddc0SDimitry Andric EvicteeInfo Evictees; 226*04eeddc0SDimitry Andric 227*04eeddc0SDimitry Andric public: 228*04eeddc0SDimitry Andric /// Clear all eviction information. 229*04eeddc0SDimitry Andric void clear() { Evictees.clear(); } 230*04eeddc0SDimitry Andric 231*04eeddc0SDimitry Andric /// Clear eviction information for the given evictee Vreg. 232*04eeddc0SDimitry Andric /// E.g. when Vreg get's a new allocation, the old eviction info is no 233*04eeddc0SDimitry Andric /// longer relevant. 234*04eeddc0SDimitry Andric /// \param Evictee The evictee Vreg for whom we want to clear collected 235*04eeddc0SDimitry Andric /// eviction info. 236*04eeddc0SDimitry Andric void clearEvicteeInfo(Register Evictee) { Evictees.erase(Evictee); } 237*04eeddc0SDimitry Andric 238*04eeddc0SDimitry Andric /// Track new eviction. 239*04eeddc0SDimitry Andric /// The Evictor vreg has evicted the Evictee vreg from Physreg. 240*04eeddc0SDimitry Andric /// \param PhysReg The physical register Evictee was evicted from. 241*04eeddc0SDimitry Andric /// \param Evictor The evictor Vreg that evicted Evictee. 242*04eeddc0SDimitry Andric /// \param Evictee The evictee Vreg. 243*04eeddc0SDimitry Andric void addEviction(MCRegister PhysReg, Register Evictor, Register Evictee) { 244*04eeddc0SDimitry Andric Evictees[Evictee].first = Evictor; 245*04eeddc0SDimitry Andric Evictees[Evictee].second = PhysReg; 246*04eeddc0SDimitry Andric } 247*04eeddc0SDimitry Andric 248*04eeddc0SDimitry Andric /// Return the Evictor Vreg which evicted Evictee Vreg from PhysReg. 249*04eeddc0SDimitry Andric /// \param Evictee The evictee vreg. 250*04eeddc0SDimitry Andric /// \return The Evictor vreg which evicted Evictee vreg from PhysReg. 0 if 251*04eeddc0SDimitry Andric /// nobody has evicted Evictee from PhysReg. 252*04eeddc0SDimitry Andric EvictorInfo getEvictor(Register Evictee) { 253*04eeddc0SDimitry Andric if (Evictees.count(Evictee)) { 254*04eeddc0SDimitry Andric return Evictees[Evictee]; 255*04eeddc0SDimitry Andric } 256*04eeddc0SDimitry Andric 257*04eeddc0SDimitry Andric return EvictorInfo(0, 0); 258*04eeddc0SDimitry Andric } 259*04eeddc0SDimitry Andric }; 260*04eeddc0SDimitry Andric 261*04eeddc0SDimitry Andric // Keeps track of past evictions in order to optimize region split decision. 262*04eeddc0SDimitry Andric EvictionTrack LastEvicted; 263*04eeddc0SDimitry Andric 264*04eeddc0SDimitry Andric // splitting state. 265*04eeddc0SDimitry Andric std::unique_ptr<SplitAnalysis> SA; 266*04eeddc0SDimitry Andric std::unique_ptr<SplitEditor> SE; 267*04eeddc0SDimitry Andric 268*04eeddc0SDimitry Andric /// Cached per-block interference maps 269*04eeddc0SDimitry Andric InterferenceCache IntfCache; 270*04eeddc0SDimitry Andric 271*04eeddc0SDimitry Andric /// All basic blocks where the current register has uses. 272*04eeddc0SDimitry Andric SmallVector<SpillPlacement::BlockConstraint, 8> SplitConstraints; 273*04eeddc0SDimitry Andric 274*04eeddc0SDimitry Andric /// Global live range splitting candidate info. 275*04eeddc0SDimitry Andric struct GlobalSplitCandidate { 276*04eeddc0SDimitry Andric // Register intended for assignment, or 0. 277*04eeddc0SDimitry Andric MCRegister PhysReg; 278*04eeddc0SDimitry Andric 279*04eeddc0SDimitry Andric // SplitKit interval index for this candidate. 280*04eeddc0SDimitry Andric unsigned IntvIdx; 281*04eeddc0SDimitry Andric 282*04eeddc0SDimitry Andric // Interference for PhysReg. 283*04eeddc0SDimitry Andric InterferenceCache::Cursor Intf; 284*04eeddc0SDimitry Andric 285*04eeddc0SDimitry Andric // Bundles where this candidate should be live. 286*04eeddc0SDimitry Andric BitVector LiveBundles; 287*04eeddc0SDimitry Andric SmallVector<unsigned, 8> ActiveBlocks; 288*04eeddc0SDimitry Andric 289*04eeddc0SDimitry Andric void reset(InterferenceCache &Cache, MCRegister Reg) { 290*04eeddc0SDimitry Andric PhysReg = Reg; 291*04eeddc0SDimitry Andric IntvIdx = 0; 292*04eeddc0SDimitry Andric Intf.setPhysReg(Cache, Reg); 293*04eeddc0SDimitry Andric LiveBundles.clear(); 294*04eeddc0SDimitry Andric ActiveBlocks.clear(); 295*04eeddc0SDimitry Andric } 296*04eeddc0SDimitry Andric 297*04eeddc0SDimitry Andric // Set B[I] = C for every live bundle where B[I] was NoCand. 298*04eeddc0SDimitry Andric unsigned getBundles(SmallVectorImpl<unsigned> &B, unsigned C) { 299*04eeddc0SDimitry Andric unsigned Count = 0; 300*04eeddc0SDimitry Andric for (unsigned I : LiveBundles.set_bits()) 301*04eeddc0SDimitry Andric if (B[I] == NoCand) { 302*04eeddc0SDimitry Andric B[I] = C; 303*04eeddc0SDimitry Andric Count++; 304*04eeddc0SDimitry Andric } 305*04eeddc0SDimitry Andric return Count; 306*04eeddc0SDimitry Andric } 307*04eeddc0SDimitry Andric }; 308*04eeddc0SDimitry Andric 309*04eeddc0SDimitry Andric /// Candidate info for each PhysReg in AllocationOrder. 310*04eeddc0SDimitry Andric /// This vector never shrinks, but grows to the size of the largest register 311*04eeddc0SDimitry Andric /// class. 312*04eeddc0SDimitry Andric SmallVector<GlobalSplitCandidate, 32> GlobalCand; 313*04eeddc0SDimitry Andric 314*04eeddc0SDimitry Andric enum : unsigned { NoCand = ~0u }; 315*04eeddc0SDimitry Andric 316*04eeddc0SDimitry Andric /// Candidate map. Each edge bundle is assigned to a GlobalCand entry, or to 317*04eeddc0SDimitry Andric /// NoCand which indicates the stack interval. 318*04eeddc0SDimitry Andric SmallVector<unsigned, 32> BundleCand; 319*04eeddc0SDimitry Andric 320*04eeddc0SDimitry Andric /// Callee-save register cost, calculated once per machine function. 321*04eeddc0SDimitry Andric BlockFrequency CSRCost; 322*04eeddc0SDimitry Andric 323*04eeddc0SDimitry Andric /// Enable or not the consideration of the cost of local intervals created 324*04eeddc0SDimitry Andric /// by a split candidate when choosing the best split candidate. 325*04eeddc0SDimitry Andric bool EnableAdvancedRASplitCost; 326*04eeddc0SDimitry Andric 327*04eeddc0SDimitry Andric /// Set of broken hints that may be reconciled later because of eviction. 328*04eeddc0SDimitry Andric SmallSetVector<LiveInterval *, 8> SetOfBrokenHints; 329*04eeddc0SDimitry Andric 330*04eeddc0SDimitry Andric /// The register cost values. This list will be recreated for each Machine 331*04eeddc0SDimitry Andric /// Function 332*04eeddc0SDimitry Andric ArrayRef<uint8_t> RegCosts; 333*04eeddc0SDimitry Andric 334*04eeddc0SDimitry Andric public: 335*04eeddc0SDimitry Andric RAGreedy(const RegClassFilterFunc F = allocateAllRegClasses); 336*04eeddc0SDimitry Andric 337*04eeddc0SDimitry Andric /// Return the pass name. 338*04eeddc0SDimitry Andric StringRef getPassName() const override { return "Greedy Register Allocator"; } 339*04eeddc0SDimitry Andric 340*04eeddc0SDimitry Andric /// RAGreedy analysis usage. 341*04eeddc0SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 342*04eeddc0SDimitry Andric void releaseMemory() override; 343*04eeddc0SDimitry Andric Spiller &spiller() override { return *SpillerInstance; } 344*04eeddc0SDimitry Andric void enqueueImpl(LiveInterval *LI) override; 345*04eeddc0SDimitry Andric LiveInterval *dequeue() override; 346*04eeddc0SDimitry Andric MCRegister selectOrSplit(LiveInterval &, 347*04eeddc0SDimitry Andric SmallVectorImpl<Register> &) override; 348*04eeddc0SDimitry Andric void aboutToRemoveInterval(LiveInterval &) override; 349*04eeddc0SDimitry Andric 350*04eeddc0SDimitry Andric /// Perform register allocation. 351*04eeddc0SDimitry Andric bool runOnMachineFunction(MachineFunction &mf) override; 352*04eeddc0SDimitry Andric 353*04eeddc0SDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 354*04eeddc0SDimitry Andric return MachineFunctionProperties().set( 355*04eeddc0SDimitry Andric MachineFunctionProperties::Property::NoPHIs); 356*04eeddc0SDimitry Andric } 357*04eeddc0SDimitry Andric 358*04eeddc0SDimitry Andric MachineFunctionProperties getClearedProperties() const override { 359*04eeddc0SDimitry Andric return MachineFunctionProperties().set( 360*04eeddc0SDimitry Andric MachineFunctionProperties::Property::IsSSA); 361*04eeddc0SDimitry Andric } 362*04eeddc0SDimitry Andric 363*04eeddc0SDimitry Andric static char ID; 364*04eeddc0SDimitry Andric 365*04eeddc0SDimitry Andric private: 366*04eeddc0SDimitry Andric MCRegister selectOrSplitImpl(LiveInterval &, SmallVectorImpl<Register> &, 367*04eeddc0SDimitry Andric SmallVirtRegSet &, unsigned = 0); 368*04eeddc0SDimitry Andric 369*04eeddc0SDimitry Andric bool LRE_CanEraseVirtReg(Register) override; 370*04eeddc0SDimitry Andric void LRE_WillShrinkVirtReg(Register) override; 371*04eeddc0SDimitry Andric void LRE_DidCloneVirtReg(Register, Register) override; 372*04eeddc0SDimitry Andric void enqueue(PQueue &CurQueue, LiveInterval *LI); 373*04eeddc0SDimitry Andric LiveInterval *dequeue(PQueue &CurQueue); 374*04eeddc0SDimitry Andric 375*04eeddc0SDimitry Andric BlockFrequency calcSpillCost(); 376*04eeddc0SDimitry Andric bool addSplitConstraints(InterferenceCache::Cursor, BlockFrequency &); 377*04eeddc0SDimitry Andric bool addThroughConstraints(InterferenceCache::Cursor, ArrayRef<unsigned>); 378*04eeddc0SDimitry Andric bool growRegion(GlobalSplitCandidate &Cand); 379*04eeddc0SDimitry Andric bool splitCanCauseEvictionChain(Register Evictee, GlobalSplitCandidate &Cand, 380*04eeddc0SDimitry Andric unsigned BBNumber, 381*04eeddc0SDimitry Andric const AllocationOrder &Order); 382*04eeddc0SDimitry Andric bool splitCanCauseLocalSpill(unsigned VirtRegToSplit, 383*04eeddc0SDimitry Andric GlobalSplitCandidate &Cand, unsigned BBNumber, 384*04eeddc0SDimitry Andric const AllocationOrder &Order); 385*04eeddc0SDimitry Andric BlockFrequency calcGlobalSplitCost(GlobalSplitCandidate &, 386*04eeddc0SDimitry Andric const AllocationOrder &Order, 387*04eeddc0SDimitry Andric bool *CanCauseEvictionChain); 388*04eeddc0SDimitry Andric bool calcCompactRegion(GlobalSplitCandidate &); 389*04eeddc0SDimitry Andric void splitAroundRegion(LiveRangeEdit &, ArrayRef<unsigned>); 390*04eeddc0SDimitry Andric void calcGapWeights(MCRegister, SmallVectorImpl<float> &); 391*04eeddc0SDimitry Andric bool canEvictInterferenceInRange(const LiveInterval &VirtReg, 392*04eeddc0SDimitry Andric MCRegister PhysReg, SlotIndex Start, 393*04eeddc0SDimitry Andric SlotIndex End, EvictionCost &MaxCost) const; 394*04eeddc0SDimitry Andric MCRegister getCheapestEvicteeWeight(const AllocationOrder &Order, 395*04eeddc0SDimitry Andric const LiveInterval &VirtReg, 396*04eeddc0SDimitry Andric SlotIndex Start, SlotIndex End, 397*04eeddc0SDimitry Andric float *BestEvictWeight) const; 398*04eeddc0SDimitry Andric void evictInterference(LiveInterval &, MCRegister, 399*04eeddc0SDimitry Andric SmallVectorImpl<Register> &); 400*04eeddc0SDimitry Andric bool mayRecolorAllInterferences(MCRegister PhysReg, LiveInterval &VirtReg, 401*04eeddc0SDimitry Andric SmallLISet &RecoloringCandidates, 402*04eeddc0SDimitry Andric const SmallVirtRegSet &FixedRegisters); 403*04eeddc0SDimitry Andric 404*04eeddc0SDimitry Andric MCRegister tryAssign(LiveInterval &, AllocationOrder &, 405*04eeddc0SDimitry Andric SmallVectorImpl<Register> &, const SmallVirtRegSet &); 406*04eeddc0SDimitry Andric MCRegister tryEvict(LiveInterval &, AllocationOrder &, 407*04eeddc0SDimitry Andric SmallVectorImpl<Register> &, uint8_t, 408*04eeddc0SDimitry Andric const SmallVirtRegSet &); 409*04eeddc0SDimitry Andric MCRegister tryRegionSplit(LiveInterval &, AllocationOrder &, 410*04eeddc0SDimitry Andric SmallVectorImpl<Register> &); 411*04eeddc0SDimitry Andric /// Calculate cost of region splitting. 412*04eeddc0SDimitry Andric unsigned calculateRegionSplitCost(LiveInterval &VirtReg, 413*04eeddc0SDimitry Andric AllocationOrder &Order, 414*04eeddc0SDimitry Andric BlockFrequency &BestCost, 415*04eeddc0SDimitry Andric unsigned &NumCands, bool IgnoreCSR, 416*04eeddc0SDimitry Andric bool *CanCauseEvictionChain = nullptr); 417*04eeddc0SDimitry Andric /// Perform region splitting. 418*04eeddc0SDimitry Andric unsigned doRegionSplit(LiveInterval &VirtReg, unsigned BestCand, 419*04eeddc0SDimitry Andric bool HasCompact, SmallVectorImpl<Register> &NewVRegs); 420*04eeddc0SDimitry Andric /// Check other options before using a callee-saved register for the first 421*04eeddc0SDimitry Andric /// time. 422*04eeddc0SDimitry Andric MCRegister tryAssignCSRFirstTime(LiveInterval &VirtReg, 423*04eeddc0SDimitry Andric AllocationOrder &Order, MCRegister PhysReg, 424*04eeddc0SDimitry Andric uint8_t &CostPerUseLimit, 425*04eeddc0SDimitry Andric SmallVectorImpl<Register> &NewVRegs); 426*04eeddc0SDimitry Andric void initializeCSRCost(); 427*04eeddc0SDimitry Andric unsigned tryBlockSplit(LiveInterval &, AllocationOrder &, 428*04eeddc0SDimitry Andric SmallVectorImpl<Register> &); 429*04eeddc0SDimitry Andric unsigned tryInstructionSplit(LiveInterval &, AllocationOrder &, 430*04eeddc0SDimitry Andric SmallVectorImpl<Register> &); 431*04eeddc0SDimitry Andric unsigned tryLocalSplit(LiveInterval &, AllocationOrder &, 432*04eeddc0SDimitry Andric SmallVectorImpl<Register> &); 433*04eeddc0SDimitry Andric unsigned trySplit(LiveInterval &, AllocationOrder &, 434*04eeddc0SDimitry Andric SmallVectorImpl<Register> &, const SmallVirtRegSet &); 435*04eeddc0SDimitry Andric unsigned tryLastChanceRecoloring(LiveInterval &, AllocationOrder &, 436*04eeddc0SDimitry Andric SmallVectorImpl<Register> &, 437*04eeddc0SDimitry Andric SmallVirtRegSet &, unsigned); 438*04eeddc0SDimitry Andric bool tryRecoloringCandidates(PQueue &, SmallVectorImpl<Register> &, 439*04eeddc0SDimitry Andric SmallVirtRegSet &, unsigned); 440*04eeddc0SDimitry Andric void tryHintRecoloring(LiveInterval &); 441*04eeddc0SDimitry Andric void tryHintsRecoloring(); 442*04eeddc0SDimitry Andric 443*04eeddc0SDimitry Andric /// Model the information carried by one end of a copy. 444*04eeddc0SDimitry Andric struct HintInfo { 445*04eeddc0SDimitry Andric /// The frequency of the copy. 446*04eeddc0SDimitry Andric BlockFrequency Freq; 447*04eeddc0SDimitry Andric /// The virtual register or physical register. 448*04eeddc0SDimitry Andric Register Reg; 449*04eeddc0SDimitry Andric /// Its currently assigned register. 450*04eeddc0SDimitry Andric /// In case of a physical register Reg == PhysReg. 451*04eeddc0SDimitry Andric MCRegister PhysReg; 452*04eeddc0SDimitry Andric 453*04eeddc0SDimitry Andric HintInfo(BlockFrequency Freq, Register Reg, MCRegister PhysReg) 454*04eeddc0SDimitry Andric : Freq(Freq), Reg(Reg), PhysReg(PhysReg) {} 455*04eeddc0SDimitry Andric }; 456*04eeddc0SDimitry Andric using HintsInfo = SmallVector<HintInfo, 4>; 457*04eeddc0SDimitry Andric 458*04eeddc0SDimitry Andric BlockFrequency getBrokenHintFreq(const HintsInfo &, MCRegister); 459*04eeddc0SDimitry Andric void collectHintInfo(Register, HintsInfo &); 460*04eeddc0SDimitry Andric 461*04eeddc0SDimitry Andric /// Greedy RA statistic to remark. 462*04eeddc0SDimitry Andric struct RAGreedyStats { 463*04eeddc0SDimitry Andric unsigned Reloads = 0; 464*04eeddc0SDimitry Andric unsigned FoldedReloads = 0; 465*04eeddc0SDimitry Andric unsigned ZeroCostFoldedReloads = 0; 466*04eeddc0SDimitry Andric unsigned Spills = 0; 467*04eeddc0SDimitry Andric unsigned FoldedSpills = 0; 468*04eeddc0SDimitry Andric unsigned Copies = 0; 469*04eeddc0SDimitry Andric float ReloadsCost = 0.0f; 470*04eeddc0SDimitry Andric float FoldedReloadsCost = 0.0f; 471*04eeddc0SDimitry Andric float SpillsCost = 0.0f; 472*04eeddc0SDimitry Andric float FoldedSpillsCost = 0.0f; 473*04eeddc0SDimitry Andric float CopiesCost = 0.0f; 474*04eeddc0SDimitry Andric 475*04eeddc0SDimitry Andric bool isEmpty() { 476*04eeddc0SDimitry Andric return !(Reloads || FoldedReloads || Spills || FoldedSpills || 477*04eeddc0SDimitry Andric ZeroCostFoldedReloads || Copies); 478*04eeddc0SDimitry Andric } 479*04eeddc0SDimitry Andric 480*04eeddc0SDimitry Andric void add(RAGreedyStats other) { 481*04eeddc0SDimitry Andric Reloads += other.Reloads; 482*04eeddc0SDimitry Andric FoldedReloads += other.FoldedReloads; 483*04eeddc0SDimitry Andric ZeroCostFoldedReloads += other.ZeroCostFoldedReloads; 484*04eeddc0SDimitry Andric Spills += other.Spills; 485*04eeddc0SDimitry Andric FoldedSpills += other.FoldedSpills; 486*04eeddc0SDimitry Andric Copies += other.Copies; 487*04eeddc0SDimitry Andric ReloadsCost += other.ReloadsCost; 488*04eeddc0SDimitry Andric FoldedReloadsCost += other.FoldedReloadsCost; 489*04eeddc0SDimitry Andric SpillsCost += other.SpillsCost; 490*04eeddc0SDimitry Andric FoldedSpillsCost += other.FoldedSpillsCost; 491*04eeddc0SDimitry Andric CopiesCost += other.CopiesCost; 492*04eeddc0SDimitry Andric } 493*04eeddc0SDimitry Andric 494*04eeddc0SDimitry Andric void report(MachineOptimizationRemarkMissed &R); 495*04eeddc0SDimitry Andric }; 496*04eeddc0SDimitry Andric 497*04eeddc0SDimitry Andric /// Compute statistic for a basic block. 498*04eeddc0SDimitry Andric RAGreedyStats computeStats(MachineBasicBlock &MBB); 499*04eeddc0SDimitry Andric 500*04eeddc0SDimitry Andric /// Compute and report statistic through a remark. 501*04eeddc0SDimitry Andric RAGreedyStats reportStats(MachineLoop *L); 502*04eeddc0SDimitry Andric 503*04eeddc0SDimitry Andric /// Report the statistic for each loop. 504*04eeddc0SDimitry Andric void reportStats(); 505*04eeddc0SDimitry Andric }; 506*04eeddc0SDimitry Andric } // namespace llvm 507*04eeddc0SDimitry Andric #endif // #ifndef LLVM_CODEGEN_REGALLOCGREEDY_H_ 508