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