[sanitizer] Improve FreeBSD ASLR detection
[llvm-project.git] / llvm / lib / CodeGen / RegAllocGreedy.h
blobbb8c3e7a5b4619a8c7ca1341cdcf3b5176906acb
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 //===----------------------------------------------------------------------===//
12 #ifndef LLVM_CODEGEN_REGALLOCGREEDY_H_
13 #define LLVM_CODEGEN_REGALLOCGREEDY_H_
15 #include "AllocationOrder.h"
16 #include "InterferenceCache.h"
17 #include "LiveDebugVariables.h"
18 #include "RegAllocBase.h"
19 #include "RegAllocEvictionAdvisor.h"
20 #include "SpillPlacement.h"
21 #include "SplitKit.h"
22 #include "llvm/ADT/ArrayRef.h"
23 #include "llvm/ADT/BitVector.h"
24 #include "llvm/ADT/DenseMap.h"
25 #include "llvm/ADT/IndexedMap.h"
26 #include "llvm/ADT/MapVector.h"
27 #include "llvm/ADT/SetVector.h"
28 #include "llvm/ADT/SmallPtrSet.h"
29 #include "llvm/ADT/SmallSet.h"
30 #include "llvm/ADT/SmallVector.h"
31 #include "llvm/ADT/StringRef.h"
32 #include "llvm/Analysis/AliasAnalysis.h"
33 #include "llvm/CodeGen/CalcSpillWeights.h"
34 #include "llvm/CodeGen/EdgeBundles.h"
35 #include "llvm/CodeGen/LiveInterval.h"
36 #include "llvm/CodeGen/LiveIntervalUnion.h"
37 #include "llvm/CodeGen/LiveIntervals.h"
38 #include "llvm/CodeGen/LiveRangeEdit.h"
39 #include "llvm/CodeGen/LiveRegMatrix.h"
40 #include "llvm/CodeGen/LiveStacks.h"
41 #include "llvm/CodeGen/MachineBasicBlock.h"
42 #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
43 #include "llvm/CodeGen/MachineDominators.h"
44 #include "llvm/CodeGen/MachineFrameInfo.h"
45 #include "llvm/CodeGen/MachineFunction.h"
46 #include "llvm/CodeGen/MachineFunctionPass.h"
47 #include "llvm/CodeGen/MachineLoopInfo.h"
48 #include "llvm/CodeGen/MachineRegisterInfo.h"
49 #include "llvm/CodeGen/RegisterClassInfo.h"
50 #include "llvm/CodeGen/SlotIndexes.h"
51 #include "llvm/CodeGen/Spiller.h"
52 #include "llvm/CodeGen/TargetInstrInfo.h"
53 #include "llvm/CodeGen/TargetRegisterInfo.h"
54 #include "llvm/CodeGen/TargetSubtargetInfo.h"
55 #include "llvm/CodeGen/VirtRegMap.h"
56 #include "llvm/IR/DebugInfoMetadata.h"
57 #include "llvm/IR/Function.h"
58 #include "llvm/IR/LLVMContext.h"
59 #include "llvm/MC/MCRegisterInfo.h"
60 #include "llvm/Pass.h"
61 #include "llvm/Support/BranchProbability.h"
62 #include "llvm/Target/TargetMachine.h"
63 #include <algorithm>
64 #include <cassert>
65 #include <cstdint>
66 #include <memory>
67 #include <queue>
68 #include <tuple>
69 #include <utility>
71 namespace llvm {
72 class LLVM_LIBRARY_VISIBILITY RAGreedy : public MachineFunctionPass,
73 public RegAllocBase,
74 private LiveRangeEdit::Delegate {
75 // Interface to eviction advisers
76 public:
77 /// Track allocation stage and eviction loop prevention during allocation.
78 class ExtraRegInfo final {
79 // RegInfo - Keep additional information about each live range.
80 struct RegInfo {
81 LiveRangeStage Stage = RS_New;
83 // Cascade - Eviction loop prevention. See
84 // canEvictInterferenceBasedOnCost().
85 unsigned Cascade = 0;
87 RegInfo() = default;
90 IndexedMap<RegInfo, VirtReg2IndexFunctor> Info;
91 unsigned NextCascade = 1;
93 public:
94 ExtraRegInfo() = default;
95 ExtraRegInfo(const ExtraRegInfo &) = delete;
97 LiveRangeStage getStage(Register Reg) const { return Info[Reg].Stage; }
99 LiveRangeStage getStage(const LiveInterval &VirtReg) const {
100 return getStage(VirtReg.reg());
103 void setStage(Register Reg, LiveRangeStage Stage) {
104 Info.grow(Reg.id());
105 Info[Reg].Stage = Stage;
108 void setStage(const LiveInterval &VirtReg, LiveRangeStage Stage) {
109 setStage(VirtReg.reg(), Stage);
112 /// Return the current stage of the register, if present, otherwise
113 /// initialize it and return that.
114 LiveRangeStage getOrInitStage(Register Reg) {
115 Info.grow(Reg.id());
116 return getStage(Reg);
119 unsigned getCascade(Register Reg) const { return Info[Reg].Cascade; }
121 void setCascade(Register Reg, unsigned Cascade) {
122 Info.grow(Reg.id());
123 Info[Reg].Cascade = Cascade;
126 unsigned getOrAssignNewCascade(Register Reg) {
127 unsigned Cascade = getCascade(Reg);
128 if (!Cascade) {
129 Cascade = NextCascade++;
130 setCascade(Reg, Cascade);
132 return Cascade;
135 unsigned getCascadeOrCurrentNext(Register Reg) const {
136 unsigned Cascade = getCascade(Reg);
137 if (!Cascade)
138 Cascade = NextCascade;
139 return Cascade;
142 template <typename Iterator>
143 void setStage(Iterator Begin, Iterator End, LiveRangeStage NewStage) {
144 for (; Begin != End; ++Begin) {
145 Register Reg = *Begin;
146 Info.grow(Reg.id());
147 if (Info[Reg].Stage == RS_New)
148 Info[Reg].Stage = NewStage;
151 void LRE_DidCloneVirtReg(Register New, Register Old);
154 LiveRegMatrix *getInterferenceMatrix() const { return Matrix; }
155 LiveIntervals *getLiveIntervals() const { return LIS; }
156 VirtRegMap *getVirtRegMap() const { return VRM; }
157 const RegisterClassInfo &getRegClassInfo() const { return RegClassInfo; }
158 const ExtraRegInfo &getExtraInfo() const { return *ExtraInfo; }
159 // end (interface to eviction advisers)
161 private:
162 // Convenient shortcuts.
163 using PQueue = std::priority_queue<std::pair<unsigned, unsigned>>;
164 using SmallLISet = SmallPtrSet<LiveInterval *, 4>;
166 // context
167 MachineFunction *MF;
169 // Shortcuts to some useful interface.
170 const TargetInstrInfo *TII;
171 const TargetRegisterInfo *TRI;
172 RegisterClassInfo RCI;
174 // analyses
175 SlotIndexes *Indexes;
176 MachineBlockFrequencyInfo *MBFI;
177 MachineDominatorTree *DomTree;
178 MachineLoopInfo *Loops;
179 MachineOptimizationRemarkEmitter *ORE;
180 EdgeBundles *Bundles;
181 SpillPlacement *SpillPlacer;
182 LiveDebugVariables *DebugVars;
183 AliasAnalysis *AA;
185 // state
186 std::unique_ptr<Spiller> SpillerInstance;
187 PQueue Queue;
188 std::unique_ptr<VirtRegAuxInfo> VRAI;
189 Optional<ExtraRegInfo> ExtraInfo;
190 std::unique_ptr<RegAllocEvictionAdvisor> EvictAdvisor;
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,
199 // lcr-max-depth cutoff encountered
200 CO_Depth = 1,
202 // lcr-max-interf cutoff encountered
203 CO_Interf = 2
206 uint8_t CutOffInfo;
208 #ifndef NDEBUG
209 static const char *const StageName[];
210 #endif
212 /// EvictionTrack - Keeps track of past evictions in order to optimize region
213 /// split decision.
214 class EvictionTrack {
216 public:
217 using EvictorInfo =
218 std::pair<Register /* evictor */, MCRegister /* physreg */>;
219 using EvicteeInfo = llvm::DenseMap<Register /* evictee */, EvictorInfo>;
221 private:
222 /// Each Vreg that has been evicted in the last stage of selectOrSplit will
223 /// be mapped to the evictor Vreg and the PhysReg it was evicted from.
224 EvicteeInfo Evictees;
226 public:
227 /// Clear all eviction information.
228 void clear() { Evictees.clear(); }
230 /// Clear eviction information for the given evictee Vreg.
231 /// E.g. when Vreg get's a new allocation, the old eviction info is no
232 /// longer relevant.
233 /// \param Evictee The evictee Vreg for whom we want to clear collected
234 /// eviction info.
235 void clearEvicteeInfo(Register Evictee) { Evictees.erase(Evictee); }
237 /// Track new eviction.
238 /// The Evictor vreg has evicted the Evictee vreg from Physreg.
239 /// \param PhysReg The physical register Evictee was evicted from.
240 /// \param Evictor The evictor Vreg that evicted Evictee.
241 /// \param Evictee The evictee Vreg.
242 void addEviction(MCRegister PhysReg, Register Evictor, Register Evictee) {
243 Evictees[Evictee].first = Evictor;
244 Evictees[Evictee].second = PhysReg;
247 /// Return the Evictor Vreg which evicted Evictee Vreg from PhysReg.
248 /// \param Evictee The evictee vreg.
249 /// \return The Evictor vreg which evicted Evictee vreg from PhysReg. 0 if
250 /// nobody has evicted Evictee from PhysReg.
251 EvictorInfo getEvictor(Register Evictee) {
252 if (Evictees.count(Evictee)) {
253 return Evictees[Evictee];
256 return EvictorInfo(0, 0);
260 // Keeps track of past evictions in order to optimize region split decision.
261 EvictionTrack LastEvicted;
263 // splitting state.
264 std::unique_ptr<SplitAnalysis> SA;
265 std::unique_ptr<SplitEditor> SE;
267 /// Cached per-block interference maps
268 InterferenceCache IntfCache;
270 /// All basic blocks where the current register has uses.
271 SmallVector<SpillPlacement::BlockConstraint, 8> SplitConstraints;
273 /// Global live range splitting candidate info.
274 struct GlobalSplitCandidate {
275 // Register intended for assignment, or 0.
276 MCRegister PhysReg;
278 // SplitKit interval index for this candidate.
279 unsigned IntvIdx;
281 // Interference for PhysReg.
282 InterferenceCache::Cursor Intf;
284 // Bundles where this candidate should be live.
285 BitVector LiveBundles;
286 SmallVector<unsigned, 8> ActiveBlocks;
288 void reset(InterferenceCache &Cache, MCRegister Reg) {
289 PhysReg = Reg;
290 IntvIdx = 0;
291 Intf.setPhysReg(Cache, Reg);
292 LiveBundles.clear();
293 ActiveBlocks.clear();
296 // Set B[I] = C for every live bundle where B[I] was NoCand.
297 unsigned getBundles(SmallVectorImpl<unsigned> &B, unsigned C) {
298 unsigned Count = 0;
299 for (unsigned I : LiveBundles.set_bits())
300 if (B[I] == NoCand) {
301 B[I] = C;
302 Count++;
304 return Count;
308 /// Candidate info for each PhysReg in AllocationOrder.
309 /// This vector never shrinks, but grows to the size of the largest register
310 /// class.
311 SmallVector<GlobalSplitCandidate, 32> GlobalCand;
313 enum : unsigned { NoCand = ~0u };
315 /// Candidate map. Each edge bundle is assigned to a GlobalCand entry, or to
316 /// NoCand which indicates the stack interval.
317 SmallVector<unsigned, 32> BundleCand;
319 /// Callee-save register cost, calculated once per machine function.
320 BlockFrequency CSRCost;
322 /// Enable or not the consideration of the cost of local intervals created
323 /// by a split candidate when choosing the best split candidate.
324 bool EnableAdvancedRASplitCost;
326 /// Set of broken hints that may be reconciled later because of eviction.
327 SmallSetVector<LiveInterval *, 8> SetOfBrokenHints;
329 /// The register cost values. This list will be recreated for each Machine
330 /// Function
331 ArrayRef<uint8_t> RegCosts;
333 public:
334 RAGreedy(const RegClassFilterFunc F = allocateAllRegClasses);
336 /// Return the pass name.
337 StringRef getPassName() const override { return "Greedy Register Allocator"; }
339 /// RAGreedy analysis usage.
340 void getAnalysisUsage(AnalysisUsage &AU) const override;
341 void releaseMemory() override;
342 Spiller &spiller() override { return *SpillerInstance; }
343 void enqueueImpl(LiveInterval *LI) override;
344 LiveInterval *dequeue() override;
345 MCRegister selectOrSplit(LiveInterval &,
346 SmallVectorImpl<Register> &) override;
347 void aboutToRemoveInterval(LiveInterval &) override;
349 /// Perform register allocation.
350 bool runOnMachineFunction(MachineFunction &mf) override;
352 MachineFunctionProperties getRequiredProperties() const override {
353 return MachineFunctionProperties().set(
354 MachineFunctionProperties::Property::NoPHIs);
357 MachineFunctionProperties getClearedProperties() const override {
358 return MachineFunctionProperties().set(
359 MachineFunctionProperties::Property::IsSSA);
362 static char ID;
364 private:
365 MCRegister selectOrSplitImpl(LiveInterval &, SmallVectorImpl<Register> &,
366 SmallVirtRegSet &, unsigned = 0);
368 bool LRE_CanEraseVirtReg(Register) override;
369 void LRE_WillShrinkVirtReg(Register) override;
370 void LRE_DidCloneVirtReg(Register, Register) override;
371 void enqueue(PQueue &CurQueue, LiveInterval *LI);
372 LiveInterval *dequeue(PQueue &CurQueue);
374 BlockFrequency calcSpillCost();
375 bool addSplitConstraints(InterferenceCache::Cursor, BlockFrequency &);
376 bool addThroughConstraints(InterferenceCache::Cursor, ArrayRef<unsigned>);
377 bool growRegion(GlobalSplitCandidate &Cand);
378 bool splitCanCauseEvictionChain(Register Evictee, GlobalSplitCandidate &Cand,
379 unsigned BBNumber,
380 const AllocationOrder &Order);
381 bool splitCanCauseLocalSpill(unsigned VirtRegToSplit,
382 GlobalSplitCandidate &Cand, unsigned BBNumber,
383 const AllocationOrder &Order);
384 BlockFrequency calcGlobalSplitCost(GlobalSplitCandidate &,
385 const AllocationOrder &Order,
386 bool *CanCauseEvictionChain);
387 bool calcCompactRegion(GlobalSplitCandidate &);
388 void splitAroundRegion(LiveRangeEdit &, ArrayRef<unsigned>);
389 void calcGapWeights(MCRegister, SmallVectorImpl<float> &);
390 bool canEvictInterferenceInRange(const LiveInterval &VirtReg,
391 MCRegister PhysReg, SlotIndex Start,
392 SlotIndex End, EvictionCost &MaxCost) const;
393 MCRegister getCheapestEvicteeWeight(const AllocationOrder &Order,
394 const LiveInterval &VirtReg,
395 SlotIndex Start, SlotIndex End,
396 float *BestEvictWeight) const;
397 void evictInterference(LiveInterval &, MCRegister,
398 SmallVectorImpl<Register> &);
399 bool mayRecolorAllInterferences(MCRegister PhysReg, LiveInterval &VirtReg,
400 SmallLISet &RecoloringCandidates,
401 const SmallVirtRegSet &FixedRegisters);
403 MCRegister tryAssign(LiveInterval &, AllocationOrder &,
404 SmallVectorImpl<Register> &, const SmallVirtRegSet &);
405 MCRegister tryEvict(LiveInterval &, AllocationOrder &,
406 SmallVectorImpl<Register> &, uint8_t,
407 const SmallVirtRegSet &);
408 MCRegister tryRegionSplit(LiveInterval &, AllocationOrder &,
409 SmallVectorImpl<Register> &);
410 /// Calculate cost of region splitting.
411 unsigned calculateRegionSplitCost(LiveInterval &VirtReg,
412 AllocationOrder &Order,
413 BlockFrequency &BestCost,
414 unsigned &NumCands, bool IgnoreCSR,
415 bool *CanCauseEvictionChain = nullptr);
416 /// Perform region splitting.
417 unsigned doRegionSplit(LiveInterval &VirtReg, unsigned BestCand,
418 bool HasCompact, SmallVectorImpl<Register> &NewVRegs);
419 /// Check other options before using a callee-saved register for the first
420 /// time.
421 MCRegister tryAssignCSRFirstTime(LiveInterval &VirtReg,
422 AllocationOrder &Order, MCRegister PhysReg,
423 uint8_t &CostPerUseLimit,
424 SmallVectorImpl<Register> &NewVRegs);
425 void initializeCSRCost();
426 unsigned tryBlockSplit(LiveInterval &, AllocationOrder &,
427 SmallVectorImpl<Register> &);
428 unsigned tryInstructionSplit(LiveInterval &, AllocationOrder &,
429 SmallVectorImpl<Register> &);
430 unsigned tryLocalSplit(LiveInterval &, AllocationOrder &,
431 SmallVectorImpl<Register> &);
432 unsigned trySplit(LiveInterval &, AllocationOrder &,
433 SmallVectorImpl<Register> &, const SmallVirtRegSet &);
434 unsigned tryLastChanceRecoloring(LiveInterval &, AllocationOrder &,
435 SmallVectorImpl<Register> &,
436 SmallVirtRegSet &, unsigned);
437 bool tryRecoloringCandidates(PQueue &, SmallVectorImpl<Register> &,
438 SmallVirtRegSet &, unsigned);
439 void tryHintRecoloring(LiveInterval &);
440 void tryHintsRecoloring();
442 /// Model the information carried by one end of a copy.
443 struct HintInfo {
444 /// The frequency of the copy.
445 BlockFrequency Freq;
446 /// The virtual register or physical register.
447 Register Reg;
448 /// Its currently assigned register.
449 /// In case of a physical register Reg == PhysReg.
450 MCRegister PhysReg;
452 HintInfo(BlockFrequency Freq, Register Reg, MCRegister PhysReg)
453 : Freq(Freq), Reg(Reg), PhysReg(PhysReg) {}
455 using HintsInfo = SmallVector<HintInfo, 4>;
457 BlockFrequency getBrokenHintFreq(const HintsInfo &, MCRegister);
458 void collectHintInfo(Register, HintsInfo &);
460 /// Greedy RA statistic to remark.
461 struct RAGreedyStats {
462 unsigned Reloads = 0;
463 unsigned FoldedReloads = 0;
464 unsigned ZeroCostFoldedReloads = 0;
465 unsigned Spills = 0;
466 unsigned FoldedSpills = 0;
467 unsigned Copies = 0;
468 float ReloadsCost = 0.0f;
469 float FoldedReloadsCost = 0.0f;
470 float SpillsCost = 0.0f;
471 float FoldedSpillsCost = 0.0f;
472 float CopiesCost = 0.0f;
474 bool isEmpty() {
475 return !(Reloads || FoldedReloads || Spills || FoldedSpills ||
476 ZeroCostFoldedReloads || Copies);
479 void add(RAGreedyStats other) {
480 Reloads += other.Reloads;
481 FoldedReloads += other.FoldedReloads;
482 ZeroCostFoldedReloads += other.ZeroCostFoldedReloads;
483 Spills += other.Spills;
484 FoldedSpills += other.FoldedSpills;
485 Copies += other.Copies;
486 ReloadsCost += other.ReloadsCost;
487 FoldedReloadsCost += other.FoldedReloadsCost;
488 SpillsCost += other.SpillsCost;
489 FoldedSpillsCost += other.FoldedSpillsCost;
490 CopiesCost += other.CopiesCost;
493 void report(MachineOptimizationRemarkMissed &R);
496 /// Compute statistic for a basic block.
497 RAGreedyStats computeStats(MachineBasicBlock &MBB);
499 /// Compute and report statistic through a remark.
500 RAGreedyStats reportStats(MachineLoop *L);
502 /// Report the statistic for each loop.
503 void reportStats();
505 } // namespace llvm
506 #endif // #ifndef LLVM_CODEGEN_REGALLOCGREEDY_H_