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