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