blob: 51829742fff21f03106a34c1cccfd578c23460f6 [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
Sergei Larin3e590402012-09-04 14:49:56 +000036namespace llvm {
Sergei Larin3e590402012-09-04 14:49:56 +000037//===----------------------------------------------------------------------===//
Sergei Larin7ae51be2012-09-10 17:31:34 +000038// ConvergingVLIWScheduler - Implementation of the standard
39// MachineSchedStrategy.
Sergei Larin3e590402012-09-04 14:49:56 +000040//===----------------------------------------------------------------------===//
41
Sergei Larin7ae51be2012-09-10 17:31:34 +000042class 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;
47
48 const InstrItineraryData *InstrItins;
49
50 /// Local packet/bundle model. Purely
51 /// internal to the MI schedulre at the time.
52 std::vector<SUnit*> Packet;
53
54 /// Total packets created.
55 unsigned TotalPackets;
56
57public:
58 VLIWResourceModel(MachineSchedContext *C, const InstrItineraryData *IID) :
59 InstrItins(IID), TotalPackets(0) {
60 const TargetMachine &TM = C->MF->getTarget();
61 ResourcesModel = TM.getInstrInfo()->CreateTargetScheduleState(&TM,NULL);
62
63 // This hard requirement could be relaxed,
64 // but for now do not let it proceed.
65 assert(ResourcesModel && "Unimplemented CreateTargetScheduleState.");
66
67 Packet.resize(InstrItins->SchedModel->IssueWidth);
68 Packet.clear();
69 ResourcesModel->clearResources();
70 }
71
72 VLIWResourceModel(const TargetMachine &TM) :
73 InstrItins(TM.getInstrItineraryData()), TotalPackets(0) {
74 ResourcesModel = TM.getInstrInfo()->CreateTargetScheduleState(&TM,NULL);
75
76 // This hard requirement could be relaxed,
77 // but for now do not let it proceed.
78 assert(ResourcesModel && "Unimplemented CreateTargetScheduleState.");
79
80 Packet.resize(InstrItins->SchedModel->IssueWidth);
81 Packet.clear();
82 ResourcesModel->clearResources();
83 }
84
85 ~VLIWResourceModel() {
86 delete ResourcesModel;
87 }
88
89 void resetPacketState() {
90 Packet.clear();
91 }
92
93 void resetDFA() {
94 ResourcesModel->clearResources();
95 }
96
97 void reset() {
98 Packet.clear();
99 ResourcesModel->clearResources();
100 }
101
102 bool isResourceAvailable(SUnit *SU);
103 bool reserveResources(SUnit *SU);
104 unsigned getTotalPackets() const { return TotalPackets; }
105};
106
Andrew Trick78e5efe2012-09-11 00:39:15 +0000107/// Extend the standard ScheduleDAGMI to provide more context and override the
108/// top-level schedule() driver.
109class VLIWMachineScheduler : public ScheduleDAGMI {
Sergei Larin7ae51be2012-09-10 17:31:34 +0000110public:
111 VLIWMachineScheduler(MachineSchedContext *C, MachineSchedStrategy *S):
Benjamin Kramere5c4fe52012-09-14 12:19:58 +0000112 ScheduleDAGMI(C, S) {}
Sergei Larin7ae51be2012-09-10 17:31:34 +0000113
114 /// Schedule - This is called back from ScheduleDAGInstrs::Run() when it's
115 /// time to do some work.
Andrew Trick78e5efe2012-09-11 00:39:15 +0000116 virtual void schedule();
Sergei Larin7ae51be2012-09-10 17:31:34 +0000117};
118
119/// ConvergingVLIWScheduler shrinks the unscheduled zone using heuristics
120/// to balance the schedule.
Sergei Larin3e590402012-09-04 14:49:56 +0000121class ConvergingVLIWScheduler : public MachineSchedStrategy {
122
Sergei Larin7ae51be2012-09-10 17:31:34 +0000123 /// Store the state used by ConvergingVLIWScheduler heuristics, required
124 /// for the lifetime of one invocation of pickNode().
Sergei Larin3e590402012-09-04 14:49:56 +0000125 struct SchedCandidate {
126 // The best SUnit candidate.
127 SUnit *SU;
128
129 // Register pressure values for the best candidate.
130 RegPressureDelta RPDelta;
131
132 // Best scheduling cost.
133 int SCost;
134
135 SchedCandidate(): SU(NULL), SCost(0) {}
136 };
137 /// Represent the type of SchedCandidate found within a single queue.
138 enum CandResult {
139 NoCand, NodeOrder, SingleExcess, SingleCritical, SingleMax, MultiPressure,
140 BestCost};
141
142 /// Each Scheduling boundary is associated with ready queues. It tracks the
143 /// current cycle in whichever direction at has moved, and maintains the state
144 /// of "hazards" and other interlocks at the current cycle.
145 struct SchedBoundary {
146 VLIWMachineScheduler *DAG;
147
148 ReadyQueue Available;
149 ReadyQueue Pending;
150 bool CheckPending;
151
152 ScheduleHazardRecognizer *HazardRec;
Sergei Larin7ae51be2012-09-10 17:31:34 +0000153 VLIWResourceModel *ResourceModel;
Sergei Larin3e590402012-09-04 14:49:56 +0000154
155 unsigned CurrCycle;
156 unsigned IssueCount;
157
158 /// MinReadyCycle - Cycle of the soonest available instruction.
159 unsigned MinReadyCycle;
160
161 // Remember the greatest min operand latency.
162 unsigned MaxMinLatency;
163
164 /// Pending queues extend the ready queues with the same ID and the
165 /// PendingFlag set.
166 SchedBoundary(unsigned ID, const Twine &Name):
167 DAG(0), Available(ID, Name+".A"),
168 Pending(ID << ConvergingVLIWScheduler::LogMaxQID, Name+".P"),
Sergei Larin7ae51be2012-09-10 17:31:34 +0000169 CheckPending(false), HazardRec(0), ResourceModel(0),
170 CurrCycle(0), IssueCount(0),
Sergei Larin3e590402012-09-04 14:49:56 +0000171 MinReadyCycle(UINT_MAX), MaxMinLatency(0) {}
172
Sergei Larin7ae51be2012-09-10 17:31:34 +0000173 ~SchedBoundary() {
174 delete ResourceModel;
175 delete HazardRec;
176 }
Sergei Larin3e590402012-09-04 14:49:56 +0000177
178 bool isTop() const {
179 return Available.getID() == ConvergingVLIWScheduler::TopQID;
180 }
181
182 bool checkHazard(SUnit *SU);
183
184 void releaseNode(SUnit *SU, unsigned ReadyCycle);
185
186 void bumpCycle();
187
188 void bumpNode(SUnit *SU);
189
190 void releasePending();
191
192 void removeReady(SUnit *SU);
193
194 SUnit *pickOnlyChoice();
195 };
196
197 VLIWMachineScheduler *DAG;
198 const TargetRegisterInfo *TRI;
199
200 // State of the top and bottom scheduled instruction boundaries.
201 SchedBoundary Top;
202 SchedBoundary Bot;
203
204public:
205 /// SUnit::NodeQueueId: 0 (none), 1 (top), 2 (bot), 3 (both)
206 enum {
207 TopQID = 1,
208 BotQID = 2,
209 LogMaxQID = 2
210 };
211
212 ConvergingVLIWScheduler():
213 DAG(0), TRI(0), Top(TopQID, "TopQ"), Bot(BotQID, "BotQ") {}
214
Andrew Trick78e5efe2012-09-11 00:39:15 +0000215 virtual void initialize(ScheduleDAGMI *dag);
Sergei Larin3e590402012-09-04 14:49:56 +0000216
217 virtual SUnit *pickNode(bool &IsTopNode);
218
219 virtual void schedNode(SUnit *SU, bool IsTopNode);
220
221 virtual void releaseTopNode(SUnit *SU);
222
223 virtual void releaseBottomNode(SUnit *SU);
224
225protected:
226 SUnit *pickNodeBidrectional(bool &IsTopNode);
227
228 int SchedulingCost(ReadyQueue &Q,
229 SUnit *SU, SchedCandidate &Candidate,
230 RegPressureDelta &Delta, bool verbose);
231
232 CandResult pickNodeFromQueue(ReadyQueue &Q,
233 const RegPressureTracker &RPTracker,
234 SchedCandidate &Candidate);
235#ifndef NDEBUG
236 void traceCandidate(const char *Label, const ReadyQueue &Q, SUnit *SU,
237 PressureElement P = PressureElement());
238#endif
239};
240
Sergei Larin3e590402012-09-04 14:49:56 +0000241} // namespace
242
243
244#endif