blob: f3643d64f6950e22636cb415d58e804e43dc1a43 [file] [log] [blame]
Sergei Larin3e590402012-09-04 14:49:56 +00001//===-- HexagonMachineScheduler.h - Custom Hexagon MI scheduler. ----===//
2//
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
14#ifndef HEXAGONASMPRINTER_H
15#define HEXAGONASMPRINTER_H
16
17#include "llvm/CodeGen/LiveIntervalAnalysis.h"
18#include "llvm/CodeGen/MachineScheduler.h"
19#include "llvm/CodeGen/Passes.h"
20#include "llvm/CodeGen/RegisterClassInfo.h"
21#include "llvm/CodeGen/RegisterPressure.h"
22#include "llvm/CodeGen/ResourcePriorityQueue.h"
23#include "llvm/CodeGen/ScheduleDAGInstrs.h"
24#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
25#include "llvm/Analysis/AliasAnalysis.h"
26#include "llvm/Target/TargetInstrInfo.h"
27#include "llvm/Support/CommandLine.h"
28#include "llvm/Support/Debug.h"
29#include "llvm/Support/ErrorHandling.h"
30#include "llvm/Support/raw_ostream.h"
31#include "llvm/ADT/OwningPtr.h"
32#include "llvm/ADT/PriorityQueue.h"
33
34using namespace llvm;
35
36//===----------------------------------------------------------------------===//
37// MachineSchedStrategy - Interface to a machine scheduling algorithm.
38//===----------------------------------------------------------------------===//
39
40namespace llvm {
41class VLIWMachineScheduler;
42
Sergei Larin7ae51be2012-09-10 17:31:34 +000043/// MachineSchedStrategy - Interface used by VLIWMachineScheduler to drive
44/// the selected scheduling algorithm.
Sergei Larin3e590402012-09-04 14:49:56 +000045///
Sergei Larin7ae51be2012-09-10 17:31:34 +000046/// TODO: Move this to ScheduleDAGInstrs.h
Sergei Larin3e590402012-09-04 14:49:56 +000047class MachineSchedStrategy {
48public:
49 virtual ~MachineSchedStrategy() {}
50
51 /// Initialize the strategy after building the DAG for a new region.
52 virtual void initialize(VLIWMachineScheduler *DAG) = 0;
53
54 /// Pick the next node to schedule, or return NULL. Set IsTopNode to true to
55 /// schedule the node at the top of the unscheduled region. Otherwise it will
56 /// be scheduled at the bottom.
57 virtual SUnit *pickNode(bool &IsTopNode) = 0;
58
Sergei Larin7ae51be2012-09-10 17:31:34 +000059 /// Notify MachineSchedStrategy that VLIWMachineScheduler has
60 /// scheduled a node.
Sergei Larin3e590402012-09-04 14:49:56 +000061 virtual void schedNode(SUnit *SU, bool IsTopNode) = 0;
62
63 /// When all predecessor dependencies have been resolved, free this node for
64 /// top-down scheduling.
65 virtual void releaseTopNode(SUnit *SU) = 0;
66 /// When all successor dependencies have been resolved, free this node for
67 /// bottom-up scheduling.
68 virtual void releaseBottomNode(SUnit *SU) = 0;
69};
70
71//===----------------------------------------------------------------------===//
Sergei Larin7ae51be2012-09-10 17:31:34 +000072// ConvergingVLIWScheduler - Implementation of the standard
73// MachineSchedStrategy.
Sergei Larin3e590402012-09-04 14:49:56 +000074//===----------------------------------------------------------------------===//
75
76/// ReadyQueue encapsulates vector of "ready" SUnits with basic convenience
77/// methods for pushing and removing nodes. ReadyQueue's are uniquely identified
78/// by an ID. SUnit::NodeQueueId is a mask of the ReadyQueues the SUnit is in.
79class ReadyQueue {
80 unsigned ID;
81 std::string Name;
82 std::vector<SUnit*> Queue;
83
84public:
85 ReadyQueue(unsigned id, const Twine &name): ID(id), Name(name.str()) {}
86
87 unsigned getID() const { return ID; }
88
89 StringRef getName() const { return Name; }
90
91 // SU is in this queue if it's NodeQueueID is a superset of this ID.
92 bool isInQueue(SUnit *SU) const { return (SU->NodeQueueId & ID); }
93
94 bool empty() const { return Queue.empty(); }
95
96 unsigned size() const { return Queue.size(); }
97
98 typedef std::vector<SUnit*>::iterator iterator;
99
100 iterator begin() { return Queue.begin(); }
101
102 iterator end() { return Queue.end(); }
103
104 iterator find(SUnit *SU) {
105 return std::find(Queue.begin(), Queue.end(), SU);
106 }
107
108 void push(SUnit *SU) {
109 Queue.push_back(SU);
110 SU->NodeQueueId |= ID;
111 }
112
113 void remove(iterator I) {
114 (*I)->NodeQueueId &= ~ID;
115 *I = Queue.back();
116 Queue.pop_back();
117 }
118
119 void dump() {
120 dbgs() << Name << ": ";
121 for (unsigned i = 0, e = Queue.size(); i < e; ++i)
122 dbgs() << Queue[i]->NodeNum << " ";
123 dbgs() << "\n";
124 }
125};
126
Sergei Larin7ae51be2012-09-10 17:31:34 +0000127class VLIWResourceModel {
128 /// ResourcesModel - Represents VLIW state.
129 /// Not limited to VLIW targets per say, but assumes
130 /// definition of DFA by a target.
131 DFAPacketizer *ResourcesModel;
132
133 const InstrItineraryData *InstrItins;
134
135 /// Local packet/bundle model. Purely
136 /// internal to the MI schedulre at the time.
137 std::vector<SUnit*> Packet;
138
139 /// Total packets created.
140 unsigned TotalPackets;
141
142public:
143 VLIWResourceModel(MachineSchedContext *C, const InstrItineraryData *IID) :
144 InstrItins(IID), TotalPackets(0) {
145 const TargetMachine &TM = C->MF->getTarget();
146 ResourcesModel = TM.getInstrInfo()->CreateTargetScheduleState(&TM,NULL);
147
148 // This hard requirement could be relaxed,
149 // but for now do not let it proceed.
150 assert(ResourcesModel && "Unimplemented CreateTargetScheduleState.");
151
152 Packet.resize(InstrItins->SchedModel->IssueWidth);
153 Packet.clear();
154 ResourcesModel->clearResources();
155 }
156
157 VLIWResourceModel(const TargetMachine &TM) :
158 InstrItins(TM.getInstrItineraryData()), TotalPackets(0) {
159 ResourcesModel = TM.getInstrInfo()->CreateTargetScheduleState(&TM,NULL);
160
161 // This hard requirement could be relaxed,
162 // but for now do not let it proceed.
163 assert(ResourcesModel && "Unimplemented CreateTargetScheduleState.");
164
165 Packet.resize(InstrItins->SchedModel->IssueWidth);
166 Packet.clear();
167 ResourcesModel->clearResources();
168 }
169
170 ~VLIWResourceModel() {
171 delete ResourcesModel;
172 }
173
174 void resetPacketState() {
175 Packet.clear();
176 }
177
178 void resetDFA() {
179 ResourcesModel->clearResources();
180 }
181
182 void reset() {
183 Packet.clear();
184 ResourcesModel->clearResources();
185 }
186
187 bool isResourceAvailable(SUnit *SU);
188 bool reserveResources(SUnit *SU);
189 unsigned getTotalPackets() const { return TotalPackets; }
190};
191
192class VLIWMachineScheduler : public ScheduleDAGInstrs {
193 /// AA - AliasAnalysis for making memory reference queries.
194 AliasAnalysis *AA;
195
196 RegisterClassInfo *RegClassInfo;
197 MachineSchedStrategy *SchedImpl;
198
199 MachineBasicBlock::iterator LiveRegionEnd;
200
201 /// Register pressure in this region computed by buildSchedGraph.
202 IntervalPressure RegPressure;
203 RegPressureTracker RPTracker;
204
205 /// List of pressure sets that exceed the target's pressure limit before
206 /// scheduling, listed in increasing set ID order. Each pressure set is paired
207 /// with its max pressure in the currently scheduled regions.
208 std::vector<PressureElement> RegionCriticalPSets;
209
210 /// The top of the unscheduled zone.
211 MachineBasicBlock::iterator CurrentTop;
212 IntervalPressure TopPressure;
213 RegPressureTracker TopRPTracker;
214
215 /// The bottom of the unscheduled zone.
216 MachineBasicBlock::iterator CurrentBottom;
217 IntervalPressure BotPressure;
218 RegPressureTracker BotRPTracker;
219
220#ifndef NDEBUG
221 /// The number of instructions scheduled so far. Used to cut off the
222 /// scheduler at the point determined by misched-cutoff.
223 unsigned NumInstrsScheduled;
224#endif
225
226 /// Total packets in the region.
227 unsigned TotalPackets;
228
229 const MachineLoopInfo *MLI;
230public:
231 VLIWMachineScheduler(MachineSchedContext *C, MachineSchedStrategy *S):
232 ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS),
233 AA(C->AA), RegClassInfo(C->RegClassInfo), SchedImpl(S),
234 RPTracker(RegPressure), CurrentTop(), TopRPTracker(TopPressure),
235 CurrentBottom(), BotRPTracker(BotPressure), MLI(C->MLI) {
236#ifndef NDEBUG
237 NumInstrsScheduled = 0;
238#endif
239 TotalPackets = 0;
240 }
241
242 virtual ~VLIWMachineScheduler() {
243 delete SchedImpl;
244 }
245
246 MachineBasicBlock::iterator top() const { return CurrentTop; }
247 MachineBasicBlock::iterator bottom() const { return CurrentBottom; }
248
249 /// Implement the ScheduleDAGInstrs interface for handling the next scheduling
250 /// region. This covers all instructions in a block, while schedule() may only
251 /// cover a subset.
252 void enterRegion(MachineBasicBlock *bb,
253 MachineBasicBlock::iterator begin,
254 MachineBasicBlock::iterator end,
255 unsigned endcount);
256
257 /// Schedule - This is called back from ScheduleDAGInstrs::Run() when it's
258 /// time to do some work.
259 void schedule();
260
261 unsigned CurCycle;
262
263 /// Get current register pressure for the top scheduled instructions.
264 const IntervalPressure &getTopPressure() const { return TopPressure; }
265 const RegPressureTracker &getTopRPTracker() const { return TopRPTracker; }
266
267 /// Get current register pressure for the bottom scheduled instructions.
268 const IntervalPressure &getBotPressure() const { return BotPressure; }
269 const RegPressureTracker &getBotRPTracker() const { return BotRPTracker; }
270
271 /// Get register pressure for the entire scheduling region before scheduling.
272 const IntervalPressure &getRegPressure() const { return RegPressure; }
273
274 const std::vector<PressureElement> &getRegionCriticalPSets() const {
275 return RegionCriticalPSets;
276 }
277
278 /// getIssueWidth - Return the max instructions per scheduling group.
279 unsigned getIssueWidth() const {
280 return (InstrItins && InstrItins->SchedModel)
281 ? InstrItins->SchedModel->IssueWidth : 1;
282 }
283
284 /// getNumMicroOps - Return the number of issue slots required for this MI.
285 unsigned getNumMicroOps(MachineInstr *MI) const {
286 return 1;
287 //if (!InstrItins) return 1;
288 //int UOps = InstrItins->getNumMicroOps(MI->getDesc().getSchedClass());
289 //return (UOps >= 0) ? UOps : TII->getNumMicroOps(InstrItins, MI);
290 }
291
292private:
293 void scheduleNodeTopDown(SUnit *SU);
294 void listScheduleTopDown();
295
296 void initRegPressure();
297 void updateScheduledPressure(std::vector<unsigned> NewMaxPressure);
298
299 void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos);
300 bool checkSchedLimit();
301
302 void releaseRoots();
303
304 void releaseSucc(SUnit *SU, SDep *SuccEdge);
305 void releaseSuccessors(SUnit *SU);
306 void releasePred(SUnit *SU, SDep *PredEdge);
307 void releasePredecessors(SUnit *SU);
308
309 void placeDebugValues();
310};
311
312/// ConvergingVLIWScheduler shrinks the unscheduled zone using heuristics
313/// to balance the schedule.
Sergei Larin3e590402012-09-04 14:49:56 +0000314class ConvergingVLIWScheduler : public MachineSchedStrategy {
315
Sergei Larin7ae51be2012-09-10 17:31:34 +0000316 /// Store the state used by ConvergingVLIWScheduler heuristics, required
317 /// for the lifetime of one invocation of pickNode().
Sergei Larin3e590402012-09-04 14:49:56 +0000318 struct SchedCandidate {
319 // The best SUnit candidate.
320 SUnit *SU;
321
322 // Register pressure values for the best candidate.
323 RegPressureDelta RPDelta;
324
325 // Best scheduling cost.
326 int SCost;
327
328 SchedCandidate(): SU(NULL), SCost(0) {}
329 };
330 /// Represent the type of SchedCandidate found within a single queue.
331 enum CandResult {
332 NoCand, NodeOrder, SingleExcess, SingleCritical, SingleMax, MultiPressure,
333 BestCost};
334
335 /// Each Scheduling boundary is associated with ready queues. It tracks the
336 /// current cycle in whichever direction at has moved, and maintains the state
337 /// of "hazards" and other interlocks at the current cycle.
338 struct SchedBoundary {
339 VLIWMachineScheduler *DAG;
340
341 ReadyQueue Available;
342 ReadyQueue Pending;
343 bool CheckPending;
344
345 ScheduleHazardRecognizer *HazardRec;
Sergei Larin7ae51be2012-09-10 17:31:34 +0000346 VLIWResourceModel *ResourceModel;
Sergei Larin3e590402012-09-04 14:49:56 +0000347
348 unsigned CurrCycle;
349 unsigned IssueCount;
350
351 /// MinReadyCycle - Cycle of the soonest available instruction.
352 unsigned MinReadyCycle;
353
354 // Remember the greatest min operand latency.
355 unsigned MaxMinLatency;
356
357 /// Pending queues extend the ready queues with the same ID and the
358 /// PendingFlag set.
359 SchedBoundary(unsigned ID, const Twine &Name):
360 DAG(0), Available(ID, Name+".A"),
361 Pending(ID << ConvergingVLIWScheduler::LogMaxQID, Name+".P"),
Sergei Larin7ae51be2012-09-10 17:31:34 +0000362 CheckPending(false), HazardRec(0), ResourceModel(0),
363 CurrCycle(0), IssueCount(0),
Sergei Larin3e590402012-09-04 14:49:56 +0000364 MinReadyCycle(UINT_MAX), MaxMinLatency(0) {}
365
Sergei Larin7ae51be2012-09-10 17:31:34 +0000366 ~SchedBoundary() {
367 delete ResourceModel;
368 delete HazardRec;
369 }
Sergei Larin3e590402012-09-04 14:49:56 +0000370
371 bool isTop() const {
372 return Available.getID() == ConvergingVLIWScheduler::TopQID;
373 }
374
375 bool checkHazard(SUnit *SU);
376
377 void releaseNode(SUnit *SU, unsigned ReadyCycle);
378
379 void bumpCycle();
380
381 void bumpNode(SUnit *SU);
382
383 void releasePending();
384
385 void removeReady(SUnit *SU);
386
387 SUnit *pickOnlyChoice();
388 };
389
390 VLIWMachineScheduler *DAG;
391 const TargetRegisterInfo *TRI;
392
393 // State of the top and bottom scheduled instruction boundaries.
394 SchedBoundary Top;
395 SchedBoundary Bot;
396
397public:
398 /// SUnit::NodeQueueId: 0 (none), 1 (top), 2 (bot), 3 (both)
399 enum {
400 TopQID = 1,
401 BotQID = 2,
402 LogMaxQID = 2
403 };
404
405 ConvergingVLIWScheduler():
406 DAG(0), TRI(0), Top(TopQID, "TopQ"), Bot(BotQID, "BotQ") {}
407
408 virtual void initialize(VLIWMachineScheduler *dag);
409
410 virtual SUnit *pickNode(bool &IsTopNode);
411
412 virtual void schedNode(SUnit *SU, bool IsTopNode);
413
414 virtual void releaseTopNode(SUnit *SU);
415
416 virtual void releaseBottomNode(SUnit *SU);
417
418protected:
419 SUnit *pickNodeBidrectional(bool &IsTopNode);
420
421 int SchedulingCost(ReadyQueue &Q,
422 SUnit *SU, SchedCandidate &Candidate,
423 RegPressureDelta &Delta, bool verbose);
424
425 CandResult pickNodeFromQueue(ReadyQueue &Q,
426 const RegPressureTracker &RPTracker,
427 SchedCandidate &Candidate);
428#ifndef NDEBUG
429 void traceCandidate(const char *Label, const ReadyQueue &Q, SUnit *SU,
430 PressureElement P = PressureElement());
431#endif
432};
433
Sergei Larin3e590402012-09-04 14:49:56 +0000434} // namespace
435
436
437#endif