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