Shave another 27K off libllvmgcc.dylib with visibility hidden
[oota-llvm.git] / lib / CodeGen / SelectionDAG / ScheduleDAGSimple.cpp
1 //===-- ScheduleDAGSimple.cpp - Implement a trivial DAG scheduler ---------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by James M. Laskey and is distributed under the
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This implements a simple two pass scheduler.  The first pass attempts to push
11 // backward any lengthy instructions and critical paths.  The second pass packs
12 // instructions into semi-optimal time slots.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #define DEBUG_TYPE "sched"
17 #include "llvm/CodeGen/ScheduleDAG.h"
18 #include "llvm/CodeGen/SelectionDAG.h"
19 #include "llvm/Target/TargetData.h"
20 #include "llvm/Target/TargetMachine.h"
21 #include "llvm/Target/TargetInstrInfo.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/Visibility.h"
24 #include <algorithm>
25 #include <iostream>
26 using namespace llvm;
27
28 namespace {
29 class NodeInfo;
30 typedef NodeInfo *NodeInfoPtr;
31 typedef std::vector<NodeInfoPtr>           NIVector;
32 typedef std::vector<NodeInfoPtr>::iterator NIIterator;
33
34 //===--------------------------------------------------------------------===//
35 ///
36 /// Node group -  This struct is used to manage flagged node groups.
37 ///
38 class NodeGroup {
39 public:
40   NodeGroup     *Next;
41 private:
42   NIVector      Members;                // Group member nodes
43   NodeInfo      *Dominator;             // Node with highest latency
44   unsigned      Latency;                // Total latency of the group
45   int           Pending;                // Number of visits pending before
46                                         // adding to order  
47
48 public:
49   // Ctor.
50   NodeGroup() : Next(NULL), Dominator(NULL), Pending(0) {}
51
52   // Accessors
53   inline void setDominator(NodeInfo *D) { Dominator = D; }
54   inline NodeInfo *getTop() { return Members.front(); }
55   inline NodeInfo *getBottom() { return Members.back(); }
56   inline NodeInfo *getDominator() { return Dominator; }
57   inline void setLatency(unsigned L) { Latency = L; }
58   inline unsigned getLatency() { return Latency; }
59   inline int getPending() const { return Pending; }
60   inline void setPending(int P)  { Pending = P; }
61   inline int addPending(int I)  { return Pending += I; }
62
63   // Pass thru
64   inline bool group_empty() { return Members.empty(); }
65   inline NIIterator group_begin() { return Members.begin(); }
66   inline NIIterator group_end() { return Members.end(); }
67   inline void group_push_back(const NodeInfoPtr &NI) {
68     Members.push_back(NI);
69   }
70   inline NIIterator group_insert(NIIterator Pos, const NodeInfoPtr &NI) {
71     return Members.insert(Pos, NI);
72   }
73   inline void group_insert(NIIterator Pos, NIIterator First,
74                            NIIterator Last) {
75     Members.insert(Pos, First, Last);
76   }
77
78   static void Add(NodeInfo *D, NodeInfo *U);
79 };
80
81 //===--------------------------------------------------------------------===//
82 ///
83 /// NodeInfo - This struct tracks information used to schedule the a node.
84 ///
85 class NodeInfo {
86 private:
87   int           Pending;                // Number of visits pending before
88                                         // adding to order
89 public:
90   SDNode        *Node;                  // DAG node
91   InstrStage    *StageBegin;            // First stage in itinerary
92   InstrStage    *StageEnd;              // Last+1 stage in itinerary
93   unsigned      Latency;                // Total cycles to complete instr
94   bool          IsCall : 1;             // Is function call
95   bool          IsLoad : 1;             // Is memory load
96   bool          IsStore : 1;            // Is memory store
97   unsigned      Slot;                   // Node's time slot
98   NodeGroup     *Group;                 // Grouping information
99 #ifndef NDEBUG
100   unsigned      Preorder;               // Index before scheduling
101 #endif
102
103   // Ctor.
104   NodeInfo(SDNode *N = NULL)
105     : Pending(0)
106     , Node(N)
107     , StageBegin(NULL)
108     , StageEnd(NULL)
109     , Latency(0)
110     , IsCall(false)
111     , Slot(0)
112     , Group(NULL)
113 #ifndef NDEBUG
114     , Preorder(0)
115 #endif
116   {}
117
118   // Accessors
119   inline bool isInGroup() const {
120     assert(!Group || !Group->group_empty() && "Group with no members");
121     return Group != NULL;
122   }
123   inline bool isGroupDominator() const {
124     return isInGroup() && Group->getDominator() == this;
125   }
126   inline int getPending() const {
127     return Group ? Group->getPending() : Pending;
128   }
129   inline void setPending(int P) {
130     if (Group) Group->setPending(P);
131     else       Pending = P;
132   }
133   inline int addPending(int I) {
134     if (Group) return Group->addPending(I);
135     else       return Pending += I;
136   }
137 };
138
139 //===--------------------------------------------------------------------===//
140 ///
141 /// NodeGroupIterator - Iterates over all the nodes indicated by the node
142 /// info. If the node is in a group then iterate over the members of the
143 /// group, otherwise just the node info.
144 ///
145 class NodeGroupIterator {
146 private:
147   NodeInfo   *NI;                       // Node info
148   NIIterator NGI;                       // Node group iterator
149   NIIterator NGE;                       // Node group iterator end
150
151 public:
152   // Ctor.
153   NodeGroupIterator(NodeInfo *N) : NI(N) {
154     // If the node is in a group then set up the group iterator.  Otherwise
155     // the group iterators will trip first time out.
156     if (N->isInGroup()) {
157       // get Group
158       NodeGroup *Group = NI->Group;
159       NGI = Group->group_begin();
160       NGE = Group->group_end();
161       // Prevent this node from being used (will be in members list
162       NI = NULL;
163     }
164   }
165
166   /// next - Return the next node info, otherwise NULL.
167   ///
168   NodeInfo *next() {
169     // If members list
170     if (NGI != NGE) return *NGI++;
171     // Use node as the result (may be NULL)
172     NodeInfo *Result = NI;
173     // Only use once
174     NI = NULL;
175     // Return node or NULL
176     return Result;
177   }
178 };
179 //===--------------------------------------------------------------------===//
180
181
182 //===--------------------------------------------------------------------===//
183 ///
184 /// NodeGroupOpIterator - Iterates over all the operands of a node.  If the
185 /// node is a member of a group, this iterates over all the operands of all
186 /// the members of the group.
187 ///
188 class NodeGroupOpIterator {
189 private:
190   NodeInfo            *NI;              // Node containing operands
191   NodeGroupIterator   GI;               // Node group iterator
192   SDNode::op_iterator OI;               // Operand iterator
193   SDNode::op_iterator OE;               // Operand iterator end
194
195   /// CheckNode - Test if node has more operands.  If not get the next node
196   /// skipping over nodes that have no operands.
197   void CheckNode() {
198     // Only if operands are exhausted first
199     while (OI == OE) {
200       // Get next node info
201       NodeInfo *NI = GI.next();
202       // Exit if nodes are exhausted
203       if (!NI) return;
204       // Get node itself
205       SDNode *Node = NI->Node;
206       // Set up the operand iterators
207       OI = Node->op_begin();
208       OE = Node->op_end();
209     }
210   }
211
212 public:
213   // Ctor.
214   NodeGroupOpIterator(NodeInfo *N)
215     : NI(N), GI(N), OI(SDNode::op_iterator()), OE(SDNode::op_iterator()) {}
216
217   /// isEnd - Returns true when not more operands are available.
218   ///
219   inline bool isEnd() { CheckNode(); return OI == OE; }
220
221   /// next - Returns the next available operand.
222   ///
223   inline SDOperand next() {
224     assert(OI != OE &&
225            "Not checking for end of NodeGroupOpIterator correctly");
226     return *OI++;
227   }
228 };
229
230
231 //===----------------------------------------------------------------------===//
232 ///
233 /// BitsIterator - Provides iteration through individual bits in a bit vector.
234 ///
235 template<class T>
236 class BitsIterator {
237 private:
238   T Bits;                               // Bits left to iterate through
239
240 public:
241   /// Ctor.
242   BitsIterator(T Initial) : Bits(Initial) {}
243   
244   /// Next - Returns the next bit set or zero if exhausted.
245   inline T Next() {
246     // Get the rightmost bit set
247     T Result = Bits & -Bits;
248     // Remove from rest
249     Bits &= ~Result;
250     // Return single bit or zero
251     return Result;
252   }
253 };
254   
255 //===----------------------------------------------------------------------===//
256
257
258 //===----------------------------------------------------------------------===//
259 ///
260 /// ResourceTally - Manages the use of resources over time intervals.  Each
261 /// item (slot) in the tally vector represents the resources used at a given
262 /// moment.  A bit set to 1 indicates that a resource is in use, otherwise
263 /// available.  An assumption is made that the tally is large enough to schedule 
264 /// all current instructions (asserts otherwise.)
265 ///
266 template<class T>
267 class ResourceTally {
268 private:
269   std::vector<T> Tally;                 // Resources used per slot
270   typedef typename std::vector<T>::iterator Iter;
271                                         // Tally iterator 
272   
273   /// SlotsAvailable - Returns true if all units are available.
274         ///
275   bool SlotsAvailable(Iter Begin, unsigned N, unsigned ResourceSet,
276                                               unsigned &Resource) {
277     assert(N && "Must check availability with N != 0");
278     // Determine end of interval
279     Iter End = Begin + N;
280     assert(End <= Tally.end() && "Tally is not large enough for schedule");
281     
282     // Iterate thru each resource
283     BitsIterator<T> Resources(ResourceSet & ~*Begin);
284     while (unsigned Res = Resources.Next()) {
285       // Check if resource is available for next N slots
286       Iter Interval = End;
287       do {
288         Interval--;
289         if (*Interval & Res) break;
290       } while (Interval != Begin);
291       
292       // If available for N
293       if (Interval == Begin) {
294         // Success
295         Resource = Res;
296         return true;
297       }
298     }
299     
300     // No luck
301     Resource = 0;
302     return false;
303   }
304         
305         /// RetrySlot - Finds a good candidate slot to retry search.
306   Iter RetrySlot(Iter Begin, unsigned N, unsigned ResourceSet) {
307     assert(N && "Must check availability with N != 0");
308     // Determine end of interval
309     Iter End = Begin + N;
310     assert(End <= Tally.end() && "Tally is not large enough for schedule");
311                 
312                 while (Begin != End--) {
313                         // Clear units in use
314                         ResourceSet &= ~*End;
315                         // If no units left then we should go no further 
316                         if (!ResourceSet) return End + 1;
317                 }
318                 // Made it all the way through
319                 return Begin;
320         }
321   
322   /// FindAndReserveStages - Return true if the stages can be completed. If
323   /// so mark as busy.
324   bool FindAndReserveStages(Iter Begin,
325                             InstrStage *Stage, InstrStage *StageEnd) {
326     // If at last stage then we're done
327     if (Stage == StageEnd) return true;
328     // Get number of cycles for current stage
329     unsigned N = Stage->Cycles;
330     // Check to see if N slots are available, if not fail
331     unsigned Resource;
332     if (!SlotsAvailable(Begin, N, Stage->Units, Resource)) return false;
333     // Check to see if remaining stages are available, if not fail
334     if (!FindAndReserveStages(Begin + N, Stage + 1, StageEnd)) return false;
335     // Reserve resource
336     Reserve(Begin, N, Resource);
337     // Success
338     return true;
339   }
340
341   /// Reserve - Mark busy (set) the specified N slots.
342   void Reserve(Iter Begin, unsigned N, unsigned Resource) {
343     // Determine end of interval
344     Iter End = Begin + N;
345     assert(End <= Tally.end() && "Tally is not large enough for schedule");
346  
347     // Set resource bit in each slot
348     for (; Begin < End; Begin++)
349       *Begin |= Resource;
350   }
351
352   /// FindSlots - Starting from Begin, locate consecutive slots where all stages
353   /// can be completed.  Returns the address of first slot.
354   Iter FindSlots(Iter Begin, InstrStage *StageBegin, InstrStage *StageEnd) {
355     // Track position      
356     Iter Cursor = Begin;
357     
358     // Try all possible slots forward
359     while (true) {
360       // Try at cursor, if successful return position.
361       if (FindAndReserveStages(Cursor, StageBegin, StageEnd)) return Cursor;
362       // Locate a better position
363                         Cursor = RetrySlot(Cursor + 1, StageBegin->Cycles, StageBegin->Units);
364     }
365   }
366   
367 public:
368   /// Initialize - Resize and zero the tally to the specified number of time
369   /// slots.
370   inline void Initialize(unsigned N) {
371     Tally.assign(N, 0);   // Initialize tally to all zeros.
372   }
373
374   // FindAndReserve - Locate an ideal slot for the specified stages and mark
375   // as busy.
376   unsigned FindAndReserve(unsigned Slot, InstrStage *StageBegin,
377                                          InstrStage *StageEnd) {
378                 // Where to begin 
379                 Iter Begin = Tally.begin() + Slot;
380                 // Find a free slot
381                 Iter Where = FindSlots(Begin, StageBegin, StageEnd);
382                 // Distance is slot number
383                 unsigned Final = Where - Tally.begin();
384     return Final;
385   }
386
387 };
388
389 //===----------------------------------------------------------------------===//
390 ///
391 /// ScheduleDAGSimple - Simple two pass scheduler.
392 ///
393 class VISIBILITY_HIDDEN ScheduleDAGSimple : public ScheduleDAG {
394 private:
395   bool NoSched;                         // Just do a BFS schedule, nothing fancy
396   bool NoItins;                         // Don't use itineraries?
397   ResourceTally<unsigned> Tally;        // Resource usage tally
398   unsigned NSlots;                      // Total latency
399   static const unsigned NotFound = ~0U; // Search marker
400
401   unsigned NodeCount;                   // Number of nodes in DAG
402   std::map<SDNode *, NodeInfo *> Map;   // Map nodes to info
403   bool HasGroups;                       // True if there are any groups
404   NodeInfo *Info;                       // Info for nodes being scheduled
405   NIVector Ordering;                    // Emit ordering of nodes
406   NodeGroup *HeadNG, *TailNG;           // Keep track of allocated NodeGroups
407   
408 public:
409
410   // Ctor.
411   ScheduleDAGSimple(bool noSched, bool noItins, SelectionDAG &dag,
412                     MachineBasicBlock *bb, const TargetMachine &tm)
413     : ScheduleDAG(dag, bb, tm), NoSched(noSched), NoItins(noItins), NSlots(0),
414     NodeCount(0), HasGroups(false), Info(NULL), HeadNG(NULL), TailNG(NULL) {
415     assert(&TII && "Target doesn't provide instr info?");
416     assert(&MRI && "Target doesn't provide register info?");
417   }
418
419   virtual ~ScheduleDAGSimple() {
420     if (Info)
421       delete[] Info;
422     
423     NodeGroup *NG = HeadNG;
424     while (NG) {
425       NodeGroup *NextSU = NG->Next;
426       delete NG;
427       NG = NextSU;
428     }
429   }
430
431   void Schedule();
432
433   /// getNI - Returns the node info for the specified node.
434   ///
435   NodeInfo *getNI(SDNode *Node) { return Map[Node]; }
436   
437 private:
438   static bool isDefiner(NodeInfo *A, NodeInfo *B);
439   void IncludeNode(NodeInfo *NI);
440   void VisitAll();
441   void GatherSchedulingInfo();
442   void FakeGroupDominators(); 
443   bool isStrongDependency(NodeInfo *A, NodeInfo *B);
444   bool isWeakDependency(NodeInfo *A, NodeInfo *B);
445   void ScheduleBackward();
446   void ScheduleForward();
447   
448   void AddToGroup(NodeInfo *D, NodeInfo *U);
449   /// PrepareNodeInfo - Set up the basic minimum node info for scheduling.
450   /// 
451   void PrepareNodeInfo();
452   
453   /// IdentifyGroups - Put flagged nodes into groups.
454   ///
455   void IdentifyGroups();
456   
457   /// print - Print ordering to specified output stream.
458   ///
459   void print(std::ostream &O) const;
460   
461   void dump(const char *tag) const;
462   
463   virtual void dump() const;
464   
465   /// EmitAll - Emit all nodes in schedule sorted order.
466   ///
467   void EmitAll();
468
469   /// printNI - Print node info.
470   ///
471   void printNI(std::ostream &O, NodeInfo *NI) const;
472   
473   /// printChanges - Hilight changes in order caused by scheduling.
474   ///
475   void printChanges(unsigned Index) const;
476 };
477
478 //===----------------------------------------------------------------------===//
479 /// Special case itineraries.
480 ///
481 enum {
482   CallLatency = 40,          // To push calls back in time
483
484   RSInteger   = 0xC0000000,  // Two integer units
485   RSFloat     = 0x30000000,  // Two float units
486   RSLoadStore = 0x0C000000,  // Two load store units
487   RSBranch    = 0x02000000   // One branch unit
488 };
489 static InstrStage CallStage  = { CallLatency, RSBranch };
490 static InstrStage LoadStage  = { 5, RSLoadStore };
491 static InstrStage StoreStage = { 2, RSLoadStore };
492 static InstrStage IntStage   = { 2, RSInteger };
493 static InstrStage FloatStage = { 3, RSFloat };
494 //===----------------------------------------------------------------------===//
495
496 } // namespace
497
498 //===----------------------------------------------------------------------===//
499
500 /// PrepareNodeInfo - Set up the basic minimum node info for scheduling.
501 /// 
502 void ScheduleDAGSimple::PrepareNodeInfo() {
503   // Allocate node information
504   Info = new NodeInfo[NodeCount];
505   
506   unsigned i = 0;
507   for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
508        E = DAG.allnodes_end(); I != E; ++I, ++i) {
509     // Fast reference to node schedule info
510     NodeInfo* NI = &Info[i];
511     // Set up map
512     Map[I] = NI;
513     // Set node
514     NI->Node = I;
515     // Set pending visit count
516     NI->setPending(I->use_size());
517   }
518 }
519
520 /// IdentifyGroups - Put flagged nodes into groups.
521 ///
522 void ScheduleDAGSimple::IdentifyGroups() {
523   for (unsigned i = 0, N = NodeCount; i < N; i++) {
524     NodeInfo* NI = &Info[i];
525     SDNode *Node = NI->Node;
526     
527     // For each operand (in reverse to only look at flags)
528     for (unsigned N = Node->getNumOperands(); 0 < N--;) {
529       // Get operand
530       SDOperand Op = Node->getOperand(N);
531       // No more flags to walk
532       if (Op.getValueType() != MVT::Flag) break;
533       // Add to node group
534       AddToGroup(getNI(Op.Val), NI);
535       // Let everyone else know
536       HasGroups = true;
537     }
538   }
539 }
540
541 /// CountInternalUses - Returns the number of edges between the two nodes.
542 ///
543 static unsigned CountInternalUses(NodeInfo *D, NodeInfo *U) {
544   unsigned N = 0;
545   for (unsigned M = U->Node->getNumOperands(); 0 < M--;) {
546     SDOperand Op = U->Node->getOperand(M);
547     if (Op.Val == D->Node) N++;
548   }
549   
550   return N;
551 }
552
553 //===----------------------------------------------------------------------===//
554 /// Add - Adds a definer and user pair to a node group.
555 ///
556 void ScheduleDAGSimple::AddToGroup(NodeInfo *D, NodeInfo *U) {
557   // Get current groups
558   NodeGroup *DGroup = D->Group;
559   NodeGroup *UGroup = U->Group;
560   // If both are members of groups
561   if (DGroup && UGroup) {
562     // There may have been another edge connecting 
563     if (DGroup == UGroup) return;
564     // Add the pending users count
565     DGroup->addPending(UGroup->getPending());
566     // For each member of the users group
567     NodeGroupIterator UNGI(U);
568     while (NodeInfo *UNI = UNGI.next() ) {
569       // Change the group
570       UNI->Group = DGroup;
571       // For each member of the definers group
572       NodeGroupIterator DNGI(D);
573       while (NodeInfo *DNI = DNGI.next() ) {
574         // Remove internal edges
575         DGroup->addPending(-CountInternalUses(DNI, UNI));
576       }
577     }
578     // Merge the two lists
579     DGroup->group_insert(DGroup->group_end(),
580                          UGroup->group_begin(), UGroup->group_end());
581   } else if (DGroup) {
582     // Make user member of definers group
583     U->Group = DGroup;
584     // Add users uses to definers group pending
585     DGroup->addPending(U->Node->use_size());
586     // For each member of the definers group
587     NodeGroupIterator DNGI(D);
588     while (NodeInfo *DNI = DNGI.next() ) {
589       // Remove internal edges
590       DGroup->addPending(-CountInternalUses(DNI, U));
591     }
592     DGroup->group_push_back(U);
593   } else if (UGroup) {
594     // Make definer member of users group
595     D->Group = UGroup;
596     // Add definers uses to users group pending
597     UGroup->addPending(D->Node->use_size());
598     // For each member of the users group
599     NodeGroupIterator UNGI(U);
600     while (NodeInfo *UNI = UNGI.next() ) {
601       // Remove internal edges
602       UGroup->addPending(-CountInternalUses(D, UNI));
603     }
604     UGroup->group_insert(UGroup->group_begin(), D);
605   } else {
606     D->Group = U->Group = DGroup = new NodeGroup();
607     DGroup->addPending(D->Node->use_size() + U->Node->use_size() -
608                        CountInternalUses(D, U));
609     DGroup->group_push_back(D);
610     DGroup->group_push_back(U);
611     
612     if (HeadNG == NULL)
613       HeadNG = DGroup;
614     if (TailNG != NULL)
615       TailNG->Next = DGroup;
616     TailNG = DGroup;
617   }
618 }
619
620
621 /// print - Print ordering to specified output stream.
622 ///
623 void ScheduleDAGSimple::print(std::ostream &O) const {
624 #ifndef NDEBUG
625   O << "Ordering\n";
626   for (unsigned i = 0, N = Ordering.size(); i < N; i++) {
627     NodeInfo *NI = Ordering[i];
628     printNI(O, NI);
629     O << "\n";
630     if (NI->isGroupDominator()) {
631       NodeGroup *Group = NI->Group;
632       for (NIIterator NII = Group->group_begin(), E = Group->group_end();
633            NII != E; NII++) {
634         O << "    ";
635         printNI(O, *NII);
636         O << "\n";
637       }
638     }
639   }
640 #endif
641 }
642
643 void ScheduleDAGSimple::dump(const char *tag) const {
644   std::cerr << tag; dump();
645 }
646
647 void ScheduleDAGSimple::dump() const {
648   print(std::cerr);
649 }
650
651
652 /// EmitAll - Emit all nodes in schedule sorted order.
653 ///
654 void ScheduleDAGSimple::EmitAll() {
655   std::map<SDNode*, unsigned> VRBaseMap;
656   
657   // For each node in the ordering
658   for (unsigned i = 0, N = Ordering.size(); i < N; i++) {
659     // Get the scheduling info
660     NodeInfo *NI = Ordering[i];
661     if (NI->isInGroup()) {
662       NodeGroupIterator NGI(Ordering[i]);
663       while (NodeInfo *NI = NGI.next()) EmitNode(NI->Node, VRBaseMap);
664     } else {
665       EmitNode(NI->Node, VRBaseMap);
666     }
667   }
668 }
669
670 /// isFlagDefiner - Returns true if the node defines a flag result.
671 static bool isFlagDefiner(SDNode *A) {
672   unsigned N = A->getNumValues();
673   return N && A->getValueType(N - 1) == MVT::Flag;
674 }
675
676 /// isFlagUser - Returns true if the node uses a flag result.
677 ///
678 static bool isFlagUser(SDNode *A) {
679   unsigned N = A->getNumOperands();
680   return N && A->getOperand(N - 1).getValueType() == MVT::Flag;
681 }
682
683 /// printNI - Print node info.
684 ///
685 void ScheduleDAGSimple::printNI(std::ostream &O, NodeInfo *NI) const {
686 #ifndef NDEBUG
687   SDNode *Node = NI->Node;
688   O << " "
689     << std::hex << Node << std::dec
690     << ", Lat=" << NI->Latency
691     << ", Slot=" << NI->Slot
692     << ", ARITY=(" << Node->getNumOperands() << ","
693     << Node->getNumValues() << ")"
694     << " " << Node->getOperationName(&DAG);
695   if (isFlagDefiner(Node)) O << "<#";
696   if (isFlagUser(Node)) O << ">#";
697 #endif
698 }
699
700 /// printChanges - Hilight changes in order caused by scheduling.
701 ///
702 void ScheduleDAGSimple::printChanges(unsigned Index) const {
703 #ifndef NDEBUG
704   // Get the ordered node count
705   unsigned N = Ordering.size();
706   // Determine if any changes
707   unsigned i = 0;
708   for (; i < N; i++) {
709     NodeInfo *NI = Ordering[i];
710     if (NI->Preorder != i) break;
711   }
712   
713   if (i < N) {
714     std::cerr << Index << ". New Ordering\n";
715     
716     for (i = 0; i < N; i++) {
717       NodeInfo *NI = Ordering[i];
718       std::cerr << "  " << NI->Preorder << ". ";
719       printNI(std::cerr, NI);
720       std::cerr << "\n";
721       if (NI->isGroupDominator()) {
722         NodeGroup *Group = NI->Group;
723         for (NIIterator NII = Group->group_begin(), E = Group->group_end();
724              NII != E; NII++) {
725           std::cerr << "          ";
726           printNI(std::cerr, *NII);
727           std::cerr << "\n";
728         }
729       }
730     }
731   } else {
732     std::cerr << Index << ". No Changes\n";
733   }
734 #endif
735 }
736
737 //===----------------------------------------------------------------------===//
738 /// isDefiner - Return true if node A is a definer for B.
739 ///
740 bool ScheduleDAGSimple::isDefiner(NodeInfo *A, NodeInfo *B) {
741   // While there are A nodes
742   NodeGroupIterator NII(A);
743   while (NodeInfo *NI = NII.next()) {
744     // Extract node
745     SDNode *Node = NI->Node;
746     // While there operands in nodes of B
747     NodeGroupOpIterator NGOI(B);
748     while (!NGOI.isEnd()) {
749       SDOperand Op = NGOI.next();
750       // If node from A defines a node in B
751       if (Node == Op.Val) return true;
752     }
753   }
754   return false;
755 }
756
757 /// IncludeNode - Add node to NodeInfo vector.
758 ///
759 void ScheduleDAGSimple::IncludeNode(NodeInfo *NI) {
760   // Get node
761   SDNode *Node = NI->Node;
762   // Ignore entry node
763   if (Node->getOpcode() == ISD::EntryToken) return;
764   // Check current count for node
765   int Count = NI->getPending();
766   // If the node is already in list
767   if (Count < 0) return;
768   // Decrement count to indicate a visit
769   Count--;
770   // If count has gone to zero then add node to list
771   if (!Count) {
772     // Add node
773     if (NI->isInGroup()) {
774       Ordering.push_back(NI->Group->getDominator());
775     } else {
776       Ordering.push_back(NI);
777     }
778     // indicate node has been added
779     Count--;
780   }
781   // Mark as visited with new count 
782   NI->setPending(Count);
783 }
784
785 /// GatherSchedulingInfo - Get latency and resource information about each node.
786 ///
787 void ScheduleDAGSimple::GatherSchedulingInfo() {
788   // Get instruction itineraries for the target
789   const InstrItineraryData &InstrItins = TM.getInstrItineraryData();
790   
791   // For each node
792   for (unsigned i = 0, N = NodeCount; i < N; i++) {
793     // Get node info
794     NodeInfo* NI = &Info[i];
795     SDNode *Node = NI->Node;
796     
797     // If there are itineraries and it is a machine instruction
798     if (InstrItins.isEmpty() || NoItins) {
799       // If machine opcode
800       if (Node->isTargetOpcode()) {
801         // Get return type to guess which processing unit 
802         MVT::ValueType VT = Node->getValueType(0);
803         // Get machine opcode
804         MachineOpCode TOpc = Node->getTargetOpcode();
805         NI->IsCall = TII->isCall(TOpc);
806         NI->IsLoad = TII->isLoad(TOpc);
807         NI->IsStore = TII->isStore(TOpc);
808
809         if (TII->isLoad(TOpc))             NI->StageBegin = &LoadStage;
810         else if (TII->isStore(TOpc))       NI->StageBegin = &StoreStage;
811         else if (MVT::isInteger(VT))       NI->StageBegin = &IntStage;
812         else if (MVT::isFloatingPoint(VT)) NI->StageBegin = &FloatStage;
813         if (NI->StageBegin) NI->StageEnd = NI->StageBegin + 1;
814       }
815     } else if (Node->isTargetOpcode()) {
816       // get machine opcode
817       MachineOpCode TOpc = Node->getTargetOpcode();
818       // Check to see if it is a call
819       NI->IsCall = TII->isCall(TOpc);
820       // Get itinerary stages for instruction
821       unsigned II = TII->getSchedClass(TOpc);
822       NI->StageBegin = InstrItins.begin(II);
823       NI->StageEnd = InstrItins.end(II);
824     }
825     
826     // One slot for the instruction itself
827     NI->Latency = 1;
828     
829     // Add long latency for a call to push it back in time
830     if (NI->IsCall) NI->Latency += CallLatency;
831     
832     // Sum up all the latencies
833     for (InstrStage *Stage = NI->StageBegin, *E = NI->StageEnd;
834         Stage != E; Stage++) {
835       NI->Latency += Stage->Cycles;
836     }
837     
838     // Sum up all the latencies for max tally size
839     NSlots += NI->Latency;
840   }
841   
842   // Unify metrics if in a group
843   if (HasGroups) {
844     for (unsigned i = 0, N = NodeCount; i < N; i++) {
845       NodeInfo* NI = &Info[i];
846       
847       if (NI->isInGroup()) {
848         NodeGroup *Group = NI->Group;
849         
850         if (!Group->getDominator()) {
851           NIIterator NGI = Group->group_begin(), NGE = Group->group_end();
852           NodeInfo *Dominator = *NGI;
853           unsigned Latency = 0;
854           
855           for (NGI++; NGI != NGE; NGI++) {
856             NodeInfo* NGNI = *NGI;
857             Latency += NGNI->Latency;
858             if (Dominator->Latency < NGNI->Latency) Dominator = NGNI;
859           }
860           
861           Dominator->Latency = Latency;
862           Group->setDominator(Dominator);
863         }
864       }
865     }
866   }
867 }
868
869 /// VisitAll - Visit each node breadth-wise to produce an initial ordering.
870 /// Note that the ordering in the Nodes vector is reversed.
871 void ScheduleDAGSimple::VisitAll() {
872   // Add first element to list
873   NodeInfo *NI = getNI(DAG.getRoot().Val);
874   if (NI->isInGroup()) {
875     Ordering.push_back(NI->Group->getDominator());
876   } else {
877     Ordering.push_back(NI);
878   }
879
880   // Iterate through all nodes that have been added
881   for (unsigned i = 0; i < Ordering.size(); i++) { // note: size() varies
882     // Visit all operands
883     NodeGroupOpIterator NGI(Ordering[i]);
884     while (!NGI.isEnd()) {
885       // Get next operand
886       SDOperand Op = NGI.next();
887       // Get node
888       SDNode *Node = Op.Val;
889       // Ignore passive nodes
890       if (isPassiveNode(Node)) continue;
891       // Check out node
892       IncludeNode(getNI(Node));
893     }
894   }
895
896   // Add entry node last (IncludeNode filters entry nodes)
897   if (DAG.getEntryNode().Val != DAG.getRoot().Val)
898     Ordering.push_back(getNI(DAG.getEntryNode().Val));
899     
900   // Reverse the order
901   std::reverse(Ordering.begin(), Ordering.end());
902 }
903
904 /// FakeGroupDominators - Set dominators for non-scheduling.
905 /// 
906 void ScheduleDAGSimple::FakeGroupDominators() {
907   for (unsigned i = 0, N = NodeCount; i < N; i++) {
908     NodeInfo* NI = &Info[i];
909     
910     if (NI->isInGroup()) {
911       NodeGroup *Group = NI->Group;
912       
913       if (!Group->getDominator()) {
914         Group->setDominator(NI);
915       }
916     }
917   }
918 }
919
920 /// isStrongDependency - Return true if node A has results used by node B. 
921 /// I.E., B must wait for latency of A.
922 bool ScheduleDAGSimple::isStrongDependency(NodeInfo *A, NodeInfo *B) {
923   // If A defines for B then it's a strong dependency or
924   // if a load follows a store (may be dependent but why take a chance.)
925   return isDefiner(A, B) || (A->IsStore && B->IsLoad);
926 }
927
928 /// isWeakDependency Return true if node A produces a result that will
929 /// conflict with operands of B.  It is assumed that we have called
930 /// isStrongDependency prior.
931 bool ScheduleDAGSimple::isWeakDependency(NodeInfo *A, NodeInfo *B) {
932   // TODO check for conflicting real registers and aliases
933 #if 0 // FIXME - Since we are in SSA form and not checking register aliasing
934   return A->Node->getOpcode() == ISD::EntryToken || isStrongDependency(B, A);
935 #else
936   return A->Node->getOpcode() == ISD::EntryToken;
937 #endif
938 }
939
940 /// ScheduleBackward - Schedule instructions so that any long latency
941 /// instructions and the critical path get pushed back in time. Time is run in
942 /// reverse to allow code reuse of the Tally and eliminate the overhead of
943 /// biasing every slot indices against NSlots.
944 void ScheduleDAGSimple::ScheduleBackward() {
945   // Size and clear the resource tally
946   Tally.Initialize(NSlots);
947   // Get number of nodes to schedule
948   unsigned N = Ordering.size();
949   
950   // For each node being scheduled
951   for (unsigned i = N; 0 < i--;) {
952     NodeInfo *NI = Ordering[i];
953     // Track insertion
954     unsigned Slot = NotFound;
955     
956     // Compare against those previously scheduled nodes
957     unsigned j = i + 1;
958     for (; j < N; j++) {
959       // Get following instruction
960       NodeInfo *Other = Ordering[j];
961       
962       // Check dependency against previously inserted nodes
963       if (isStrongDependency(NI, Other)) {
964         Slot = Other->Slot + Other->Latency;
965         break;
966       } else if (isWeakDependency(NI, Other)) {
967         Slot = Other->Slot;
968         break;
969       }
970     }
971     
972     // If independent of others (or first entry)
973     if (Slot == NotFound) Slot = 0;
974     
975 #if 0 // FIXME - measure later
976     // Find a slot where the needed resources are available
977     if (NI->StageBegin != NI->StageEnd)
978       Slot = Tally.FindAndReserve(Slot, NI->StageBegin, NI->StageEnd);
979 #endif
980       
981     // Set node slot
982     NI->Slot = Slot;
983     
984     // Insert sort based on slot
985     j = i + 1;
986     for (; j < N; j++) {
987       // Get following instruction
988       NodeInfo *Other = Ordering[j];
989       // Should we look further (remember slots are in reverse time)
990       if (Slot >= Other->Slot) break;
991       // Shuffle other into ordering
992       Ordering[j - 1] = Other;
993     }
994     // Insert node in proper slot
995     if (j != i + 1) Ordering[j - 1] = NI;
996   }
997 }
998
999 /// ScheduleForward - Schedule instructions to maximize packing.
1000 ///
1001 void ScheduleDAGSimple::ScheduleForward() {
1002   // Size and clear the resource tally
1003   Tally.Initialize(NSlots);
1004   // Get number of nodes to schedule
1005   unsigned N = Ordering.size();
1006   
1007   // For each node being scheduled
1008   for (unsigned i = 0; i < N; i++) {
1009     NodeInfo *NI = Ordering[i];
1010     // Track insertion
1011     unsigned Slot = NotFound;
1012     
1013     // Compare against those previously scheduled nodes
1014     unsigned j = i;
1015     for (; 0 < j--;) {
1016       // Get following instruction
1017       NodeInfo *Other = Ordering[j];
1018       
1019       // Check dependency against previously inserted nodes
1020       if (isStrongDependency(Other, NI)) {
1021         Slot = Other->Slot + Other->Latency;
1022         break;
1023       } else if (Other->IsCall || isWeakDependency(Other, NI)) {
1024         Slot = Other->Slot;
1025         break;
1026       }
1027     }
1028     
1029     // If independent of others (or first entry)
1030     if (Slot == NotFound) Slot = 0;
1031     
1032     // Find a slot where the needed resources are available
1033     if (NI->StageBegin != NI->StageEnd)
1034       Slot = Tally.FindAndReserve(Slot, NI->StageBegin, NI->StageEnd);
1035       
1036     // Set node slot
1037     NI->Slot = Slot;
1038     
1039     // Insert sort based on slot
1040     j = i;
1041     for (; 0 < j--;) {
1042       // Get prior instruction
1043       NodeInfo *Other = Ordering[j];
1044       // Should we look further
1045       if (Slot >= Other->Slot) break;
1046       // Shuffle other into ordering
1047       Ordering[j + 1] = Other;
1048     }
1049     // Insert node in proper slot
1050     if (j != i) Ordering[j + 1] = NI;
1051   }
1052 }
1053
1054 /// Schedule - Order nodes according to selected style.
1055 ///
1056 void ScheduleDAGSimple::Schedule() {
1057   // Number the nodes
1058   NodeCount = std::distance(DAG.allnodes_begin(), DAG.allnodes_end());
1059
1060   // Set up minimum info for scheduling
1061   PrepareNodeInfo();
1062   // Construct node groups for flagged nodes
1063   IdentifyGroups();
1064   
1065   // Test to see if scheduling should occur
1066   bool ShouldSchedule = NodeCount > 3 && !NoSched;
1067   // Don't waste time if is only entry and return
1068   if (ShouldSchedule) {
1069     // Get latency and resource requirements
1070     GatherSchedulingInfo();
1071   } else if (HasGroups) {
1072     // Make sure all the groups have dominators
1073     FakeGroupDominators();
1074   }
1075
1076   // Breadth first walk of DAG
1077   VisitAll();
1078
1079 #ifndef NDEBUG
1080   static unsigned Count = 0;
1081   Count++;
1082   for (unsigned i = 0, N = Ordering.size(); i < N; i++) {
1083     NodeInfo *NI = Ordering[i];
1084     NI->Preorder = i;
1085   }
1086 #endif  
1087   
1088   // Don't waste time if is only entry and return
1089   if (ShouldSchedule) {
1090     // Push back long instructions and critical path
1091     ScheduleBackward();
1092     
1093     // Pack instructions to maximize resource utilization
1094     ScheduleForward();
1095   }
1096   
1097   DEBUG(printChanges(Count));
1098   
1099   // Emit in scheduled order
1100   EmitAll();
1101 }
1102
1103
1104 /// createSimpleDAGScheduler - This creates a simple two pass instruction
1105 /// scheduler.
1106 llvm::ScheduleDAG* llvm::createSimpleDAGScheduler(bool NoItins,
1107                                                   SelectionDAG &DAG,
1108                                                   MachineBasicBlock *BB) {
1109   return new ScheduleDAGSimple(false, NoItins, DAG, BB, DAG.getTarget());
1110 }
1111
1112 llvm::ScheduleDAG* llvm::createBFS_DAGScheduler(SelectionDAG &DAG,
1113                                                 MachineBasicBlock *BB) {
1114   return new ScheduleDAGSimple(true, false, DAG, BB,  DAG.getTarget());
1115 }