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"
36 class VLIWResourceModel {
37 /// ResourcesModel - Represents VLIW state.
38 /// Not limited to VLIW targets per se, but assumes
39 /// definition of DFA by a target.
40 DFAPacketizer *ResourcesModel;
42 const TargetSchedModel *SchedModel;
44 /// Local packet/bundle model. Purely
45 /// internal to the MI schedulre at the time.
46 std::vector<SUnit*> Packet;
48 /// Total packets created.
49 unsigned TotalPackets;
52 /// Save the last formed packet.
53 std::vector<SUnit*> OldPacket;
56 VLIWResourceModel(const TargetSubtargetInfo &STI, const TargetSchedModel *SM)
57 : SchedModel(SM), TotalPackets(0) {
58 ResourcesModel = STI.getInstrInfo()->CreateTargetScheduleState(STI);
60 // This hard requirement could be relaxed,
61 // but for now do not let it proceed.
62 assert(ResourcesModel && "Unimplemented CreateTargetScheduleState.");
64 Packet.resize(SchedModel->getIssueWidth());
66 OldPacket.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);
91 unsigned getTotalPackets() const { return TotalPackets; }
93 bool isInPacket(SUnit *SU) const { return is_contained(Packet, SU); }
96 /// Extend the standard ScheduleDAGMI to provide more context and override the
97 /// top-level schedule() driver.
98 class VLIWMachineScheduler : public ScheduleDAGMILive {
100 VLIWMachineScheduler(MachineSchedContext *C,
101 std::unique_ptr<MachineSchedStrategy> S)
102 : ScheduleDAGMILive(C, std::move(S)) {}
104 /// Schedule - This is called back from ScheduleDAGInstrs::Run() when it's
105 /// time to do some work.
106 void schedule() override;
109 //===----------------------------------------------------------------------===//
110 // ConvergingVLIWScheduler - Implementation of the standard
111 // MachineSchedStrategy.
112 //===----------------------------------------------------------------------===//
114 /// ConvergingVLIWScheduler shrinks the unscheduled zone using heuristics
115 /// to balance the schedule.
116 class ConvergingVLIWScheduler : public MachineSchedStrategy {
118 /// Store the state used by ConvergingVLIWScheduler heuristics, required
119 /// for the lifetime of one invocation of pickNode().
120 struct SchedCandidate {
121 // The best SUnit candidate.
124 // Register pressure values for the best candidate.
125 RegPressureDelta RPDelta;
127 // Best scheduling cost.
130 SchedCandidate(): SU(nullptr), SCost(0) {}
132 /// Represent the type of SchedCandidate found within a single queue.
134 NoCand, NodeOrder, SingleExcess, SingleCritical, SingleMax, MultiPressure,
137 /// Each Scheduling boundary is associated with ready queues. It tracks the
138 /// current cycle in whichever direction at has moved, and maintains the state
139 /// of "hazards" and other interlocks at the current cycle.
140 struct VLIWSchedBoundary {
141 VLIWMachineScheduler *DAG;
142 const TargetSchedModel *SchedModel;
144 ReadyQueue Available;
148 ScheduleHazardRecognizer *HazardRec;
149 VLIWResourceModel *ResourceModel;
154 /// MinReadyCycle - Cycle of the soonest available instruction.
155 unsigned MinReadyCycle;
157 // Remember the greatest min operand latency.
158 unsigned MaxMinLatency;
160 /// Pending queues extend the ready queues with the same ID and the
162 VLIWSchedBoundary(unsigned ID, const Twine &Name):
163 DAG(nullptr), SchedModel(nullptr), Available(ID, Name+".A"),
164 Pending(ID << ConvergingVLIWScheduler::LogMaxQID, Name+".P"),
165 CheckPending(false), HazardRec(nullptr), ResourceModel(nullptr),
166 CurrCycle(0), IssueCount(0),
167 MinReadyCycle(UINT_MAX), MaxMinLatency(0) {}
169 ~VLIWSchedBoundary() {
170 delete ResourceModel;
174 void init(VLIWMachineScheduler *dag, const TargetSchedModel *smodel) {
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 TargetSchedModel *SchedModel;
202 // State of the top and bottom scheduled instruction boundaries.
203 VLIWSchedBoundary Top;
204 VLIWSchedBoundary Bot;
207 /// SUnit::NodeQueueId: 0 (none), 1 (top), 2 (bot), 3 (both)
214 ConvergingVLIWScheduler()
215 : DAG(nullptr), SchedModel(nullptr), Top(TopQID, "TopQ"),
216 Bot(BotQID, "BotQ") {}
218 void initialize(ScheduleDAGMI *dag) override;
220 SUnit *pickNode(bool &IsTopNode) override;
222 void schedNode(SUnit *SU, bool IsTopNode) override;
224 void releaseTopNode(SUnit *SU) override;
226 void releaseBottomNode(SUnit *SU) override;
228 unsigned ReportPackets() {
229 return Top.ResourceModel->getTotalPackets() +
230 Bot.ResourceModel->getTotalPackets();
234 SUnit *pickNodeBidrectional(bool &IsTopNode);
236 int SchedulingCost(ReadyQueue &Q,
237 SUnit *SU, SchedCandidate &Candidate,
238 RegPressureDelta &Delta, bool verbose);
240 CandResult pickNodeFromQueue(ReadyQueue &Q,
241 const RegPressureTracker &RPTracker,
242 SchedCandidate &Candidate);
244 void traceCandidate(const char *Label, const ReadyQueue &Q, SUnit *SU,
245 int Cost, PressureChange P = PressureChange());
247 void readyQueueVerboseDump(const RegPressureTracker &RPTracker,
248 SchedCandidate &Candidate, ReadyQueue &Q);