1 //===- RegAllocEvictionAdvisor.cpp - eviction advisor ---------------------===// 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 // 9 // Implementation of the default eviction advisor and of the Analysis pass. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "RegAllocEvictionAdvisor.h" 14 #include "AllocationOrder.h" 15 #include "RegAllocGreedy.h" 16 #include "llvm/CodeGen/LiveRegMatrix.h" 17 #include "llvm/CodeGen/MachineFunction.h" 18 #include "llvm/CodeGen/RegisterClassInfo.h" 19 #include "llvm/CodeGen/VirtRegMap.h" 20 #include "llvm/IR/Module.h" 21 #include "llvm/InitializePasses.h" 22 #include "llvm/Pass.h" 23 #include "llvm/Support/CommandLine.h" 24 #include "llvm/Support/ErrorHandling.h" 25 #include "llvm/Target/TargetMachine.h" 26 27 using namespace llvm; 28 29 static cl::opt<RegAllocEvictionAdvisorAnalysis::AdvisorMode> Mode( 30 "regalloc-enable-advisor", cl::Hidden, 31 cl::init(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default), 32 cl::desc("Enable regalloc advisor mode"), 33 cl::values( 34 clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default, 35 "default", "Default"), 36 clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Release, 37 "release", "precompiled"), 38 clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Development, 39 "development", "for training"))); 40 41 static cl::opt<bool> EnableLocalReassignment( 42 "enable-local-reassign", cl::Hidden, 43 cl::desc("Local reassignment can yield better allocation decisions, but " 44 "may be compile time intensive"), 45 cl::init(false)); 46 47 namespace llvm { 48 cl::opt<unsigned> EvictInterferenceCutoff( 49 "regalloc-eviction-max-interference-cutoff", cl::Hidden, 50 cl::desc("Number of interferences after which we declare " 51 "an interference unevictable and bail out. This " 52 "is a compilation cost-saving consideration. To " 53 "disable, pass a very large number."), 54 cl::init(10)); 55 } 56 57 #define DEBUG_TYPE "regalloc" 58 #ifdef LLVM_HAVE_TF_AOT_REGALLOCEVICTMODEL 59 #define LLVM_HAVE_TF_AOT 60 #endif 61 62 char RegAllocEvictionAdvisorAnalysis::ID = 0; 63 INITIALIZE_PASS(RegAllocEvictionAdvisorAnalysis, "regalloc-evict", 64 "Regalloc eviction policy", false, true) 65 66 namespace { 67 class DefaultEvictionAdvisorAnalysis final 68 : public RegAllocEvictionAdvisorAnalysis { 69 public: 70 DefaultEvictionAdvisorAnalysis(bool NotAsRequested) 71 : RegAllocEvictionAdvisorAnalysis(AdvisorMode::Default), 72 NotAsRequested(NotAsRequested) {} 73 74 // support for isa<> and dyn_cast. 75 static bool classof(const RegAllocEvictionAdvisorAnalysis *R) { 76 return R->getAdvisorMode() == AdvisorMode::Default; 77 } 78 79 private: 80 std::unique_ptr<RegAllocEvictionAdvisor> 81 getAdvisor(const MachineFunction &MF, const RAGreedy &RA) override { 82 return std::make_unique<DefaultEvictionAdvisor>(MF, RA); 83 } 84 bool doInitialization(Module &M) override { 85 if (NotAsRequested) 86 M.getContext().emitError("Requested regalloc eviction advisor analysis " 87 "could not be created. Using default"); 88 return RegAllocEvictionAdvisorAnalysis::doInitialization(M); 89 } 90 const bool NotAsRequested; 91 }; 92 } // namespace 93 94 template <> Pass *llvm::callDefaultCtor<RegAllocEvictionAdvisorAnalysis>() { 95 Pass *Ret = nullptr; 96 switch (Mode) { 97 case RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default: 98 Ret = new DefaultEvictionAdvisorAnalysis(/*NotAsRequested*/ false); 99 break; 100 case RegAllocEvictionAdvisorAnalysis::AdvisorMode::Development: 101 #if defined(LLVM_HAVE_TFLITE) 102 Ret = createDevelopmentModeAdvisor(); 103 #endif 104 break; 105 case RegAllocEvictionAdvisorAnalysis::AdvisorMode::Release: 106 Ret = createReleaseModeAdvisor(); 107 break; 108 } 109 if (Ret) 110 return Ret; 111 return new DefaultEvictionAdvisorAnalysis(/*NotAsRequested*/ true); 112 } 113 114 StringRef RegAllocEvictionAdvisorAnalysis::getPassName() const { 115 switch (getAdvisorMode()) { 116 case AdvisorMode::Default: 117 return "Default Regalloc Eviction Advisor"; 118 case AdvisorMode::Release: 119 return "Release mode Regalloc Eviction Advisor"; 120 case AdvisorMode::Development: 121 return "Development mode Regalloc Eviction Advisor"; 122 } 123 llvm_unreachable("Unknown advisor kind"); 124 } 125 126 RegAllocEvictionAdvisor::RegAllocEvictionAdvisor(const MachineFunction &MF, 127 const RAGreedy &RA) 128 : MF(MF), RA(RA), Matrix(RA.getInterferenceMatrix()), 129 LIS(RA.getLiveIntervals()), VRM(RA.getVirtRegMap()), 130 MRI(&VRM->getRegInfo()), TRI(MF.getSubtarget().getRegisterInfo()), 131 RegClassInfo(RA.getRegClassInfo()), RegCosts(TRI->getRegisterCosts(MF)), 132 EnableLocalReassign(EnableLocalReassignment || 133 MF.getSubtarget().enableRALocalReassignment( 134 MF.getTarget().getOptLevel())) {} 135 136 /// shouldEvict - determine if A should evict the assigned live range B. The 137 /// eviction policy defined by this function together with the allocation order 138 /// defined by enqueue() decides which registers ultimately end up being split 139 /// and spilled. 140 /// 141 /// Cascade numbers are used to prevent infinite loops if this function is a 142 /// cyclic relation. 143 /// 144 /// @param A The live range to be assigned. 145 /// @param IsHint True when A is about to be assigned to its preferred 146 /// register. 147 /// @param B The live range to be evicted. 148 /// @param BreaksHint True when B is already assigned to its preferred register. 149 bool DefaultEvictionAdvisor::shouldEvict(const LiveInterval &A, bool IsHint, 150 const LiveInterval &B, 151 bool BreaksHint) const { 152 bool CanSplit = RA.getExtraInfo().getStage(B) < RS_Spill; 153 154 // Be fairly aggressive about following hints as long as the evictee can be 155 // split. 156 if (CanSplit && IsHint && !BreaksHint) 157 return true; 158 159 if (A.weight() > B.weight()) { 160 LLVM_DEBUG(dbgs() << "should evict: " << B << " w= " << B.weight() << '\n'); 161 return true; 162 } 163 return false; 164 } 165 166 /// canEvictHintInterference - return true if the interference for VirtReg 167 /// on the PhysReg, which is VirtReg's hint, can be evicted in favor of VirtReg. 168 bool DefaultEvictionAdvisor::canEvictHintInterference( 169 const LiveInterval &VirtReg, MCRegister PhysReg, 170 const SmallVirtRegSet &FixedRegisters) const { 171 EvictionCost MaxCost; 172 MaxCost.setBrokenHints(1); 173 return canEvictInterferenceBasedOnCost(VirtReg, PhysReg, true, MaxCost, 174 FixedRegisters); 175 } 176 177 /// canEvictInterferenceBasedOnCost - Return true if all interferences between 178 /// VirtReg and PhysReg can be evicted. 179 /// 180 /// @param VirtReg Live range that is about to be assigned. 181 /// @param PhysReg Desired register for assignment. 182 /// @param IsHint True when PhysReg is VirtReg's preferred register. 183 /// @param MaxCost Only look for cheaper candidates and update with new cost 184 /// when returning true. 185 /// @returns True when interference can be evicted cheaper than MaxCost. 186 bool DefaultEvictionAdvisor::canEvictInterferenceBasedOnCost( 187 const LiveInterval &VirtReg, MCRegister PhysReg, bool IsHint, 188 EvictionCost &MaxCost, const SmallVirtRegSet &FixedRegisters) const { 189 // It is only possible to evict virtual register interference. 190 if (Matrix->checkInterference(VirtReg, PhysReg) > LiveRegMatrix::IK_VirtReg) 191 return false; 192 193 bool IsLocal = VirtReg.empty() || LIS->intervalIsInOneMBB(VirtReg); 194 195 // Find VirtReg's cascade number. This will be unassigned if VirtReg was never 196 // involved in an eviction before. If a cascade number was assigned, deny 197 // evicting anything with the same or a newer cascade number. This prevents 198 // infinite eviction loops. 199 // 200 // This works out so a register without a cascade number is allowed to evict 201 // anything, and it can be evicted by anything. 202 unsigned Cascade = RA.getExtraInfo().getCascadeOrCurrentNext(VirtReg.reg()); 203 204 EvictionCost Cost; 205 for (MCRegUnit Unit : TRI->regunits(PhysReg)) { 206 LiveIntervalUnion::Query &Q = Matrix->query(VirtReg, Unit); 207 // If there is 10 or more interferences, chances are one is heavier. 208 const auto &Interferences = Q.interferingVRegs(EvictInterferenceCutoff); 209 if (Interferences.size() >= EvictInterferenceCutoff) 210 return false; 211 212 // Check if any interfering live range is heavier than MaxWeight. 213 for (const LiveInterval *Intf : reverse(Interferences)) { 214 assert(Intf->reg().isVirtual() && 215 "Only expecting virtual register interference from query"); 216 217 // Do not allow eviction of a virtual register if we are in the middle 218 // of last-chance recoloring and this virtual register is one that we 219 // have scavenged a physical register for. 220 if (FixedRegisters.count(Intf->reg())) 221 return false; 222 223 // Never evict spill products. They cannot split or spill. 224 if (RA.getExtraInfo().getStage(*Intf) == RS_Done) 225 return false; 226 // Once a live range becomes small enough, it is urgent that we find a 227 // register for it. This is indicated by an infinite spill weight. These 228 // urgent live ranges get to evict almost anything. 229 // 230 // Also allow urgent evictions of unspillable ranges from a strictly 231 // larger allocation order. 232 bool Urgent = 233 !VirtReg.isSpillable() && 234 (Intf->isSpillable() || 235 RegClassInfo.getNumAllocatableRegs(MRI->getRegClass(VirtReg.reg())) < 236 RegClassInfo.getNumAllocatableRegs( 237 MRI->getRegClass(Intf->reg()))); 238 // Only evict older cascades or live ranges without a cascade. 239 unsigned IntfCascade = RA.getExtraInfo().getCascade(Intf->reg()); 240 if (Cascade == IntfCascade) 241 return false; 242 243 if (Cascade < IntfCascade) { 244 if (!Urgent) 245 return false; 246 // We permit breaking cascades for urgent evictions. It should be the 247 // last resort, though, so make it really expensive. 248 Cost.BrokenHints += 10; 249 } 250 // Would this break a satisfied hint? 251 bool BreaksHint = VRM->hasPreferredPhys(Intf->reg()); 252 // Update eviction cost. 253 Cost.BrokenHints += BreaksHint; 254 Cost.MaxWeight = std::max(Cost.MaxWeight, Intf->weight()); 255 // Abort if this would be too expensive. 256 if (!(Cost < MaxCost)) 257 return false; 258 if (Urgent) 259 continue; 260 // Apply the eviction policy for non-urgent evictions. 261 if (!shouldEvict(VirtReg, IsHint, *Intf, BreaksHint)) 262 return false; 263 // If !MaxCost.isMax(), then we're just looking for a cheap register. 264 // Evicting another local live range in this case could lead to suboptimal 265 // coloring. 266 if (!MaxCost.isMax() && IsLocal && LIS->intervalIsInOneMBB(*Intf) && 267 (!EnableLocalReassign || !canReassign(*Intf, PhysReg))) { 268 return false; 269 } 270 } 271 } 272 MaxCost = Cost; 273 return true; 274 } 275 276 MCRegister DefaultEvictionAdvisor::tryFindEvictionCandidate( 277 const LiveInterval &VirtReg, const AllocationOrder &Order, 278 uint8_t CostPerUseLimit, const SmallVirtRegSet &FixedRegisters) const { 279 // Keep track of the cheapest interference seen so far. 280 EvictionCost BestCost; 281 BestCost.setMax(); 282 MCRegister BestPhys; 283 auto MaybeOrderLimit = getOrderLimit(VirtReg, Order, CostPerUseLimit); 284 if (!MaybeOrderLimit) 285 return MCRegister::NoRegister; 286 unsigned OrderLimit = *MaybeOrderLimit; 287 288 // When we are just looking for a reduced cost per use, don't break any 289 // hints, and only evict smaller spill weights. 290 if (CostPerUseLimit < uint8_t(~0u)) { 291 BestCost.BrokenHints = 0; 292 BestCost.MaxWeight = VirtReg.weight(); 293 } 294 295 for (auto I = Order.begin(), E = Order.getOrderLimitEnd(OrderLimit); I != E; 296 ++I) { 297 MCRegister PhysReg = *I; 298 assert(PhysReg); 299 if (!canAllocatePhysReg(CostPerUseLimit, PhysReg) || 300 !canEvictInterferenceBasedOnCost(VirtReg, PhysReg, false, BestCost, 301 FixedRegisters)) 302 continue; 303 304 // Best so far. 305 BestPhys = PhysReg; 306 307 // Stop if the hint can be used. 308 if (I.isHint()) 309 break; 310 } 311 return BestPhys; 312 } 313