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/ADT/OwningPtr.h"
18 #include "llvm/ADT/PriorityQueue.h"
19 #include "llvm/Analysis/AliasAnalysis.h"
20 #include "llvm/CodeGen/LiveIntervalAnalysis.h"
21 #include "llvm/CodeGen/MachineScheduler.h"
22 #include "llvm/CodeGen/Passes.h"
23 #include "llvm/CodeGen/RegisterClassInfo.h"
24 #include "llvm/CodeGen/RegisterPressure.h"
25 #include "llvm/CodeGen/ResourcePriorityQueue.h"
26 #include "llvm/CodeGen/ScheduleDAGInstrs.h"
27 #include "llvm/CodeGen/ScheduleHazardRecognizer.h"
28 #include "llvm/Support/CommandLine.h"
29 #include "llvm/Support/Debug.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/raw_ostream.h"
32 #include "llvm/Target/TargetInstrInfo.h"
37 //===----------------------------------------------------------------------===//
38 // ConvergingVLIWScheduler - Implementation of the standard
39 // MachineSchedStrategy.
40 //===----------------------------------------------------------------------===//
42 class VLIWResourceModel {
43 /// ResourcesModel - Represents VLIW state.
44 /// Not limited to VLIW targets per say, but assumes
45 /// definition of DFA by a target.
46 DFAPacketizer *ResourcesModel;
48 const TargetSchedModel *SchedModel;
50 /// Local packet/bundle model. Purely
51 /// internal to the MI schedulre at the time.
52 std::vector<SUnit*> Packet;
54 /// Total packets created.
55 unsigned TotalPackets;
58 VLIWResourceModel(const TargetMachine &TM, const TargetSchedModel *SM) :
59 SchedModel(SM), TotalPackets(0) {
60 ResourcesModel = TM.getInstrInfo()->CreateTargetScheduleState(&TM,NULL);
62 // This hard requirement could be relaxed,
63 // but for now do not let it proceed.
64 assert(ResourcesModel && "Unimplemented CreateTargetScheduleState.");
66 Packet.resize(SchedModel->getIssueWidth());
68 ResourcesModel->clearResources();
71 ~VLIWResourceModel() {
72 delete ResourcesModel;
75 void resetPacketState() {
80 ResourcesModel->clearResources();
85 ResourcesModel->clearResources();
88 bool isResourceAvailable(SUnit *SU);
89 bool reserveResources(SUnit *SU);
90 unsigned getTotalPackets() const { return TotalPackets; }
93 /// Extend the standard ScheduleDAGMI to provide more context and override the
94 /// top-level schedule() driver.
95 class VLIWMachineScheduler : public ScheduleDAGMILive {
97 VLIWMachineScheduler(MachineSchedContext *C, MachineSchedStrategy *S):
98 ScheduleDAGMILive(C, S) {}
100 /// Schedule - This is called back from ScheduleDAGInstrs::Run() when it's
101 /// time to do some work.
102 virtual void schedule() override;
103 /// Perform platform specific DAG postprocessing.
104 void postprocessDAG();
107 /// ConvergingVLIWScheduler shrinks the unscheduled zone using heuristics
108 /// to balance the schedule.
109 class ConvergingVLIWScheduler : public MachineSchedStrategy {
111 /// Store the state used by ConvergingVLIWScheduler heuristics, required
112 /// for the lifetime of one invocation of pickNode().
113 struct SchedCandidate {
114 // The best SUnit candidate.
117 // Register pressure values for the best candidate.
118 RegPressureDelta RPDelta;
120 // Best scheduling cost.
123 SchedCandidate(): SU(NULL), SCost(0) {}
125 /// Represent the type of SchedCandidate found within a single queue.
127 NoCand, NodeOrder, SingleExcess, SingleCritical, SingleMax, MultiPressure,
130 /// Each Scheduling boundary is associated with ready queues. It tracks the
131 /// current cycle in whichever direction at has moved, and maintains the state
132 /// of "hazards" and other interlocks at the current cycle.
133 struct VLIWSchedBoundary {
134 VLIWMachineScheduler *DAG;
135 const TargetSchedModel *SchedModel;
137 ReadyQueue Available;
141 ScheduleHazardRecognizer *HazardRec;
142 VLIWResourceModel *ResourceModel;
147 /// MinReadyCycle - Cycle of the soonest available instruction.
148 unsigned MinReadyCycle;
150 // Remember the greatest min operand latency.
151 unsigned MaxMinLatency;
153 /// Pending queues extend the ready queues with the same ID and the
155 VLIWSchedBoundary(unsigned ID, const Twine &Name):
156 DAG(0), SchedModel(0), Available(ID, Name+".A"),
157 Pending(ID << ConvergingVLIWScheduler::LogMaxQID, Name+".P"),
158 CheckPending(false), HazardRec(0), ResourceModel(0),
159 CurrCycle(0), IssueCount(0),
160 MinReadyCycle(UINT_MAX), MaxMinLatency(0) {}
162 ~VLIWSchedBoundary() {
163 delete ResourceModel;
167 void init(VLIWMachineScheduler *dag, const TargetSchedModel *smodel) {
173 return Available.getID() == ConvergingVLIWScheduler::TopQID;
176 bool checkHazard(SUnit *SU);
178 void releaseNode(SUnit *SU, unsigned ReadyCycle);
182 void bumpNode(SUnit *SU);
184 void releasePending();
186 void removeReady(SUnit *SU);
188 SUnit *pickOnlyChoice();
191 VLIWMachineScheduler *DAG;
192 const TargetSchedModel *SchedModel;
194 // State of the top and bottom scheduled instruction boundaries.
195 VLIWSchedBoundary Top;
196 VLIWSchedBoundary Bot;
199 /// SUnit::NodeQueueId: 0 (none), 1 (top), 2 (bot), 3 (both)
206 ConvergingVLIWScheduler():
207 DAG(0), SchedModel(0), Top(TopQID, "TopQ"), Bot(BotQID, "BotQ") {}
209 virtual void initialize(ScheduleDAGMI *dag) override;
211 virtual SUnit *pickNode(bool &IsTopNode) override;
213 virtual void schedNode(SUnit *SU, bool IsTopNode) override;
215 virtual void releaseTopNode(SUnit *SU) override;
217 virtual void releaseBottomNode(SUnit *SU) override;
219 unsigned ReportPackets() {
220 return Top.ResourceModel->getTotalPackets() +
221 Bot.ResourceModel->getTotalPackets();
225 SUnit *pickNodeBidrectional(bool &IsTopNode);
227 int SchedulingCost(ReadyQueue &Q,
228 SUnit *SU, SchedCandidate &Candidate,
229 RegPressureDelta &Delta, bool verbose);
231 CandResult pickNodeFromQueue(ReadyQueue &Q,
232 const RegPressureTracker &RPTracker,
233 SchedCandidate &Candidate);
235 void traceCandidate(const char *Label, const ReadyQueue &Q, SUnit *SU,
236 PressureChange P = PressureChange());