blob: e7e14516eb7383287ef2c0794393ee3aaea6e01f [file] [log] [blame]
Evan Chengab495562006-01-25 09:14:32 +00001//===---- ScheduleDAGList.cpp - Implement a list scheduler for isel DAG ---===//
Evan Cheng31272342006-01-23 08:26:10 +00002//
3// The LLVM Compiler Infrastructure
4//
Chris Lattnerf3ebc3f2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Evan Cheng31272342006-01-23 08:26:10 +00007//
8//===----------------------------------------------------------------------===//
9//
Evan Chengd38c22b2006-05-11 23:55:42 +000010// This implements a top-down list scheduler, using standard algorithms.
11// The basic approach uses a priority queue of available nodes to schedule.
12// One at a time, nodes are taken from the priority queue (thus in priority
13// order), checked for legality to schedule, and emitted if legal.
Chris Lattner01aa7522006-03-06 17:58:04 +000014//
15// Nodes may not be legal to schedule either due to structural hazards (e.g.
16// pipeline or resource constraints) or because an input to the instruction has
17// not completed execution.
Evan Cheng31272342006-01-23 08:26:10 +000018//
19//===----------------------------------------------------------------------===//
20
Dale Johannesen2182f062007-07-13 17:13:54 +000021#define DEBUG_TYPE "pre-RA-sched"
Evan Cheng31272342006-01-23 08:26:10 +000022#include "llvm/CodeGen/ScheduleDAG.h"
Jim Laskey29e635d2006-08-02 12:30:23 +000023#include "llvm/CodeGen/SchedulerRegistry.h"
Jim Laskey03593f72006-08-01 18:29:48 +000024#include "llvm/CodeGen/SelectionDAGISel.h"
Dan Gohman3a4be0f2008-02-10 18:45:23 +000025#include "llvm/Target/TargetRegisterInfo.h"
Owen Anderson8c2c1e92006-05-12 06:33:49 +000026#include "llvm/Target/TargetData.h"
Evan Cheng31272342006-01-23 08:26:10 +000027#include "llvm/Target/TargetMachine.h"
28#include "llvm/Target/TargetInstrInfo.h"
Evan Chengab495562006-01-25 09:14:32 +000029#include "llvm/Support/Debug.h"
Chris Lattner3d27be12006-08-27 12:54:02 +000030#include "llvm/Support/Compiler.h"
Dan Gohman0d8a61e2008-06-23 23:40:09 +000031#include "llvm/ADT/PriorityQueue.h"
Chris Lattnerfa5e1c92006-03-05 23:13:56 +000032#include "llvm/ADT/Statistic.h"
Dan Gohmand2760c02008-11-15 00:23:40 +000033#include "LatencyPriorityQueue.h"
Evan Chengab495562006-01-25 09:14:32 +000034#include <climits>
Evan Cheng31272342006-01-23 08:26:10 +000035using namespace llvm;
36
Chris Lattneraee775a2006-12-19 22:41:21 +000037STATISTIC(NumNoops , "Number of noops inserted");
38STATISTIC(NumStalls, "Number of pipeline stalls");
Evan Chengab495562006-01-25 09:14:32 +000039
Jim Laskey95eda5b2006-08-01 14:21:23 +000040static RegisterScheduler
Dan Gohman9c4b7d52008-10-14 20:25:08 +000041 tdListDAGScheduler("list-td", "Top-down list scheduler",
Jim Laskey95eda5b2006-08-01 14:21:23 +000042 createTDListDAGScheduler);
43
Chris Lattneraf5e26c2006-03-08 04:37:58 +000044namespace {
Chris Lattner9e95acc2006-03-09 06:37:29 +000045//===----------------------------------------------------------------------===//
46/// ScheduleDAGList - The actual list scheduler implementation. This supports
Evan Chengd38c22b2006-05-11 23:55:42 +000047/// top-down scheduling.
Chris Lattner9e95acc2006-03-09 06:37:29 +000048///
Chris Lattnere097e6f2006-06-28 22:17:39 +000049class VISIBILITY_HIDDEN ScheduleDAGList : public ScheduleDAG {
Evan Cheng31272342006-01-23 08:26:10 +000050private:
Chris Lattner356183d2006-03-11 22:44:37 +000051 /// AvailableQueue - The priority queue to use for the available SUnits.
52 ///
53 SchedulingPriorityQueue *AvailableQueue;
Chris Lattner9df64752006-03-09 06:35:14 +000054
Chris Lattner572003c2006-03-12 00:38:57 +000055 /// PendingQueue - This contains all of the instructions whose operands have
56 /// been issued, but their results are not ready yet (due to the latency of
57 /// the operation). Once the operands becomes available, the instruction is
Dan Gohmana687fd82008-11-17 19:45:19 +000058 /// added to the AvailableQueue.
59 std::vector<SUnit*> PendingQueue;
Evan Cheng9add8802006-05-04 19:16:39 +000060
Chris Lattnere50c0922006-03-05 22:45:01 +000061 /// HazardRec - The hazard recognizer to use.
Chris Lattner543832d2006-03-08 04:25:59 +000062 HazardRecognizer *HazardRec;
Evan Cheng9add8802006-05-04 19:16:39 +000063
Evan Cheng31272342006-01-23 08:26:10 +000064public:
Dan Gohman5a390b92008-11-13 21:21:28 +000065 ScheduleDAGList(SelectionDAG *dag, MachineBasicBlock *bb,
Evan Chengd38c22b2006-05-11 23:55:42 +000066 const TargetMachine &tm,
Chris Lattner356183d2006-03-11 22:44:37 +000067 SchedulingPriorityQueue *availqueue,
Chris Lattner543832d2006-03-08 04:25:59 +000068 HazardRecognizer *HR)
Evan Chengd38c22b2006-05-11 23:55:42 +000069 : ScheduleDAG(dag, bb, tm),
Chris Lattner356183d2006-03-11 22:44:37 +000070 AvailableQueue(availqueue), HazardRec(HR) {
Chris Lattnere50c0922006-03-05 22:45:01 +000071 }
Evan Chengab495562006-01-25 09:14:32 +000072
73 ~ScheduleDAGList() {
Chris Lattner543832d2006-03-08 04:25:59 +000074 delete HazardRec;
Chris Lattner356183d2006-03-11 22:44:37 +000075 delete AvailableQueue;
Evan Chengab495562006-01-25 09:14:32 +000076 }
Evan Cheng31272342006-01-23 08:26:10 +000077
78 void Schedule();
Evan Cheng31272342006-01-23 08:26:10 +000079
Evan Chengab495562006-01-25 09:14:32 +000080private:
Dan Gohman5ebdb982008-11-18 00:38:59 +000081 void ReleaseSucc(SUnit *SU, SUnit *SuccSU, bool isChain);
Chris Lattner063086b2006-03-11 22:34:41 +000082 void ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle);
Chris Lattner399bee22006-03-09 06:48:37 +000083 void ListScheduleTopDown();
Evan Chengab495562006-01-25 09:14:32 +000084};
Chris Lattneraf5e26c2006-03-08 04:37:58 +000085} // end anonymous namespace
Evan Chengab495562006-01-25 09:14:32 +000086
Chris Lattner47639db2006-03-06 00:22:00 +000087HazardRecognizer::~HazardRecognizer() {}
88
Evan Chengc4c339c2006-01-26 00:30:29 +000089
Chris Lattner9995a0c2006-03-11 22:28:35 +000090/// Schedule - Schedule the DAG using list scheduling.
Chris Lattner9995a0c2006-03-11 22:28:35 +000091void ScheduleDAGList::Schedule() {
Bill Wendling22e978a2006-12-07 20:04:42 +000092 DOUT << "********** List Scheduling **********\n";
Chris Lattner9995a0c2006-03-11 22:28:35 +000093
94 // Build scheduling units.
95 BuildSchedUnits();
Evan Cheng7d693892006-05-09 07:13:34 +000096
Dan Gohman46520a22008-06-21 19:18:17 +000097 AvailableQueue->initNodes(SUnits);
Chris Lattner9995a0c2006-03-11 22:28:35 +000098
Evan Chengd38c22b2006-05-11 23:55:42 +000099 ListScheduleTopDown();
Chris Lattner9995a0c2006-03-11 22:28:35 +0000100
Chris Lattner356183d2006-03-11 22:44:37 +0000101 AvailableQueue->releaseState();
Chris Lattner9995a0c2006-03-11 22:28:35 +0000102}
103
104//===----------------------------------------------------------------------===//
Chris Lattner9995a0c2006-03-11 22:28:35 +0000105// Top-Down Scheduling
106//===----------------------------------------------------------------------===//
107
108/// ReleaseSucc - Decrement the NumPredsLeft count of a successor. Add it to
Dan Gohman5ebdb982008-11-18 00:38:59 +0000109/// the PendingQueue if the count reaches zero. Also update its cycle bound.
110void ScheduleDAGList::ReleaseSucc(SUnit *SU, SUnit *SuccSU, bool isChain) {
111 --SuccSU->NumPredsLeft;
Chris Lattner9995a0c2006-03-11 22:28:35 +0000112
Dan Gohman5ebdb982008-11-18 00:38:59 +0000113#ifndef NDEBUG
114 if (SuccSU->NumPredsLeft < 0) {
115 cerr << "*** Scheduling failed! ***\n";
Dan Gohman22d07b12008-11-18 02:06:40 +0000116 SuccSU->dump(this);
Dan Gohman5ebdb982008-11-18 00:38:59 +0000117 cerr << " has been released too many times!\n";
118 assert(0);
119 }
120#endif
121
122 // Compute how many cycles it will be before this actually becomes
123 // available. This is the max of the start time of all predecessors plus
124 // their latencies.
125 // If this is a token edge, we don't need to wait for the latency of the
126 // preceeding instruction (e.g. a long-latency load) unless there is also
127 // some other data dependence.
128 unsigned PredDoneCycle = SU->Cycle;
129 if (!isChain)
130 PredDoneCycle += SU->Latency;
131 else if (SU->Latency)
132 PredDoneCycle += 1;
133 SuccSU->CycleBound = std::max(SuccSU->CycleBound, PredDoneCycle);
Chris Lattner9995a0c2006-03-11 22:28:35 +0000134
Evan Cheng038dcc52007-09-28 19:24:24 +0000135 if (SuccSU->NumPredsLeft == 0) {
Dan Gohmana687fd82008-11-17 19:45:19 +0000136 PendingQueue.push_back(SuccSU);
Chris Lattner9995a0c2006-03-11 22:28:35 +0000137 }
138}
139
140/// ScheduleNodeTopDown - Add the node to the schedule. Decrement the pending
141/// count of its successors. If a successor pending count is zero, add it to
142/// the Available queue.
Chris Lattner356183d2006-03-11 22:44:37 +0000143void ScheduleDAGList::ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle) {
Bill Wendling22e978a2006-12-07 20:04:42 +0000144 DOUT << "*** Scheduling [" << CurCycle << "]: ";
Dan Gohman22d07b12008-11-18 02:06:40 +0000145 DEBUG(SU->dump(this));
Chris Lattner9995a0c2006-03-11 22:28:35 +0000146
147 Sequence.push_back(SU);
Chris Lattner356183d2006-03-11 22:44:37 +0000148 SU->Cycle = CurCycle;
Dan Gohman92a36d72008-11-17 21:31:02 +0000149
Dan Gohman68294c02008-11-15 00:24:23 +0000150 // Top down: release successors.
Chris Lattnerd86418a2006-08-17 00:09:56 +0000151 for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
152 I != E; ++I)
Dan Gohman5ebdb982008-11-18 00:38:59 +0000153 ReleaseSucc(SU, I->Dep, I->isCtrl);
Dan Gohman92a36d72008-11-17 21:31:02 +0000154
155 SU->isScheduled = true;
156 AvailableQueue->ScheduledNode(SU);
Chris Lattner9995a0c2006-03-11 22:28:35 +0000157}
158
Chris Lattner98ecb8e2006-03-05 21:10:33 +0000159/// ListScheduleTopDown - The main loop of list scheduling for top-down
160/// schedulers.
Chris Lattner399bee22006-03-09 06:48:37 +0000161void ScheduleDAGList::ListScheduleTopDown() {
Chris Lattner572003c2006-03-12 00:38:57 +0000162 unsigned CurCycle = 0;
Chris Lattner572003c2006-03-12 00:38:57 +0000163
Chris Lattner98ecb8e2006-03-05 21:10:33 +0000164 // All leaves to Available queue.
Chris Lattner42e20262006-03-08 04:54:34 +0000165 for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
Chris Lattner98ecb8e2006-03-05 21:10:33 +0000166 // It is available if it has no predecessors.
Dan Gohman4370f262008-04-15 01:22:18 +0000167 if (SUnits[i].Preds.empty()) {
Chris Lattner356183d2006-03-11 22:44:37 +0000168 AvailableQueue->push(&SUnits[i]);
Dan Gohman17c226b2008-11-17 16:37:30 +0000169 SUnits[i].isAvailable = true;
Chris Lattner572003c2006-03-12 00:38:57 +0000170 }
Chris Lattner98ecb8e2006-03-05 21:10:33 +0000171 }
172
173 // While Available queue is not empty, grab the node with the highest
174 // priority. If it is not ready put it back. Schedule the node.
175 std::vector<SUnit*> NotReady;
Dan Gohmane6e13482008-06-21 15:52:51 +0000176 Sequence.reserve(SUnits.size());
Chris Lattner572003c2006-03-12 00:38:57 +0000177 while (!AvailableQueue->empty() || !PendingQueue.empty()) {
178 // Check to see if any of the pending instructions are ready to issue. If
179 // so, add them to the available queue.
Chris Lattnera767dbf2006-03-12 09:01:41 +0000180 for (unsigned i = 0, e = PendingQueue.size(); i != e; ++i) {
Dan Gohmana687fd82008-11-17 19:45:19 +0000181 if (PendingQueue[i]->CycleBound == CurCycle) {
182 AvailableQueue->push(PendingQueue[i]);
183 PendingQueue[i]->isAvailable = true;
Chris Lattner572003c2006-03-12 00:38:57 +0000184 PendingQueue[i] = PendingQueue.back();
185 PendingQueue.pop_back();
186 --i; --e;
187 } else {
Dan Gohmana687fd82008-11-17 19:45:19 +0000188 assert(PendingQueue[i]->CycleBound > CurCycle && "Negative latency?");
Chris Lattner572003c2006-03-12 00:38:57 +0000189 }
Chris Lattnera767dbf2006-03-12 09:01:41 +0000190 }
Chris Lattner572003c2006-03-12 00:38:57 +0000191
Chris Lattnera767dbf2006-03-12 09:01:41 +0000192 // If there are no instructions available, don't try to issue anything, and
193 // don't advance the hazard recognizer.
194 if (AvailableQueue->empty()) {
195 ++CurCycle;
196 continue;
197 }
Chris Lattner98ecb8e2006-03-05 21:10:33 +0000198
Chris Lattnera767dbf2006-03-12 09:01:41 +0000199 SUnit *FoundSUnit = 0;
200 SDNode *FoundNode = 0;
201
Chris Lattnere50c0922006-03-05 22:45:01 +0000202 bool HasNoopHazards = false;
Chris Lattner572003c2006-03-12 00:38:57 +0000203 while (!AvailableQueue->empty()) {
Chris Lattnera767dbf2006-03-12 09:01:41 +0000204 SUnit *CurSUnit = AvailableQueue->pop();
Chris Lattner0c801bd2006-03-07 05:40:43 +0000205
206 // Get the node represented by this SUnit.
Dan Gohman1ddfcba2008-11-13 21:36:12 +0000207 FoundNode = CurSUnit->getNode();
Chris Lattnera767dbf2006-03-12 09:01:41 +0000208
Chris Lattner0c801bd2006-03-07 05:40:43 +0000209 // If this is a pseudo op, like copyfromreg, look to see if there is a
210 // real target node flagged to it. If so, use the target node.
Dan Gohman072734e2008-11-13 23:24:17 +0000211 while (!FoundNode->isMachineOpcode()) {
212 SDNode *N = FoundNode->getFlaggedNode();
213 if (!N) break;
214 FoundNode = N;
215 }
Chris Lattner0c801bd2006-03-07 05:40:43 +0000216
Chris Lattnera767dbf2006-03-12 09:01:41 +0000217 HazardRecognizer::HazardType HT = HazardRec->getHazardType(FoundNode);
Chris Lattnere50c0922006-03-05 22:45:01 +0000218 if (HT == HazardRecognizer::NoHazard) {
Chris Lattnera767dbf2006-03-12 09:01:41 +0000219 FoundSUnit = CurSUnit;
Chris Lattnere50c0922006-03-05 22:45:01 +0000220 break;
221 }
222
223 // Remember if this is a noop hazard.
224 HasNoopHazards |= HT == HazardRecognizer::NoopHazard;
225
Chris Lattnera767dbf2006-03-12 09:01:41 +0000226 NotReady.push_back(CurSUnit);
Chris Lattner572003c2006-03-12 00:38:57 +0000227 }
Chris Lattnere50c0922006-03-05 22:45:01 +0000228
Chris Lattner98ecb8e2006-03-05 21:10:33 +0000229 // Add the nodes that aren't ready back onto the available list.
Chris Lattnera767dbf2006-03-12 09:01:41 +0000230 if (!NotReady.empty()) {
231 AvailableQueue->push_all(NotReady);
232 NotReady.clear();
233 }
Chris Lattnere50c0922006-03-05 22:45:01 +0000234
235 // If we found a node to schedule, do it now.
Chris Lattnera767dbf2006-03-12 09:01:41 +0000236 if (FoundSUnit) {
237 ScheduleNodeTopDown(FoundSUnit, CurCycle);
238 HazardRec->EmitInstruction(FoundNode);
Chris Lattner572003c2006-03-12 00:38:57 +0000239
240 // If this is a pseudo-op node, we don't want to increment the current
241 // cycle.
Chris Lattnera767dbf2006-03-12 09:01:41 +0000242 if (FoundSUnit->Latency) // Don't increment CurCycle for pseudo-ops!
243 ++CurCycle;
Chris Lattnere50c0922006-03-05 22:45:01 +0000244 } else if (!HasNoopHazards) {
245 // Otherwise, we have a pipeline stall, but no other problem, just advance
246 // the current cycle and try again.
Bill Wendling22e978a2006-12-07 20:04:42 +0000247 DOUT << "*** Advancing cycle, no work to do\n";
Chris Lattner543832d2006-03-08 04:25:59 +0000248 HazardRec->AdvanceCycle();
Chris Lattnerfa5e1c92006-03-05 23:13:56 +0000249 ++NumStalls;
Chris Lattnera767dbf2006-03-12 09:01:41 +0000250 ++CurCycle;
Chris Lattnere50c0922006-03-05 22:45:01 +0000251 } else {
252 // Otherwise, we have no instructions to issue and we have instructions
253 // that will fault if we don't do this right. This is the case for
254 // processors without pipeline interlocks and other cases.
Bill Wendling22e978a2006-12-07 20:04:42 +0000255 DOUT << "*** Emitting noop\n";
Chris Lattner543832d2006-03-08 04:25:59 +0000256 HazardRec->EmitNoop();
Chris Lattner00b52ea2006-03-05 23:59:20 +0000257 Sequence.push_back(0); // NULL SUnit* -> noop
Chris Lattnerfa5e1c92006-03-05 23:13:56 +0000258 ++NumNoops;
Chris Lattnera767dbf2006-03-12 09:01:41 +0000259 ++CurCycle;
Chris Lattnere50c0922006-03-05 22:45:01 +0000260 }
Chris Lattner98ecb8e2006-03-05 21:10:33 +0000261 }
262
263#ifndef NDEBUG
264 // Verify that all SUnits were scheduled.
265 bool AnyNotSched = false;
Chris Lattner42e20262006-03-08 04:54:34 +0000266 for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
Evan Cheng038dcc52007-09-28 19:24:24 +0000267 if (SUnits[i].NumPredsLeft != 0) {
Chris Lattner98ecb8e2006-03-05 21:10:33 +0000268 if (!AnyNotSched)
Bill Wendling22e978a2006-12-07 20:04:42 +0000269 cerr << "*** List scheduling failed! ***\n";
Dan Gohman22d07b12008-11-18 02:06:40 +0000270 SUnits[i].dump(this);
Bill Wendling22e978a2006-12-07 20:04:42 +0000271 cerr << "has not been scheduled!\n";
Chris Lattner98ecb8e2006-03-05 21:10:33 +0000272 AnyNotSched = true;
273 }
274 }
275 assert(!AnyNotSched);
276#endif
277}
278
Chris Lattner9df64752006-03-09 06:35:14 +0000279//===----------------------------------------------------------------------===//
Chris Lattner9df64752006-03-09 06:35:14 +0000280// Public Constructor Functions
281//===----------------------------------------------------------------------===//
282
Jim Laskey95eda5b2006-08-01 14:21:23 +0000283/// createTDListDAGScheduler - This creates a top-down list scheduler with a
284/// new hazard recognizer. This scheduler takes ownership of the hazard
285/// recognizer and deletes it when done.
Jim Laskey03593f72006-08-01 18:29:48 +0000286ScheduleDAG* llvm::createTDListDAGScheduler(SelectionDAGISel *IS,
287 SelectionDAG *DAG,
Dan Gohman5499e892008-11-11 17:50:47 +0000288 const TargetMachine *TM,
Evan Cheng2c977312008-07-01 18:05:03 +0000289 MachineBasicBlock *BB, bool Fast) {
Dan Gohman5a390b92008-11-13 21:21:28 +0000290 return new ScheduleDAGList(DAG, BB, *TM,
Chris Lattner6398c132006-03-09 07:38:27 +0000291 new LatencyPriorityQueue(),
Jim Laskey03593f72006-08-01 18:29:48 +0000292 IS->CreateTargetHazardRecognizer());
Evan Cheng31272342006-01-23 08:26:10 +0000293}