1*9880d681SAndroid Build Coastguard Worker //===- ScheduleDAGVLIW.cpp - SelectionDAG list scheduler for VLIW -*- C++ -*-=//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This implements a top-down list scheduler, using standard algorithms.
11*9880d681SAndroid Build Coastguard Worker // The basic approach uses a priority queue of available nodes to schedule.
12*9880d681SAndroid Build Coastguard Worker // One at a time, nodes are taken from the priority queue (thus in priority
13*9880d681SAndroid Build Coastguard Worker // order), checked for legality to schedule, and emitted if legal.
14*9880d681SAndroid Build Coastguard Worker //
15*9880d681SAndroid Build Coastguard Worker // Nodes may not be legal to schedule either due to structural hazards (e.g.
16*9880d681SAndroid Build Coastguard Worker // pipeline or resource constraints) or because an input to the instruction has
17*9880d681SAndroid Build Coastguard Worker // not completed execution.
18*9880d681SAndroid Build Coastguard Worker //
19*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
20*9880d681SAndroid Build Coastguard Worker
21*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/SchedulerRegistry.h"
22*9880d681SAndroid Build Coastguard Worker #include "ScheduleDAGSDNodes.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/LatencyPriorityQueue.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/ResourcePriorityQueue.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/ScheduleHazardRecognizer.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/SelectionDAGISel.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DataLayout.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetInstrInfo.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetRegisterInfo.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetSubtargetInfo.h"
35*9880d681SAndroid Build Coastguard Worker #include <climits>
36*9880d681SAndroid Build Coastguard Worker using namespace llvm;
37*9880d681SAndroid Build Coastguard Worker
38*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "pre-RA-sched"
39*9880d681SAndroid Build Coastguard Worker
40*9880d681SAndroid Build Coastguard Worker STATISTIC(NumNoops , "Number of noops inserted");
41*9880d681SAndroid Build Coastguard Worker STATISTIC(NumStalls, "Number of pipeline stalls");
42*9880d681SAndroid Build Coastguard Worker
43*9880d681SAndroid Build Coastguard Worker static RegisterScheduler
44*9880d681SAndroid Build Coastguard Worker VLIWScheduler("vliw-td", "VLIW scheduler",
45*9880d681SAndroid Build Coastguard Worker createVLIWDAGScheduler);
46*9880d681SAndroid Build Coastguard Worker
47*9880d681SAndroid Build Coastguard Worker namespace {
48*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
49*9880d681SAndroid Build Coastguard Worker /// ScheduleDAGVLIW - The actual DFA list scheduler implementation. This
50*9880d681SAndroid Build Coastguard Worker /// supports / top-down scheduling.
51*9880d681SAndroid Build Coastguard Worker ///
52*9880d681SAndroid Build Coastguard Worker class ScheduleDAGVLIW : public ScheduleDAGSDNodes {
53*9880d681SAndroid Build Coastguard Worker private:
54*9880d681SAndroid Build Coastguard Worker /// AvailableQueue - The priority queue to use for the available SUnits.
55*9880d681SAndroid Build Coastguard Worker ///
56*9880d681SAndroid Build Coastguard Worker SchedulingPriorityQueue *AvailableQueue;
57*9880d681SAndroid Build Coastguard Worker
58*9880d681SAndroid Build Coastguard Worker /// PendingQueue - This contains all of the instructions whose operands have
59*9880d681SAndroid Build Coastguard Worker /// been issued, but their results are not ready yet (due to the latency of
60*9880d681SAndroid Build Coastguard Worker /// the operation). Once the operands become available, the instruction is
61*9880d681SAndroid Build Coastguard Worker /// added to the AvailableQueue.
62*9880d681SAndroid Build Coastguard Worker std::vector<SUnit*> PendingQueue;
63*9880d681SAndroid Build Coastguard Worker
64*9880d681SAndroid Build Coastguard Worker /// HazardRec - The hazard recognizer to use.
65*9880d681SAndroid Build Coastguard Worker ScheduleHazardRecognizer *HazardRec;
66*9880d681SAndroid Build Coastguard Worker
67*9880d681SAndroid Build Coastguard Worker /// AA - AliasAnalysis for making memory reference queries.
68*9880d681SAndroid Build Coastguard Worker AliasAnalysis *AA;
69*9880d681SAndroid Build Coastguard Worker
70*9880d681SAndroid Build Coastguard Worker public:
ScheduleDAGVLIW(MachineFunction & mf,AliasAnalysis * aa,SchedulingPriorityQueue * availqueue)71*9880d681SAndroid Build Coastguard Worker ScheduleDAGVLIW(MachineFunction &mf,
72*9880d681SAndroid Build Coastguard Worker AliasAnalysis *aa,
73*9880d681SAndroid Build Coastguard Worker SchedulingPriorityQueue *availqueue)
74*9880d681SAndroid Build Coastguard Worker : ScheduleDAGSDNodes(mf), AvailableQueue(availqueue), AA(aa) {
75*9880d681SAndroid Build Coastguard Worker const TargetSubtargetInfo &STI = mf.getSubtarget();
76*9880d681SAndroid Build Coastguard Worker HazardRec = STI.getInstrInfo()->CreateTargetHazardRecognizer(&STI, this);
77*9880d681SAndroid Build Coastguard Worker }
78*9880d681SAndroid Build Coastguard Worker
~ScheduleDAGVLIW()79*9880d681SAndroid Build Coastguard Worker ~ScheduleDAGVLIW() override {
80*9880d681SAndroid Build Coastguard Worker delete HazardRec;
81*9880d681SAndroid Build Coastguard Worker delete AvailableQueue;
82*9880d681SAndroid Build Coastguard Worker }
83*9880d681SAndroid Build Coastguard Worker
84*9880d681SAndroid Build Coastguard Worker void Schedule() override;
85*9880d681SAndroid Build Coastguard Worker
86*9880d681SAndroid Build Coastguard Worker private:
87*9880d681SAndroid Build Coastguard Worker void releaseSucc(SUnit *SU, const SDep &D);
88*9880d681SAndroid Build Coastguard Worker void releaseSuccessors(SUnit *SU);
89*9880d681SAndroid Build Coastguard Worker void scheduleNodeTopDown(SUnit *SU, unsigned CurCycle);
90*9880d681SAndroid Build Coastguard Worker void listScheduleTopDown();
91*9880d681SAndroid Build Coastguard Worker };
92*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
93*9880d681SAndroid Build Coastguard Worker
94*9880d681SAndroid Build Coastguard Worker /// Schedule - Schedule the DAG using list scheduling.
Schedule()95*9880d681SAndroid Build Coastguard Worker void ScheduleDAGVLIW::Schedule() {
96*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs()
97*9880d681SAndroid Build Coastguard Worker << "********** List Scheduling BB#" << BB->getNumber()
98*9880d681SAndroid Build Coastguard Worker << " '" << BB->getName() << "' **********\n");
99*9880d681SAndroid Build Coastguard Worker
100*9880d681SAndroid Build Coastguard Worker // Build the scheduling graph.
101*9880d681SAndroid Build Coastguard Worker BuildSchedGraph(AA);
102*9880d681SAndroid Build Coastguard Worker
103*9880d681SAndroid Build Coastguard Worker AvailableQueue->initNodes(SUnits);
104*9880d681SAndroid Build Coastguard Worker
105*9880d681SAndroid Build Coastguard Worker listScheduleTopDown();
106*9880d681SAndroid Build Coastguard Worker
107*9880d681SAndroid Build Coastguard Worker AvailableQueue->releaseState();
108*9880d681SAndroid Build Coastguard Worker }
109*9880d681SAndroid Build Coastguard Worker
110*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
111*9880d681SAndroid Build Coastguard Worker // Top-Down Scheduling
112*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
113*9880d681SAndroid Build Coastguard Worker
114*9880d681SAndroid Build Coastguard Worker /// releaseSucc - Decrement the NumPredsLeft count of a successor. Add it to
115*9880d681SAndroid Build Coastguard Worker /// the PendingQueue if the count reaches zero. Also update its cycle bound.
releaseSucc(SUnit * SU,const SDep & D)116*9880d681SAndroid Build Coastguard Worker void ScheduleDAGVLIW::releaseSucc(SUnit *SU, const SDep &D) {
117*9880d681SAndroid Build Coastguard Worker SUnit *SuccSU = D.getSUnit();
118*9880d681SAndroid Build Coastguard Worker
119*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
120*9880d681SAndroid Build Coastguard Worker if (SuccSU->NumPredsLeft == 0) {
121*9880d681SAndroid Build Coastguard Worker dbgs() << "*** Scheduling failed! ***\n";
122*9880d681SAndroid Build Coastguard Worker SuccSU->dump(this);
123*9880d681SAndroid Build Coastguard Worker dbgs() << " has been released too many times!\n";
124*9880d681SAndroid Build Coastguard Worker llvm_unreachable(nullptr);
125*9880d681SAndroid Build Coastguard Worker }
126*9880d681SAndroid Build Coastguard Worker #endif
127*9880d681SAndroid Build Coastguard Worker assert(!D.isWeak() && "unexpected artificial DAG edge");
128*9880d681SAndroid Build Coastguard Worker
129*9880d681SAndroid Build Coastguard Worker --SuccSU->NumPredsLeft;
130*9880d681SAndroid Build Coastguard Worker
131*9880d681SAndroid Build Coastguard Worker SuccSU->setDepthToAtLeast(SU->getDepth() + D.getLatency());
132*9880d681SAndroid Build Coastguard Worker
133*9880d681SAndroid Build Coastguard Worker // If all the node's predecessors are scheduled, this node is ready
134*9880d681SAndroid Build Coastguard Worker // to be scheduled. Ignore the special ExitSU node.
135*9880d681SAndroid Build Coastguard Worker if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU) {
136*9880d681SAndroid Build Coastguard Worker PendingQueue.push_back(SuccSU);
137*9880d681SAndroid Build Coastguard Worker }
138*9880d681SAndroid Build Coastguard Worker }
139*9880d681SAndroid Build Coastguard Worker
releaseSuccessors(SUnit * SU)140*9880d681SAndroid Build Coastguard Worker void ScheduleDAGVLIW::releaseSuccessors(SUnit *SU) {
141*9880d681SAndroid Build Coastguard Worker // Top down: release successors.
142*9880d681SAndroid Build Coastguard Worker for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
143*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
144*9880d681SAndroid Build Coastguard Worker assert(!I->isAssignedRegDep() &&
145*9880d681SAndroid Build Coastguard Worker "The list-td scheduler doesn't yet support physreg dependencies!");
146*9880d681SAndroid Build Coastguard Worker
147*9880d681SAndroid Build Coastguard Worker releaseSucc(SU, *I);
148*9880d681SAndroid Build Coastguard Worker }
149*9880d681SAndroid Build Coastguard Worker }
150*9880d681SAndroid Build Coastguard Worker
151*9880d681SAndroid Build Coastguard Worker /// scheduleNodeTopDown - Add the node to the schedule. Decrement the pending
152*9880d681SAndroid Build Coastguard Worker /// count of its successors. If a successor pending count is zero, add it to
153*9880d681SAndroid Build Coastguard Worker /// the Available queue.
scheduleNodeTopDown(SUnit * SU,unsigned CurCycle)154*9880d681SAndroid Build Coastguard Worker void ScheduleDAGVLIW::scheduleNodeTopDown(SUnit *SU, unsigned CurCycle) {
155*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "*** Scheduling [" << CurCycle << "]: ");
156*9880d681SAndroid Build Coastguard Worker DEBUG(SU->dump(this));
157*9880d681SAndroid Build Coastguard Worker
158*9880d681SAndroid Build Coastguard Worker Sequence.push_back(SU);
159*9880d681SAndroid Build Coastguard Worker assert(CurCycle >= SU->getDepth() && "Node scheduled above its depth!");
160*9880d681SAndroid Build Coastguard Worker SU->setDepthToAtLeast(CurCycle);
161*9880d681SAndroid Build Coastguard Worker
162*9880d681SAndroid Build Coastguard Worker releaseSuccessors(SU);
163*9880d681SAndroid Build Coastguard Worker SU->isScheduled = true;
164*9880d681SAndroid Build Coastguard Worker AvailableQueue->scheduledNode(SU);
165*9880d681SAndroid Build Coastguard Worker }
166*9880d681SAndroid Build Coastguard Worker
167*9880d681SAndroid Build Coastguard Worker /// listScheduleTopDown - The main loop of list scheduling for top-down
168*9880d681SAndroid Build Coastguard Worker /// schedulers.
listScheduleTopDown()169*9880d681SAndroid Build Coastguard Worker void ScheduleDAGVLIW::listScheduleTopDown() {
170*9880d681SAndroid Build Coastguard Worker unsigned CurCycle = 0;
171*9880d681SAndroid Build Coastguard Worker
172*9880d681SAndroid Build Coastguard Worker // Release any successors of the special Entry node.
173*9880d681SAndroid Build Coastguard Worker releaseSuccessors(&EntrySU);
174*9880d681SAndroid Build Coastguard Worker
175*9880d681SAndroid Build Coastguard Worker // All leaves to AvailableQueue.
176*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
177*9880d681SAndroid Build Coastguard Worker // It is available if it has no predecessors.
178*9880d681SAndroid Build Coastguard Worker if (SUnits[i].Preds.empty()) {
179*9880d681SAndroid Build Coastguard Worker AvailableQueue->push(&SUnits[i]);
180*9880d681SAndroid Build Coastguard Worker SUnits[i].isAvailable = true;
181*9880d681SAndroid Build Coastguard Worker }
182*9880d681SAndroid Build Coastguard Worker }
183*9880d681SAndroid Build Coastguard Worker
184*9880d681SAndroid Build Coastguard Worker // While AvailableQueue is not empty, grab the node with the highest
185*9880d681SAndroid Build Coastguard Worker // priority. If it is not ready put it back. Schedule the node.
186*9880d681SAndroid Build Coastguard Worker std::vector<SUnit*> NotReady;
187*9880d681SAndroid Build Coastguard Worker Sequence.reserve(SUnits.size());
188*9880d681SAndroid Build Coastguard Worker while (!AvailableQueue->empty() || !PendingQueue.empty()) {
189*9880d681SAndroid Build Coastguard Worker // Check to see if any of the pending instructions are ready to issue. If
190*9880d681SAndroid Build Coastguard Worker // so, add them to the available queue.
191*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = PendingQueue.size(); i != e; ++i) {
192*9880d681SAndroid Build Coastguard Worker if (PendingQueue[i]->getDepth() == CurCycle) {
193*9880d681SAndroid Build Coastguard Worker AvailableQueue->push(PendingQueue[i]);
194*9880d681SAndroid Build Coastguard Worker PendingQueue[i]->isAvailable = true;
195*9880d681SAndroid Build Coastguard Worker PendingQueue[i] = PendingQueue.back();
196*9880d681SAndroid Build Coastguard Worker PendingQueue.pop_back();
197*9880d681SAndroid Build Coastguard Worker --i; --e;
198*9880d681SAndroid Build Coastguard Worker }
199*9880d681SAndroid Build Coastguard Worker else {
200*9880d681SAndroid Build Coastguard Worker assert(PendingQueue[i]->getDepth() > CurCycle && "Negative latency?");
201*9880d681SAndroid Build Coastguard Worker }
202*9880d681SAndroid Build Coastguard Worker }
203*9880d681SAndroid Build Coastguard Worker
204*9880d681SAndroid Build Coastguard Worker // If there are no instructions available, don't try to issue anything, and
205*9880d681SAndroid Build Coastguard Worker // don't advance the hazard recognizer.
206*9880d681SAndroid Build Coastguard Worker if (AvailableQueue->empty()) {
207*9880d681SAndroid Build Coastguard Worker // Reset DFA state.
208*9880d681SAndroid Build Coastguard Worker AvailableQueue->scheduledNode(nullptr);
209*9880d681SAndroid Build Coastguard Worker ++CurCycle;
210*9880d681SAndroid Build Coastguard Worker continue;
211*9880d681SAndroid Build Coastguard Worker }
212*9880d681SAndroid Build Coastguard Worker
213*9880d681SAndroid Build Coastguard Worker SUnit *FoundSUnit = nullptr;
214*9880d681SAndroid Build Coastguard Worker
215*9880d681SAndroid Build Coastguard Worker bool HasNoopHazards = false;
216*9880d681SAndroid Build Coastguard Worker while (!AvailableQueue->empty()) {
217*9880d681SAndroid Build Coastguard Worker SUnit *CurSUnit = AvailableQueue->pop();
218*9880d681SAndroid Build Coastguard Worker
219*9880d681SAndroid Build Coastguard Worker ScheduleHazardRecognizer::HazardType HT =
220*9880d681SAndroid Build Coastguard Worker HazardRec->getHazardType(CurSUnit, 0/*no stalls*/);
221*9880d681SAndroid Build Coastguard Worker if (HT == ScheduleHazardRecognizer::NoHazard) {
222*9880d681SAndroid Build Coastguard Worker FoundSUnit = CurSUnit;
223*9880d681SAndroid Build Coastguard Worker break;
224*9880d681SAndroid Build Coastguard Worker }
225*9880d681SAndroid Build Coastguard Worker
226*9880d681SAndroid Build Coastguard Worker // Remember if this is a noop hazard.
227*9880d681SAndroid Build Coastguard Worker HasNoopHazards |= HT == ScheduleHazardRecognizer::NoopHazard;
228*9880d681SAndroid Build Coastguard Worker
229*9880d681SAndroid Build Coastguard Worker NotReady.push_back(CurSUnit);
230*9880d681SAndroid Build Coastguard Worker }
231*9880d681SAndroid Build Coastguard Worker
232*9880d681SAndroid Build Coastguard Worker // Add the nodes that aren't ready back onto the available list.
233*9880d681SAndroid Build Coastguard Worker if (!NotReady.empty()) {
234*9880d681SAndroid Build Coastguard Worker AvailableQueue->push_all(NotReady);
235*9880d681SAndroid Build Coastguard Worker NotReady.clear();
236*9880d681SAndroid Build Coastguard Worker }
237*9880d681SAndroid Build Coastguard Worker
238*9880d681SAndroid Build Coastguard Worker // If we found a node to schedule, do it now.
239*9880d681SAndroid Build Coastguard Worker if (FoundSUnit) {
240*9880d681SAndroid Build Coastguard Worker scheduleNodeTopDown(FoundSUnit, CurCycle);
241*9880d681SAndroid Build Coastguard Worker HazardRec->EmitInstruction(FoundSUnit);
242*9880d681SAndroid Build Coastguard Worker
243*9880d681SAndroid Build Coastguard Worker // If this is a pseudo-op node, we don't want to increment the current
244*9880d681SAndroid Build Coastguard Worker // cycle.
245*9880d681SAndroid Build Coastguard Worker if (FoundSUnit->Latency) // Don't increment CurCycle for pseudo-ops!
246*9880d681SAndroid Build Coastguard Worker ++CurCycle;
247*9880d681SAndroid Build Coastguard Worker } else if (!HasNoopHazards) {
248*9880d681SAndroid Build Coastguard Worker // Otherwise, we have a pipeline stall, but no other problem, just advance
249*9880d681SAndroid Build Coastguard Worker // the current cycle and try again.
250*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "*** Advancing cycle, no work to do\n");
251*9880d681SAndroid Build Coastguard Worker HazardRec->AdvanceCycle();
252*9880d681SAndroid Build Coastguard Worker ++NumStalls;
253*9880d681SAndroid Build Coastguard Worker ++CurCycle;
254*9880d681SAndroid Build Coastguard Worker } else {
255*9880d681SAndroid Build Coastguard Worker // Otherwise, we have no instructions to issue and we have instructions
256*9880d681SAndroid Build Coastguard Worker // that will fault if we don't do this right. This is the case for
257*9880d681SAndroid Build Coastguard Worker // processors without pipeline interlocks and other cases.
258*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "*** Emitting noop\n");
259*9880d681SAndroid Build Coastguard Worker HazardRec->EmitNoop();
260*9880d681SAndroid Build Coastguard Worker Sequence.push_back(nullptr); // NULL here means noop
261*9880d681SAndroid Build Coastguard Worker ++NumNoops;
262*9880d681SAndroid Build Coastguard Worker ++CurCycle;
263*9880d681SAndroid Build Coastguard Worker }
264*9880d681SAndroid Build Coastguard Worker }
265*9880d681SAndroid Build Coastguard Worker
266*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
267*9880d681SAndroid Build Coastguard Worker VerifyScheduledSequence(/*isBottomUp=*/false);
268*9880d681SAndroid Build Coastguard Worker #endif
269*9880d681SAndroid Build Coastguard Worker }
270*9880d681SAndroid Build Coastguard Worker
271*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
272*9880d681SAndroid Build Coastguard Worker // Public Constructor Functions
273*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
274*9880d681SAndroid Build Coastguard Worker
275*9880d681SAndroid Build Coastguard Worker /// createVLIWDAGScheduler - This creates a top-down list scheduler.
276*9880d681SAndroid Build Coastguard Worker ScheduleDAGSDNodes *
createVLIWDAGScheduler(SelectionDAGISel * IS,CodeGenOpt::Level)277*9880d681SAndroid Build Coastguard Worker llvm::createVLIWDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level) {
278*9880d681SAndroid Build Coastguard Worker return new ScheduleDAGVLIW(*IS->MF, IS->AA, new ResourcePriorityQueue(IS));
279*9880d681SAndroid Build Coastguard Worker }
280