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// -------------------------- Pre RA scheduling ----------------------------- //
10//
11// SystemZPreRASchedStrategy reduces register pressure by scheduling a (live)
12// definition low if it does not cause another register to become live (all
13// uses live). In most regions it then reduces the scheduled latency but only
14// if the SU that is higher (by Height) than the scheduled latency is as well
15// lower (by Depth) than the remaining latency. It also helps copy coalescing
16// and comparison elimination.
17//
18// -------------------------- Post RA scheduling ---------------------------- //
19//
20// SystemZPostRASchedStrategy is a scheduling strategy which is plugged into
21// the MachineScheduler. It has a sorted Available set of SUs and a pickNode()
22// implementation that looks to optimize decoder grouping and balance the
23// usage of processor resources. Scheduler states are saved for the end
24// region of each MBB, so that a successor block can learn from it.
25//
26//----------------------------------------------------------------------------//
27
28#ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H
29#define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H
30
31#include "SystemZHazardRecognizer.h"
32#include "llvm/CodeGen/MachineScheduler.h"
33#include "llvm/CodeGen/ScheduleDAG.h"
34#include <set>
35
36namespace llvm {
37
38/// A MachineSchedStrategy implementation for SystemZ pre RA scheduling.
39class SystemZPreRASchedStrategy : public GenericScheduler {
40 Register Cmp0SrcReg;
41 // Return true if MI defines the Cmp0SrcReg that is used by a scheduled
42 // compare with 0. If CCDef is true MI must also have an implicit def of CC.
43 bool definesCmp0Src(const MachineInstr *MI, bool CCDef = true) const;
44
45 // SUs that have a Height of at least this value will not be scheduled
46 // "low" to reduce liveness.
47 unsigned LivenessHeightCutOff;
48
49 // Return true if the instruction defines a register while all use operands
50 // are already live.
51 bool closesLiveRange(const SUnit *SU, ScheduleDAGMILive *DAG) const;
52
53protected:
54 bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand,
55 SchedBoundary *Zone) const override;
56
57public:
58 SystemZPreRASchedStrategy(const MachineSchedContext *C)
59 : GenericScheduler(C) {}
60
61 void initPolicy(MachineBasicBlock::iterator Begin,
62 MachineBasicBlock::iterator End,
63 unsigned NumRegionInstrs) override;
64 void initialize(ScheduleDAGMI *dag) override;
65 void schedNode(SUnit *SU, bool IsTopNode) override;
66};
67
68/// A MachineSchedStrategy implementation for SystemZ post RA scheduling.
69class SystemZPostRASchedStrategy : public MachineSchedStrategy {
70
71 const MachineLoopInfo *MLI;
72 const SystemZInstrInfo *TII;
73
74 // A SchedModel is needed before any DAG is built while advancing past
75 // non-scheduled instructions, so it would not always be possible to call
76 // DAG->getSchedClass(SU).
77 TargetSchedModel SchedModel;
78
79 /// A candidate during instruction evaluation.
80 struct Candidate {
81 SUnit *SU = nullptr;
82
83 /// The decoding cost.
84 int GroupingCost = 0;
85
86 /// The processor resources cost.
87 int ResourcesCost = 0;
88
89 Candidate() = default;
90 Candidate(SUnit *SU_, SystemZHazardRecognizer &HazardRec);
91
92 // Compare two candidates.
93 bool operator<(const Candidate &other);
94
95 // Check if this node is free of cost ("as good as any").
96 bool noCost() const {
97 return (GroupingCost <= 0 && !ResourcesCost);
98 }
99
100#ifndef NDEBUG
101 void dumpCosts() {
102 if (GroupingCost != 0)
103 dbgs() << " Grouping cost:" << GroupingCost;
104 if (ResourcesCost != 0)
105 dbgs() << " Resource cost:" << ResourcesCost;
106 }
107#endif
108 };
109
110 // A sorter for the Available set that makes sure that SUs are considered
111 // in the best order.
112 struct SUSorter {
113 bool operator() (SUnit *lhs, SUnit *rhs) const {
114 if (lhs->isScheduleHigh && !rhs->isScheduleHigh)
115 return true;
116 if (!lhs->isScheduleHigh && rhs->isScheduleHigh)
117 return false;
118
119 if (lhs->getHeight() > rhs->getHeight())
120 return true;
121 else if (lhs->getHeight() < rhs->getHeight())
122 return false;
123
124 return (lhs->NodeNum < rhs->NodeNum);
125 }
126 };
127 // A set of SUs with a sorter and dump method.
128 struct SUSet : std::set<SUnit*, SUSorter> {
129 #ifndef NDEBUG
130 void dump(SystemZHazardRecognizer &HazardRec) const;
131 #endif
132 };
133
134 /// The set of available SUs to schedule next.
135 SUSet Available;
136
137 /// Current MBB
138 MachineBasicBlock *MBB;
139
140 /// Maintain hazard recognizers for all blocks, so that the scheduler state
141 /// can be maintained past BB boundaries when appropariate.
142 typedef std::map<MachineBasicBlock*, SystemZHazardRecognizer*> MBB2HazRec;
143 MBB2HazRec SchedStates;
144
145 /// Pointer to the HazardRecognizer that tracks the scheduler state for
146 /// the current region.
147 SystemZHazardRecognizer *HazardRec;
148
149 /// Update the scheduler state by emitting (non-scheduled) instructions
150 /// up to, but not including, NextBegin.
151 void advanceTo(MachineBasicBlock::iterator NextBegin);
152
153public:
154 SystemZPostRASchedStrategy(const MachineSchedContext *C);
155 ~SystemZPostRASchedStrategy() override;
156
157 /// Called for a region before scheduling.
158 void initPolicy(MachineBasicBlock::iterator Begin,
159 MachineBasicBlock::iterator End,
160 unsigned NumRegionInstrs) override;
161
162 /// PostRA scheduling does not track pressure.
163 bool shouldTrackPressure() const override { return false; }
164
165 // Process scheduling regions top-down so that scheduler states can be
166 // transferrred over scheduling boundaries.
167 bool doMBBSchedRegionsTopDown() const override { return true; }
168
169 void initialize(ScheduleDAGMI *dag) override;
170
171 /// Tell the strategy that MBB is about to be processed.
172 void enterMBB(MachineBasicBlock *NextMBB) override;
173
174 /// Tell the strategy that current MBB is done.
175 void leaveMBB() override;
176
177 /// Pick the next node to schedule, or return NULL.
178 SUnit *pickNode(bool &IsTopNode) override;
179
180 /// ScheduleDAGMI has scheduled an instruction - tell HazardRec
181 /// about it.
182 void schedNode(SUnit *SU, bool IsTopNode) override;
183
184 /// SU has had all predecessor dependencies resolved. Put it into
185 /// Available.
186 void releaseTopNode(SUnit *SU) override;
187
188 /// Currently only scheduling top-down, so this method is empty.
189 void releaseBottomNode(SUnit *SU) override {};
190};
191
192} // end namespace llvm
193
194#endif // LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H
195