blob: c8d21584616a775885fa7cb041d9e9a0e34d21e6 [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"
Dan Gohman483377c2009-02-06 17:22:58 +000022#include "ScheduleDAGSDNodes.h"
Dan Gohman60cb69e2008-11-19 23:18:57 +000023#include "llvm/CodeGen/LatencyPriorityQueue.h"
Dan Gohman7e105f02009-01-15 22:18:12 +000024#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
Jim Laskey29e635d2006-08-02 12:30:23 +000025#include "llvm/CodeGen/SchedulerRegistry.h"
Jim Laskey03593f72006-08-01 18:29:48 +000026#include "llvm/CodeGen/SelectionDAGISel.h"
Dan Gohman3a4be0f2008-02-10 18:45:23 +000027#include "llvm/Target/TargetRegisterInfo.h"
Owen Anderson8c2c1e92006-05-12 06:33:49 +000028#include "llvm/Target/TargetData.h"
Evan Cheng31272342006-01-23 08:26:10 +000029#include "llvm/Target/TargetInstrInfo.h"
Evan Chengab495562006-01-25 09:14:32 +000030#include "llvm/Support/Debug.h"
Chris Lattner3d27be12006-08-27 12:54:02 +000031#include "llvm/Support/Compiler.h"
Torok Edwin56d06592009-07-11 20:10:48 +000032#include "llvm/Support/ErrorHandling.h"
Chris Lattner4dc3edd2009-08-23 06:35:02 +000033#include "llvm/Support/raw_ostream.h"
Dan Gohman0d8a61e2008-06-23 23:40:09 +000034#include "llvm/ADT/PriorityQueue.h"
Chris Lattnerfa5e1c92006-03-05 23:13:56 +000035#include "llvm/ADT/Statistic.h"
Evan Chengab495562006-01-25 09:14:32 +000036#include <climits>
Evan Cheng31272342006-01-23 08:26:10 +000037using namespace llvm;
38
Chris Lattneraee775a2006-12-19 22:41:21 +000039STATISTIC(NumNoops , "Number of noops inserted");
40STATISTIC(NumStalls, "Number of pipeline stalls");
Evan Chengab495562006-01-25 09:14:32 +000041
Jim Laskey95eda5b2006-08-01 14:21:23 +000042static RegisterScheduler
Dan Gohman9c4b7d52008-10-14 20:25:08 +000043 tdListDAGScheduler("list-td", "Top-down list scheduler",
Jim Laskey95eda5b2006-08-01 14:21:23 +000044 createTDListDAGScheduler);
45
Chris Lattneraf5e26c2006-03-08 04:37:58 +000046namespace {
Chris Lattner9e95acc2006-03-09 06:37:29 +000047//===----------------------------------------------------------------------===//
48/// ScheduleDAGList - The actual list scheduler implementation. This supports
Evan Chengd38c22b2006-05-11 23:55:42 +000049/// top-down scheduling.
Chris Lattner9e95acc2006-03-09 06:37:29 +000050///
Dan Gohman60cb69e2008-11-19 23:18:57 +000051class VISIBILITY_HIDDEN ScheduleDAGList : public ScheduleDAGSDNodes {
Evan Cheng31272342006-01-23 08:26:10 +000052private:
Chris Lattner356183d2006-03-11 22:44:37 +000053 /// AvailableQueue - The priority queue to use for the available SUnits.
54 ///
55 SchedulingPriorityQueue *AvailableQueue;
Chris Lattner9df64752006-03-09 06:35:14 +000056
Chris Lattner572003c2006-03-12 00:38:57 +000057 /// PendingQueue - This contains all of the instructions whose operands have
58 /// been issued, but their results are not ready yet (due to the latency of
Dan Gohmanfe1748d2008-11-18 02:50:01 +000059 /// the operation). Once the operands become available, the instruction is
Dan Gohmana687fd82008-11-17 19:45:19 +000060 /// added to the AvailableQueue.
61 std::vector<SUnit*> PendingQueue;
Evan Cheng9add8802006-05-04 19:16:39 +000062
Chris Lattnere50c0922006-03-05 22:45:01 +000063 /// HazardRec - The hazard recognizer to use.
Dan Gohman7e105f02009-01-15 22:18:12 +000064 ScheduleHazardRecognizer *HazardRec;
Evan Cheng9add8802006-05-04 19:16:39 +000065
Evan Cheng31272342006-01-23 08:26:10 +000066public:
Dan Gohman619ef482009-01-15 19:20:50 +000067 ScheduleDAGList(MachineFunction &mf,
Chris Lattner356183d2006-03-11 22:44:37 +000068 SchedulingPriorityQueue *availqueue,
Dan Gohman7e105f02009-01-15 22:18:12 +000069 ScheduleHazardRecognizer *HR)
Dan Gohman619ef482009-01-15 19:20:50 +000070 : ScheduleDAGSDNodes(mf),
Chris Lattner356183d2006-03-11 22:44:37 +000071 AvailableQueue(availqueue), HazardRec(HR) {
Chris Lattnere50c0922006-03-05 22:45:01 +000072 }
Evan Chengab495562006-01-25 09:14:32 +000073
74 ~ScheduleDAGList() {
Chris Lattner543832d2006-03-08 04:25:59 +000075 delete HazardRec;
Chris Lattner356183d2006-03-11 22:44:37 +000076 delete AvailableQueue;
Evan Chengab495562006-01-25 09:14:32 +000077 }
Evan Cheng31272342006-01-23 08:26:10 +000078
79 void Schedule();
Evan Cheng31272342006-01-23 08:26:10 +000080
Evan Chengab495562006-01-25 09:14:32 +000081private:
Dan Gohman2d170892008-12-09 22:54:47 +000082 void ReleaseSucc(SUnit *SU, const SDep &D);
Dan Gohmanb9543432009-02-10 23:27:53 +000083 void ReleaseSuccessors(SUnit *SU);
Chris Lattner063086b2006-03-11 22:34:41 +000084 void ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle);
Chris Lattner399bee22006-03-09 06:48:37 +000085 void ListScheduleTopDown();
Evan Chengab495562006-01-25 09:14:32 +000086};
Chris Lattneraf5e26c2006-03-08 04:37:58 +000087} // end anonymous namespace
Evan Chengab495562006-01-25 09:14:32 +000088
Chris Lattner9995a0c2006-03-11 22:28:35 +000089/// Schedule - Schedule the DAG using list scheduling.
Chris Lattner9995a0c2006-03-11 22:28:35 +000090void ScheduleDAGList::Schedule() {
Chris Lattner4dc3edd2009-08-23 06:35:02 +000091 DEBUG(errs() << "********** List Scheduling **********\n");
Chris Lattner9995a0c2006-03-11 22:28:35 +000092
Dan Gohman04543e72008-12-23 18:36:58 +000093 // Build the scheduling graph.
Dan Gohman918ec532009-10-09 23:33:48 +000094 BuildSchedGraph(NULL);
Evan Cheng7d693892006-05-09 07:13:34 +000095
Dan Gohman46520a22008-06-21 19:18:17 +000096 AvailableQueue->initNodes(SUnits);
Chris Lattner9995a0c2006-03-11 22:28:35 +000097
Evan Chengd38c22b2006-05-11 23:55:42 +000098 ListScheduleTopDown();
Chris Lattner9995a0c2006-03-11 22:28:35 +000099
Chris Lattner356183d2006-03-11 22:44:37 +0000100 AvailableQueue->releaseState();
Chris Lattner9995a0c2006-03-11 22:28:35 +0000101}
102
103//===----------------------------------------------------------------------===//
Chris Lattner9995a0c2006-03-11 22:28:35 +0000104// Top-Down Scheduling
105//===----------------------------------------------------------------------===//
106
107/// ReleaseSucc - Decrement the NumPredsLeft count of a successor. Add it to
Dan Gohman5ebdb982008-11-18 00:38:59 +0000108/// the PendingQueue if the count reaches zero. Also update its cycle bound.
Dan Gohman2d170892008-12-09 22:54:47 +0000109void ScheduleDAGList::ReleaseSucc(SUnit *SU, const SDep &D) {
110 SUnit *SuccSU = D.getSUnit();
Reid Kleckner8ff5c192009-09-30 20:15:38 +0000111
Dan Gohman5ebdb982008-11-18 00:38:59 +0000112#ifndef NDEBUG
Reid Kleckner8ff5c192009-09-30 20:15:38 +0000113 if (SuccSU->NumPredsLeft == 0) {
Chris Lattner317dbbc2009-08-23 07:05:07 +0000114 errs() << "*** Scheduling failed! ***\n";
Dan Gohman22d07b12008-11-18 02:06:40 +0000115 SuccSU->dump(this);
Chris Lattner317dbbc2009-08-23 07:05:07 +0000116 errs() << " has been released too many times!\n";
Torok Edwinfbcc6632009-07-14 16:55:14 +0000117 llvm_unreachable(0);
Dan Gohman5ebdb982008-11-18 00:38:59 +0000118 }
119#endif
Reid Kleckner8ff5c192009-09-30 20:15:38 +0000120 --SuccSU->NumPredsLeft;
121
Dan Gohmandddc1ac2008-12-16 03:25:46 +0000122 SuccSU->setDepthToAtLeast(SU->getDepth() + D.getLatency());
Chris Lattner9995a0c2006-03-11 22:28:35 +0000123
Dan Gohmanb9543432009-02-10 23:27:53 +0000124 // If all the node's predecessors are scheduled, this node is ready
125 // to be scheduled. Ignore the special ExitSU node.
126 if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU)
Dan Gohmana687fd82008-11-17 19:45:19 +0000127 PendingQueue.push_back(SuccSU);
Dan Gohmanb9543432009-02-10 23:27:53 +0000128}
129
130void ScheduleDAGList::ReleaseSuccessors(SUnit *SU) {
131 // Top down: release successors.
132 for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
133 I != E; ++I) {
134 assert(!I->isAssignedRegDep() &&
135 "The list-td scheduler doesn't yet support physreg dependencies!");
136
137 ReleaseSucc(SU, *I);
Chris Lattner9995a0c2006-03-11 22:28:35 +0000138 }
139}
140
141/// ScheduleNodeTopDown - Add the node to the schedule. Decrement the pending
142/// count of its successors. If a successor pending count is zero, add it to
143/// the Available queue.
Chris Lattner356183d2006-03-11 22:44:37 +0000144void ScheduleDAGList::ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle) {
Chris Lattner4dc3edd2009-08-23 06:35:02 +0000145 DEBUG(errs() << "*** Scheduling [" << CurCycle << "]: ");
Dan Gohman22d07b12008-11-18 02:06:40 +0000146 DEBUG(SU->dump(this));
Chris Lattner9995a0c2006-03-11 22:28:35 +0000147
148 Sequence.push_back(SU);
Dan Gohmandddc1ac2008-12-16 03:25:46 +0000149 assert(CurCycle >= SU->getDepth() && "Node scheduled above its depth!");
150 SU->setDepthToAtLeast(CurCycle);
Dan Gohman92a36d72008-11-17 21:31:02 +0000151
Dan Gohmanb9543432009-02-10 23:27:53 +0000152 ReleaseSuccessors(SU);
Dan Gohman92a36d72008-11-17 21:31:02 +0000153 SU->isScheduled = true;
154 AvailableQueue->ScheduledNode(SU);
Chris Lattner9995a0c2006-03-11 22:28:35 +0000155}
156
Chris Lattner98ecb8e2006-03-05 21:10:33 +0000157/// ListScheduleTopDown - The main loop of list scheduling for top-down
158/// schedulers.
Chris Lattner399bee22006-03-09 06:48:37 +0000159void ScheduleDAGList::ListScheduleTopDown() {
Chris Lattner572003c2006-03-12 00:38:57 +0000160 unsigned CurCycle = 0;
Chris Lattner572003c2006-03-12 00:38:57 +0000161
Dan Gohmanb9543432009-02-10 23:27:53 +0000162 // Release any successors of the special Entry node.
163 ReleaseSuccessors(&EntrySU);
164
Chris Lattner98ecb8e2006-03-05 21:10:33 +0000165 // All leaves to Available queue.
Chris Lattner42e20262006-03-08 04:54:34 +0000166 for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
Chris Lattner98ecb8e2006-03-05 21:10:33 +0000167 // It is available if it has no predecessors.
Dan Gohman4370f262008-04-15 01:22:18 +0000168 if (SUnits[i].Preds.empty()) {
Chris Lattner356183d2006-03-11 22:44:37 +0000169 AvailableQueue->push(&SUnits[i]);
Dan Gohman17c226b2008-11-17 16:37:30 +0000170 SUnits[i].isAvailable = true;
Chris Lattner572003c2006-03-12 00:38:57 +0000171 }
Chris Lattner98ecb8e2006-03-05 21:10:33 +0000172 }
173
174 // While Available queue is not empty, grab the node with the highest
175 // priority. If it is not ready put it back. Schedule the node.
176 std::vector<SUnit*> NotReady;
Dan Gohmane6e13482008-06-21 15:52:51 +0000177 Sequence.reserve(SUnits.size());
Chris Lattner572003c2006-03-12 00:38:57 +0000178 while (!AvailableQueue->empty() || !PendingQueue.empty()) {
179 // Check to see if any of the pending instructions are ready to issue. If
180 // so, add them to the available queue.
Chris Lattnera767dbf2006-03-12 09:01:41 +0000181 for (unsigned i = 0, e = PendingQueue.size(); i != e; ++i) {
Dan Gohmandddc1ac2008-12-16 03:25:46 +0000182 if (PendingQueue[i]->getDepth() == CurCycle) {
Dan Gohmana687fd82008-11-17 19:45:19 +0000183 AvailableQueue->push(PendingQueue[i]);
184 PendingQueue[i]->isAvailable = true;
Chris Lattner572003c2006-03-12 00:38:57 +0000185 PendingQueue[i] = PendingQueue.back();
186 PendingQueue.pop_back();
187 --i; --e;
188 } else {
Dan Gohmandddc1ac2008-12-16 03:25:46 +0000189 assert(PendingQueue[i]->getDepth() > CurCycle && "Negative latency?");
Chris Lattner572003c2006-03-12 00:38:57 +0000190 }
Chris Lattnera767dbf2006-03-12 09:01:41 +0000191 }
Chris Lattner572003c2006-03-12 00:38:57 +0000192
Chris Lattnera767dbf2006-03-12 09:01:41 +0000193 // If there are no instructions available, don't try to issue anything, and
194 // don't advance the hazard recognizer.
195 if (AvailableQueue->empty()) {
196 ++CurCycle;
197 continue;
198 }
Chris Lattner98ecb8e2006-03-05 21:10:33 +0000199
Chris Lattnera767dbf2006-03-12 09:01:41 +0000200 SUnit *FoundSUnit = 0;
Chris Lattnera767dbf2006-03-12 09:01:41 +0000201
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
Dan Gohman7e105f02009-01-15 22:18:12 +0000206 ScheduleHazardRecognizer::HazardType HT =
207 HazardRec->getHazardType(CurSUnit);
208 if (HT == ScheduleHazardRecognizer::NoHazard) {
Chris Lattnera767dbf2006-03-12 09:01:41 +0000209 FoundSUnit = CurSUnit;
Chris Lattnere50c0922006-03-05 22:45:01 +0000210 break;
211 }
Dan Gohman60cb69e2008-11-19 23:18:57 +0000212
Chris Lattnere50c0922006-03-05 22:45:01 +0000213 // Remember if this is a noop hazard.
Dan Gohman7e105f02009-01-15 22:18:12 +0000214 HasNoopHazards |= HT == ScheduleHazardRecognizer::NoopHazard;
Chris Lattnere50c0922006-03-05 22:45:01 +0000215
Chris Lattnera767dbf2006-03-12 09:01:41 +0000216 NotReady.push_back(CurSUnit);
Chris Lattner572003c2006-03-12 00:38:57 +0000217 }
Chris Lattnere50c0922006-03-05 22:45:01 +0000218
Chris Lattner98ecb8e2006-03-05 21:10:33 +0000219 // Add the nodes that aren't ready back onto the available list.
Chris Lattnera767dbf2006-03-12 09:01:41 +0000220 if (!NotReady.empty()) {
221 AvailableQueue->push_all(NotReady);
222 NotReady.clear();
223 }
Chris Lattnere50c0922006-03-05 22:45:01 +0000224
225 // If we found a node to schedule, do it now.
Chris Lattnera767dbf2006-03-12 09:01:41 +0000226 if (FoundSUnit) {
227 ScheduleNodeTopDown(FoundSUnit, CurCycle);
Dan Gohman7e105f02009-01-15 22:18:12 +0000228 HazardRec->EmitInstruction(FoundSUnit);
Chris Lattner572003c2006-03-12 00:38:57 +0000229
230 // If this is a pseudo-op node, we don't want to increment the current
231 // cycle.
Chris Lattnera767dbf2006-03-12 09:01:41 +0000232 if (FoundSUnit->Latency) // Don't increment CurCycle for pseudo-ops!
233 ++CurCycle;
Chris Lattnere50c0922006-03-05 22:45:01 +0000234 } else if (!HasNoopHazards) {
235 // Otherwise, we have a pipeline stall, but no other problem, just advance
236 // the current cycle and try again.
Chris Lattner4dc3edd2009-08-23 06:35:02 +0000237 DEBUG(errs() << "*** Advancing cycle, no work to do\n");
Chris Lattner543832d2006-03-08 04:25:59 +0000238 HazardRec->AdvanceCycle();
Chris Lattnerfa5e1c92006-03-05 23:13:56 +0000239 ++NumStalls;
Chris Lattnera767dbf2006-03-12 09:01:41 +0000240 ++CurCycle;
Chris Lattnere50c0922006-03-05 22:45:01 +0000241 } else {
242 // Otherwise, we have no instructions to issue and we have instructions
243 // that will fault if we don't do this right. This is the case for
244 // processors without pipeline interlocks and other cases.
Chris Lattner4dc3edd2009-08-23 06:35:02 +0000245 DEBUG(errs() << "*** Emitting noop\n");
Chris Lattner543832d2006-03-08 04:25:59 +0000246 HazardRec->EmitNoop();
Dan Gohmanceac7c32009-01-16 01:33:36 +0000247 Sequence.push_back(0); // NULL here means noop
Chris Lattnerfa5e1c92006-03-05 23:13:56 +0000248 ++NumNoops;
Chris Lattnera767dbf2006-03-12 09:01:41 +0000249 ++CurCycle;
Chris Lattnere50c0922006-03-05 22:45:01 +0000250 }
Chris Lattner98ecb8e2006-03-05 21:10:33 +0000251 }
252
253#ifndef NDEBUG
Dan Gohman4ce15e12008-11-20 01:26:25 +0000254 VerifySchedule(/*isBottomUp=*/false);
Chris Lattner98ecb8e2006-03-05 21:10:33 +0000255#endif
256}
257
Chris Lattner9df64752006-03-09 06:35:14 +0000258//===----------------------------------------------------------------------===//
Chris Lattner9df64752006-03-09 06:35:14 +0000259// Public Constructor Functions
260//===----------------------------------------------------------------------===//
261
Jim Laskey95eda5b2006-08-01 14:21:23 +0000262/// createTDListDAGScheduler - This creates a top-down list scheduler with a
263/// new hazard recognizer. This scheduler takes ownership of the hazard
264/// recognizer and deletes it when done.
Dan Gohmandfaf6462009-02-11 04:27:20 +0000265ScheduleDAGSDNodes *
Bill Wendling026e5d72009-04-29 23:29:43 +0000266llvm::createTDListDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level) {
Dan Gohman619ef482009-01-15 19:20:50 +0000267 return new ScheduleDAGList(*IS->MF,
Chris Lattner6398c132006-03-09 07:38:27 +0000268 new LatencyPriorityQueue(),
Jim Laskey03593f72006-08-01 18:29:48 +0000269 IS->CreateTargetHazardRecognizer());
Evan Cheng31272342006-01-23 08:26:10 +0000270}