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 LLVM_LIB_TARGET_HEXAGON_HEXAGONMACHINESCHEDULER_H
15 #define LLVM_LIB_TARGET_HEXAGON_HEXAGONMACHINESCHEDULER_H
17 #include "llvm/ADT/PriorityQueue.h"
18 #include "llvm/Analysis/AliasAnalysis.h"
19 #include "llvm/CodeGen/LiveIntervalAnalysis.h"
20 #include "llvm/CodeGen/MachineScheduler.h"
21 #include "llvm/CodeGen/Passes.h"
22 #include "llvm/CodeGen/RegisterClassInfo.h"
23 #include "llvm/CodeGen/RegisterPressure.h"
24 #include "llvm/CodeGen/ResourcePriorityQueue.h"
25 #include "llvm/CodeGen/ScheduleDAGInstrs.h"
26 #include "llvm/CodeGen/ScheduleHazardRecognizer.h"
27 #include "llvm/Support/Debug.h"
28 #include "llvm/Support/ErrorHandling.h"
29 #include "llvm/Support/raw_ostream.h"
30 #include "llvm/Target/TargetInstrInfo.h"
35 //===----------------------------------------------------------------------===//
36 // ConvergingVLIWScheduler - Implementation of the standard
37 // MachineSchedStrategy.
38 //===----------------------------------------------------------------------===//
40 class VLIWResourceModel {
41 /// ResourcesModel - Represents VLIW state.
42 /// Not limited to VLIW targets per say, but assumes
43 /// definition of DFA by a target.
44 DFAPacketizer *ResourcesModel;
46 const TargetSchedModel *SchedModel;
48 /// Local packet/bundle model. Purely
49 /// internal to the MI schedulre at the time.
50 std::vector<SUnit*> Packet;
52 /// Total packets created.
53 unsigned TotalPackets;
56 /// Save the last formed packet.
57 std::vector<SUnit*> OldPacket;
60 VLIWResourceModel(const TargetSubtargetInfo &STI, const TargetSchedModel *SM)
61 : SchedModel(SM), TotalPackets(0) {
62 ResourcesModel = STI.getInstrInfo()->CreateTargetScheduleState(STI);
64 // This hard requirement could be relaxed,
65 // but for now do not let it proceed.
66 assert(ResourcesModel && "Unimplemented CreateTargetScheduleState.");
68 Packet.resize(SchedModel->getIssueWidth());
70 OldPacket.resize(SchedModel->getIssueWidth());
72 ResourcesModel->clearResources();
75 ~VLIWResourceModel() {
76 delete ResourcesModel;
79 void resetPacketState() {
84 ResourcesModel->clearResources();
89 ResourcesModel->clearResources();
92 bool isResourceAvailable(SUnit *SU);
93 bool reserveResources(SUnit *SU);
95 unsigned getTotalPackets() const { return TotalPackets; }
97 bool isInPacket(SUnit *SU) const { return is_contained(Packet, SU); }
100 /// Extend the standard ScheduleDAGMI to provide more context and override the
101 /// top-level schedule() driver.
102 class VLIWMachineScheduler : public ScheduleDAGMILive {
104 VLIWMachineScheduler(MachineSchedContext *C,
105 std::unique_ptr<MachineSchedStrategy> S)
106 : ScheduleDAGMILive(C, std::move(S)) {}
108 /// Schedule - This is called back from ScheduleDAGInstrs::Run() when it's
109 /// time to do some work.
110 void schedule() override;
113 /// ConvergingVLIWScheduler shrinks the unscheduled zone using heuristics
114 /// to balance the schedule.
115 class ConvergingVLIWScheduler : public MachineSchedStrategy {
117 /// Store the state used by ConvergingVLIWScheduler heuristics, required
118 /// for the lifetime of one invocation of pickNode().
119 struct SchedCandidate {
120 // The best SUnit candidate.
123 // Register pressure values for the best candidate.
124 RegPressureDelta RPDelta;
126 // Best scheduling cost.
129 SchedCandidate(): SU(nullptr), SCost(0) {}
131 /// Represent the type of SchedCandidate found within a single queue.
133 NoCand, NodeOrder, SingleExcess, SingleCritical, SingleMax, MultiPressure,
136 /// Each Scheduling boundary is associated with ready queues. It tracks the
137 /// current cycle in whichever direction at has moved, and maintains the state
138 /// of "hazards" and other interlocks at the current cycle.
139 struct VLIWSchedBoundary {
140 VLIWMachineScheduler *DAG;
141 const TargetSchedModel *SchedModel;
143 ReadyQueue Available;
147 ScheduleHazardRecognizer *HazardRec;
148 VLIWResourceModel *ResourceModel;
153 /// MinReadyCycle - Cycle of the soonest available instruction.
154 unsigned MinReadyCycle;
156 // Remember the greatest min operand latency.
157 unsigned MaxMinLatency;
159 /// Pending queues extend the ready queues with the same ID and the
161 VLIWSchedBoundary(unsigned ID, const Twine &Name):
162 DAG(nullptr), SchedModel(nullptr), Available(ID, Name+".A"),
163 Pending(ID << ConvergingVLIWScheduler::LogMaxQID, Name+".P"),
164 CheckPending(false), HazardRec(nullptr), ResourceModel(nullptr),
165 CurrCycle(0), IssueCount(0),
166 MinReadyCycle(UINT_MAX), MaxMinLatency(0) {}
168 ~VLIWSchedBoundary() {
169 delete ResourceModel;
173 void init(VLIWMachineScheduler *dag, const TargetSchedModel *smodel) {
180 return Available.getID() == ConvergingVLIWScheduler::TopQID;
183 bool checkHazard(SUnit *SU);
185 void releaseNode(SUnit *SU, unsigned ReadyCycle);
189 void bumpNode(SUnit *SU);
191 void releasePending();
193 void removeReady(SUnit *SU);
195 SUnit *pickOnlyChoice();
198 VLIWMachineScheduler *DAG;
199 const TargetSchedModel *SchedModel;
201 // State of the top and bottom scheduled instruction boundaries.
202 VLIWSchedBoundary Top;
203 VLIWSchedBoundary Bot;
206 /// SUnit::NodeQueueId: 0 (none), 1 (top), 2 (bot), 3 (both)
213 ConvergingVLIWScheduler()
214 : DAG(nullptr), SchedModel(nullptr), Top(TopQID, "TopQ"),
215 Bot(BotQID, "BotQ") {}
217 void initialize(ScheduleDAGMI *dag) override;
219 SUnit *pickNode(bool &IsTopNode) override;
221 void schedNode(SUnit *SU, bool IsTopNode) override;
223 void releaseTopNode(SUnit *SU) override;
225 void releaseBottomNode(SUnit *SU) override;
227 unsigned ReportPackets() {
228 return Top.ResourceModel->getTotalPackets() +
229 Bot.ResourceModel->getTotalPackets();
233 SUnit *pickNodeBidrectional(bool &IsTopNode);
235 int SchedulingCost(ReadyQueue &Q,
236 SUnit *SU, SchedCandidate &Candidate,
237 RegPressureDelta &Delta, bool verbose);
239 CandResult pickNodeFromQueue(ReadyQueue &Q,
240 const RegPressureTracker &RPTracker,
241 SchedCandidate &Candidate);
243 void traceCandidate(const char *Label, const ReadyQueue &Q, SUnit *SU,
244 int Cost, PressureChange P = PressureChange());
246 void readyQueueVerboseDump(const RegPressureTracker &RPTracker,
247 SchedCandidate &Candidate, ReadyQueue &Q);