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