6ad5d9814e469bdebf2f38d5ad335dfd5a247402
[oota-llvm.git] / lib / CodeGen / SelectionDAG / ScheduleDAGList.cpp
1 //===---- ScheduleDAGList.cpp - Implement a list scheduler for isel DAG ---===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Evan Cheng and is distributed under the
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This implements bottom-up and top-down list schedulers, using standard
11 // algorithms.  The basic approach uses a priority queue of available nodes to
12 // schedule.  One at a time, nodes are taken from the priority queue (thus in
13 // priority order), checked for legality to schedule, and emitted if legal.
14 //
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.
18 //
19 //===----------------------------------------------------------------------===//
20
21 #define DEBUG_TYPE "sched"
22 #include "llvm/CodeGen/ScheduleDAG.h"
23 #include "llvm/Target/TargetMachine.h"
24 #include "llvm/Target/TargetInstrInfo.h"
25 #include "llvm/Support/Debug.h"
26 #include "llvm/ADT/Statistic.h"
27 #include <climits>
28 #include <iostream>
29 #include <queue>
30 #include <set>
31 #include <vector>
32 #include "llvm/Support/CommandLine.h"
33 using namespace llvm;
34
35 namespace {
36   // FIXME: UseLatencies is temporary.
37   cl::opt<bool> UseLatencies("use-sched-latencies");
38   Statistic<> NumNoops ("scheduler", "Number of noops inserted");
39   Statistic<> NumStalls("scheduler", "Number of pipeline stalls");
40
41   /// SUnit - Scheduling unit. It's an wrapper around either a single SDNode or
42   /// a group of nodes flagged together.
43   struct SUnit {
44     SDNode *Node;                       // Representative node.
45     std::vector<SDNode*> FlaggedNodes;  // All nodes flagged to Node.
46     std::set<SUnit*> Preds;             // All real predecessors.
47     std::set<SUnit*> ChainPreds;        // All chain predecessors.
48     std::set<SUnit*> Succs;             // All real successors.
49     std::set<SUnit*> ChainSuccs;        // All chain successors.
50     short NumPredsLeft;                 // # of preds not scheduled.
51     short NumSuccsLeft;                 // # of succs not scheduled.
52     short NumChainPredsLeft;            // # of chain preds not scheduled.
53     short NumChainSuccsLeft;            // # of chain succs not scheduled.
54     bool isTwoAddress     : 1;          // Is a two-address instruction.
55     bool isDefNUseOperand : 1;          // Is a def&use operand.
56     unsigned short Latency;             // Node latency.
57     unsigned CycleBound;                // Upper/lower cycle to be scheduled at.
58     unsigned NodeNum;                   // Entry # of node in the node vector.
59     
60     SUnit(SDNode *node, unsigned nodenum)
61       : Node(node), NumPredsLeft(0), NumSuccsLeft(0),
62       NumChainPredsLeft(0), NumChainSuccsLeft(0),
63       isTwoAddress(false), isDefNUseOperand(false),
64       Latency(0), CycleBound(0), NodeNum(nodenum) {}
65     
66     void dump(const SelectionDAG *G) const;
67     void dumpAll(const SelectionDAG *G) const;
68   };
69 }
70
71 void SUnit::dump(const SelectionDAG *G) const {
72   std::cerr << "SU: ";
73   Node->dump(G);
74   std::cerr << "\n";
75   if (FlaggedNodes.size() != 0) {
76     for (unsigned i = 0, e = FlaggedNodes.size(); i != e; i++) {
77       std::cerr << "    ";
78       FlaggedNodes[i]->dump(G);
79       std::cerr << "\n";
80     }
81   }
82 }
83
84 void SUnit::dumpAll(const SelectionDAG *G) const {
85   dump(G);
86
87   std::cerr << "  # preds left       : " << NumPredsLeft << "\n";
88   std::cerr << "  # succs left       : " << NumSuccsLeft << "\n";
89   std::cerr << "  # chain preds left : " << NumChainPredsLeft << "\n";
90   std::cerr << "  # chain succs left : " << NumChainSuccsLeft << "\n";
91   std::cerr << "  Latency            : " << Latency << "\n";
92
93   if (Preds.size() != 0) {
94     std::cerr << "  Predecessors:\n";
95     for (std::set<SUnit*>::const_iterator I = Preds.begin(),
96            E = Preds.end(); I != E; ++I) {
97       std::cerr << "    ";
98       (*I)->dump(G);
99     }
100   }
101   if (ChainPreds.size() != 0) {
102     std::cerr << "  Chained Preds:\n";
103     for (std::set<SUnit*>::const_iterator I = ChainPreds.begin(),
104            E = ChainPreds.end(); I != E; ++I) {
105       std::cerr << "    ";
106       (*I)->dump(G);
107     }
108   }
109   if (Succs.size() != 0) {
110     std::cerr << "  Successors:\n";
111     for (std::set<SUnit*>::const_iterator I = Succs.begin(),
112            E = Succs.end(); I != E; ++I) {
113       std::cerr << "    ";
114       (*I)->dump(G);
115     }
116   }
117   if (ChainSuccs.size() != 0) {
118     std::cerr << "  Chained succs:\n";
119     for (std::set<SUnit*>::const_iterator I = ChainSuccs.begin(),
120            E = ChainSuccs.end(); I != E; ++I) {
121       std::cerr << "    ";
122       (*I)->dump(G);
123     }
124   }
125   std::cerr << "\n";
126 }
127
128 //===----------------------------------------------------------------------===//
129 /// SchedulingPriorityQueue - This interface is used to plug different
130 /// priorities computation algorithms into the list scheduler. It implements the
131 /// interface of a standard priority queue, where nodes are inserted in 
132 /// arbitrary order and returned in priority order.  The computation of the
133 /// priority and the representation of the queue are totally up to the
134 /// implementation to decide.
135 /// 
136 namespace {
137 class SchedulingPriorityQueue {
138 public:
139   virtual ~SchedulingPriorityQueue() {}
140   
141   virtual void initNodes(const std::vector<SUnit> &SUnits) = 0;
142   virtual void releaseState() = 0;
143   
144   virtual bool empty() const = 0;
145   virtual void push(SUnit *U) = 0;
146   virtual SUnit *pop() = 0;
147 };
148 }
149
150
151
152 namespace {
153 //===----------------------------------------------------------------------===//
154 /// ScheduleDAGList - The actual list scheduler implementation.  This supports
155 /// both top-down and bottom-up scheduling.
156 ///
157 class ScheduleDAGList : public ScheduleDAG {
158 private:
159   // SDNode to SUnit mapping (many to one).
160   std::map<SDNode*, SUnit*> SUnitMap;
161   // The schedule.  Null SUnit*'s represent noop instructions.
162   std::vector<SUnit*> Sequence;
163   // Current scheduling cycle.
164   unsigned CurrCycle;
165   
166   // The scheduling units.
167   std::vector<SUnit> SUnits;
168
169   /// isBottomUp - This is true if the scheduling problem is bottom-up, false if
170   /// it is top-down.
171   bool isBottomUp;
172   
173   /// PriorityQueue - The priority queue to use.
174   SchedulingPriorityQueue *PriorityQueue;
175   
176   /// HazardRec - The hazard recognizer to use.
177   HazardRecognizer *HazardRec;
178   
179 public:
180   ScheduleDAGList(SelectionDAG &dag, MachineBasicBlock *bb,
181                   const TargetMachine &tm, bool isbottomup,
182                   SchedulingPriorityQueue *priorityqueue,
183                   HazardRecognizer *HR)
184     : ScheduleDAG(listSchedulingBURR, dag, bb, tm),
185       CurrCycle(0), isBottomUp(isbottomup), 
186       PriorityQueue(priorityqueue), HazardRec(HR) {
187     }
188
189   ~ScheduleDAGList() {
190     delete HazardRec;
191     delete PriorityQueue;
192   }
193
194   void Schedule();
195
196   void dumpSchedule() const;
197
198 private:
199   SUnit *NewSUnit(SDNode *N);
200   void ReleasePred(SUnit *PredSU, bool isChain = false);
201   void ReleaseSucc(SUnit *SuccSU, bool isChain = false);
202   void ScheduleNodeBottomUp(SUnit *SU);
203   void ScheduleNodeTopDown(SUnit *SU);
204   void ListScheduleTopDown();
205   void ListScheduleBottomUp();
206   void BuildSchedUnits();
207   void EmitSchedule();
208 };
209 }  // end anonymous namespace
210
211 HazardRecognizer::~HazardRecognizer() {}
212
213
214 /// NewSUnit - Creates a new SUnit and return a ptr to it.
215 SUnit *ScheduleDAGList::NewSUnit(SDNode *N) {
216   SUnits.push_back(SUnit(N, SUnits.size()));
217   return &SUnits.back();
218 }
219
220 /// ReleasePred - Decrement the NumSuccsLeft count of a predecessor. Add it to
221 /// the Available queue is the count reaches zero. Also update its cycle bound.
222 void ScheduleDAGList::ReleasePred(SUnit *PredSU, bool isChain) {
223   // FIXME: the distance between two nodes is not always == the predecessor's
224   // latency. For example, the reader can very well read the register written
225   // by the predecessor later than the issue cycle. It also depends on the
226   // interrupt model (drain vs. freeze).
227   PredSU->CycleBound = std::max(PredSU->CycleBound,CurrCycle + PredSU->Latency);
228
229   if (!isChain)
230     PredSU->NumSuccsLeft--;
231   else
232     PredSU->NumChainSuccsLeft--;
233   
234 #ifndef NDEBUG
235   if (PredSU->NumSuccsLeft < 0 || PredSU->NumChainSuccsLeft < 0) {
236     std::cerr << "*** List scheduling failed! ***\n";
237     PredSU->dump(&DAG);
238     std::cerr << " has been released too many times!\n";
239     assert(0);
240   }
241 #endif
242   
243   if ((PredSU->NumSuccsLeft + PredSU->NumChainSuccsLeft) == 0) {
244     // EntryToken has to go last!  Special case it here.
245     if (PredSU->Node->getOpcode() != ISD::EntryToken)
246       PriorityQueue->push(PredSU);
247   }
248 }
249
250 /// ReleaseSucc - Decrement the NumPredsLeft count of a successor. Add it to
251 /// the Available queue is the count reaches zero. Also update its cycle bound.
252 void ScheduleDAGList::ReleaseSucc(SUnit *SuccSU, bool isChain) {
253   // FIXME: the distance between two nodes is not always == the predecessor's
254   // latency. For example, the reader can very well read the register written
255   // by the predecessor later than the issue cycle. It also depends on the
256   // interrupt model (drain vs. freeze).
257   SuccSU->CycleBound = std::max(SuccSU->CycleBound,CurrCycle + SuccSU->Latency);
258   
259   if (!isChain)
260     SuccSU->NumPredsLeft--;
261   else
262     SuccSU->NumChainPredsLeft--;
263   
264 #ifndef NDEBUG
265   if (SuccSU->NumPredsLeft < 0 || SuccSU->NumChainPredsLeft < 0) {
266     std::cerr << "*** List scheduling failed! ***\n";
267     SuccSU->dump(&DAG);
268     std::cerr << " has been released too many times!\n";
269     abort();
270   }
271 #endif
272   
273   if ((SuccSU->NumPredsLeft + SuccSU->NumChainPredsLeft) == 0)
274     PriorityQueue->push(SuccSU);
275 }
276
277 /// ScheduleNodeBottomUp - Add the node to the schedule. Decrement the pending
278 /// count of its predecessors. If a predecessor pending count is zero, add it to
279 /// the Available queue.
280 void ScheduleDAGList::ScheduleNodeBottomUp(SUnit *SU) {
281   DEBUG(std::cerr << "*** Scheduling: ");
282   DEBUG(SU->dump(&DAG));
283
284   Sequence.push_back(SU);
285
286   // Bottom up: release predecessors
287   for (std::set<SUnit*>::iterator I1 = SU->Preds.begin(),
288          E1 = SU->Preds.end(); I1 != E1; ++I1) {
289     ReleasePred(*I1);
290     SU->NumPredsLeft--;
291   }
292   for (std::set<SUnit*>::iterator I2 = SU->ChainPreds.begin(),
293          E2 = SU->ChainPreds.end(); I2 != E2; ++I2)
294     ReleasePred(*I2, true);
295
296   CurrCycle++;
297 }
298
299 /// ScheduleNodeTopDown - Add the node to the schedule. Decrement the pending
300 /// count of its successors. If a successor pending count is zero, add it to
301 /// the Available queue.
302 void ScheduleDAGList::ScheduleNodeTopDown(SUnit *SU) {
303   DEBUG(std::cerr << "*** Scheduling: ");
304   DEBUG(SU->dump(&DAG));
305   
306   Sequence.push_back(SU);
307   
308   // Bottom up: release successors.
309   for (std::set<SUnit*>::iterator I1 = SU->Succs.begin(),
310        E1 = SU->Succs.end(); I1 != E1; ++I1) {
311     ReleaseSucc(*I1);
312     SU->NumSuccsLeft--;
313   }
314   for (std::set<SUnit*>::iterator I2 = SU->ChainSuccs.begin(),
315        E2 = SU->ChainSuccs.end(); I2 != E2; ++I2)
316     ReleaseSucc(*I2, true);
317   
318   CurrCycle++;
319 }
320
321 /// isReady - True if node's lower cycle bound is less or equal to the current
322 /// scheduling cycle. Always true if all nodes have uniform latency 1.
323 static inline bool isReady(SUnit *SU, unsigned CurrCycle) {
324   return SU->CycleBound <= CurrCycle;
325 }
326
327 /// ListScheduleBottomUp - The main loop of list scheduling for bottom-up
328 /// schedulers.
329 void ScheduleDAGList::ListScheduleBottomUp() {
330   // Add root to Available queue.
331   PriorityQueue->push(SUnitMap[DAG.getRoot().Val]);
332
333   // While Available queue is not empty, grab the node with the highest
334   // priority. If it is not ready put it back. Schedule the node.
335   std::vector<SUnit*> NotReady;
336   while (!PriorityQueue->empty()) {
337     SUnit *CurrNode = PriorityQueue->pop();
338
339     while (!isReady(CurrNode, CurrCycle)) {
340       NotReady.push_back(CurrNode);
341       CurrNode = PriorityQueue->pop();
342     }
343     
344     // Add the nodes that aren't ready back onto the available list.
345     while (!NotReady.empty()) {
346       PriorityQueue->push(NotReady.back());
347       NotReady.pop_back();
348     }
349
350     ScheduleNodeBottomUp(CurrNode);
351   }
352
353   // Add entry node last
354   if (DAG.getEntryNode().Val != DAG.getRoot().Val) {
355     SUnit *Entry = SUnitMap[DAG.getEntryNode().Val];
356     Sequence.push_back(Entry);
357   }
358
359   // Reverse the order if it is bottom up.
360   std::reverse(Sequence.begin(), Sequence.end());
361   
362   
363 #ifndef NDEBUG
364   // Verify that all SUnits were scheduled.
365   bool AnyNotSched = false;
366   for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
367     if (SUnits[i].NumSuccsLeft != 0 || SUnits[i].NumChainSuccsLeft != 0) {
368       if (!AnyNotSched)
369         std::cerr << "*** List scheduling failed! ***\n";
370       SUnits[i].dump(&DAG);
371       std::cerr << "has not been scheduled!\n";
372       AnyNotSched = true;
373     }
374   }
375   assert(!AnyNotSched);
376 #endif
377 }
378
379 /// ListScheduleTopDown - The main loop of list scheduling for top-down
380 /// schedulers.
381 void ScheduleDAGList::ListScheduleTopDown() {
382   // Emit the entry node first.
383   SUnit *Entry = SUnitMap[DAG.getEntryNode().Val];
384   ScheduleNodeTopDown(Entry);
385   HazardRec->EmitInstruction(Entry->Node);
386                       
387   // All leaves to Available queue.
388   for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
389     // It is available if it has no predecessors.
390     if ((SUnits[i].Preds.size() + SUnits[i].ChainPreds.size()) == 0 &&
391         &SUnits[i] != Entry)
392       PriorityQueue->push(&SUnits[i]);
393   }
394   
395   // While Available queue is not empty, grab the node with the highest
396   // priority. If it is not ready put it back.  Schedule the node.
397   std::vector<SUnit*> NotReady;
398   while (!PriorityQueue->empty()) {
399     SUnit *FoundNode = 0;
400
401     bool HasNoopHazards = false;
402     do {
403       SUnit *CurNode = PriorityQueue->pop();
404       
405       // Get the node represented by this SUnit.
406       SDNode *N = CurNode->Node;
407       // If this is a pseudo op, like copyfromreg, look to see if there is a
408       // real target node flagged to it.  If so, use the target node.
409       for (unsigned i = 0, e = CurNode->FlaggedNodes.size(); 
410            N->getOpcode() < ISD::BUILTIN_OP_END && i != e; ++i)
411         N = CurNode->FlaggedNodes[i];
412       
413       HazardRecognizer::HazardType HT = HazardRec->getHazardType(N);
414       if (HT == HazardRecognizer::NoHazard) {
415         FoundNode = CurNode;
416         break;
417       }
418       
419       // Remember if this is a noop hazard.
420       HasNoopHazards |= HT == HazardRecognizer::NoopHazard;
421       
422       NotReady.push_back(CurNode);
423     } while (!PriorityQueue->empty());
424     
425     // Add the nodes that aren't ready back onto the available list.
426     while (!NotReady.empty()) {
427       PriorityQueue->push(NotReady.back());
428       NotReady.pop_back();
429     }
430
431     // If we found a node to schedule, do it now.
432     if (FoundNode) {
433       ScheduleNodeTopDown(FoundNode);
434       HazardRec->EmitInstruction(FoundNode->Node);
435     } else if (!HasNoopHazards) {
436       // Otherwise, we have a pipeline stall, but no other problem, just advance
437       // the current cycle and try again.
438       DEBUG(std::cerr << "*** Advancing cycle, no work to do\n");
439       HazardRec->AdvanceCycle();
440       ++NumStalls;
441     } else {
442       // Otherwise, we have no instructions to issue and we have instructions
443       // that will fault if we don't do this right.  This is the case for
444       // processors without pipeline interlocks and other cases.
445       DEBUG(std::cerr << "*** Emitting noop\n");
446       HazardRec->EmitNoop();
447       Sequence.push_back(0);   // NULL SUnit* -> noop
448       ++NumNoops;
449     }
450   }
451
452 #ifndef NDEBUG
453   // Verify that all SUnits were scheduled.
454   bool AnyNotSched = false;
455   for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
456     if (SUnits[i].NumPredsLeft != 0 || SUnits[i].NumChainPredsLeft != 0) {
457       if (!AnyNotSched)
458         std::cerr << "*** List scheduling failed! ***\n";
459       SUnits[i].dump(&DAG);
460       std::cerr << "has not been scheduled!\n";
461       AnyNotSched = true;
462     }
463   }
464   assert(!AnyNotSched);
465 #endif
466 }
467
468
469 void ScheduleDAGList::BuildSchedUnits() {
470   // Reserve entries in the vector for each of the SUnits we are creating.  This
471   // ensure that reallocation of the vector won't happen, so SUnit*'s won't get
472   // invalidated.
473   SUnits.reserve(NodeCount);
474   
475   const InstrItineraryData &InstrItins = TM.getInstrItineraryData();
476
477   // Pass 1: create the SUnit's.
478   for (unsigned i = 0, NC = NodeCount; i < NC; i++) {
479     NodeInfo *NI = &Info[i];
480     SDNode *N = NI->Node;
481     if (isPassiveNode(N))
482       continue;
483
484     SUnit *SU;
485     if (NI->isInGroup()) {
486       if (NI != NI->Group->getBottom())  // Bottom up, so only look at bottom
487         continue;                        // node of the NodeGroup
488
489       SU = NewSUnit(N);
490       // Find the flagged nodes.
491       SDOperand  FlagOp = N->getOperand(N->getNumOperands() - 1);
492       SDNode    *Flag   = FlagOp.Val;
493       unsigned   ResNo  = FlagOp.ResNo;
494       while (Flag->getValueType(ResNo) == MVT::Flag) {
495         NodeInfo *FNI = getNI(Flag);
496         assert(FNI->Group == NI->Group);
497         SU->FlaggedNodes.insert(SU->FlaggedNodes.begin(), Flag);
498         SUnitMap[Flag] = SU;
499
500         FlagOp = Flag->getOperand(Flag->getNumOperands() - 1);
501         Flag   = FlagOp.Val;
502         ResNo  = FlagOp.ResNo;
503       }
504     } else {
505       SU = NewSUnit(N);
506     }
507     SUnitMap[N] = SU;
508
509     // Compute the latency for the node.  We use the sum of the latencies for
510     // all nodes flagged together into this SUnit.
511     if (InstrItins.isEmpty() || !UseLatencies) {
512       // No latency information.
513       SU->Latency = 1;
514     } else {
515       SU->Latency = 0;
516       if (N->isTargetOpcode()) {
517         unsigned SchedClass = TII->getSchedClass(N->getTargetOpcode());
518         InstrStage *S = InstrItins.begin(SchedClass);
519         InstrStage *E = InstrItins.end(SchedClass);
520         for (; S != E; ++S)
521           SU->Latency += S->Cycles;
522       }
523       for (unsigned i = 0, e = SU->FlaggedNodes.size(); i != e; ++i) {
524         SDNode *FNode = SU->FlaggedNodes[i];
525         if (FNode->isTargetOpcode()) {
526           unsigned SchedClass = TII->getSchedClass(FNode->getTargetOpcode());
527           InstrStage *S = InstrItins.begin(SchedClass);
528           InstrStage *E = InstrItins.end(SchedClass);
529           for (; S != E; ++S)
530             SU->Latency += S->Cycles;
531         }
532       }
533     }
534   }
535
536   // Pass 2: add the preds, succs, etc.
537   for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
538     SUnit *SU = &SUnits[i];
539     SDNode   *N  = SU->Node;
540     NodeInfo *NI = getNI(N);
541     
542     if (N->isTargetOpcode() && TII->isTwoAddrInstr(N->getTargetOpcode()))
543       SU->isTwoAddress = true;
544
545     if (NI->isInGroup()) {
546       // Find all predecessors (of the group).
547       NodeGroupOpIterator NGOI(NI);
548       while (!NGOI.isEnd()) {
549         SDOperand Op  = NGOI.next();
550         SDNode   *OpN = Op.Val;
551         MVT::ValueType VT = OpN->getValueType(Op.ResNo);
552         NodeInfo *OpNI = getNI(OpN);
553         if (OpNI->Group != NI->Group && !isPassiveNode(OpN)) {
554           assert(VT != MVT::Flag);
555           SUnit *OpSU = SUnitMap[OpN];
556           if (VT == MVT::Other) {
557             if (SU->ChainPreds.insert(OpSU).second)
558               SU->NumChainPredsLeft++;
559             if (OpSU->ChainSuccs.insert(SU).second)
560               OpSU->NumChainSuccsLeft++;
561           } else {
562             if (SU->Preds.insert(OpSU).second)
563               SU->NumPredsLeft++;
564             if (OpSU->Succs.insert(SU).second)
565               OpSU->NumSuccsLeft++;
566           }
567         }
568       }
569     } else {
570       // Find node predecessors.
571       for (unsigned j = 0, e = N->getNumOperands(); j != e; j++) {
572         SDOperand Op  = N->getOperand(j);
573         SDNode   *OpN = Op.Val;
574         MVT::ValueType VT = OpN->getValueType(Op.ResNo);
575         if (!isPassiveNode(OpN)) {
576           assert(VT != MVT::Flag);
577           SUnit *OpSU = SUnitMap[OpN];
578           if (VT == MVT::Other) {
579             if (SU->ChainPreds.insert(OpSU).second)
580               SU->NumChainPredsLeft++;
581             if (OpSU->ChainSuccs.insert(SU).second)
582               OpSU->NumChainSuccsLeft++;
583           } else {
584             if (SU->Preds.insert(OpSU).second)
585               SU->NumPredsLeft++;
586             if (OpSU->Succs.insert(SU).second)
587               OpSU->NumSuccsLeft++;
588             if (j == 0 && SU->isTwoAddress) 
589               OpSU->isDefNUseOperand = true;
590           }
591         }
592       }
593     }
594     
595     DEBUG(SU->dumpAll(&DAG));
596   }
597 }
598
599 /// EmitSchedule - Emit the machine code in scheduled order.
600 void ScheduleDAGList::EmitSchedule() {
601   for (unsigned i = 0, e = Sequence.size(); i != e; i++) {
602     if (SUnit *SU = Sequence[i]) {
603       for (unsigned j = 0, ee = SU->FlaggedNodes.size(); j != ee; j++) {
604         SDNode *N = SU->FlaggedNodes[j];
605         EmitNode(getNI(N));
606       }
607       EmitNode(getNI(SU->Node));
608     } else {
609       // Null SUnit* is a noop.
610       EmitNoop();
611     }
612   }
613 }
614
615 /// dump - dump the schedule.
616 void ScheduleDAGList::dumpSchedule() const {
617   for (unsigned i = 0, e = Sequence.size(); i != e; i++) {
618     if (SUnit *SU = Sequence[i])
619       SU->dump(&DAG);
620     else
621       std::cerr << "**** NOOP ****\n";
622   }
623 }
624
625 /// Schedule - Schedule the DAG using list scheduling.
626 /// FIXME: Right now it only supports the burr (bottom up register reducing)
627 /// heuristic.
628 void ScheduleDAGList::Schedule() {
629   DEBUG(std::cerr << "********** List Scheduling **********\n");
630
631   // Build scheduling units.
632   BuildSchedUnits();
633   
634   PriorityQueue->initNodes(SUnits);
635   
636   // Execute the actual scheduling loop Top-Down or Bottom-Up as appropriate.
637   if (isBottomUp)
638     ListScheduleBottomUp();
639   else
640     ListScheduleTopDown();
641
642   PriorityQueue->releaseState();
643
644   DEBUG(std::cerr << "*** Final schedule ***\n");
645   DEBUG(dumpSchedule());
646   DEBUG(std::cerr << "\n");
647   
648   // Emit in scheduled order
649   EmitSchedule();
650 }
651
652 //===----------------------------------------------------------------------===//
653 //                RegReductionPriorityQueue Implementation
654 //===----------------------------------------------------------------------===//
655 //
656 // This is a SchedulingPriorityQueue that schedules using Sethi Ullman numbers
657 // to reduce register pressure.
658 // 
659 namespace {
660   class RegReductionPriorityQueue;
661   
662   /// Sorting functions for the Available queue.
663   struct ls_rr_sort : public std::binary_function<SUnit*, SUnit*, bool> {
664     RegReductionPriorityQueue *SPQ;
665     ls_rr_sort(RegReductionPriorityQueue *spq) : SPQ(spq) {}
666     ls_rr_sort(const ls_rr_sort &RHS) : SPQ(RHS.SPQ) {}
667     
668     bool operator()(const SUnit* left, const SUnit* right) const;
669   };
670 }  // end anonymous namespace
671
672 namespace {
673   class RegReductionPriorityQueue : public SchedulingPriorityQueue {
674     // SUnits - The SUnits for the current graph.
675     const std::vector<SUnit> *SUnits;
676     
677     // SethiUllmanNumbers - The SethiUllman number for each node.
678     std::vector<int> SethiUllmanNumbers;
679     
680     std::priority_queue<SUnit*, std::vector<SUnit*>, ls_rr_sort> Queue;
681   public:
682     RegReductionPriorityQueue() : Queue(ls_rr_sort(this)) {
683     }
684     
685     void initNodes(const std::vector<SUnit> &sunits) {
686       SUnits = &sunits;
687       // Calculate node priorities.
688       CalculatePriorities();
689     }
690     void releaseState() {
691       SUnits = 0;
692       SethiUllmanNumbers.clear();
693     }
694     
695     unsigned getSethiUllmanNumber(unsigned NodeNum) const {
696       assert(NodeNum < SethiUllmanNumbers.size());
697       return SethiUllmanNumbers[NodeNum];
698     }
699     
700     bool empty() const { return Queue.empty(); }
701     
702     void push(SUnit *U) {
703       Queue.push(U);
704     }
705     SUnit *pop() {
706       SUnit *V = Queue.top();
707       Queue.pop();
708       return V;
709     }
710   private:
711     void CalculatePriorities();
712     int CalcNodePriority(const SUnit *SU);
713   };
714 }
715
716 bool ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const {
717   unsigned LeftNum  = left->NodeNum;
718   unsigned RightNum = right->NodeNum;
719   
720   int LBonus = (int)left ->isDefNUseOperand;
721   int RBonus = (int)right->isDefNUseOperand;
722   
723   // Special tie breaker: if two nodes share a operand, the one that
724   // use it as a def&use operand is preferred.
725   if (left->isTwoAddress && !right->isTwoAddress) {
726     SDNode *DUNode = left->Node->getOperand(0).Val;
727     if (DUNode->isOperand(right->Node))
728       LBonus++;
729   }
730   if (!left->isTwoAddress && right->isTwoAddress) {
731     SDNode *DUNode = right->Node->getOperand(0).Val;
732     if (DUNode->isOperand(left->Node))
733       RBonus++;
734   }
735   
736   // Priority1 is just the number of live range genned.
737   int LPriority1 = left ->NumPredsLeft - LBonus;
738   int RPriority1 = right->NumPredsLeft - RBonus;
739   int LPriority2 = SPQ->getSethiUllmanNumber(LeftNum) + LBonus;
740   int RPriority2 = SPQ->getSethiUllmanNumber(RightNum) + RBonus;
741   
742   if (LPriority1 > RPriority1)
743     return true;
744   else if (LPriority1 == RPriority1)
745     if (LPriority2 < RPriority2)
746       return true;
747     else if (LPriority2 == RPriority2)
748       if (left->CycleBound > right->CycleBound) 
749         return true;
750   
751   return false;
752 }
753
754
755 /// CalcNodePriority - Priority is the Sethi Ullman number. 
756 /// Smaller number is the higher priority.
757 int RegReductionPriorityQueue::CalcNodePriority(const SUnit *SU) {
758   int &SethiUllmanNumber = SethiUllmanNumbers[SU->NodeNum];
759   if (SethiUllmanNumber != INT_MIN)
760     return SethiUllmanNumber;
761   
762   if (SU->Preds.size() == 0) {
763     SethiUllmanNumber = 1;
764   } else {
765     int Extra = 0;
766     for (std::set<SUnit*>::iterator I = SU->Preds.begin(),
767          E = SU->Preds.end(); I != E; ++I) {
768       SUnit *PredSU = *I;
769       int PredSethiUllman = CalcNodePriority(PredSU);
770       if (PredSethiUllman > SethiUllmanNumber) {
771         SethiUllmanNumber = PredSethiUllman;
772         Extra = 0;
773       } else if (PredSethiUllman == SethiUllmanNumber)
774         Extra++;
775     }
776     
777     if (SU->Node->getOpcode() != ISD::TokenFactor)
778       SethiUllmanNumber += Extra;
779     else
780       SethiUllmanNumber = (Extra == 1) ? 0 : Extra-1;
781   }
782   
783   return SethiUllmanNumber;
784 }
785
786 /// CalculatePriorities - Calculate priorities of all scheduling units.
787 void RegReductionPriorityQueue::CalculatePriorities() {
788   SethiUllmanNumbers.assign(SUnits->size(), INT_MIN);
789   
790   for (unsigned i = 0, e = SUnits->size(); i != e; ++i)
791     CalcNodePriority(&(*SUnits)[i]);
792 }
793
794 //===----------------------------------------------------------------------===//
795 //                    LatencyPriorityQueue Implementation
796 //===----------------------------------------------------------------------===//
797 //
798 // This is a SchedulingPriorityQueue that schedules using latency information to
799 // reduce the length of the critical path through the basic block.
800 // 
801 namespace {
802   class LatencyPriorityQueue;
803   
804   /// Sorting functions for the Available queue.
805   struct latency_sort : public std::binary_function<SUnit*, SUnit*, bool> {
806     LatencyPriorityQueue *PQ;
807     latency_sort(LatencyPriorityQueue *pq) : PQ(pq) {}
808     latency_sort(const latency_sort &RHS) : PQ(RHS.PQ) {}
809     
810     bool operator()(const SUnit* left, const SUnit* right) const;
811   };
812 }  // end anonymous namespace
813
814 namespace {
815   class LatencyPriorityQueue : public SchedulingPriorityQueue {
816     // SUnits - The SUnits for the current graph.
817     const std::vector<SUnit> *SUnits;
818     
819     // Latencies - The latency (max of latency from this node to the bb exit)
820     // for each node.
821     std::vector<int> Latencies;
822     
823     std::priority_queue<SUnit*, std::vector<SUnit*>, latency_sort> Queue;
824 public:
825     LatencyPriorityQueue() : Queue(latency_sort(this)) {
826     }
827     
828     void initNodes(const std::vector<SUnit> &sunits) {
829       SUnits = &sunits;
830       // Calculate node priorities.
831       CalculatePriorities();
832     }
833     void releaseState() {
834       SUnits = 0;
835       Latencies.clear();
836     }
837     
838     unsigned getLatency(unsigned NodeNum) const {
839       assert(NodeNum < Latencies.size());
840       return Latencies[NodeNum];
841     }
842     
843     bool empty() const { return Queue.empty(); }
844     
845     void push(SUnit *U) {
846       Queue.push(U);
847     }
848     SUnit *pop() {
849       SUnit *V = Queue.top();
850       Queue.pop();
851       
852       std::cerr << "Got node.  Latency: " << getLatency(V->NodeNum)
853                 << "  \n";
854       return V;
855     }
856 private:
857     void CalculatePriorities();
858     int CalcLatency(const SUnit &SU);
859   };
860 }
861
862 bool latency_sort::operator()(const SUnit *LHS, const SUnit *RHS) const {
863   unsigned LHSNum = LHS->NodeNum;
864   unsigned RHSNum = RHS->NodeNum;
865   
866   return PQ->getLatency(LHSNum) < PQ->getLatency(RHSNum);
867 }
868
869
870 /// CalcNodePriority - Calculate the maximal path from the node to the exit.
871 ///
872 int LatencyPriorityQueue::CalcLatency(const SUnit &SU) {
873   int &Latency = Latencies[SU.NodeNum];
874   if (Latency != -1)
875     return Latency;
876   
877   int MaxSuccLatency = 0;
878   for (std::set<SUnit*>::iterator I = SU.Succs.begin(),
879        E = SU.Succs.end(); I != E; ++I)
880     MaxSuccLatency = std::max(MaxSuccLatency, CalcLatency(**I));
881
882   for (std::set<SUnit*>::iterator I = SU.ChainSuccs.begin(),
883        E = SU.ChainSuccs.end(); I != E; ++I)
884     MaxSuccLatency = std::max(MaxSuccLatency, CalcLatency(**I));
885
886   return Latency = MaxSuccLatency + SU.Latency;
887 }
888
889 /// CalculatePriorities - Calculate priorities of all scheduling units.
890 void LatencyPriorityQueue::CalculatePriorities() {
891   Latencies.assign(SUnits->size(), -1);
892   
893   for (unsigned i = 0, e = SUnits->size(); i != e; ++i)
894     CalcLatency((*SUnits)[i]);
895 }
896
897
898 //===----------------------------------------------------------------------===//
899 //                         Public Constructor Functions
900 //===----------------------------------------------------------------------===//
901
902 llvm::ScheduleDAG* llvm::createBURRListDAGScheduler(SelectionDAG &DAG,
903                                                     MachineBasicBlock *BB) {
904   return new ScheduleDAGList(DAG, BB, DAG.getTarget(), true, 
905                              new RegReductionPriorityQueue(),
906                              new HazardRecognizer());
907 }
908
909 /// createTDListDAGScheduler - This creates a top-down list scheduler with the
910 /// specified hazard recognizer.
911 ScheduleDAG* llvm::createTDListDAGScheduler(SelectionDAG &DAG,
912                                             MachineBasicBlock *BB,
913                                             HazardRecognizer *HR) {
914   return new ScheduleDAGList(DAG, BB, DAG.getTarget(), false,
915                              new LatencyPriorityQueue(),
916                              HR);
917 }