LLVM 20.0.0git
RegAllocGreedy.h
Go to the documentation of this file.
1//==- RegAllocGreedy.h ------- greedy register allocator ----------*-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// This file defines the RAGreedy function pass for register allocation in
9// optimized builds.
10//===----------------------------------------------------------------------===//
11
12#ifndef LLVM_CODEGEN_REGALLOCGREEDY_H_
13#define LLVM_CODEGEN_REGALLOCGREEDY_H_
14
15#include "InterferenceCache.h"
16#include "RegAllocBase.h"
19#include "SplitKit.h"
20#include "llvm/ADT/ArrayRef.h"
21#include "llvm/ADT/BitVector.h"
22#include "llvm/ADT/IndexedMap.h"
23#include "llvm/ADT/SetVector.h"
25#include "llvm/ADT/StringRef.h"
36#include <algorithm>
37#include <cstdint>
38#include <memory>
39#include <queue>
40#include <utility>
41
42namespace llvm {
43class AllocationOrder;
44class AnalysisUsage;
45class EdgeBundles;
46class LiveDebugVariablesWrapperLegacy;
47class LiveIntervals;
48class LiveRegMatrix;
49class MachineBasicBlock;
50class MachineBlockFrequencyInfo;
51class MachineDominatorTree;
52class MachineLoop;
53class MachineLoopInfo;
54class MachineOptimizationRemarkEmitter;
55class MachineOptimizationRemarkMissed;
56class SlotIndexes;
57class TargetInstrInfo;
58class VirtRegMap;
59
61 public RegAllocBase,
63 // Interface to eviction advisers
64public:
65 /// Track allocation stage and eviction loop prevention during allocation.
66 class ExtraRegInfo final {
67 // RegInfo - Keep additional information about each live range.
68 struct RegInfo {
69 LiveRangeStage Stage = RS_New;
70
71 // Cascade - Eviction loop prevention. See
72 // canEvictInterferenceBasedOnCost().
73 unsigned Cascade = 0;
74
75 RegInfo() = default;
76 };
77
79 unsigned NextCascade = 1;
80
81 public:
83 ExtraRegInfo(const ExtraRegInfo &) = delete;
84
85 LiveRangeStage getStage(Register Reg) const { return Info[Reg].Stage; }
86
87 LiveRangeStage getStage(const LiveInterval &VirtReg) const {
88 return getStage(VirtReg.reg());
89 }
90
92 Info.grow(Reg.id());
93 Info[Reg].Stage = Stage;
94 }
95
96 void setStage(const LiveInterval &VirtReg, LiveRangeStage Stage) {
97 setStage(VirtReg.reg(), Stage);
98 }
99
100 /// Return the current stage of the register, if present, otherwise
101 /// initialize it and return that.
103 Info.grow(Reg.id());
104 return getStage(Reg);
105 }
106
107 unsigned getCascade(Register Reg) const { return Info[Reg].Cascade; }
108
109 void setCascade(Register Reg, unsigned Cascade) {
110 Info.grow(Reg.id());
111 Info[Reg].Cascade = Cascade;
112 }
113
115 unsigned Cascade = getCascade(Reg);
116 if (!Cascade) {
117 Cascade = NextCascade++;
118 setCascade(Reg, Cascade);
119 }
120 return Cascade;
121 }
122
124 unsigned Cascade = getCascade(Reg);
125 if (!Cascade)
126 Cascade = NextCascade;
127 return Cascade;
128 }
129
130 template <typename Iterator>
131 void setStage(Iterator Begin, Iterator End, LiveRangeStage NewStage) {
132 for (; Begin != End; ++Begin) {
133 Register Reg = *Begin;
134 Info.grow(Reg.id());
135 if (Info[Reg].Stage == RS_New)
136 Info[Reg].Stage = NewStage;
137 }
138 }
139 void LRE_DidCloneVirtReg(Register New, Register Old);
140 };
141
143 LiveIntervals *getLiveIntervals() const { return LIS; }
144 VirtRegMap *getVirtRegMap() const { return VRM; }
145 const RegisterClassInfo &getRegClassInfo() const { return RegClassInfo; }
146 const ExtraRegInfo &getExtraInfo() const { return *ExtraInfo; }
147 size_t getQueueSize() const { return Queue.size(); }
148 // end (interface to eviction advisers)
149
150 // Interface to priority advisers
152 return RegClassPriorityTrumpsGlobalness;
153 }
154 bool getReverseLocalAssignment() const { return ReverseLocalAssignment; }
155 // end (interface to priority advisers)
156
157private:
158 // Convenient shortcuts.
159 using PQueue = std::priority_queue<std::pair<unsigned, unsigned>>;
161
162 // We need to track all tentative recolorings so we can roll back any
163 // successful and unsuccessful recoloring attempts.
164 using RecoloringStack =
166
167 // context
168 MachineFunction *MF = nullptr;
169
170 // Shortcuts to some useful interface.
171 const TargetInstrInfo *TII = nullptr;
172
173 // analyses
174 SlotIndexes *Indexes = nullptr;
175 MachineBlockFrequencyInfo *MBFI = nullptr;
176 MachineDominatorTree *DomTree = nullptr;
177 MachineLoopInfo *Loops = nullptr;
179 EdgeBundles *Bundles = nullptr;
180 SpillPlacement *SpillPlacer = nullptr;
181 LiveDebugVariables *DebugVars = nullptr;
182
183 // state
184 std::unique_ptr<Spiller> SpillerInstance;
185 PQueue Queue;
186 std::unique_ptr<VirtRegAuxInfo> VRAI;
187 std::optional<ExtraRegInfo> ExtraInfo;
188 std::unique_ptr<RegAllocEvictionAdvisor> EvictAdvisor;
189
190 std::unique_ptr<RegAllocPriorityAdvisor> PriorityAdvisor;
191
192 // Enum CutOffStage to keep a track whether the register allocation failed
193 // because of the cutoffs encountered in last chance recoloring.
194 // Note: This is used as bitmask. New value should be next power of 2.
195 enum CutOffStage {
196 // No cutoffs encountered
197 CO_None = 0,
198
199 // lcr-max-depth cutoff encountered
200 CO_Depth = 1,
201
202 // lcr-max-interf cutoff encountered
203 CO_Interf = 2
204 };
205
206 uint8_t CutOffInfo = CutOffStage::CO_None;
207
208#ifndef NDEBUG
209 static const char *const StageName[];
210#endif
211
212 // splitting state.
213 std::unique_ptr<SplitAnalysis> SA;
214 std::unique_ptr<SplitEditor> SE;
215
216 /// Cached per-block interference maps
217 InterferenceCache IntfCache;
218
219 /// All basic blocks where the current register has uses.
220 SmallVector<SpillPlacement::BlockConstraint, 8> SplitConstraints;
221
222 /// Global live range splitting candidate info.
223 struct GlobalSplitCandidate {
224 // Register intended for assignment, or 0.
225 MCRegister PhysReg;
226
227 // SplitKit interval index for this candidate.
228 unsigned IntvIdx;
229
230 // Interference for PhysReg.
231 InterferenceCache::Cursor Intf;
232
233 // Bundles where this candidate should be live.
234 BitVector LiveBundles;
235 SmallVector<unsigned, 8> ActiveBlocks;
236
237 void reset(InterferenceCache &Cache, MCRegister Reg) {
238 PhysReg = Reg;
239 IntvIdx = 0;
240 Intf.setPhysReg(Cache, Reg);
241 LiveBundles.clear();
242 ActiveBlocks.clear();
243 }
244
245 // Set B[I] = C for every live bundle where B[I] was NoCand.
246 unsigned getBundles(SmallVectorImpl<unsigned> &B, unsigned C) {
247 unsigned Count = 0;
248 for (unsigned I : LiveBundles.set_bits())
249 if (B[I] == NoCand) {
250 B[I] = C;
251 Count++;
252 }
253 return Count;
254 }
255 };
256
257 /// Candidate info for each PhysReg in AllocationOrder.
258 /// This vector never shrinks, but grows to the size of the largest register
259 /// class.
260 SmallVector<GlobalSplitCandidate, 32> GlobalCand;
261
262 enum : unsigned { NoCand = ~0u };
263
264 /// Candidate map. Each edge bundle is assigned to a GlobalCand entry, or to
265 /// NoCand which indicates the stack interval.
266 SmallVector<unsigned, 32> BundleCand;
267
268 /// Callee-save register cost, calculated once per machine function.
269 BlockFrequency CSRCost;
270
271 /// Set of broken hints that may be reconciled later because of eviction.
272 SmallSetVector<const LiveInterval *, 8> SetOfBrokenHints;
273
274 /// The register cost values. This list will be recreated for each Machine
275 /// Function
276 ArrayRef<uint8_t> RegCosts;
277
278 /// Flags for the live range priority calculation, determined once per
279 /// machine function.
280 bool RegClassPriorityTrumpsGlobalness = false;
281
282 bool ReverseLocalAssignment = false;
283
284public:
285 RAGreedy(const RegAllocFilterFunc F = nullptr);
286
287 /// Return the pass name.
288 StringRef getPassName() const override { return "Greedy Register Allocator"; }
289
290 /// RAGreedy analysis usage.
291 void getAnalysisUsage(AnalysisUsage &AU) const override;
292 void releaseMemory() override;
293 Spiller &spiller() override { return *SpillerInstance; }
294 void enqueueImpl(const LiveInterval *LI) override;
295 const LiveInterval *dequeue() override;
296 MCRegister selectOrSplit(const LiveInterval &,
297 SmallVectorImpl<Register> &) override;
298 void aboutToRemoveInterval(const LiveInterval &) override;
299
300 /// Perform register allocation.
301 bool runOnMachineFunction(MachineFunction &mf) override;
302
305 MachineFunctionProperties::Property::NoPHIs);
306 }
307
310 MachineFunctionProperties::Property::IsSSA);
311 }
312
313 static char ID;
314
315private:
316 MCRegister selectOrSplitImpl(const LiveInterval &,
318 RecoloringStack &, unsigned = 0);
319
320 bool LRE_CanEraseVirtReg(Register) override;
321 void LRE_WillShrinkVirtReg(Register) override;
322 void LRE_DidCloneVirtReg(Register, Register) override;
323 void enqueue(PQueue &CurQueue, const LiveInterval *LI);
324 const LiveInterval *dequeue(PQueue &CurQueue);
325
326 bool hasVirtRegAlloc();
327 BlockFrequency calcSpillCost();
328 bool addSplitConstraints(InterferenceCache::Cursor, BlockFrequency &);
329 bool addThroughConstraints(InterferenceCache::Cursor, ArrayRef<unsigned>);
330 bool growRegion(GlobalSplitCandidate &Cand);
331 BlockFrequency calcGlobalSplitCost(GlobalSplitCandidate &,
332 const AllocationOrder &Order);
333 bool calcCompactRegion(GlobalSplitCandidate &);
334 void splitAroundRegion(LiveRangeEdit &, ArrayRef<unsigned>);
335 void calcGapWeights(MCRegister, SmallVectorImpl<float> &);
336 void evictInterference(const LiveInterval &, MCRegister,
338 bool mayRecolorAllInterferences(MCRegister PhysReg,
339 const LiveInterval &VirtReg,
340 SmallLISet &RecoloringCandidates,
341 const SmallVirtRegSet &FixedRegisters);
342
343 MCRegister tryAssign(const LiveInterval &, AllocationOrder &,
345 MCRegister tryEvict(const LiveInterval &, AllocationOrder &,
347 const SmallVirtRegSet &);
348 MCRegister tryRegionSplit(const LiveInterval &, AllocationOrder &,
350 /// Calculate cost of region splitting around the specified register.
351 unsigned calculateRegionSplitCostAroundReg(MCPhysReg PhysReg,
352 AllocationOrder &Order,
353 BlockFrequency &BestCost,
354 unsigned &NumCands,
355 unsigned &BestCand);
356 /// Calculate cost of region splitting.
357 unsigned calculateRegionSplitCost(const LiveInterval &VirtReg,
358 AllocationOrder &Order,
359 BlockFrequency &BestCost,
360 unsigned &NumCands, bool IgnoreCSR);
361 /// Perform region splitting.
362 unsigned doRegionSplit(const LiveInterval &VirtReg, unsigned BestCand,
363 bool HasCompact, SmallVectorImpl<Register> &NewVRegs);
364 /// Try to split VirtReg around physical Hint register.
365 bool trySplitAroundHintReg(MCPhysReg Hint, const LiveInterval &VirtReg,
367 AllocationOrder &Order);
368 /// Check other options before using a callee-saved register for the first
369 /// time.
370 MCRegister tryAssignCSRFirstTime(const LiveInterval &VirtReg,
371 AllocationOrder &Order, MCRegister PhysReg,
372 uint8_t &CostPerUseLimit,
373 SmallVectorImpl<Register> &NewVRegs);
374 void initializeCSRCost();
375 unsigned tryBlockSplit(const LiveInterval &, AllocationOrder &,
377 unsigned tryInstructionSplit(const LiveInterval &, AllocationOrder &,
379 unsigned tryLocalSplit(const LiveInterval &, AllocationOrder &,
381 unsigned trySplit(const LiveInterval &, AllocationOrder &,
383 unsigned tryLastChanceRecoloring(const LiveInterval &, AllocationOrder &,
386 unsigned);
387 bool tryRecoloringCandidates(PQueue &, SmallVectorImpl<Register> &,
388 SmallVirtRegSet &, RecoloringStack &, unsigned);
389 void tryHintRecoloring(const LiveInterval &);
390 void tryHintsRecoloring();
391
392 /// Model the information carried by one end of a copy.
393 struct HintInfo {
394 /// The frequency of the copy.
395 BlockFrequency Freq;
396 /// The virtual register or physical register.
398 /// Its currently assigned register.
399 /// In case of a physical register Reg == PhysReg.
400 MCRegister PhysReg;
401
402 HintInfo(BlockFrequency Freq, Register Reg, MCRegister PhysReg)
403 : Freq(Freq), Reg(Reg), PhysReg(PhysReg) {}
404 };
405 using HintsInfo = SmallVector<HintInfo, 4>;
406
407 BlockFrequency getBrokenHintFreq(const HintsInfo &, MCRegister);
408 void collectHintInfo(Register, HintsInfo &);
409
410 /// Greedy RA statistic to remark.
411 struct RAGreedyStats {
412 unsigned Reloads = 0;
413 unsigned FoldedReloads = 0;
414 unsigned ZeroCostFoldedReloads = 0;
415 unsigned Spills = 0;
416 unsigned FoldedSpills = 0;
417 unsigned Copies = 0;
418 float ReloadsCost = 0.0f;
419 float FoldedReloadsCost = 0.0f;
420 float SpillsCost = 0.0f;
421 float FoldedSpillsCost = 0.0f;
422 float CopiesCost = 0.0f;
423
424 bool isEmpty() {
425 return !(Reloads || FoldedReloads || Spills || FoldedSpills ||
426 ZeroCostFoldedReloads || Copies);
427 }
428
429 void add(const RAGreedyStats &other) {
430 Reloads += other.Reloads;
431 FoldedReloads += other.FoldedReloads;
432 ZeroCostFoldedReloads += other.ZeroCostFoldedReloads;
433 Spills += other.Spills;
434 FoldedSpills += other.FoldedSpills;
435 Copies += other.Copies;
436 ReloadsCost += other.ReloadsCost;
437 FoldedReloadsCost += other.FoldedReloadsCost;
438 SpillsCost += other.SpillsCost;
439 FoldedSpillsCost += other.FoldedSpillsCost;
440 CopiesCost += other.CopiesCost;
441 }
442
443 void report(MachineOptimizationRemarkMissed &R);
444 };
445
446 /// Compute statistic for a basic block.
447 RAGreedyStats computeStats(MachineBasicBlock &MBB);
448
449 /// Compute and report statistic through a remark.
450 RAGreedyStats reportStats(MachineLoop *L);
451
452 /// Report the statistic for each loop.
453 void reportStats();
454};
455} // namespace llvm
456#endif // #ifndef LLVM_CODEGEN_REGALLOCGREEDY_H_
MachineBasicBlock & MBB
This file implements the BitVector class.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
#define LLVM_LIBRARY_VISIBILITY
Definition: Compiler.h:133
bool End
Definition: ELF_riscv.cpp:480
const HexagonInstrInfo * TII
Hexagon Hardware Loops
This file implements an indexed map.
Live Register Matrix
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
unsigned Reg
Promote Memory to Register
Definition: Mem2Reg.cpp:110
SI Lower i1 Copies
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
Represent the analysis usage information of a pass.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
Cursor - The primary query interface for the block interference cache.
LiveInterval - This class represents the liveness of a register, or stack slot.
Definition: LiveInterval.h:687
Register reg() const
Definition: LiveInterval.h:718
Callback methods for LiveRangeEdit owners.
Definition: LiveRangeEdit.h:45
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & set(Property P)
Track allocation stage and eviction loop prevention during allocation.
LiveRangeStage getStage(Register Reg) const
void setCascade(Register Reg, unsigned Cascade)
unsigned getOrAssignNewCascade(Register Reg)
LiveRangeStage getStage(const LiveInterval &VirtReg) const
ExtraRegInfo(const ExtraRegInfo &)=delete
void setStage(Register Reg, LiveRangeStage Stage)
void setStage(const LiveInterval &VirtReg, LiveRangeStage Stage)
void setStage(Iterator Begin, Iterator End, LiveRangeStage NewStage)
unsigned getCascade(Register Reg) const
unsigned getCascadeOrCurrentNext(Register Reg) const
LiveRangeStage getOrInitStage(Register Reg)
Return the current stage of the register, if present, otherwise initialize it and return that.
StringRef getPassName() const override
Return the pass name.
MachineFunctionProperties getClearedProperties() const override
const ExtraRegInfo & getExtraInfo() const
Spiller & spiller() override
MachineFunctionProperties getRequiredProperties() const override
VirtRegMap * getVirtRegMap() const
LiveIntervals * getLiveIntervals() const
const RegisterClassInfo & getRegClassInfo() const
bool getReverseLocalAssignment() const
static char ID
size_t getQueueSize() const
LiveRegMatrix * getInterferenceMatrix() const
bool getRegClassPriorityTrumpsGlobalness() const
RegAllocBase provides the register allocation driver and interface that can be extended to add intere...
Definition: RegAllocBase.h:62
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
SlotIndexes pass.
Definition: SlotIndexes.h:297
A SetVector that performs no allocations if smaller than a certain size.
Definition: SetVector.h:370
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:132
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
Spiller interface.
Definition: Spiller.h:27
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
TargetInstrInfo - Interface to description of machine instruction set.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ RS_New
Newly created live range that has never been queued.