1 //===-- HexagonMachineScheduler.h - Custom Hexagon MI scheduler. ----===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Custom Hexagon MI scheduler.
12 //===----------------------------------------------------------------------===//
14 #ifndef HEXAGONASMPRINTER_H
15 #define HEXAGONASMPRINTER_H
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"
36 //===----------------------------------------------------------------------===//
37 // MachineSchedStrategy - Interface to a machine scheduling algorithm.
38 //===----------------------------------------------------------------------===//
41 class VLIWMachineScheduler;
43 /// MachineSchedStrategy - Interface used by VLIWMachineScheduler to drive the selected
44 /// scheduling algorithm.
46 /// If this works well and targets wish to reuse VLIWMachineScheduler, we may expose it
47 /// in ScheduleDAGInstrs.h
48 class MachineSchedStrategy {
50 virtual ~MachineSchedStrategy() {}
52 /// Initialize the strategy after building the DAG for a new region.
53 virtual void initialize(VLIWMachineScheduler *DAG) = 0;
55 /// Pick the next node to schedule, or return NULL. Set IsTopNode to true to
56 /// schedule the node at the top of the unscheduled region. Otherwise it will
57 /// be scheduled at the bottom.
58 virtual SUnit *pickNode(bool &IsTopNode) = 0;
60 /// Notify MachineSchedStrategy that VLIWMachineScheduler has scheduled a node.
61 virtual void schedNode(SUnit *SU, bool IsTopNode) = 0;
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;
71 //===----------------------------------------------------------------------===//
72 // ConvergingVLIWScheduler - Implementation of the standard MachineSchedStrategy.
73 //===----------------------------------------------------------------------===//
75 /// ReadyQueue encapsulates vector of "ready" SUnits with basic convenience
76 /// methods for pushing and removing nodes. ReadyQueue's are uniquely identified
77 /// by an ID. SUnit::NodeQueueId is a mask of the ReadyQueues the SUnit is in.
81 std::vector<SUnit*> Queue;
84 ReadyQueue(unsigned id, const Twine &name): ID(id), Name(name.str()) {}
86 unsigned getID() const { return ID; }
88 StringRef getName() const { return Name; }
90 // SU is in this queue if it's NodeQueueID is a superset of this ID.
91 bool isInQueue(SUnit *SU) const { return (SU->NodeQueueId & ID); }
93 bool empty() const { return Queue.empty(); }
95 unsigned size() const { return Queue.size(); }
97 typedef std::vector<SUnit*>::iterator iterator;
99 iterator begin() { return Queue.begin(); }
101 iterator end() { return Queue.end(); }
103 iterator find(SUnit *SU) {
104 return std::find(Queue.begin(), Queue.end(), SU);
107 void push(SUnit *SU) {
109 SU->NodeQueueId |= ID;
112 void remove(iterator I) {
113 (*I)->NodeQueueId &= ~ID;
119 dbgs() << Name << ": ";
120 for (unsigned i = 0, e = Queue.size(); i < e; ++i)
121 dbgs() << Queue[i]->NodeNum << " ";
126 /// ConvergingVLIWScheduler shrinks the unscheduled zone using heuristics to balance
128 class ConvergingVLIWScheduler : public MachineSchedStrategy {
130 /// Store the state used by ConvergingVLIWScheduler heuristics, required for the
131 /// lifetime of one invocation of pickNode().
132 struct SchedCandidate {
133 // The best SUnit candidate.
136 // Register pressure values for the best candidate.
137 RegPressureDelta RPDelta;
139 // Best scheduling cost.
142 SchedCandidate(): SU(NULL), SCost(0) {}
144 /// Represent the type of SchedCandidate found within a single queue.
146 NoCand, NodeOrder, SingleExcess, SingleCritical, SingleMax, MultiPressure,
149 /// Each Scheduling boundary is associated with ready queues. It tracks the
150 /// current cycle in whichever direction at has moved, and maintains the state
151 /// of "hazards" and other interlocks at the current cycle.
152 struct SchedBoundary {
153 VLIWMachineScheduler *DAG;
155 ReadyQueue Available;
159 ScheduleHazardRecognizer *HazardRec;
164 /// MinReadyCycle - Cycle of the soonest available instruction.
165 unsigned MinReadyCycle;
167 // Remember the greatest min operand latency.
168 unsigned MaxMinLatency;
170 /// Pending queues extend the ready queues with the same ID and the
172 SchedBoundary(unsigned ID, const Twine &Name):
173 DAG(0), Available(ID, Name+".A"),
174 Pending(ID << ConvergingVLIWScheduler::LogMaxQID, Name+".P"),
175 CheckPending(false), HazardRec(0), CurrCycle(0), IssueCount(0),
176 MinReadyCycle(UINT_MAX), MaxMinLatency(0) {}
178 ~SchedBoundary() { delete HazardRec; }
181 return Available.getID() == ConvergingVLIWScheduler::TopQID;
184 bool checkHazard(SUnit *SU);
186 void releaseNode(SUnit *SU, unsigned ReadyCycle);
190 void bumpNode(SUnit *SU);
192 void releasePending();
194 void removeReady(SUnit *SU);
196 SUnit *pickOnlyChoice();
199 VLIWMachineScheduler *DAG;
200 const TargetRegisterInfo *TRI;
202 // State of the top and bottom scheduled instruction boundaries.
207 /// SUnit::NodeQueueId: 0 (none), 1 (top), 2 (bot), 3 (both)
214 ConvergingVLIWScheduler():
215 DAG(0), TRI(0), Top(TopQID, "TopQ"), Bot(BotQID, "BotQ") {}
217 virtual void initialize(VLIWMachineScheduler *dag);
219 virtual SUnit *pickNode(bool &IsTopNode);
221 virtual void schedNode(SUnit *SU, bool IsTopNode);
223 virtual void releaseTopNode(SUnit *SU);
225 virtual void releaseBottomNode(SUnit *SU);
228 SUnit *pickNodeBidrectional(bool &IsTopNode);
230 int SchedulingCost(ReadyQueue &Q,
231 SUnit *SU, SchedCandidate &Candidate,
232 RegPressureDelta &Delta, bool verbose);
234 CandResult pickNodeFromQueue(ReadyQueue &Q,
235 const RegPressureTracker &RPTracker,
236 SchedCandidate &Candidate);
238 void traceCandidate(const char *Label, const ReadyQueue &Q, SUnit *SU,
239 PressureElement P = PressureElement());
243 class VLIWResourceModel {
244 /// ResourcesModel - Represents VLIW state.
245 /// Not limited to VLIW targets per say, but assumes
246 /// definition of DFA by a target.
247 DFAPacketizer *ResourcesModel;
249 const InstrItineraryData *InstrItins;
251 /// Local packet/bundle model. Purely
252 /// internal to the MI schedulre at the time.
253 std::vector<SUnit*> Packet;
255 /// Total packets created.
256 unsigned TotalPackets;
259 VLIWResourceModel(MachineSchedContext *C, const InstrItineraryData *IID) :
260 InstrItins(IID), TotalPackets(0) {
261 const TargetMachine &TM = C->MF->getTarget();
262 ResourcesModel = TM.getInstrInfo()->CreateTargetScheduleState(&TM,NULL);
264 // This hard requirement could be relaxed, but for now do not let it proceed.
265 assert(ResourcesModel && "Unimplemented CreateTargetScheduleState.");
267 Packet.resize(InstrItins->SchedModel->IssueWidth);
269 ResourcesModel->clearResources();
272 ~VLIWResourceModel() {
273 delete ResourcesModel;
276 void resetPacketState() {
281 ResourcesModel->clearResources();
284 bool isResourceAvailable(SUnit *SU);
285 void reserveResources(SUnit *SU);
286 unsigned getTotalPackets() const { return TotalPackets; }
289 class VLIWMachineScheduler : public ScheduleDAGInstrs {
290 /// AA - AliasAnalysis for making memory reference queries.
293 RegisterClassInfo *RegClassInfo;
294 MachineSchedStrategy *SchedImpl;
296 /// state separatly for top/bottom sectioins.
297 VLIWResourceModel *TopResourceModel;
298 VLIWResourceModel *BotResourceModel;
300 MachineBasicBlock::iterator LiveRegionEnd;
302 /// Register pressure in this region computed by buildSchedGraph.
303 IntervalPressure RegPressure;
304 RegPressureTracker RPTracker;
306 /// List of pressure sets that exceed the target's pressure limit before
307 /// scheduling, listed in increasing set ID order. Each pressure set is paired
308 /// with its max pressure in the currently scheduled regions.
309 std::vector<PressureElement> RegionCriticalPSets;
311 /// The top of the unscheduled zone.
312 MachineBasicBlock::iterator CurrentTop;
313 IntervalPressure TopPressure;
314 RegPressureTracker TopRPTracker;
316 /// The bottom of the unscheduled zone.
317 MachineBasicBlock::iterator CurrentBottom;
318 IntervalPressure BotPressure;
319 RegPressureTracker BotRPTracker;
322 /// The number of instructions scheduled so far. Used to cut off the
323 /// scheduler at the point determined by misched-cutoff.
324 unsigned NumInstrsScheduled;
327 /// Total packets in the region.
328 unsigned TotalPackets;
330 const MachineLoopInfo *MLI;
332 VLIWMachineScheduler(MachineSchedContext *C, MachineSchedStrategy *S):
333 ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS),
334 AA(C->AA), RegClassInfo(C->RegClassInfo), SchedImpl(S),
335 RPTracker(RegPressure), CurrentTop(), TopRPTracker(TopPressure),
336 CurrentBottom(), BotRPTracker(BotPressure), MLI(C->MLI) {
338 TopResourceModel = new VLIWResourceModel(C, InstrItins);
339 BotResourceModel = new VLIWResourceModel(C, InstrItins);
342 NumInstrsScheduled = 0;
347 virtual ~VLIWMachineScheduler() {
349 delete TopResourceModel;
350 delete BotResourceModel;
353 MachineBasicBlock::iterator top() const { return CurrentTop; }
354 MachineBasicBlock::iterator bottom() const { return CurrentBottom; }
356 /// Implement the ScheduleDAGInstrs interface for handling the next scheduling
357 /// region. This covers all instructions in a block, while schedule() may only
359 void enterRegion(MachineBasicBlock *bb,
360 MachineBasicBlock::iterator begin,
361 MachineBasicBlock::iterator end,
364 /// Schedule - This is called back from ScheduleDAGInstrs::Run() when it's
365 /// time to do some work.
370 /// Get current register pressure for the top scheduled instructions.
371 const IntervalPressure &getTopPressure() const { return TopPressure; }
372 const RegPressureTracker &getTopRPTracker() const { return TopRPTracker; }
374 /// Get current register pressure for the bottom scheduled instructions.
375 const IntervalPressure &getBotPressure() const { return BotPressure; }
376 const RegPressureTracker &getBotRPTracker() const { return BotRPTracker; }
378 /// Get register pressure for the entire scheduling region before scheduling.
379 const IntervalPressure &getRegPressure() const { return RegPressure; }
381 const std::vector<PressureElement> &getRegionCriticalPSets() const {
382 return RegionCriticalPSets;
385 VLIWResourceModel *getTopResourceModel() { return TopResourceModel; }
386 VLIWResourceModel *getBotResourceModel() { return BotResourceModel; }
388 /// getIssueWidth - Return the max instructions per scheduling group.
389 unsigned getIssueWidth() const {
390 return (InstrItins && InstrItins->SchedModel)
391 ? InstrItins->SchedModel->IssueWidth : 1;
394 /// getNumMicroOps - Return the number of issue slots required for this MI.
395 unsigned getNumMicroOps(MachineInstr *MI) const {
396 if (!InstrItins) return 1;
397 int UOps = InstrItins->getNumMicroOps(MI->getDesc().getSchedClass());
398 return (UOps >= 0) ? UOps : TII->getNumMicroOps(InstrItins, MI);
402 void scheduleNodeTopDown(SUnit *SU);
403 void listScheduleTopDown();
405 void initRegPressure();
406 void updateScheduledPressure(std::vector<unsigned> NewMaxPressure);
408 void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos);
409 bool checkSchedLimit();
413 void releaseSucc(SUnit *SU, SDep *SuccEdge);
414 void releaseSuccessors(SUnit *SU);
415 void releasePred(SUnit *SU, SDep *PredEdge);
416 void releasePredecessors(SUnit *SU);
418 void placeDebugValues();