LLVM 24.0.0git
RegAllocEvictionAdvisor.cpp
Go to the documentation of this file.
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//===----------------------------------------------------------------------===//
13#include "AllocationOrder.h"
14#include "RegAllocGreedy.h"
22#include "llvm/IR/Module.h"
23#include "llvm/Pass.h"
27
28using namespace llvm;
29
31 "regalloc-enable-advisor", cl::Hidden,
33 cl::desc("Enable regalloc advisor mode"),
36 "default", "Default"),
38 "release", "precompiled"),
41 "development", "for training")));
42
44 "enable-local-reassign", cl::Hidden,
45 cl::desc("Local reassignment can yield better allocation decisions, but "
46 "may be compile time intensive"));
47
48namespace llvm {
50 "regalloc-eviction-max-interference-cutoff", cl::Hidden,
51 cl::desc("Number of interferences after which we declare "
52 "an interference unevictable and bail out. This "
53 "is a compilation cost-saving consideration. To "
54 "disable, pass a very large number."),
55 cl::init(10));
56}
57
58#define DEBUG_TYPE "regalloc"
59#ifdef LLVM_HAVE_TF_AOT_REGALLOCEVICTMODEL
60#define LLVM_HAVE_TF_AOT
61#endif
62
65 "Regalloc eviction policy", false, true)
66
67namespace {
68class DefaultEvictionAdvisorProvider final
70public:
71 DefaultEvictionAdvisorProvider(bool NotAsRequested, LLVMContext &Ctx)
72 : RegAllocEvictionAdvisorProvider(AdvisorMode::Default, Ctx) {
73 if (NotAsRequested)
74 Ctx.emitError("Requested regalloc eviction advisor analysis "
75 "could not be created. Using default");
76 }
77
78 // support for isa<> and dyn_cast.
79 static bool classof(const RegAllocEvictionAdvisorProvider *R) {
80 return R->getAdvisorMode() == AdvisorMode::Default;
81 }
82
83 std::unique_ptr<RegAllocEvictionAdvisor>
84 getAdvisor(const MachineFunction &MF, const RAGreedy &RA,
86 return std::make_unique<DefaultEvictionAdvisor>(MF, RA);
87 }
88};
89
90class DefaultEvictionAdvisorAnalysisLegacy final
92public:
93 DefaultEvictionAdvisorAnalysisLegacy(bool NotAsRequested)
94 : RegAllocEvictionAdvisorAnalysisLegacy(AdvisorMode::Default),
95 NotAsRequested(NotAsRequested) {}
96
97 bool doInitialization(Module &M) override {
98 Provider.reset(
99 new DefaultEvictionAdvisorProvider(NotAsRequested, M.getContext()));
100 return false;
101 }
102
103 // support for isa<> and dyn_cast.
104 static bool classof(const RegAllocEvictionAdvisorAnalysisLegacy *R) {
105 return R->getAdvisorMode() == AdvisorMode::Default;
106 }
107
108private:
109 const bool NotAsRequested;
110};
111} // namespace
112
113AnalysisKey RegAllocEvictionAdvisorAnalysis::Key;
114
115void RegAllocEvictionAdvisorAnalysis::initializeProvider(
117 if (Provider)
118 return;
119 switch (Mode) {
121 Provider.reset(
122 new DefaultEvictionAdvisorProvider(/*NotAsRequested=*/false, Ctx));
123 return;
125 Provider.reset(createDevelopmentModeAdvisorProvider(Ctx));
126 break;
128 Provider.reset(createReleaseModeAdvisorProvider(Ctx));
129 break;
130 }
131 if (!Provider)
132 Provider.reset(
133 new DefaultEvictionAdvisorProvider(/*NotAsRequested=*/true, Ctx));
134}
135
139 // Lazy initialization of the provider.
140 initializeProvider(::Mode, MF.getFunction().getContext());
141 return Result{Provider.get()};
142}
143
144template <>
146 switch (Mode) {
148 return new DefaultEvictionAdvisorAnalysisLegacy(/*NotAsRequested=*/false);
151 // release mode advisor may not be supported
152 if (Ret)
153 return Ret;
154 return new DefaultEvictionAdvisorAnalysisLegacy(/*NotAsRequested=*/true);
155 }
157#if defined(LLVM_HAVE_TFLITE)
159#else
160 return new DefaultEvictionAdvisorAnalysisLegacy(/*NotAsRequested=*/true);
161#endif
162 }
163 llvm_unreachable("unexpected advisor mode");
164}
165
167 switch (getAdvisorMode()) {
169 return "Default Regalloc Eviction Advisor";
171 return "Release mode Regalloc Eviction Advisor";
173 return "Development mode Regalloc Eviction Advisor";
174 }
175 llvm_unreachable("Unknown advisor kind");
176}
177
179 const RAGreedy &RA)
180 : MF(MF), RA(RA), Matrix(RA.getInterferenceMatrix()),
181 LIS(RA.getLiveIntervals()), VRM(RA.getVirtRegMap()),
182 MRI(&VRM->getRegInfo()), TRI(MF.getSubtarget().getRegisterInfo()),
183 RegClassInfo(RA.getRegClassInfo()), RegCosts(TRI->getRegisterCosts(MF)),
185 EnableLocalReassignment == cl::boolOrDefault::BOU_TRUE ||
186 (EnableLocalReassignment != cl::boolOrDefault::BOU_FALSE &&
187 MF.getSubtarget().enableRALocalReassignment(
188 MF.getTarget().getOptLevel()))) {}
189
190/// isUrgentEviction - Returns true if this is an urgent eviction. Once a live
191/// range becomes small enough, it is urgent that we find a register for it.
192/// This is indicated by an infinite spill weight. These urgent live ranges
193/// get to evict almost anything.
194///
195/// Also allow urgent evictions of unspillable ranges from a strictly larger
196/// allocation order.
198 const LiveInterval &Intf) const {
199 return !VirtReg.isSpillable() &&
200 (Intf.isSpillable() ||
201 RegClassInfo.getNumAllocatableRegs(MRI->getRegClass(VirtReg.reg())) <
202 RegClassInfo.getNumAllocatableRegs(MRI->getRegClass(Intf.reg())));
203}
204
205/// shouldEvict - determine if A should evict the assigned live range B. The
206/// eviction policy defined by this function together with the allocation order
207/// defined by enqueue() decides which registers ultimately end up being split
208/// and spilled.
209///
210/// Cascade numbers are used to prevent infinite loops if this function is a
211/// cyclic relation.
212///
213/// @param A The live range to be assigned.
214/// @param IsHint True when A is about to be assigned to its preferred
215/// register.
216/// @param B The live range to be evicted.
217/// @param BreaksHint True when B is already assigned to its preferred register.
218bool DefaultEvictionAdvisor::shouldEvict(const LiveInterval &A, bool IsHint,
219 const LiveInterval &B,
220 bool BreaksHint) const {
221 bool CanSplit = RA.getExtraInfo().getStage(B) < RS_Spill;
222
223 // Be fairly aggressive about following hints as long as the evictee can be
224 // split.
225 if (CanSplit && IsHint && !BreaksHint)
226 return true;
227
228 if (A.weight() > B.weight()) {
229 LLVM_DEBUG(dbgs() << "should evict: " << B << '\n');
230 return true;
231 }
232 return false;
233}
234
235/// canEvictHintInterference - return true if the interference for VirtReg
236/// on the PhysReg, which is VirtReg's hint, can be evicted in favor of VirtReg.
237bool DefaultEvictionAdvisor::canEvictHintInterference(
238 const LiveInterval &VirtReg, MCRegister PhysReg,
239 const SmallVirtRegSet &FixedRegisters) const {
240 EvictionCost MaxCost;
241 MaxCost.setBrokenHints(MRI->getRegClass(VirtReg.reg())->getCopyCost());
242 return canEvictInterferenceBasedOnCost(VirtReg, PhysReg, true, MaxCost,
243 FixedRegisters);
244}
245
246/// canEvictInterferenceBasedOnCost - Return true if all interferences between
247/// VirtReg and PhysReg can be evicted.
248///
249/// @param VirtReg Live range that is about to be assigned.
250/// @param PhysReg Desired register for assignment.
251/// @param IsHint True when PhysReg is VirtReg's preferred register.
252/// @param MaxCost Only look for cheaper candidates and update with new cost
253/// when returning true.
254/// @returns True when interference can be evicted cheaper than MaxCost.
255bool DefaultEvictionAdvisor::canEvictInterferenceBasedOnCost(
256 const LiveInterval &VirtReg, MCRegister PhysReg, bool IsHint,
257 EvictionCost &MaxCost, const SmallVirtRegSet &FixedRegisters) const {
258 // It is only possible to evict virtual register interference.
259 if (Matrix->checkInterference(VirtReg, PhysReg) > LiveRegMatrix::IK_VirtReg)
260 return false;
261
262 bool IsLocal = VirtReg.empty() || LIS->intervalIsInOneMBB(VirtReg);
263
264 // Find VirtReg's cascade number. This will be unassigned if VirtReg was never
265 // involved in an eviction before. If a cascade number was assigned, deny
266 // evicting anything with the same or a newer cascade number. This prevents
267 // infinite eviction loops.
268 //
269 // This works out so a register without a cascade number is allowed to evict
270 // anything, and it can be evicted by anything.
271 unsigned Cascade = RA.getExtraInfo().getCascadeOrCurrentNext(VirtReg.reg());
272
273 EvictionCost Cost;
274 for (MCRegUnit Unit : TRI->regunits(PhysReg)) {
275 LiveIntervalUnion::Query &Q = Matrix->query(VirtReg, Unit);
276 // If there is 10 or more interferences, chances are one is heavier.
277 const auto &Interferences = Q.interferingVRegs(EvictInterferenceCutoff);
278 if (Interferences.size() >= EvictInterferenceCutoff)
279 return false;
280
281 // Check if any interfering live range is heavier than MaxWeight.
282 for (const LiveInterval *Intf : reverse(Interferences)) {
283 assert(Intf->reg().isVirtual() &&
284 "Only expecting virtual register interference from query");
285
286 // Do not allow eviction of a virtual register if we are in the middle
287 // of last-chance recoloring and this virtual register is one that we
288 // have scavenged a physical register for.
289 if (FixedRegisters.count(Intf->reg()))
290 return false;
291
292 // Never evict spill products. They cannot split or spill.
293 if (RA.getExtraInfo().getStage(*Intf) == RS_Done)
294 return false;
295
296 bool Urgent = isUrgentEviction(VirtReg, *Intf);
297 // Only evict older cascades or live ranges without a cascade.
298 unsigned IntfCascade = RA.getExtraInfo().getCascade(Intf->reg());
299 if (Cascade == IntfCascade)
300 return false;
301
302 if (Cascade < IntfCascade) {
303 if (!Urgent)
304 return false;
305 // We permit breaking cascades for urgent evictions. It should be the
306 // last resort, though, so make it really expensive.
307 Cost.BrokenHints += 10 * MRI->getRegClass(Intf->reg())->getCopyCost();
308 }
309 // Would this break a satisfied hint?
310 bool BreaksHint = VRM->hasPreferredPhys(Intf->reg());
311 // Update eviction cost.
312 if (BreaksHint)
313 Cost.BrokenHints += MRI->getRegClass(Intf->reg())->getCopyCost();
314
315 Cost.MaxWeight = std::max(Cost.MaxWeight, Intf->weight());
316 // Abort if this would be too expensive.
317 if (Cost >= MaxCost)
318 return false;
319 if (Urgent)
320 continue;
321 // Apply the eviction policy for non-urgent evictions.
322 if (!shouldEvict(VirtReg, IsHint, *Intf, BreaksHint))
323 return false;
324 // If !MaxCost.isMax(), then we're just looking for a cheap register.
325 // Evicting another local live range in this case could lead to suboptimal
326 // coloring.
327 if (!MaxCost.isMax() && IsLocal && LIS->intervalIsInOneMBB(*Intf) &&
328 (!EnableLocalReassign || !canReassign(*Intf, PhysReg))) {
329 return false;
330 }
331 }
332 }
333 MaxCost = Cost;
334 return true;
335}
336
337MCRegister DefaultEvictionAdvisor::tryFindEvictionCandidate(
338 const LiveInterval &VirtReg, const AllocationOrder &Order,
339 uint8_t CostPerUseLimit, const SmallVirtRegSet &FixedRegisters) const {
340 // Keep track of the cheapest interference seen so far.
341 EvictionCost BestCost;
342 BestCost.setMax();
343 MCRegister BestPhys;
344 auto MaybeOrderLimit = getOrderLimit(VirtReg, Order, CostPerUseLimit);
345 if (!MaybeOrderLimit)
347 unsigned OrderLimit = *MaybeOrderLimit;
348
349 // When we are just looking for a reduced cost per use, don't break any
350 // hints, and only evict smaller spill weights.
351 if (CostPerUseLimit < uint8_t(~0u)) {
352 BestCost.BrokenHints = 0;
353 BestCost.MaxWeight = VirtReg.weight();
354 }
355
356 for (auto I = Order.begin(), E = Order.getOrderLimitEnd(OrderLimit); I != E;
357 ++I) {
358 MCRegister PhysReg = *I;
359 assert(PhysReg);
360 if (!canAllocatePhysReg(CostPerUseLimit, PhysReg) ||
361 !canEvictInterferenceBasedOnCost(VirtReg, PhysReg, false, BestCost,
362 FixedRegisters))
363 continue;
364
365 // Best so far.
366 BestPhys = PhysReg;
367
368 // Stop if the hint can be used.
369 if (I.isHint())
370 break;
371 }
372 return BestPhys;
373}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
Module.h This file contains the declarations for the Module class.
#define I(x, y, z)
Definition MD5.cpp:57
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static cl::opt< cl::boolOrDefault > EnableLocalReassignment("enable-local-reassign", cl::Hidden, cl::desc("Local reassignment can yield better allocation decisions, but " "may be compile time intensive"))
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
SI optimize exec mask operations pre RA
#define LLVM_DEBUG(...)
Definition Debug.h:119
Iterator getOrderLimitEnd(unsigned OrderLimit) const
Iterator begin() const
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:356
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
const SmallVectorImpl< const LiveInterval * > & interferingVRegs(unsigned MaxInterferingRegs=std::numeric_limits< unsigned >::max())
LiveInterval - This class represents the liveness of a register, or stack slot.
float weight() const
Register reg() const
bool isSpillable() const
isSpillable - Can this interval be spilled?
bool empty() const
@ IK_VirtReg
Virtual register interference.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
static constexpr unsigned NoRegister
Definition MCRegister.h:60
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
Function & getFunction()
Return the LLVM function that this machine code represents.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
Pass interface - Implemented by all 'passes'.
Definition Pass.h:99
virtual bool doInitialization(Module &)
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
Definition Pass.h:128
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition Pass.cpp:86
ImmutableAnalysis abstraction for fetching the Eviction Advisor.
LLVM_ABI Result run(MachineFunction &MF, MachineFunctionAnalysisManager &MAM)
Common provider for legacy and new pass managers.
virtual std::unique_ptr< RegAllocEvictionAdvisor > getAdvisor(const MachineFunction &MF, const RAGreedy &RA, MachineBlockFrequencyInfo *MBFI, MachineLoopInfo *Loops)=0
RegAllocEvictionAdvisorProvider(AdvisorMode Mode, LLVMContext &Ctx)
const TargetRegisterInfo *const TRI
LLVM_ABI std::optional< unsigned > getOrderLimit(const LiveInterval &VirtReg, const AllocationOrder &Order, unsigned CostPerUseLimit) const
const RegisterClassInfo & RegClassInfo
RegAllocEvictionAdvisor(const RegAllocEvictionAdvisor &)=delete
LLVM_ABI bool isUrgentEviction(const LiveInterval &VirtReg, const LiveInterval &Intf) const
Returns true if this is an urgent eviction.
LLVM_ABI bool canReassign(const LiveInterval &VirtReg, MCRegister FromReg) const
const bool EnableLocalReassign
Run or not the local reassignment heuristic.
LLVM_ABI bool canAllocatePhysReg(unsigned CostPerUseLimit, MCRegister PhysReg) const
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
Definition SmallSet.h:176
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This namespace contains all of the command line option processing machinery.
Definition MCSchedule.h:35
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
InstructionCost Cost
SmallSet< Register, 16 > SmallVirtRegSet
LLVM_ABI RegAllocEvictionAdvisorAnalysisLegacy * createReleaseModeAdvisorAnalysisLegacy()
LLVM_ABI RegAllocEvictionAdvisorProvider * createDevelopmentModeAdvisorProvider(LLVMContext &Ctx)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI RegAllocEvictionAdvisorAnalysisLegacy * createDevelopmentModeAdvisorAnalysisLegacy()
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
LLVM_ABI Pass * callDefaultCtor< RegAllocEvictionAdvisorAnalysisLegacy >()
Specialization for the API used by the analysis infrastructure to create an instance of the eviction ...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
@ RS_Spill
Live range will be spilled. No more splitting will be attempted.
@ RS_Done
There is nothing more we can do to this live range.
cl::opt< unsigned > EvictInterferenceCutoff
LLVM_ABI RegAllocEvictionAdvisorProvider * createReleaseModeAdvisorProvider(LLVMContext &Ctx)
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition Analysis.h:29
Cost of evicting interference - used by default advisor, and the eviction chain heuristic in RegAlloc...
unsigned BrokenHints
Total number of broken hints.
float MaxWeight
Maximum spill weight evicted.
void setBrokenHints(unsigned NHints)