xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/GCNSchedStrategy.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10b57cec5SDimitry Andric //===-- GCNSchedStrategy.h - GCN Scheduler Strategy -*- C++ -*-------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AMDGPU_GCNSCHEDSTRATEGY_H
140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AMDGPU_GCNSCHEDSTRATEGY_H
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "GCNRegPressure.h"
1781ad6265SDimitry Andric #include "llvm/ADT/MapVector.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineScheduler.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric namespace llvm {
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric class SIMachineFunctionInfo;
230b57cec5SDimitry Andric class SIRegisterInfo;
240b57cec5SDimitry Andric class GCNSubtarget;
25*bdd1243dSDimitry Andric class GCNSchedStage;
26*bdd1243dSDimitry Andric 
27*bdd1243dSDimitry Andric enum class GCNSchedStageID : unsigned {
28*bdd1243dSDimitry Andric   OccInitialSchedule = 0,
29*bdd1243dSDimitry Andric   UnclusteredHighRPReschedule = 1,
30*bdd1243dSDimitry Andric   ClusteredLowOccupancyReschedule = 2,
31*bdd1243dSDimitry Andric   PreRARematerialize = 3,
32*bdd1243dSDimitry Andric   ILPInitialSchedule = 4
33*bdd1243dSDimitry Andric };
34*bdd1243dSDimitry Andric 
35*bdd1243dSDimitry Andric #ifndef NDEBUG
36*bdd1243dSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const GCNSchedStageID &StageID);
37*bdd1243dSDimitry Andric #endif
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric /// This is a minimal scheduler strategy.  The main difference between this
400b57cec5SDimitry Andric /// and the GenericScheduler is that GCNSchedStrategy uses different
41*bdd1243dSDimitry Andric /// heuristics to determine excess/critical pressure sets.
42*bdd1243dSDimitry Andric class GCNSchedStrategy : public GenericScheduler {
43*bdd1243dSDimitry Andric protected:
440b57cec5SDimitry Andric   SUnit *pickNodeBidirectional(bool &IsTopNode);
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   void pickNodeFromQueue(SchedBoundary &Zone, const CandPolicy &ZonePolicy,
470b57cec5SDimitry Andric                          const RegPressureTracker &RPTracker,
480b57cec5SDimitry Andric                          SchedCandidate &Cand);
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric   void initCandidate(SchedCandidate &Cand, SUnit *SU,
510b57cec5SDimitry Andric                      bool AtTop, const RegPressureTracker &RPTracker,
520b57cec5SDimitry Andric                      const SIRegisterInfo *SRI,
530b57cec5SDimitry Andric                      unsigned SGPRPressure, unsigned VGPRPressure);
540b57cec5SDimitry Andric 
558bcb0991SDimitry Andric   std::vector<unsigned> Pressure;
56972a253aSDimitry Andric 
578bcb0991SDimitry Andric   std::vector<unsigned> MaxPressure;
588bcb0991SDimitry Andric 
590b57cec5SDimitry Andric   unsigned SGPRExcessLimit;
60972a253aSDimitry Andric 
610b57cec5SDimitry Andric   unsigned VGPRExcessLimit;
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric   unsigned TargetOccupancy;
640b57cec5SDimitry Andric 
65972a253aSDimitry Andric   MachineFunction *MF;
66972a253aSDimitry Andric 
67*bdd1243dSDimitry Andric   // Scheduling stages for this strategy.
68*bdd1243dSDimitry Andric   SmallVector<GCNSchedStageID, 4> SchedStages;
69fe6060f1SDimitry Andric 
70*bdd1243dSDimitry Andric   // Pointer to the current SchedStageID.
71*bdd1243dSDimitry Andric   SmallVectorImpl<GCNSchedStageID>::iterator CurrentStage = nullptr;
72*bdd1243dSDimitry Andric 
73*bdd1243dSDimitry Andric public:
74*bdd1243dSDimitry Andric   // schedule() have seen register pressure over the critical limits and had to
75*bdd1243dSDimitry Andric   // track register pressure for actual scheduling heuristics.
76*bdd1243dSDimitry Andric   bool HasHighPressure;
77*bdd1243dSDimitry Andric 
78*bdd1243dSDimitry Andric   // Schedule known to have excess register pressure. Be more conservative in
79*bdd1243dSDimitry Andric   // increasing ILP and preserving VGPRs.
80*bdd1243dSDimitry Andric   bool KnownExcessRP = false;
81*bdd1243dSDimitry Andric 
82*bdd1243dSDimitry Andric   // An error margin is necessary because of poor performance of the generic RP
83*bdd1243dSDimitry Andric   // tracker and can be adjusted up for tuning heuristics to try and more
84*bdd1243dSDimitry Andric   // aggressively reduce register pressure.
85*bdd1243dSDimitry Andric   unsigned ErrorMargin = 3;
86*bdd1243dSDimitry Andric 
87*bdd1243dSDimitry Andric   // Bias for SGPR limits under a high register pressure.
88*bdd1243dSDimitry Andric   const unsigned HighRPSGPRBias = 7;
89*bdd1243dSDimitry Andric 
90*bdd1243dSDimitry Andric   // Bias for VGPR limits under a high register pressure.
91*bdd1243dSDimitry Andric   const unsigned HighRPVGPRBias = 7;
92fe6060f1SDimitry Andric 
93972a253aSDimitry Andric   unsigned SGPRCriticalLimit;
940b57cec5SDimitry Andric 
95972a253aSDimitry Andric   unsigned VGPRCriticalLimit;
96972a253aSDimitry Andric 
97*bdd1243dSDimitry Andric   unsigned SGPRLimitBias = 0;
98*bdd1243dSDimitry Andric 
99*bdd1243dSDimitry Andric   unsigned VGPRLimitBias = 0;
100*bdd1243dSDimitry Andric 
101*bdd1243dSDimitry Andric   GCNSchedStrategy(const MachineSchedContext *C);
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   SUnit *pickNode(bool &IsTopNode) override;
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   void initialize(ScheduleDAGMI *DAG) override;
1060b57cec5SDimitry Andric 
107972a253aSDimitry Andric   unsigned getTargetOccupancy() { return TargetOccupancy; }
108972a253aSDimitry Andric 
1090b57cec5SDimitry Andric   void setTargetOccupancy(unsigned Occ) { TargetOccupancy = Occ; }
110*bdd1243dSDimitry Andric 
111*bdd1243dSDimitry Andric   GCNSchedStageID getCurrentStage();
112*bdd1243dSDimitry Andric 
113*bdd1243dSDimitry Andric   // Advances stage. Returns true if there are remaining stages.
114*bdd1243dSDimitry Andric   bool advanceStage();
115*bdd1243dSDimitry Andric 
116*bdd1243dSDimitry Andric   bool hasNextStage() const;
117*bdd1243dSDimitry Andric 
118*bdd1243dSDimitry Andric   GCNSchedStageID getNextStage() const;
1190b57cec5SDimitry Andric };
1200b57cec5SDimitry Andric 
121*bdd1243dSDimitry Andric /// The goal of this scheduling strategy is to maximize kernel occupancy (i.e.
122*bdd1243dSDimitry Andric /// maximum number of waves per simd).
123*bdd1243dSDimitry Andric class GCNMaxOccupancySchedStrategy final : public GCNSchedStrategy {
124*bdd1243dSDimitry Andric public:
125*bdd1243dSDimitry Andric   GCNMaxOccupancySchedStrategy(const MachineSchedContext *C);
1265ffd83dbSDimitry Andric };
1275ffd83dbSDimitry Andric 
128*bdd1243dSDimitry Andric /// The goal of this scheduling strategy is to maximize ILP for a single wave
129*bdd1243dSDimitry Andric /// (i.e. latency hiding).
130*bdd1243dSDimitry Andric class GCNMaxILPSchedStrategy final : public GCNSchedStrategy {
131*bdd1243dSDimitry Andric protected:
132*bdd1243dSDimitry Andric   bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand,
133*bdd1243dSDimitry Andric                     SchedBoundary *Zone) const override;
134972a253aSDimitry Andric 
135*bdd1243dSDimitry Andric public:
136*bdd1243dSDimitry Andric   GCNMaxILPSchedStrategy(const MachineSchedContext *C);
137*bdd1243dSDimitry Andric };
138*bdd1243dSDimitry Andric 
139*bdd1243dSDimitry Andric class ScheduleMetrics {
140*bdd1243dSDimitry Andric   unsigned ScheduleLength;
141*bdd1243dSDimitry Andric   unsigned BubbleCycles;
142*bdd1243dSDimitry Andric 
143*bdd1243dSDimitry Andric public:
144*bdd1243dSDimitry Andric   ScheduleMetrics() {}
145*bdd1243dSDimitry Andric   ScheduleMetrics(unsigned L, unsigned BC)
146*bdd1243dSDimitry Andric       : ScheduleLength(L), BubbleCycles(BC) {}
147*bdd1243dSDimitry Andric   unsigned getLength() const { return ScheduleLength; }
148*bdd1243dSDimitry Andric   unsigned getBubbles() const { return BubbleCycles; }
149*bdd1243dSDimitry Andric   unsigned getMetric() const {
150*bdd1243dSDimitry Andric     unsigned Metric = (BubbleCycles * ScaleFactor) / ScheduleLength;
151*bdd1243dSDimitry Andric     // Metric is zero if the amount of bubbles is less than 1% which is too
152*bdd1243dSDimitry Andric     // small. So, return 1.
153*bdd1243dSDimitry Andric     return Metric ? Metric : 1;
154972a253aSDimitry Andric   }
155*bdd1243dSDimitry Andric   static const unsigned ScaleFactor;
156*bdd1243dSDimitry Andric };
157972a253aSDimitry Andric 
158*bdd1243dSDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const ScheduleMetrics &Sm) {
159*bdd1243dSDimitry Andric   dbgs() << "\n Schedule Metric (scaled by "
160*bdd1243dSDimitry Andric          << ScheduleMetrics::ScaleFactor
161*bdd1243dSDimitry Andric          << " ) is: " << Sm.getMetric() << " [ " << Sm.getBubbles() << "/"
162*bdd1243dSDimitry Andric          << Sm.getLength() << " ]\n";
163*bdd1243dSDimitry Andric   return OS;
164972a253aSDimitry Andric }
165972a253aSDimitry Andric 
166972a253aSDimitry Andric class GCNScheduleDAGMILive final : public ScheduleDAGMILive {
167972a253aSDimitry Andric   friend class GCNSchedStage;
168*bdd1243dSDimitry Andric   friend class OccInitialScheduleStage;
169*bdd1243dSDimitry Andric   friend class UnclusteredHighRPStage;
170972a253aSDimitry Andric   friend class ClusteredLowOccStage;
171972a253aSDimitry Andric   friend class PreRARematStage;
172*bdd1243dSDimitry Andric   friend class ILPInitialScheduleStage;
173972a253aSDimitry Andric 
1740b57cec5SDimitry Andric   const GCNSubtarget &ST;
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric   SIMachineFunctionInfo &MFI;
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric   // Occupancy target at the beginning of function scheduling cycle.
1790b57cec5SDimitry Andric   unsigned StartingOccupancy;
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   // Minimal real occupancy recorder for the function.
1820b57cec5SDimitry Andric   unsigned MinOccupancy;
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric   // Vector of regions recorder for later rescheduling
1850b57cec5SDimitry Andric   SmallVector<std::pair<MachineBasicBlock::iterator,
1860b57cec5SDimitry Andric                         MachineBasicBlock::iterator>, 32> Regions;
1870b57cec5SDimitry Andric 
1885ffd83dbSDimitry Andric   // Records if a region is not yet scheduled, or schedule has been reverted,
1895ffd83dbSDimitry Andric   // or we generally desire to reschedule it.
1905ffd83dbSDimitry Andric   BitVector RescheduleRegions;
1915ffd83dbSDimitry Andric 
192fe6060f1SDimitry Andric   // Record regions with high register pressure.
193fe6060f1SDimitry Andric   BitVector RegionsWithHighRP;
194fe6060f1SDimitry Andric 
195*bdd1243dSDimitry Andric   // Record regions with excess register pressure over the physical register
196*bdd1243dSDimitry Andric   // limit. Register pressure in these regions usually will result in spilling.
197*bdd1243dSDimitry Andric   BitVector RegionsWithExcessRP;
198*bdd1243dSDimitry Andric 
19981ad6265SDimitry Andric   // Regions that has the same occupancy as the latest MinOccupancy
20081ad6265SDimitry Andric   BitVector RegionsWithMinOcc;
20181ad6265SDimitry Andric 
202*bdd1243dSDimitry Andric   // Regions that have IGLP instructions (SCHED_GROUP_BARRIER or IGLP_OPT).
203*bdd1243dSDimitry Andric   BitVector RegionsWithIGLPInstrs;
204*bdd1243dSDimitry Andric 
2050b57cec5SDimitry Andric   // Region live-in cache.
2060b57cec5SDimitry Andric   SmallVector<GCNRPTracker::LiveRegSet, 32> LiveIns;
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric   // Region pressure cache.
2090b57cec5SDimitry Andric   SmallVector<GCNRegPressure, 32> Pressure;
2100b57cec5SDimitry Andric 
211972a253aSDimitry Andric   // Temporary basic block live-in cache.
212972a253aSDimitry Andric   DenseMap<const MachineBasicBlock *, GCNRPTracker::LiveRegSet> MBBLiveIns;
213972a253aSDimitry Andric 
214972a253aSDimitry Andric   DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet> BBLiveInMap;
215972a253aSDimitry Andric 
216972a253aSDimitry Andric   DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet> getBBLiveInMap() const;
217972a253aSDimitry Andric 
218972a253aSDimitry Andric   // Return current region pressure.
219972a253aSDimitry Andric   GCNRegPressure getRealRegPressure(unsigned RegionIdx) const;
220972a253aSDimitry Andric 
221972a253aSDimitry Andric   // Compute and cache live-ins and pressure for all regions in block.
222972a253aSDimitry Andric   void computeBlockPressure(unsigned RegionIdx, const MachineBasicBlock *MBB);
223972a253aSDimitry Andric 
224972a253aSDimitry Andric   // Update region boundaries when removing MI or inserting NewMI before MI.
225972a253aSDimitry Andric   void updateRegionBoundaries(
226972a253aSDimitry Andric       SmallVectorImpl<std::pair<MachineBasicBlock::iterator,
227972a253aSDimitry Andric                                 MachineBasicBlock::iterator>> &RegionBoundaries,
228972a253aSDimitry Andric       MachineBasicBlock::iterator MI, MachineInstr *NewMI,
229972a253aSDimitry Andric       bool Removing = false);
230972a253aSDimitry Andric 
231972a253aSDimitry Andric   void runSchedStages();
232972a253aSDimitry Andric 
233*bdd1243dSDimitry Andric   std::unique_ptr<GCNSchedStage> createSchedStage(GCNSchedStageID SchedStageID);
234*bdd1243dSDimitry Andric 
235972a253aSDimitry Andric public:
236972a253aSDimitry Andric   GCNScheduleDAGMILive(MachineSchedContext *C,
237972a253aSDimitry Andric                        std::unique_ptr<MachineSchedStrategy> S);
238972a253aSDimitry Andric 
239972a253aSDimitry Andric   void schedule() override;
240972a253aSDimitry Andric 
241972a253aSDimitry Andric   void finalizeSchedule() override;
242972a253aSDimitry Andric };
243972a253aSDimitry Andric 
244972a253aSDimitry Andric // GCNSchedStrategy applies multiple scheduling stages to a function.
245972a253aSDimitry Andric class GCNSchedStage {
246972a253aSDimitry Andric protected:
247972a253aSDimitry Andric   GCNScheduleDAGMILive &DAG;
248972a253aSDimitry Andric 
249*bdd1243dSDimitry Andric   GCNSchedStrategy &S;
250972a253aSDimitry Andric 
251972a253aSDimitry Andric   MachineFunction &MF;
252972a253aSDimitry Andric 
253972a253aSDimitry Andric   SIMachineFunctionInfo &MFI;
254972a253aSDimitry Andric 
255972a253aSDimitry Andric   const GCNSubtarget &ST;
256972a253aSDimitry Andric 
257972a253aSDimitry Andric   const GCNSchedStageID StageID;
258972a253aSDimitry Andric 
259972a253aSDimitry Andric   // The current block being scheduled.
260972a253aSDimitry Andric   MachineBasicBlock *CurrentMBB = nullptr;
261972a253aSDimitry Andric 
262972a253aSDimitry Andric   // Current region index.
263972a253aSDimitry Andric   unsigned RegionIdx = 0;
264972a253aSDimitry Andric 
265972a253aSDimitry Andric   // Record the original order of instructions before scheduling.
266972a253aSDimitry Andric   std::vector<MachineInstr *> Unsched;
267972a253aSDimitry Andric 
268972a253aSDimitry Andric   // RP before scheduling the current region.
269972a253aSDimitry Andric   GCNRegPressure PressureBefore;
270972a253aSDimitry Andric 
271972a253aSDimitry Andric   // RP after scheduling the current region.
272972a253aSDimitry Andric   GCNRegPressure PressureAfter;
273972a253aSDimitry Andric 
274*bdd1243dSDimitry Andric   std::vector<std::unique_ptr<ScheduleDAGMutation>> SavedMutations;
275*bdd1243dSDimitry Andric 
276972a253aSDimitry Andric   GCNSchedStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG);
277972a253aSDimitry Andric 
278972a253aSDimitry Andric public:
279972a253aSDimitry Andric   // Initialize state for a scheduling stage. Returns false if the current stage
280972a253aSDimitry Andric   // should be skipped.
281972a253aSDimitry Andric   virtual bool initGCNSchedStage();
282972a253aSDimitry Andric 
283972a253aSDimitry Andric   // Finalize state after finishing a scheduling pass on the function.
284972a253aSDimitry Andric   virtual void finalizeGCNSchedStage();
285972a253aSDimitry Andric 
286972a253aSDimitry Andric   // Setup for scheduling a region. Returns false if the current region should
287972a253aSDimitry Andric   // be skipped.
288972a253aSDimitry Andric   virtual bool initGCNRegion();
289972a253aSDimitry Andric 
290972a253aSDimitry Andric   // Track whether a new region is also a new MBB.
291972a253aSDimitry Andric   void setupNewBlock();
292972a253aSDimitry Andric 
293972a253aSDimitry Andric   // Finalize state after scheudling a region.
294*bdd1243dSDimitry Andric   void finalizeGCNRegion();
295972a253aSDimitry Andric 
296972a253aSDimitry Andric   // Check result of scheduling.
297972a253aSDimitry Andric   void checkScheduling();
298972a253aSDimitry Andric 
299*bdd1243dSDimitry Andric   // computes the given schedule virtual execution time in clocks
300*bdd1243dSDimitry Andric   ScheduleMetrics getScheduleMetrics(const std::vector<SUnit> &InputSchedule);
301*bdd1243dSDimitry Andric   ScheduleMetrics getScheduleMetrics(const GCNScheduleDAGMILive &DAG);
302*bdd1243dSDimitry Andric   unsigned computeSUnitReadyCycle(const SUnit &SU, unsigned CurrCycle,
303*bdd1243dSDimitry Andric                                   DenseMap<unsigned, unsigned> &ReadyCycles,
304*bdd1243dSDimitry Andric                                   const TargetSchedModel &SM);
305*bdd1243dSDimitry Andric 
306972a253aSDimitry Andric   // Returns true if scheduling should be reverted.
307972a253aSDimitry Andric   virtual bool shouldRevertScheduling(unsigned WavesAfter);
308972a253aSDimitry Andric 
309*bdd1243dSDimitry Andric   // Returns true if current region has known excess pressure.
310*bdd1243dSDimitry Andric   bool isRegionWithExcessRP() const {
311*bdd1243dSDimitry Andric     return DAG.RegionsWithExcessRP[RegionIdx];
312*bdd1243dSDimitry Andric   }
313*bdd1243dSDimitry Andric 
314972a253aSDimitry Andric   // Returns true if the new schedule may result in more spilling.
315972a253aSDimitry Andric   bool mayCauseSpilling(unsigned WavesAfter);
316972a253aSDimitry Andric 
317972a253aSDimitry Andric   // Attempt to revert scheduling for this region.
318972a253aSDimitry Andric   void revertScheduling();
319972a253aSDimitry Andric 
320972a253aSDimitry Andric   void advanceRegion() { RegionIdx++; }
321972a253aSDimitry Andric 
322972a253aSDimitry Andric   virtual ~GCNSchedStage() = default;
323972a253aSDimitry Andric };
324972a253aSDimitry Andric 
325*bdd1243dSDimitry Andric class OccInitialScheduleStage : public GCNSchedStage {
326972a253aSDimitry Andric public:
327972a253aSDimitry Andric   bool shouldRevertScheduling(unsigned WavesAfter) override;
328972a253aSDimitry Andric 
329*bdd1243dSDimitry Andric   OccInitialScheduleStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG)
330972a253aSDimitry Andric       : GCNSchedStage(StageID, DAG) {}
331972a253aSDimitry Andric };
332972a253aSDimitry Andric 
333*bdd1243dSDimitry Andric class UnclusteredHighRPStage : public GCNSchedStage {
334972a253aSDimitry Andric private:
335*bdd1243dSDimitry Andric   // Save the initial occupancy before starting this stage.
336*bdd1243dSDimitry Andric   unsigned InitialOccupancy;
337972a253aSDimitry Andric 
338972a253aSDimitry Andric public:
339972a253aSDimitry Andric   bool initGCNSchedStage() override;
340972a253aSDimitry Andric 
341972a253aSDimitry Andric   void finalizeGCNSchedStage() override;
342972a253aSDimitry Andric 
343972a253aSDimitry Andric   bool initGCNRegion() override;
344972a253aSDimitry Andric 
345972a253aSDimitry Andric   bool shouldRevertScheduling(unsigned WavesAfter) override;
346972a253aSDimitry Andric 
347*bdd1243dSDimitry Andric   UnclusteredHighRPStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG)
348972a253aSDimitry Andric       : GCNSchedStage(StageID, DAG) {}
349972a253aSDimitry Andric };
350972a253aSDimitry Andric 
351972a253aSDimitry Andric // Retry function scheduling if we found resulting occupancy and it is
352972a253aSDimitry Andric // lower than used for other scheduling passes. This will give more freedom
353972a253aSDimitry Andric // to schedule low register pressure blocks.
354972a253aSDimitry Andric class ClusteredLowOccStage : public GCNSchedStage {
355972a253aSDimitry Andric public:
356972a253aSDimitry Andric   bool initGCNSchedStage() override;
357972a253aSDimitry Andric 
358972a253aSDimitry Andric   bool initGCNRegion() override;
359972a253aSDimitry Andric 
360972a253aSDimitry Andric   bool shouldRevertScheduling(unsigned WavesAfter) override;
361972a253aSDimitry Andric 
362972a253aSDimitry Andric   ClusteredLowOccStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG)
363972a253aSDimitry Andric       : GCNSchedStage(StageID, DAG) {}
364972a253aSDimitry Andric };
365972a253aSDimitry Andric 
366972a253aSDimitry Andric class PreRARematStage : public GCNSchedStage {
367972a253aSDimitry Andric private:
36881ad6265SDimitry Andric   // Each region at MinOccupancy will have their own list of trivially
36981ad6265SDimitry Andric   // rematerializable instructions we can remat to reduce RP. The list maps an
37081ad6265SDimitry Andric   // instruction to the position we should remat before, usually the MI using
37181ad6265SDimitry Andric   // the rematerializable instruction.
37281ad6265SDimitry Andric   MapVector<unsigned, MapVector<MachineInstr *, MachineInstr *>>
37381ad6265SDimitry Andric       RematerializableInsts;
37481ad6265SDimitry Andric 
37581ad6265SDimitry Andric   // Map a trivially remateriazable def to a list of regions at MinOccupancy
37681ad6265SDimitry Andric   // that has the defined reg as a live-in.
37781ad6265SDimitry Andric   DenseMap<MachineInstr *, SmallVector<unsigned, 4>> RematDefToLiveInRegions;
37881ad6265SDimitry Andric 
37981ad6265SDimitry Andric   // Collect all trivially rematerializable VGPR instructions with a single def
38081ad6265SDimitry Andric   // and single use outside the defining block into RematerializableInsts.
38181ad6265SDimitry Andric   void collectRematerializableInstructions();
38281ad6265SDimitry Andric 
383fcaf7f86SDimitry Andric   bool isTriviallyReMaterializable(const MachineInstr &MI);
38481ad6265SDimitry Andric 
38581ad6265SDimitry Andric   // TODO: Should also attempt to reduce RP of SGPRs and AGPRs
38681ad6265SDimitry Andric   // Attempt to reduce RP of VGPR by sinking trivially rematerializable
38781ad6265SDimitry Andric   // instructions. Returns true if we were able to sink instruction(s).
38881ad6265SDimitry Andric   bool sinkTriviallyRematInsts(const GCNSubtarget &ST,
38981ad6265SDimitry Andric                                const TargetInstrInfo *TII);
39081ad6265SDimitry Andric 
3910b57cec5SDimitry Andric public:
392972a253aSDimitry Andric   bool initGCNSchedStage() override;
3930b57cec5SDimitry Andric 
394972a253aSDimitry Andric   bool initGCNRegion() override;
3950b57cec5SDimitry Andric 
396972a253aSDimitry Andric   bool shouldRevertScheduling(unsigned WavesAfter) override;
397972a253aSDimitry Andric 
398972a253aSDimitry Andric   PreRARematStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG)
399972a253aSDimitry Andric       : GCNSchedStage(StageID, DAG) {}
4000b57cec5SDimitry Andric };
4010b57cec5SDimitry Andric 
402*bdd1243dSDimitry Andric class ILPInitialScheduleStage : public GCNSchedStage {
403*bdd1243dSDimitry Andric public:
404*bdd1243dSDimitry Andric   bool shouldRevertScheduling(unsigned WavesAfter) override;
405*bdd1243dSDimitry Andric 
406*bdd1243dSDimitry Andric   ILPInitialScheduleStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG)
407*bdd1243dSDimitry Andric       : GCNSchedStage(StageID, DAG) {}
408*bdd1243dSDimitry Andric };
409*bdd1243dSDimitry Andric 
410*bdd1243dSDimitry Andric class GCNPostScheduleDAGMILive final : public ScheduleDAGMI {
411*bdd1243dSDimitry Andric private:
412*bdd1243dSDimitry Andric   std::vector<std::unique_ptr<ScheduleDAGMutation>> SavedMutations;
413*bdd1243dSDimitry Andric 
414*bdd1243dSDimitry Andric   bool HasIGLPInstrs = false;
415*bdd1243dSDimitry Andric 
416*bdd1243dSDimitry Andric public:
417*bdd1243dSDimitry Andric   void schedule() override;
418*bdd1243dSDimitry Andric 
419*bdd1243dSDimitry Andric   void finalizeSchedule() override;
420*bdd1243dSDimitry Andric 
421*bdd1243dSDimitry Andric   GCNPostScheduleDAGMILive(MachineSchedContext *C,
422*bdd1243dSDimitry Andric                            std::unique_ptr<MachineSchedStrategy> S,
423*bdd1243dSDimitry Andric                            bool RemoveKillFlags);
424*bdd1243dSDimitry Andric };
425*bdd1243dSDimitry Andric 
4260b57cec5SDimitry Andric } // End namespace llvm
4270b57cec5SDimitry Andric 
42804eeddc0SDimitry Andric #endif // LLVM_LIB_TARGET_AMDGPU_GCNSCHEDSTRATEGY_H
429