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