xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZMachineScheduler.h (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1 //==- SystemZMachineScheduler.h - SystemZ Scheduler Interface ----*- 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 // -------------------------- Post RA scheduling ---------------------------- //
10 // SystemZPostRASchedStrategy is a scheduling strategy which is plugged into
11 // the MachineScheduler. It has a sorted Available set of SUs and a pickNode()
12 // implementation that looks to optimize decoder grouping and balance the
13 // usage of processor resources. Scheduler states are saved for the end
14 // region of each MBB, so that a successor block can learn from it.
15 //===----------------------------------------------------------------------===//
16 
17 #ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H
18 #define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H
19 
20 #include "SystemZHazardRecognizer.h"
21 #include "llvm/CodeGen/MachineScheduler.h"
22 #include "llvm/CodeGen/ScheduleDAG.h"
23 #include <set>
24 
25 using namespace llvm;
26 
27 namespace llvm {
28 
29 /// A MachineSchedStrategy implementation for SystemZ post RA scheduling.
30 class SystemZPostRASchedStrategy : public MachineSchedStrategy {
31 
32   const MachineLoopInfo *MLI;
33   const SystemZInstrInfo *TII;
34 
35   // A SchedModel is needed before any DAG is built while advancing past
36   // non-scheduled instructions, so it would not always be possible to call
37   // DAG->getSchedClass(SU).
38   TargetSchedModel SchedModel;
39 
40   /// A candidate during instruction evaluation.
41   struct Candidate {
42     SUnit *SU = nullptr;
43 
44     /// The decoding cost.
45     int GroupingCost = 0;
46 
47     /// The processor resources cost.
48     int ResourcesCost = 0;
49 
50     Candidate() = default;
51     Candidate(SUnit *SU_, SystemZHazardRecognizer &HazardRec);
52 
53     // Compare two candidates.
54     bool operator<(const Candidate &other);
55 
56     // Check if this node is free of cost ("as good as any").
noCostCandidate57     bool noCost() const {
58       return (GroupingCost <= 0 && !ResourcesCost);
59     }
60 
61 #ifndef NDEBUG
dumpCostsCandidate62     void dumpCosts() {
63       if (GroupingCost != 0)
64         dbgs() << "  Grouping cost:" << GroupingCost;
65       if (ResourcesCost != 0)
66         dbgs() << "  Resource cost:" << ResourcesCost;
67     }
68 #endif
69   };
70 
71   // A sorter for the Available set that makes sure that SUs are considered
72   // in the best order.
73   struct SUSorter {
operatorSUSorter74     bool operator() (SUnit *lhs, SUnit *rhs) const {
75       if (lhs->isScheduleHigh && !rhs->isScheduleHigh)
76         return true;
77       if (!lhs->isScheduleHigh && rhs->isScheduleHigh)
78         return false;
79 
80       if (lhs->getHeight() > rhs->getHeight())
81         return true;
82       else if (lhs->getHeight() < rhs->getHeight())
83         return false;
84 
85       return (lhs->NodeNum < rhs->NodeNum);
86     }
87   };
88   // A set of SUs with a sorter and dump method.
89   struct SUSet : std::set<SUnit*, SUSorter> {
90     #ifndef NDEBUG
91     void dump(SystemZHazardRecognizer &HazardRec) const;
92     #endif
93   };
94 
95   /// The set of available SUs to schedule next.
96   SUSet Available;
97 
98   /// Current MBB
99   MachineBasicBlock *MBB;
100 
101   /// Maintain hazard recognizers for all blocks, so that the scheduler state
102   /// can be maintained past BB boundaries when appropariate.
103   typedef std::map<MachineBasicBlock*, SystemZHazardRecognizer*> MBB2HazRec;
104   MBB2HazRec SchedStates;
105 
106   /// Pointer to the HazardRecognizer that tracks the scheduler state for
107   /// the current region.
108   SystemZHazardRecognizer *HazardRec;
109 
110   /// Update the scheduler state by emitting (non-scheduled) instructions
111   /// up to, but not including, NextBegin.
112   void advanceTo(MachineBasicBlock::iterator NextBegin);
113 
114 public:
115   SystemZPostRASchedStrategy(const MachineSchedContext *C);
116   virtual ~SystemZPostRASchedStrategy();
117 
118   /// Called for a region before scheduling.
119   void initPolicy(MachineBasicBlock::iterator Begin,
120                   MachineBasicBlock::iterator End,
121                   unsigned NumRegionInstrs) override;
122 
123   /// PostRA scheduling does not track pressure.
shouldTrackPressure()124   bool shouldTrackPressure() const override { return false; }
125 
126   // Process scheduling regions top-down so that scheduler states can be
127   // transferrred over scheduling boundaries.
doMBBSchedRegionsTopDown()128   bool doMBBSchedRegionsTopDown() const override { return true; }
129 
130   void initialize(ScheduleDAGMI *dag) override;
131 
132   /// Tell the strategy that MBB is about to be processed.
133   void enterMBB(MachineBasicBlock *NextMBB) override;
134 
135   /// Tell the strategy that current MBB is done.
136   void leaveMBB() override;
137 
138   /// Pick the next node to schedule, or return NULL.
139   SUnit *pickNode(bool &IsTopNode) override;
140 
141   /// ScheduleDAGMI has scheduled an instruction - tell HazardRec
142   /// about it.
143   void schedNode(SUnit *SU, bool IsTopNode) override;
144 
145   /// SU has had all predecessor dependencies resolved. Put it into
146   /// Available.
147   void releaseTopNode(SUnit *SU) override;
148 
149   /// Currently only scheduling top-down, so this method is empty.
releaseBottomNode(SUnit * SU)150   void releaseBottomNode(SUnit *SU) override {};
151 };
152 
153 } // end namespace llvm
154 
155 #endif // LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H
156