blob: 585a7858ad2b98d8ea1551128f99a6a2e6d8c256 [file] [log] [blame]
Eugene Zelenko3b873362017-09-28 22:27:31 +00001//===- HexagonMachineScheduler.h - Custom Hexagon MI scheduler --*- C++ -*-===//
Sergei Larin4d8986a2012-09-04 14:49:56 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Custom Hexagon MI scheduler.
11//
12//===----------------------------------------------------------------------===//
13
Benjamin Kramera7c40ef2014-08-13 16:26:38 +000014#ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONMACHINESCHEDULER_H
15#define LLVM_LIB_TARGET_HEXAGON_HEXAGONMACHINESCHEDULER_H
Sergei Larin4d8986a2012-09-04 14:49:56 +000016
Eugene Zelenko3b873362017-09-28 22:27:31 +000017#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/Twine.h"
19#include "llvm/CodeGen/DFAPacketizer.h"
Sergei Larin4d8986a2012-09-04 14:49:56 +000020#include "llvm/CodeGen/MachineScheduler.h"
Sergei Larin4d8986a2012-09-04 14:49:56 +000021#include "llvm/CodeGen/RegisterPressure.h"
Sergei Larin4d8986a2012-09-04 14:49:56 +000022#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
David Blaikie3f833ed2017-11-08 01:01:31 +000023#include "llvm/CodeGen/TargetInstrInfo.h"
Eugene Zelenko3b873362017-09-28 22:27:31 +000024#include "llvm/CodeGen/TargetSchedule.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000025#include "llvm/CodeGen/TargetSubtargetInfo.h"
Eugene Zelenko3b873362017-09-28 22:27:31 +000026#include <algorithm>
27#include <cassert>
28#include <limits>
29#include <memory>
30#include <vector>
Sergei Larin4d8986a2012-09-04 14:49:56 +000031
Sergei Larin4d8986a2012-09-04 14:49:56 +000032namespace llvm {
Sergei Larin4d8986a2012-09-04 14:49:56 +000033
Eugene Zelenko3b873362017-09-28 22:27:31 +000034class SUnit;
35
Sergei Larinef4cc112012-09-10 17:31:34 +000036class VLIWResourceModel {
37 /// ResourcesModel - Represents VLIW state.
Krzysztof Parzyszek14f10e02017-04-27 14:38:21 +000038 /// Not limited to VLIW targets per se, but assumes
Sergei Larinef4cc112012-09-10 17:31:34 +000039 /// definition of DFA by a target.
40 DFAPacketizer *ResourcesModel;
41
Andrew Trickdd79f0f2012-10-10 05:43:09 +000042 const TargetSchedModel *SchedModel;
Sergei Larinef4cc112012-09-10 17:31:34 +000043
44 /// Local packet/bundle model. Purely
45 /// internal to the MI schedulre at the time.
Eugene Zelenko3b873362017-09-28 22:27:31 +000046 std::vector<SUnit *> Packet;
Sergei Larinef4cc112012-09-10 17:31:34 +000047
48 /// Total packets created.
Eugene Zelenko3b873362017-09-28 22:27:31 +000049 unsigned TotalPackets = 0;
Sergei Larinef4cc112012-09-10 17:31:34 +000050
51public:
Eric Christopherf8b8e4a2015-02-02 22:11:40 +000052 VLIWResourceModel(const TargetSubtargetInfo &STI, const TargetSchedModel *SM)
Eugene Zelenko3b873362017-09-28 22:27:31 +000053 : SchedModel(SM) {
54 ResourcesModel = STI.getInstrInfo()->CreateTargetScheduleState(STI);
Sergei Larinef4cc112012-09-10 17:31:34 +000055
56 // This hard requirement could be relaxed,
57 // but for now do not let it proceed.
58 assert(ResourcesModel && "Unimplemented CreateTargetScheduleState.");
59
Andrew Trickdd79f0f2012-10-10 05:43:09 +000060 Packet.resize(SchedModel->getIssueWidth());
Sergei Larinef4cc112012-09-10 17:31:34 +000061 Packet.clear();
62 ResourcesModel->clearResources();
63 }
64
65 ~VLIWResourceModel() {
66 delete ResourcesModel;
67 }
68
69 void resetPacketState() {
70 Packet.clear();
71 }
72
73 void resetDFA() {
74 ResourcesModel->clearResources();
75 }
76
77 void reset() {
78 Packet.clear();
79 ResourcesModel->clearResources();
80 }
81
Krzysztof Parzyszekdca38312018-03-20 12:28:43 +000082 bool isResourceAvailable(SUnit *SU, bool IsTop);
83 bool reserveResources(SUnit *SU, bool IsTop);
Sergei Larinef4cc112012-09-10 17:31:34 +000084 unsigned getTotalPackets() const { return TotalPackets; }
David Majnemer0d955d02016-08-11 22:21:41 +000085 bool isInPacket(SUnit *SU) const { return is_contained(Packet, SU); }
Sergei Larinef4cc112012-09-10 17:31:34 +000086};
87
Andrew Trick7a8e1002012-09-11 00:39:15 +000088/// Extend the standard ScheduleDAGMI to provide more context and override the
89/// top-level schedule() driver.
Andrew Trickd7f890e2013-12-28 21:56:47 +000090class VLIWMachineScheduler : public ScheduleDAGMILive {
Sergei Larinef4cc112012-09-10 17:31:34 +000091public:
David Blaikie422b93d2014-04-21 20:32:32 +000092 VLIWMachineScheduler(MachineSchedContext *C,
93 std::unique_ptr<MachineSchedStrategy> S)
94 : ScheduleDAGMILive(C, std::move(S)) {}
Sergei Larinef4cc112012-09-10 17:31:34 +000095
96 /// Schedule - This is called back from ScheduleDAGInstrs::Run() when it's
97 /// time to do some work.
Craig Topperfd38cbe2014-08-30 16:48:34 +000098 void schedule() override;
Krzysztof Parzyszekdca38312018-03-20 12:28:43 +000099
100 RegisterClassInfo *getRegClassInfo() { return RegClassInfo; }
Krzysztof Parzyszek5ffd8082018-03-20 14:54:01 +0000101 int getBBSize() { return BB->size(); }
Sergei Larinef4cc112012-09-10 17:31:34 +0000102};
103
Krzysztof Parzyszek14f10e02017-04-27 14:38:21 +0000104//===----------------------------------------------------------------------===//
105// ConvergingVLIWScheduler - Implementation of the standard
106// MachineSchedStrategy.
107//===----------------------------------------------------------------------===//
108
Sergei Larinef4cc112012-09-10 17:31:34 +0000109/// ConvergingVLIWScheduler shrinks the unscheduled zone using heuristics
110/// to balance the schedule.
Sergei Larin4d8986a2012-09-04 14:49:56 +0000111class ConvergingVLIWScheduler : public MachineSchedStrategy {
Sergei Larinef4cc112012-09-10 17:31:34 +0000112 /// Store the state used by ConvergingVLIWScheduler heuristics, required
113 /// for the lifetime of one invocation of pickNode().
Sergei Larin4d8986a2012-09-04 14:49:56 +0000114 struct SchedCandidate {
115 // The best SUnit candidate.
Eugene Zelenko3b873362017-09-28 22:27:31 +0000116 SUnit *SU = nullptr;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000117
118 // Register pressure values for the best candidate.
119 RegPressureDelta RPDelta;
120
121 // Best scheduling cost.
Eugene Zelenko3b873362017-09-28 22:27:31 +0000122 int SCost = 0;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000123
Eugene Zelenko3b873362017-09-28 22:27:31 +0000124 SchedCandidate() = default;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000125 };
126 /// Represent the type of SchedCandidate found within a single queue.
127 enum CandResult {
128 NoCand, NodeOrder, SingleExcess, SingleCritical, SingleMax, MultiPressure,
Krzysztof Parzyszek65059ee2018-03-20 19:26:27 +0000129 BestCost, Weak};
Sergei Larin4d8986a2012-09-04 14:49:56 +0000130
131 /// Each Scheduling boundary is associated with ready queues. It tracks the
132 /// current cycle in whichever direction at has moved, and maintains the state
133 /// of "hazards" and other interlocks at the current cycle.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000134 struct VLIWSchedBoundary {
Eugene Zelenko3b873362017-09-28 22:27:31 +0000135 VLIWMachineScheduler *DAG = nullptr;
136 const TargetSchedModel *SchedModel = nullptr;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000137
138 ReadyQueue Available;
139 ReadyQueue Pending;
Eugene Zelenko3b873362017-09-28 22:27:31 +0000140 bool CheckPending = false;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000141
Eugene Zelenko3b873362017-09-28 22:27:31 +0000142 ScheduleHazardRecognizer *HazardRec = nullptr;
143 VLIWResourceModel *ResourceModel = nullptr;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000144
Eugene Zelenko3b873362017-09-28 22:27:31 +0000145 unsigned CurrCycle = 0;
146 unsigned IssueCount = 0;
Krzysztof Parzyszek5ffd8082018-03-20 14:54:01 +0000147 unsigned CriticalPathLength = 0;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000148
149 /// MinReadyCycle - Cycle of the soonest available instruction.
Eugene Zelenko3b873362017-09-28 22:27:31 +0000150 unsigned MinReadyCycle = std::numeric_limits<unsigned>::max();
Sergei Larin4d8986a2012-09-04 14:49:56 +0000151
152 // Remember the greatest min operand latency.
Eugene Zelenko3b873362017-09-28 22:27:31 +0000153 unsigned MaxMinLatency = 0;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000154
155 /// Pending queues extend the ready queues with the same ID and the
156 /// PendingFlag set.
Eugene Zelenko3b873362017-09-28 22:27:31 +0000157 VLIWSchedBoundary(unsigned ID, const Twine &Name)
158 : Available(ID, Name+".A"),
159 Pending(ID << ConvergingVLIWScheduler::LogMaxQID, Name+".P") {}
Sergei Larin4d8986a2012-09-04 14:49:56 +0000160
Andrew Trickd7f890e2013-12-28 21:56:47 +0000161 ~VLIWSchedBoundary() {
Sergei Larinef4cc112012-09-10 17:31:34 +0000162 delete ResourceModel;
163 delete HazardRec;
164 }
Sergei Larin4d8986a2012-09-04 14:49:56 +0000165
Andrew Trickdd79f0f2012-10-10 05:43:09 +0000166 void init(VLIWMachineScheduler *dag, const TargetSchedModel *smodel) {
167 DAG = dag;
168 SchedModel = smodel;
Krzysztof Parzyszekdca38312018-03-20 12:28:43 +0000169 CurrCycle = 0;
Krzysztof Parzyszek6c715e12016-07-15 20:16:03 +0000170 IssueCount = 0;
Krzysztof Parzyszek5ffd8082018-03-20 14:54:01 +0000171 // Initialize the critical path length limit, which used by the scheduling
172 // cost model to determine the value for scheduling an instruction. We use
173 // a slightly different heuristic for small and large functions. For small
174 // functions, it's important to use the height/depth of the instruction.
175 // For large functions, prioritizing by height or depth increases spills.
176 CriticalPathLength = DAG->getBBSize() / SchedModel->getIssueWidth();
177 if (DAG->getBBSize() < 50)
178 // We divide by two as a cheap and simple heuristic to reduce the
179 // critcal path length, which increases the priority of using the graph
180 // height/depth in the scheduler's cost computation.
181 CriticalPathLength >>= 1;
182 else {
183 // For large basic blocks, we prefer a larger critical path length to
184 // decrease the priority of using the graph height/depth.
185 unsigned MaxPath = 0;
186 for (auto &SU : DAG->SUnits)
187 MaxPath = std::max(MaxPath, isTop() ? SU.getHeight() : SU.getDepth());
188 CriticalPathLength = std::max(CriticalPathLength, MaxPath) + 1;
189 }
Andrew Trickdd79f0f2012-10-10 05:43:09 +0000190 }
191
Sergei Larin4d8986a2012-09-04 14:49:56 +0000192 bool isTop() const {
193 return Available.getID() == ConvergingVLIWScheduler::TopQID;
194 }
195
196 bool checkHazard(SUnit *SU);
197
198 void releaseNode(SUnit *SU, unsigned ReadyCycle);
199
200 void bumpCycle();
201
202 void bumpNode(SUnit *SU);
203
204 void releasePending();
205
206 void removeReady(SUnit *SU);
207
208 SUnit *pickOnlyChoice();
Krzysztof Parzyszek65059ee2018-03-20 19:26:27 +0000209
Krzysztof Parzyszek5ffd8082018-03-20 14:54:01 +0000210 bool isLatencyBound(SUnit *SU) {
211 if (CurrCycle >= CriticalPathLength)
212 return true;
213 unsigned PathLength = isTop() ? SU->getHeight() : SU->getDepth();
214 return CriticalPathLength - CurrCycle <= PathLength;
215 }
Sergei Larin4d8986a2012-09-04 14:49:56 +0000216 };
217
Eugene Zelenko3b873362017-09-28 22:27:31 +0000218 VLIWMachineScheduler *DAG = nullptr;
219 const TargetSchedModel *SchedModel = nullptr;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000220
221 // State of the top and bottom scheduled instruction boundaries.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000222 VLIWSchedBoundary Top;
223 VLIWSchedBoundary Bot;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000224
Krzysztof Parzyszekdca38312018-03-20 12:28:43 +0000225 /// List of pressure sets that have a high pressure level in the region.
226 std::vector<bool> HighPressureSets;
227
Sergei Larin4d8986a2012-09-04 14:49:56 +0000228public:
229 /// SUnit::NodeQueueId: 0 (none), 1 (top), 2 (bot), 3 (both)
230 enum {
231 TopQID = 1,
232 BotQID = 2,
233 LogMaxQID = 2
234 };
235
Eugene Zelenko3b873362017-09-28 22:27:31 +0000236 ConvergingVLIWScheduler() : Top(TopQID, "TopQ"), Bot(BotQID, "BotQ") {}
Sergei Larin4d8986a2012-09-04 14:49:56 +0000237
Craig Topperfd38cbe2014-08-30 16:48:34 +0000238 void initialize(ScheduleDAGMI *dag) override;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000239
Craig Topperfd38cbe2014-08-30 16:48:34 +0000240 SUnit *pickNode(bool &IsTopNode) override;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000241
Craig Topperfd38cbe2014-08-30 16:48:34 +0000242 void schedNode(SUnit *SU, bool IsTopNode) override;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000243
Craig Topperfd38cbe2014-08-30 16:48:34 +0000244 void releaseTopNode(SUnit *SU) override;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000245
Craig Topperfd38cbe2014-08-30 16:48:34 +0000246 void releaseBottomNode(SUnit *SU) override;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000247
Krzysztof Parzyszek65059ee2018-03-20 19:26:27 +0000248 unsigned reportPackets() {
Sergei Larin2db64a72012-09-14 15:07:59 +0000249 return Top.ResourceModel->getTotalPackets() +
250 Bot.ResourceModel->getTotalPackets();
251 }
252
Sergei Larin4d8986a2012-09-04 14:49:56 +0000253protected:
254 SUnit *pickNodeBidrectional(bool &IsTopNode);
255
Krzysztof Parzyszekdca38312018-03-20 12:28:43 +0000256 int pressureChange(const SUnit *SU, bool isBotUp);
257
Sergei Larin4d8986a2012-09-04 14:49:56 +0000258 int SchedulingCost(ReadyQueue &Q,
259 SUnit *SU, SchedCandidate &Candidate,
260 RegPressureDelta &Delta, bool verbose);
261
Krzysztof Parzyszek65059ee2018-03-20 19:26:27 +0000262 CandResult pickNodeFromQueue(VLIWSchedBoundary &Zone,
Sergei Larin4d8986a2012-09-04 14:49:56 +0000263 const RegPressureTracker &RPTracker,
264 SchedCandidate &Candidate);
265#ifndef NDEBUG
266 void traceCandidate(const char *Label, const ReadyQueue &Q, SUnit *SU,
Krzysztof Parzyszekf05dc4d2016-07-18 15:47:25 +0000267 int Cost, PressureChange P = PressureChange());
268
269 void readyQueueVerboseDump(const RegPressureTracker &RPTracker,
270 SchedCandidate &Candidate, ReadyQueue &Q);
Sergei Larin4d8986a2012-09-04 14:49:56 +0000271#endif
272};
273
Eugene Zelenko3b873362017-09-28 22:27:31 +0000274} // end namespace llvm
Sergei Larin4d8986a2012-09-04 14:49:56 +0000275
Eugene Zelenko3b873362017-09-28 22:27:31 +0000276#endif // LLVM_LIB_TARGET_HEXAGON_HEXAGONMACHINESCHEDULER_H