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
27using namespace llvm;
28
29static cl::opt<RegAllocEvictionAdvisorAnalysis::AdvisorMode> Mode(
30 "regalloc-enable-advisor", cl::Hidden,
31 cl::init(Val: 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
41static 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(Val: false));
46
47namespace llvm {
48cl::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(Val: 10));
55}
56
57#define DEBUG_TYPE "regalloc"
58#ifdef LLVM_HAVE_TF_AOT_REGALLOCEVICTMODEL
59#define LLVM_HAVE_TF_AOT
60#endif
61
62char RegAllocEvictionAdvisorAnalysis::ID = 0;
63INITIALIZE_PASS(RegAllocEvictionAdvisorAnalysis, "regalloc-evict",
64 "Regalloc eviction policy", false, true)
65
66namespace {
67class DefaultEvictionAdvisorAnalysis final
68 : public RegAllocEvictionAdvisorAnalysis {
69public:
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
79private:
80 std::unique_ptr<RegAllocEvictionAdvisor>
81 getAdvisor(const MachineFunction &MF, const RAGreedy &RA) override {
82 return std::make_unique<DefaultEvictionAdvisor>(args: MF, args: RA);
83 }
84 bool doInitialization(Module &M) override {
85 if (NotAsRequested)
86 M.getContext().emitError(ErrorStr: "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
94template <> 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
114StringRef 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
126RegAllocEvictionAdvisor::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 OptLevel: 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.
149bool DefaultEvictionAdvisor::shouldEvict(const LiveInterval &A, bool IsHint,
150 const LiveInterval &B,
151 bool BreaksHint) const {
152 bool CanSplit = RA.getExtraInfo().getStage(VirtReg: 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.
168bool 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.
186bool 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(LI: 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(Reg: VirtReg.reg());
203
204 EvictionCost Cost;
205 for (MCRegUnit Unit : TRI->regunits(Reg: PhysReg)) {
206 LiveIntervalUnion::Query &Q = Matrix->query(LR: VirtReg, RegUnit: Unit);
207 // If there is 10 or more interferences, chances are one is heavier.
208 const auto &Interferences = Q.interferingVRegs(MaxInterferingRegs: 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(C: 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(V: Intf->reg()))
221 return false;
222
223 // Never evict spill products. They cannot split or spill.
224 if (RA.getExtraInfo().getStage(VirtReg: *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(RC: MRI->getRegClass(Reg: VirtReg.reg())) <
236 RegClassInfo.getNumAllocatableRegs(
237 RC: MRI->getRegClass(Reg: Intf->reg())));
238 // Only evict older cascades or live ranges without a cascade.
239 unsigned IntfCascade = RA.getExtraInfo().getCascade(Reg: 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(VirtReg: Intf->reg());
252 // Update eviction cost.
253 Cost.BrokenHints += BreaksHint;
254 Cost.MaxWeight = std::max(a: Cost.MaxWeight, b: 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(A: VirtReg, IsHint, B: *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(LI: *Intf) &&
267 (!EnableLocalReassign || !canReassign(VirtReg: *Intf, FromReg: PhysReg))) {
268 return false;
269 }
270 }
271 }
272 MaxCost = Cost;
273 return true;
274}
275
276MCRegister 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, IsHint: false, MaxCost&: 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