xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AMDGPU/GCNSchedStrategy.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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;
25bdd1243dSDimitry Andric class GCNSchedStage;
26bdd1243dSDimitry Andric 
27bdd1243dSDimitry Andric enum class GCNSchedStageID : unsigned {
28bdd1243dSDimitry Andric   OccInitialSchedule = 0,
29bdd1243dSDimitry Andric   UnclusteredHighRPReschedule = 1,
30bdd1243dSDimitry Andric   ClusteredLowOccupancyReschedule = 2,
31bdd1243dSDimitry Andric   PreRARematerialize = 3,
32bdd1243dSDimitry Andric   ILPInitialSchedule = 4
33bdd1243dSDimitry Andric };
34bdd1243dSDimitry Andric 
35bdd1243dSDimitry Andric #ifndef NDEBUG
36bdd1243dSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const GCNSchedStageID &StageID);
37bdd1243dSDimitry 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
41bdd1243dSDimitry Andric /// heuristics to determine excess/critical pressure sets.
42bdd1243dSDimitry Andric class GCNSchedStrategy : public GenericScheduler {
43bdd1243dSDimitry Andric protected:
440b57cec5SDimitry Andric   SUnit *pickNodeBidirectional(bool &IsTopNode);
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   void pickNodeFromQueue(SchedBoundary &Zone, const CandPolicy &ZonePolicy,
470b57cec5SDimitry Andric                          const RegPressureTracker &RPTracker,
48*0fca6ea1SDimitry Andric                          SchedCandidate &Cand, bool IsBottomUp);
490b57cec5SDimitry Andric 
50*0fca6ea1SDimitry Andric   void initCandidate(SchedCandidate &Cand, SUnit *SU, bool AtTop,
51*0fca6ea1SDimitry Andric                      const RegPressureTracker &RPTracker,
52*0fca6ea1SDimitry Andric                      const SIRegisterInfo *SRI, unsigned SGPRPressure,
53*0fca6ea1SDimitry Andric                      unsigned VGPRPressure, bool IsBottomUp);
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 
67bdd1243dSDimitry Andric   // Scheduling stages for this strategy.
68bdd1243dSDimitry Andric   SmallVector<GCNSchedStageID, 4> SchedStages;
69fe6060f1SDimitry Andric 
70bdd1243dSDimitry Andric   // Pointer to the current SchedStageID.
71bdd1243dSDimitry Andric   SmallVectorImpl<GCNSchedStageID>::iterator CurrentStage = nullptr;
72bdd1243dSDimitry Andric 
73bdd1243dSDimitry Andric public:
74bdd1243dSDimitry Andric   // schedule() have seen register pressure over the critical limits and had to
75bdd1243dSDimitry Andric   // track register pressure for actual scheduling heuristics.
76bdd1243dSDimitry Andric   bool HasHighPressure;
77bdd1243dSDimitry Andric 
78bdd1243dSDimitry Andric   // Schedule known to have excess register pressure. Be more conservative in
79bdd1243dSDimitry Andric   // increasing ILP and preserving VGPRs.
80bdd1243dSDimitry Andric   bool KnownExcessRP = false;
81bdd1243dSDimitry Andric 
82bdd1243dSDimitry Andric   // An error margin is necessary because of poor performance of the generic RP
83bdd1243dSDimitry Andric   // tracker and can be adjusted up for tuning heuristics to try and more
84bdd1243dSDimitry Andric   // aggressively reduce register pressure.
85bdd1243dSDimitry Andric   unsigned ErrorMargin = 3;
86bdd1243dSDimitry Andric 
87bdd1243dSDimitry Andric   // Bias for SGPR limits under a high register pressure.
88bdd1243dSDimitry Andric   const unsigned HighRPSGPRBias = 7;
89bdd1243dSDimitry Andric 
90bdd1243dSDimitry Andric   // Bias for VGPR limits under a high register pressure.
91bdd1243dSDimitry Andric   const unsigned HighRPVGPRBias = 7;
92fe6060f1SDimitry Andric 
93972a253aSDimitry Andric   unsigned SGPRCriticalLimit;
940b57cec5SDimitry Andric 
95972a253aSDimitry Andric   unsigned VGPRCriticalLimit;
96972a253aSDimitry Andric 
97bdd1243dSDimitry Andric   unsigned SGPRLimitBias = 0;
98bdd1243dSDimitry Andric 
99bdd1243dSDimitry Andric   unsigned VGPRLimitBias = 0;
100bdd1243dSDimitry Andric 
101bdd1243dSDimitry 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; }
110bdd1243dSDimitry Andric 
111bdd1243dSDimitry Andric   GCNSchedStageID getCurrentStage();
112bdd1243dSDimitry Andric 
113bdd1243dSDimitry Andric   // Advances stage. Returns true if there are remaining stages.
114bdd1243dSDimitry Andric   bool advanceStage();
115bdd1243dSDimitry Andric 
116bdd1243dSDimitry Andric   bool hasNextStage() const;
117bdd1243dSDimitry Andric 
118bdd1243dSDimitry Andric   GCNSchedStageID getNextStage() const;
1190b57cec5SDimitry Andric };
1200b57cec5SDimitry Andric 
121bdd1243dSDimitry Andric /// The goal of this scheduling strategy is to maximize kernel occupancy (i.e.
122bdd1243dSDimitry Andric /// maximum number of waves per simd).
123bdd1243dSDimitry Andric class GCNMaxOccupancySchedStrategy final : public GCNSchedStrategy {
124bdd1243dSDimitry Andric public:
125bdd1243dSDimitry Andric   GCNMaxOccupancySchedStrategy(const MachineSchedContext *C);
1265ffd83dbSDimitry Andric };
1275ffd83dbSDimitry Andric 
128bdd1243dSDimitry Andric /// The goal of this scheduling strategy is to maximize ILP for a single wave
129bdd1243dSDimitry Andric /// (i.e. latency hiding).
130bdd1243dSDimitry Andric class GCNMaxILPSchedStrategy final : public GCNSchedStrategy {
131bdd1243dSDimitry Andric protected:
132bdd1243dSDimitry Andric   bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand,
133bdd1243dSDimitry Andric                     SchedBoundary *Zone) const override;
134972a253aSDimitry Andric 
135bdd1243dSDimitry Andric public:
136bdd1243dSDimitry Andric   GCNMaxILPSchedStrategy(const MachineSchedContext *C);
137bdd1243dSDimitry Andric };
138bdd1243dSDimitry Andric 
139bdd1243dSDimitry Andric class ScheduleMetrics {
140bdd1243dSDimitry Andric   unsigned ScheduleLength;
141bdd1243dSDimitry Andric   unsigned BubbleCycles;
142bdd1243dSDimitry Andric 
143bdd1243dSDimitry Andric public:
144bdd1243dSDimitry Andric   ScheduleMetrics() {}
145bdd1243dSDimitry Andric   ScheduleMetrics(unsigned L, unsigned BC)
146bdd1243dSDimitry Andric       : ScheduleLength(L), BubbleCycles(BC) {}
147bdd1243dSDimitry Andric   unsigned getLength() const { return ScheduleLength; }
148bdd1243dSDimitry Andric   unsigned getBubbles() const { return BubbleCycles; }
149bdd1243dSDimitry Andric   unsigned getMetric() const {
150bdd1243dSDimitry Andric     unsigned Metric = (BubbleCycles * ScaleFactor) / ScheduleLength;
151bdd1243dSDimitry Andric     // Metric is zero if the amount of bubbles is less than 1% which is too
152bdd1243dSDimitry Andric     // small. So, return 1.
153bdd1243dSDimitry Andric     return Metric ? Metric : 1;
154972a253aSDimitry Andric   }
155bdd1243dSDimitry Andric   static const unsigned ScaleFactor;
156bdd1243dSDimitry Andric };
157972a253aSDimitry Andric 
158bdd1243dSDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const ScheduleMetrics &Sm) {
159bdd1243dSDimitry Andric   dbgs() << "\n Schedule Metric (scaled by "
160bdd1243dSDimitry Andric          << ScheduleMetrics::ScaleFactor
161bdd1243dSDimitry Andric          << " ) is: " << Sm.getMetric() << " [ " << Sm.getBubbles() << "/"
162bdd1243dSDimitry Andric          << Sm.getLength() << " ]\n";
163bdd1243dSDimitry Andric   return OS;
164972a253aSDimitry Andric }
165972a253aSDimitry Andric 
166972a253aSDimitry Andric class GCNScheduleDAGMILive final : public ScheduleDAGMILive {
167972a253aSDimitry Andric   friend class GCNSchedStage;
168bdd1243dSDimitry Andric   friend class OccInitialScheduleStage;
169bdd1243dSDimitry Andric   friend class UnclusteredHighRPStage;
170972a253aSDimitry Andric   friend class ClusteredLowOccStage;
171972a253aSDimitry Andric   friend class PreRARematStage;
172bdd1243dSDimitry 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 
195bdd1243dSDimitry Andric   // Record regions with excess register pressure over the physical register
196bdd1243dSDimitry Andric   // limit. Register pressure in these regions usually will result in spilling.
197bdd1243dSDimitry Andric   BitVector RegionsWithExcessRP;
198bdd1243dSDimitry Andric 
19981ad6265SDimitry Andric   // Regions that has the same occupancy as the latest MinOccupancy
20081ad6265SDimitry Andric   BitVector RegionsWithMinOcc;
20181ad6265SDimitry Andric 
202bdd1243dSDimitry Andric   // Regions that have IGLP instructions (SCHED_GROUP_BARRIER or IGLP_OPT).
203bdd1243dSDimitry Andric   BitVector RegionsWithIGLPInstrs;
204bdd1243dSDimitry 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 
233bdd1243dSDimitry Andric   std::unique_ptr<GCNSchedStage> createSchedStage(GCNSchedStageID SchedStageID);
234bdd1243dSDimitry 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 
249bdd1243dSDimitry 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 
274bdd1243dSDimitry Andric   std::vector<std::unique_ptr<ScheduleDAGMutation>> SavedMutations;
275bdd1243dSDimitry 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.
294bdd1243dSDimitry Andric   void finalizeGCNRegion();
295972a253aSDimitry Andric 
296972a253aSDimitry Andric   // Check result of scheduling.
297972a253aSDimitry Andric   void checkScheduling();
298972a253aSDimitry Andric 
299bdd1243dSDimitry Andric   // computes the given schedule virtual execution time in clocks
300bdd1243dSDimitry Andric   ScheduleMetrics getScheduleMetrics(const std::vector<SUnit> &InputSchedule);
301bdd1243dSDimitry Andric   ScheduleMetrics getScheduleMetrics(const GCNScheduleDAGMILive &DAG);
302bdd1243dSDimitry Andric   unsigned computeSUnitReadyCycle(const SUnit &SU, unsigned CurrCycle,
303bdd1243dSDimitry Andric                                   DenseMap<unsigned, unsigned> &ReadyCycles,
304bdd1243dSDimitry Andric                                   const TargetSchedModel &SM);
305bdd1243dSDimitry Andric 
306972a253aSDimitry Andric   // Returns true if scheduling should be reverted.
307972a253aSDimitry Andric   virtual bool shouldRevertScheduling(unsigned WavesAfter);
308972a253aSDimitry Andric 
309bdd1243dSDimitry Andric   // Returns true if current region has known excess pressure.
310bdd1243dSDimitry Andric   bool isRegionWithExcessRP() const {
311bdd1243dSDimitry Andric     return DAG.RegionsWithExcessRP[RegionIdx];
312bdd1243dSDimitry Andric   }
313bdd1243dSDimitry 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 
325bdd1243dSDimitry Andric class OccInitialScheduleStage : public GCNSchedStage {
326972a253aSDimitry Andric public:
327972a253aSDimitry Andric   bool shouldRevertScheduling(unsigned WavesAfter) override;
328972a253aSDimitry Andric 
329bdd1243dSDimitry Andric   OccInitialScheduleStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG)
330972a253aSDimitry Andric       : GCNSchedStage(StageID, DAG) {}
331972a253aSDimitry Andric };
332972a253aSDimitry Andric 
333bdd1243dSDimitry Andric class UnclusteredHighRPStage : public GCNSchedStage {
334972a253aSDimitry Andric private:
335bdd1243dSDimitry Andric   // Save the initial occupancy before starting this stage.
336bdd1243dSDimitry 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 
347bdd1243dSDimitry 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 
375*0fca6ea1SDimitry Andric   // Map a trivially rematerializable 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 
402bdd1243dSDimitry Andric class ILPInitialScheduleStage : public GCNSchedStage {
403bdd1243dSDimitry Andric public:
404bdd1243dSDimitry Andric   bool shouldRevertScheduling(unsigned WavesAfter) override;
405bdd1243dSDimitry Andric 
406bdd1243dSDimitry Andric   ILPInitialScheduleStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG)
407bdd1243dSDimitry Andric       : GCNSchedStage(StageID, DAG) {}
408bdd1243dSDimitry Andric };
409bdd1243dSDimitry Andric 
410bdd1243dSDimitry Andric class GCNPostScheduleDAGMILive final : public ScheduleDAGMI {
411bdd1243dSDimitry Andric private:
412bdd1243dSDimitry Andric   std::vector<std::unique_ptr<ScheduleDAGMutation>> SavedMutations;
413bdd1243dSDimitry Andric 
414bdd1243dSDimitry Andric   bool HasIGLPInstrs = false;
415bdd1243dSDimitry Andric 
416bdd1243dSDimitry Andric public:
417bdd1243dSDimitry Andric   void schedule() override;
418bdd1243dSDimitry Andric 
419bdd1243dSDimitry Andric   void finalizeSchedule() override;
420bdd1243dSDimitry Andric 
421bdd1243dSDimitry Andric   GCNPostScheduleDAGMILive(MachineSchedContext *C,
422bdd1243dSDimitry Andric                            std::unique_ptr<MachineSchedStrategy> S,
423bdd1243dSDimitry Andric                            bool RemoveKillFlags);
424bdd1243dSDimitry Andric };
425bdd1243dSDimitry Andric 
4260b57cec5SDimitry Andric } // End namespace llvm
4270b57cec5SDimitry Andric 
42804eeddc0SDimitry Andric #endif // LLVM_LIB_TARGET_AMDGPU_GCNSCHEDSTRATEGY_H
429