1 //===- GCNIterativeScheduler.h - GCN Scheduler ------------------*- 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 ///
9 /// \file
10 /// This file defines the class GCNIterativeScheduler, which uses an iterative
11 /// approach to find a best schedule for GCN architecture. It basically makes
12 /// use of various lightweight schedules, scores them, chooses best one based on
13 /// their scores, and finally implements the chosen one.
14 ///
15 //===----------------------------------------------------------------------===//
16 
17 #ifndef LLVM_LIB_TARGET_AMDGPU_GCNITERATIVESCHEDULER_H
18 #define LLVM_LIB_TARGET_AMDGPU_GCNITERATIVESCHEDULER_H
19 
20 #include "GCNRegPressure.h"
21 #include "llvm/ADT/ArrayRef.h"
22 #include "llvm/CodeGen/MachineBasicBlock.h"
23 #include "llvm/CodeGen/MachineScheduler.h"
24 #include "llvm/Support/Allocator.h"
25 #include <limits>
26 #include <memory>
27 #include <vector>
28 
29 namespace llvm {
30 
31 class MachineInstr;
32 class SUnit;
33 class raw_ostream;
34 
35 class GCNIterativeScheduler : public ScheduleDAGMILive {
36   using BaseClass = ScheduleDAGMILive;
37 
38 public:
39   enum StrategyKind {
40     SCHEDULE_MINREGONLY,
41     SCHEDULE_MINREGFORCED,
42     SCHEDULE_LEGACYMAXOCCUPANCY,
43     SCHEDULE_ILP
44   };
45 
46   GCNIterativeScheduler(MachineSchedContext *C,
47                         StrategyKind S);
48 
49   void schedule() override;
50 
51   void enterRegion(MachineBasicBlock *BB,
52                    MachineBasicBlock::iterator Begin,
53                    MachineBasicBlock::iterator End,
54                    unsigned RegionInstrs) override;
55 
56   void finalizeSchedule() override;
57 
58 protected:
59   using ScheduleRef = ArrayRef<const SUnit *>;
60 
61   struct TentativeSchedule {
62     std::vector<MachineInstr *> Schedule;
63     GCNRegPressure MaxPressure;
64   };
65 
66   struct Region {
67     // Fields except for BestSchedule are supposed to reflect current IR state
68     // `const` fields are to emphasize they shouldn't change for any schedule.
69     MachineBasicBlock::iterator Begin;
70     // End is either a boundary instruction or end of basic block
71     const MachineBasicBlock::iterator End;
72     const unsigned NumRegionInstrs;
73     GCNRegPressure MaxPressure;
74 
75     // best schedule for the region so far (not scheduled yet)
76     std::unique_ptr<TentativeSchedule> BestSchedule;
77   };
78 
79   SpecificBumpPtrAllocator<Region> Alloc;
80   std::vector<Region*> Regions;
81 
82   MachineSchedContext *Context;
83   const StrategyKind Strategy;
84   mutable GCNUpwardRPTracker UPTracker;
85 
86   class BuildDAG;
87   class OverrideLegacyStrategy;
88 
89   template <typename Range>
90   GCNRegPressure getSchedulePressure(const Region &R,
91                                      Range &&Schedule) const;
92 
93   GCNRegPressure getRegionPressure(MachineBasicBlock::iterator Begin,
94                                    MachineBasicBlock::iterator End) const;
95 
96   GCNRegPressure getRegionPressure(const Region &R) const {
97     return getRegionPressure(R.Begin, R.End);
98   }
99 
100   void setBestSchedule(Region &R,
101                        ScheduleRef Schedule,
102                        const GCNRegPressure &MaxRP = GCNRegPressure());
103 
104   void scheduleBest(Region &R);
105 
106   std::vector<MachineInstr*> detachSchedule(ScheduleRef Schedule) const;
107 
108   void sortRegionsByPressure(unsigned TargetOcc);
109 
110   template <typename Range>
111   void scheduleRegion(Region &R, Range &&Schedule,
112                       const GCNRegPressure &MaxRP = GCNRegPressure());
113 
114   unsigned tryMaximizeOccupancy(unsigned TargetOcc =
115                                 std::numeric_limits<unsigned>::max());
116 
117   void scheduleLegacyMaxOccupancy(bool TryMaximizeOccupancy = true);
118   void scheduleMinReg(bool force = false);
119   void scheduleILP(bool TryMaximizeOccupancy = true);
120 
121   void printRegions(raw_ostream &OS) const;
122   void printSchedResult(raw_ostream &OS,
123                         const Region *R,
124                         const GCNRegPressure &RP) const;
125   void printSchedRP(raw_ostream &OS,
126                     const GCNRegPressure &Before,
127                     const GCNRegPressure &After) const;
128 };
129 
130 } // end namespace llvm
131 
132 #endif // LLVM_LIB_TARGET_AMDGPU_GCNITERATIVESCHEDULER_H
133