LLVM 23.0.0git
RegAllocEvictionAdvisor.h
Go to the documentation of this file.
1//===- RegAllocEvictionAdvisor.h - Interference resolution ------*- 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
9#ifndef LLVM_CODEGEN_REGALLOCEVICTIONADVISOR_H
10#define LLVM_CODEGEN_REGALLOCEVICTIONADVISOR_H
11
12#include "llvm/ADT/Any.h"
13#include "llvm/ADT/ArrayRef.h"
14#include "llvm/ADT/SmallSet.h"
15#include "llvm/ADT/StringRef.h"
19#include "llvm/Config/llvm-config.h"
20#include "llvm/IR/PassManager.h"
21#include "llvm/MC/MCRegister.h"
22#include "llvm/Pass.h"
24
25namespace llvm {
26class AllocationOrder;
27class LiveInterval;
28class LiveIntervals;
29class LiveRegMatrix;
30class MachineFunction;
34class VirtRegMap;
35
37
38// Live ranges pass through a number of stages as we try to allocate them.
39// Some of the stages may also create new live ranges:
40//
41// - Region splitting.
42// - Per-block splitting.
43// - Local splitting.
44// - Spilling.
45//
46// Ranges produced by one of the stages skip the previous stages when they are
47// dequeued. This improves performance because we can skip interference checks
48// that are unlikely to give any results. It also guarantees that the live
49// range splitting algorithm terminates, something that is otherwise hard to
50// ensure.
52 /// Newly created live range that has never been queued.
54
55 /// Only attempt assignment and eviction. Then requeue as RS_Split.
57
58 /// Attempt live range splitting if assignment is impossible.
60
61 /// Attempt more aggressive live range splitting that is guaranteed to make
62 /// progress. This is used for split products that may not be making
63 /// progress.
65
66 /// Live range will be spilled. No more splitting will be attempted.
68
69 /// There is nothing more we can do to this live range. Abort compilation
70 /// if it can't be assigned.
72};
73
74/// Cost of evicting interference - used by default advisor, and the eviction
75/// chain heuristic in RegAllocGreedy.
76// FIXME: this can be probably made an implementation detail of the default
77// advisor, if the eviction chain logic can be refactored.
79 unsigned BrokenHints = 0; ///< Total number of broken hints.
80 float MaxWeight = 0; ///< Maximum spill weight evicted.
81
82 EvictionCost() = default;
83
84 bool isMax() const { return BrokenHints == ~0u; }
85
86 void setMax() { BrokenHints = ~0u; }
87
88 void setBrokenHints(unsigned NHints) { BrokenHints = NHints; }
89
90 bool operator<(const EvictionCost &O) const {
91 return std::tie(BrokenHints, MaxWeight) <
92 std::tie(O.BrokenHints, O.MaxWeight);
93 }
94
95 bool operator>=(const EvictionCost &O) const { return !(*this < O); }
96};
97
98/// Interface to the eviction advisor, which is responsible for making a
99/// decision as to which live ranges should be evicted (if any).
100class RAGreedy;
102public:
105 virtual ~RegAllocEvictionAdvisor() = default;
106
107 /// Find a physical register that can be freed by evicting the FixedRegisters,
108 /// or return NoRegister. The eviction decision is assumed to be correct (i.e.
109 /// no fixed live ranges are evicted) and profitable.
111 const LiveInterval &VirtReg, const AllocationOrder &Order,
112 uint8_t CostPerUseLimit, const SmallVirtRegSet &FixedRegisters) const = 0;
113
114 /// Find out if we can evict the live ranges occupying the given PhysReg,
115 /// which is a hint (preferred register) for VirtReg.
116 virtual bool
118 const SmallVirtRegSet &FixedRegisters) const = 0;
119
120 /// Returns true if the given \p PhysReg is a callee saved register and has
121 /// not been used for allocation yet.
122 LLVM_ABI bool isUnusedCalleeSavedReg(MCRegister PhysReg) const;
123
124 /// Returns true if this is an urgent eviction.
125 bool isUrgentEviction(const LiveInterval &VirtReg,
126 const LiveInterval &Intf) const;
127
128protected:
130 const RAGreedy &RA);
131
132 LLVM_ABI bool canReassign(const LiveInterval &VirtReg,
133 MCRegister FromReg) const;
134
135 // Get the upper limit of elements in the given Order we need to analize.
136 // TODO: is this heuristic, we could consider learning it.
137 LLVM_ABI std::optional<unsigned>
138 getOrderLimit(const LiveInterval &VirtReg, const AllocationOrder &Order,
139 unsigned CostPerUseLimit) const;
140
141 // Determine if it's worth trying to allocate this reg, given the
142 // CostPerUseLimit
143 // TODO: this is a heuristic component we could consider learning, too.
144 LLVM_ABI bool canAllocatePhysReg(unsigned CostPerUseLimit,
145 MCRegister PhysReg) const;
146
148 const RAGreedy &RA;
156
157 /// Run or not the local reassignment heuristic. This information is
158 /// obtained from the TargetSubtargetInfo.
160};
161
162/// Common provider for legacy and new pass managers.
163/// This keeps the state for logging, and sets up and holds the provider.
164/// The legacy pass itself used to keep the logging state and provider,
165/// so this extraction helps the NPM analysis to reuse the logic.
166/// TODO: Coalesce this with the NPM analysis when legacy PM is removed.
168public:
169 enum class AdvisorMode : int { Default, Release, Development };
172
174
175 virtual void logRewardIfNeeded(const MachineFunction &MF,
176 llvm::function_ref<float()> GetReward) {}
177
178 virtual std::unique_ptr<RegAllocEvictionAdvisor>
181
182 AdvisorMode getAdvisorMode() const { return Mode; }
183
184protected:
186
187private:
188 const AdvisorMode Mode;
189};
190
191/// ImmutableAnalysis abstraction for fetching the Eviction Advisor. We model it
192/// as an analysis to decouple the user from the implementation insofar as
193/// dependencies on other analyses goes. The motivation for it being an
194/// immutable pass is twofold:
195/// - in the ML implementation case, the evaluator is stateless but (especially
196/// in the development mode) expensive to set up. With an immutable pass, we set
197/// it up once.
198/// - in the 'development' mode ML case, we want to capture the training log
199/// during allocation (this is a log of features encountered and decisions
200/// made), and then measure a score, potentially a few steps after allocation
201/// completes. So we need the properties of an immutable pass to keep the logger
202/// state around until we can make that measurement.
203///
204/// Because we need to offer additional services in 'development' mode, the
205/// implementations of this analysis need to implement RTTI support.
207public:
208 enum class AdvisorMode : int { Default, Release, Development };
209
212 static char ID;
213
214 /// Get an advisor for the given context (i.e. machine function, etc)
216
217 AdvisorMode getAdvisorMode() const { return Mode; }
218 virtual void logRewardIfNeeded(const MachineFunction &MF,
219 function_ref<float()> GetReward) {};
220
221protected:
222 // This analysis preserves everything, and subclasses may have additional
223 // requirements.
224 void getAnalysisUsage(AnalysisUsage &AU) const override {
225 AU.setPreservesAll();
226 }
227 std::unique_ptr<RegAllocEvictionAdvisorProvider> Provider;
228
229private:
230 StringRef getPassName() const override;
231 const AdvisorMode Mode;
232};
233
234/// A MachineFunction analysis for fetching the Eviction Advisor.
235/// This sets up the Provider lazily and caches it.
236/// - in the ML implementation case, the evaluator is stateless but (especially
237/// in the development mode) expensive to set up. With a Module Analysis, we
238/// `require` it and set it up once.
239/// - in the 'development' mode ML case, we want to capture the training log
240/// during allocation (this is a log of features encountered and decisions
241/// made), and then measure a score, potentially a few steps after allocation
242/// completes. So we need a Module analysis to keep the logger state around
243/// until we can make that measurement.
245 : public AnalysisInfoMixin<RegAllocEvictionAdvisorAnalysis> {
246 static AnalysisKey Key;
248
249public:
250 struct Result {
251 // owned by this analysis
253
255 MachineFunctionAnalysisManager::Invalidator &Inv) {
256 // Provider is stateless and constructed only once. Do not get
257 // invalidated.
258 return false;
259 }
260 };
261
263
264private:
265 void
267 LLVMContext &Ctx);
268
269 std::unique_ptr<RegAllocEvictionAdvisorProvider> Provider;
270};
271
272/// Specialization for the API used by the analysis infrastructure to create
273/// an instance of the eviction advisor.
274template <>
276
277LLVM_ABI RegAllocEvictionAdvisorAnalysisLegacy *
279
280LLVM_ABI RegAllocEvictionAdvisorAnalysisLegacy *
282
285
288
289// TODO: move to RegAllocEvictionAdvisor.cpp when we move implementation
290// out of RegAllocGreedy.cpp
292public:
295
296private:
297 MCRegister tryFindEvictionCandidate(const LiveInterval &,
298 const AllocationOrder &, uint8_t,
299 const SmallVirtRegSet &) const override;
300 bool canEvictHintInterference(const LiveInterval &, MCRegister,
301 const SmallVirtRegSet &) const override;
302 bool canEvictInterferenceBasedOnCost(const LiveInterval &, MCRegister, bool,
303 EvictionCost &,
304 const SmallVirtRegSet &) const;
305 bool shouldEvict(const LiveInterval &A, bool, const LiveInterval &B,
306 bool) const;
307};
308} // namespace llvm
309
310#endif // LLVM_CODEGEN_REGALLOCEVICTIONADVISOR_H
This file provides Any, a non-template class modeled in the spirit of std::any.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_ATTRIBUTE_RETURNS_NONNULL
Definition Compiler.h:373
Hexagon Hardware Loops
This header defines various interfaces for pass management in LLVM.
print mir2vec MIR2Vec Vocabulary Printer Pass
Definition MIR2Vec.cpp:598
ModuleAnalysisManager MAM
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
This file defines the SmallSet class.
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
DefaultEvictionAdvisor(const MachineFunction &MF, const RAGreedy &RA)
ImmutablePass(char &pid)
Definition Pass.h:287
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
LiveInterval - This class represents the liveness of a register, or stack slot.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
std::unique_ptr< RegAllocEvictionAdvisorProvider > Provider
RegAllocEvictionAdvisorProvider & getProvider()
Get an advisor for the given context (i.e. machine function, etc)
virtual void logRewardIfNeeded(const MachineFunction &MF, function_ref< float()> GetReward)
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
A MachineFunction analysis 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
virtual void logRewardIfNeeded(const MachineFunction &MF, llvm::function_ref< float()> GetReward)
RegAllocEvictionAdvisorProvider(AdvisorMode Mode, LLVMContext &Ctx)
virtual ~RegAllocEvictionAdvisorProvider()=default
const TargetRegisterInfo *const TRI
virtual bool canEvictHintInterference(const LiveInterval &VirtReg, MCRegister PhysReg, const SmallVirtRegSet &FixedRegisters) const =0
Find out if we can evict the live ranges occupying the given PhysReg, which is a hint (preferred regi...
RegAllocEvictionAdvisor(RegAllocEvictionAdvisor &&)=delete
LLVM_ABI std::optional< unsigned > getOrderLimit(const LiveInterval &VirtReg, const AllocationOrder &Order, unsigned CostPerUseLimit) const
virtual MCRegister tryFindEvictionCandidate(const LiveInterval &VirtReg, const AllocationOrder &Order, uint8_t CostPerUseLimit, const SmallVirtRegSet &FixedRegisters) const =0
Find a physical register that can be freed by evicting the FixedRegisters, or return NoRegister.
const RegisterClassInfo & RegClassInfo
LLVM_ABI bool isUnusedCalleeSavedReg(MCRegister PhysReg) const
Returns true if the given PhysReg is a callee saved register and has not been used for allocation yet...
RegAllocEvictionAdvisor(const RegAllocEvictionAdvisor &)=delete
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.
virtual ~RegAllocEvictionAdvisor()=default
LLVM_ABI bool canAllocatePhysReg(unsigned CostPerUseLimit, MCRegister PhysReg) const
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition SmallSet.h:134
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
An efficient, type-erasing, non-owning reference to a callable.
This is an optimization pass for GlobalISel generic memory operations.
SmallSet< Register, 16 > SmallVirtRegSet
LLVM_ABI RegAllocEvictionAdvisorAnalysisLegacy * createReleaseModeAdvisorAnalysisLegacy()
LLVM_ABI RegAllocEvictionAdvisorProvider * createDevelopmentModeAdvisorProvider(LLVMContext &Ctx)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI RegAllocEvictionAdvisorAnalysisLegacy * createDevelopmentModeAdvisorAnalysisLegacy()
LLVM_ABI Pass * callDefaultCtor< RegAllocEvictionAdvisorAnalysisLegacy >()
Specialization for the API used by the analysis infrastructure to create an instance of the eviction ...
@ RS_Split2
Attempt more aggressive live range splitting that is guaranteed to make progress.
@ RS_Spill
Live range will be spilled. No more splitting will be attempted.
@ RS_Split
Attempt live range splitting if assignment is impossible.
@ RS_New
Newly created live range that has never been queued.
@ RS_Done
There is nothing more we can do to this live range.
@ RS_Assign
Only attempt assignment and eviction. Then requeue as RS_Split.
LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ABI RegAllocEvictionAdvisorProvider * createReleaseModeAdvisorProvider(LLVMContext &Ctx)
A CRTP mix-in that provides informational APIs needed for analysis passes.
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...
bool operator>=(const EvictionCost &O) const
EvictionCost()=default
unsigned BrokenHints
Total number of broken hints.
bool operator<(const EvictionCost &O) const
float MaxWeight
Maximum spill weight evicted.
void setBrokenHints(unsigned NHints)
bool invalidate(MachineFunction &MF, const PreservedAnalyses &PA, MachineFunctionAnalysisManager::Invalidator &Inv)