| //===-- ScheduleDAGSimple.cpp - Implement a trivial DAG scheduler ---------===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file was developed by James M. Laskey and is distributed under the | 
 | // University of Illinois Open Source License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | // | 
 | // This implements a simple two pass scheduler.  The first pass attempts to push | 
 | // backward any lengthy instructions and critical paths.  The second pass packs | 
 | // instructions into semi-optimal time slots. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #define DEBUG_TYPE "sched" | 
 | #include "llvm/CodeGen/ScheduleDAG.h" | 
 | #include "llvm/CodeGen/SelectionDAG.h" | 
 | #include "llvm/Target/TargetMachine.h" | 
 | #include "llvm/Target/TargetInstrInfo.h" | 
 | #include "llvm/Support/Debug.h" | 
 | #include <algorithm> | 
 | using namespace llvm; | 
 |  | 
 | namespace { | 
 | //===----------------------------------------------------------------------===// | 
 | /// | 
 | /// BitsIterator - Provides iteration through individual bits in a bit vector. | 
 | /// | 
 | template<class T> | 
 | class BitsIterator { | 
 | private: | 
 |   T Bits;                               // Bits left to iterate through | 
 |  | 
 | public: | 
 |   /// Ctor. | 
 |   BitsIterator(T Initial) : Bits(Initial) {} | 
 |    | 
 |   /// Next - Returns the next bit set or zero if exhausted. | 
 |   inline T Next() { | 
 |     // Get the rightmost bit set | 
 |     T Result = Bits & -Bits; | 
 |     // Remove from rest | 
 |     Bits &= ~Result; | 
 |     // Return single bit or zero | 
 |     return Result; | 
 |   } | 
 | }; | 
 |    | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | /// | 
 | /// ResourceTally - Manages the use of resources over time intervals.  Each | 
 | /// item (slot) in the tally vector represents the resources used at a given | 
 | /// moment.  A bit set to 1 indicates that a resource is in use, otherwise | 
 | /// available.  An assumption is made that the tally is large enough to schedule  | 
 | /// all current instructions (asserts otherwise.) | 
 | /// | 
 | template<class T> | 
 | class ResourceTally { | 
 | private: | 
 |   std::vector<T> Tally;                 // Resources used per slot | 
 |   typedef typename std::vector<T>::iterator Iter; | 
 |                                         // Tally iterator  | 
 |    | 
 |   /// SlotsAvailable - Returns true if all units are available. | 
 | 	/// | 
 |   bool SlotsAvailable(Iter Begin, unsigned N, unsigned ResourceSet, | 
 |                                               unsigned &Resource) { | 
 |     assert(N && "Must check availability with N != 0"); | 
 |     // Determine end of interval | 
 |     Iter End = Begin + N; | 
 |     assert(End <= Tally.end() && "Tally is not large enough for schedule"); | 
 |      | 
 |     // Iterate thru each resource | 
 |     BitsIterator<T> Resources(ResourceSet & ~*Begin); | 
 |     while (unsigned Res = Resources.Next()) { | 
 |       // Check if resource is available for next N slots | 
 |       Iter Interval = End; | 
 |       do { | 
 |         Interval--; | 
 |         if (*Interval & Res) break; | 
 |       } while (Interval != Begin); | 
 |        | 
 |       // If available for N | 
 |       if (Interval == Begin) { | 
 |         // Success | 
 |         Resource = Res; | 
 |         return true; | 
 |       } | 
 |     } | 
 |      | 
 |     // No luck | 
 |     Resource = 0; | 
 |     return false; | 
 |   } | 
 | 	 | 
 | 	/// RetrySlot - Finds a good candidate slot to retry search. | 
 |   Iter RetrySlot(Iter Begin, unsigned N, unsigned ResourceSet) { | 
 |     assert(N && "Must check availability with N != 0"); | 
 |     // Determine end of interval | 
 |     Iter End = Begin + N; | 
 |     assert(End <= Tally.end() && "Tally is not large enough for schedule"); | 
 | 		 | 
 | 		while (Begin != End--) { | 
 | 			// Clear units in use | 
 | 			ResourceSet &= ~*End; | 
 | 			// If no units left then we should go no further  | 
 | 			if (!ResourceSet) return End + 1; | 
 | 		} | 
 | 		// Made it all the way through | 
 | 		return Begin; | 
 | 	} | 
 |    | 
 |   /// FindAndReserveStages - Return true if the stages can be completed. If | 
 |   /// so mark as busy. | 
 |   bool FindAndReserveStages(Iter Begin, | 
 |                             InstrStage *Stage, InstrStage *StageEnd) { | 
 |     // If at last stage then we're done | 
 |     if (Stage == StageEnd) return true; | 
 |     // Get number of cycles for current stage | 
 |     unsigned N = Stage->Cycles; | 
 |     // Check to see if N slots are available, if not fail | 
 |     unsigned Resource; | 
 |     if (!SlotsAvailable(Begin, N, Stage->Units, Resource)) return false; | 
 |     // Check to see if remaining stages are available, if not fail | 
 |     if (!FindAndReserveStages(Begin + N, Stage + 1, StageEnd)) return false; | 
 |     // Reserve resource | 
 |     Reserve(Begin, N, Resource); | 
 |     // Success | 
 |     return true; | 
 |   } | 
 |  | 
 |   /// Reserve - Mark busy (set) the specified N slots. | 
 |   void Reserve(Iter Begin, unsigned N, unsigned Resource) { | 
 |     // Determine end of interval | 
 |     Iter End = Begin + N; | 
 |     assert(End <= Tally.end() && "Tally is not large enough for schedule"); | 
 |   | 
 |     // Set resource bit in each slot | 
 |     for (; Begin < End; Begin++) | 
 |       *Begin |= Resource; | 
 |   } | 
 |  | 
 |   /// FindSlots - Starting from Begin, locate consecutive slots where all stages | 
 |   /// can be completed.  Returns the address of first slot. | 
 |   Iter FindSlots(Iter Begin, InstrStage *StageBegin, InstrStage *StageEnd) { | 
 |     // Track position       | 
 |     Iter Cursor = Begin; | 
 |      | 
 |     // Try all possible slots forward | 
 |     while (true) { | 
 |       // Try at cursor, if successful return position. | 
 |       if (FindAndReserveStages(Cursor, StageBegin, StageEnd)) return Cursor; | 
 |       // Locate a better position | 
 | 			Cursor = RetrySlot(Cursor + 1, StageBegin->Cycles, StageBegin->Units); | 
 |     } | 
 |   } | 
 |    | 
 | public: | 
 |   /// Initialize - Resize and zero the tally to the specified number of time | 
 |   /// slots. | 
 |   inline void Initialize(unsigned N) { | 
 |     Tally.assign(N, 0);   // Initialize tally to all zeros. | 
 |   } | 
 |  | 
 |   // FindAndReserve - Locate an ideal slot for the specified stages and mark | 
 |   // as busy. | 
 |   unsigned FindAndReserve(unsigned Slot, InstrStage *StageBegin, | 
 |                                          InstrStage *StageEnd) { | 
 | 		// Where to begin  | 
 | 		Iter Begin = Tally.begin() + Slot; | 
 | 		// Find a free slot | 
 | 		Iter Where = FindSlots(Begin, StageBegin, StageEnd); | 
 | 		// Distance is slot number | 
 | 		unsigned Final = Where - Tally.begin(); | 
 |     return Final; | 
 |   } | 
 |  | 
 | }; | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | /// | 
 | /// ScheduleDAGSimple - Simple two pass scheduler. | 
 | /// | 
 | class ScheduleDAGSimple : public ScheduleDAG { | 
 | private: | 
 |   ResourceTally<unsigned> Tally;        // Resource usage tally | 
 |   unsigned NSlots;                      // Total latency | 
 |   static const unsigned NotFound = ~0U; // Search marker | 
 |    | 
 | public: | 
 |  | 
 |   // Ctor. | 
 |   ScheduleDAGSimple(SchedHeuristics hstc, SelectionDAG &dag, | 
 |                     MachineBasicBlock *bb, const TargetMachine &tm) | 
 |     : ScheduleDAG(hstc, dag, bb, tm), Tally(), NSlots(0) { | 
 |     assert(&TII && "Target doesn't provide instr info?"); | 
 |     assert(&MRI && "Target doesn't provide register info?"); | 
 |   } | 
 |  | 
 |   virtual ~ScheduleDAGSimple() {}; | 
 |  | 
 |   void Schedule(); | 
 |  | 
 | private: | 
 |   static bool isDefiner(NodeInfo *A, NodeInfo *B); | 
 |   void IncludeNode(NodeInfo *NI); | 
 |   void VisitAll(); | 
 |   void GatherSchedulingInfo(); | 
 |   void FakeGroupDominators();  | 
 |   bool isStrongDependency(NodeInfo *A, NodeInfo *B); | 
 |   bool isWeakDependency(NodeInfo *A, NodeInfo *B); | 
 |   void ScheduleBackward(); | 
 |   void ScheduleForward(); | 
 | }; | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | /// Special case itineraries. | 
 | /// | 
 | enum { | 
 |   CallLatency = 40,          // To push calls back in time | 
 |  | 
 |   RSInteger   = 0xC0000000,  // Two integer units | 
 |   RSFloat     = 0x30000000,  // Two float units | 
 |   RSLoadStore = 0x0C000000,  // Two load store units | 
 |   RSBranch    = 0x02000000   // One branch unit | 
 | }; | 
 | static InstrStage CallStage  = { CallLatency, RSBranch }; | 
 | static InstrStage LoadStage  = { 5, RSLoadStore }; | 
 | static InstrStage StoreStage = { 2, RSLoadStore }; | 
 | static InstrStage IntStage   = { 2, RSInteger }; | 
 | static InstrStage FloatStage = { 3, RSFloat }; | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | } // namespace | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | /// isDefiner - Return true if node A is a definer for B. | 
 | /// | 
 | bool ScheduleDAGSimple::isDefiner(NodeInfo *A, NodeInfo *B) { | 
 |   // While there are A nodes | 
 |   NodeGroupIterator NII(A); | 
 |   while (NodeInfo *NI = NII.next()) { | 
 |     // Extract node | 
 |     SDNode *Node = NI->Node; | 
 |     // While there operands in nodes of B | 
 |     NodeGroupOpIterator NGOI(B); | 
 |     while (!NGOI.isEnd()) { | 
 |       SDOperand Op = NGOI.next(); | 
 |       // If node from A defines a node in B | 
 |       if (Node == Op.Val) return true; | 
 |     } | 
 |   } | 
 |   return false; | 
 | } | 
 |  | 
 | /// IncludeNode - Add node to NodeInfo vector. | 
 | /// | 
 | void ScheduleDAGSimple::IncludeNode(NodeInfo *NI) { | 
 |   // Get node | 
 |   SDNode *Node = NI->Node; | 
 |   // Ignore entry node | 
 |   if (Node->getOpcode() == ISD::EntryToken) return; | 
 |   // Check current count for node | 
 |   int Count = NI->getPending(); | 
 |   // If the node is already in list | 
 |   if (Count < 0) return; | 
 |   // Decrement count to indicate a visit | 
 |   Count--; | 
 |   // If count has gone to zero then add node to list | 
 |   if (!Count) { | 
 |     // Add node | 
 |     if (NI->isInGroup()) { | 
 |       Ordering.push_back(NI->Group->getDominator()); | 
 |     } else { | 
 |       Ordering.push_back(NI); | 
 |     } | 
 |     // indicate node has been added | 
 |     Count--; | 
 |   } | 
 |   // Mark as visited with new count  | 
 |   NI->setPending(Count); | 
 | } | 
 |  | 
 | /// GatherSchedulingInfo - Get latency and resource information about each node. | 
 | /// | 
 | void ScheduleDAGSimple::GatherSchedulingInfo() { | 
 |   // Get instruction itineraries for the target | 
 |   const InstrItineraryData InstrItins = TM.getInstrItineraryData(); | 
 |    | 
 |   // For each node | 
 |   for (unsigned i = 0, N = NodeCount; i < N; i++) { | 
 |     // Get node info | 
 |     NodeInfo* NI = &Info[i]; | 
 |     SDNode *Node = NI->Node; | 
 |      | 
 |     // If there are itineraries and it is a machine instruction | 
 |     if (InstrItins.isEmpty() || Heuristic == simpleNoItinScheduling) { | 
 |       // If machine opcode | 
 |       if (Node->isTargetOpcode()) { | 
 |         // Get return type to guess which processing unit  | 
 |         MVT::ValueType VT = Node->getValueType(0); | 
 |         // Get machine opcode | 
 |         MachineOpCode TOpc = Node->getTargetOpcode(); | 
 |         NI->IsCall = TII->isCall(TOpc); | 
 |         NI->IsLoad = TII->isLoad(TOpc); | 
 |         NI->IsStore = TII->isStore(TOpc); | 
 |  | 
 |         if (TII->isLoad(TOpc))             NI->StageBegin = &LoadStage; | 
 |         else if (TII->isStore(TOpc))       NI->StageBegin = &StoreStage; | 
 |         else if (MVT::isInteger(VT))       NI->StageBegin = &IntStage; | 
 |         else if (MVT::isFloatingPoint(VT)) NI->StageBegin = &FloatStage; | 
 |         if (NI->StageBegin) NI->StageEnd = NI->StageBegin + 1; | 
 |       } | 
 |     } else if (Node->isTargetOpcode()) { | 
 |       // get machine opcode | 
 |       MachineOpCode TOpc = Node->getTargetOpcode(); | 
 |       // Check to see if it is a call | 
 |       NI->IsCall = TII->isCall(TOpc); | 
 |       // Get itinerary stages for instruction | 
 |       unsigned II = TII->getSchedClass(TOpc); | 
 |       NI->StageBegin = InstrItins.begin(II); | 
 |       NI->StageEnd = InstrItins.end(II); | 
 |     } | 
 |      | 
 |     // One slot for the instruction itself | 
 |     NI->Latency = 1; | 
 |      | 
 |     // Add long latency for a call to push it back in time | 
 |     if (NI->IsCall) NI->Latency += CallLatency; | 
 |      | 
 |     // Sum up all the latencies | 
 |     for (InstrStage *Stage = NI->StageBegin, *E = NI->StageEnd; | 
 |         Stage != E; Stage++) { | 
 |       NI->Latency += Stage->Cycles; | 
 |     } | 
 |      | 
 |     // Sum up all the latencies for max tally size | 
 |     NSlots += NI->Latency; | 
 |   } | 
 |    | 
 |   // Unify metrics if in a group | 
 |   if (HasGroups) { | 
 |     for (unsigned i = 0, N = NodeCount; i < N; i++) { | 
 |       NodeInfo* NI = &Info[i]; | 
 |        | 
 |       if (NI->isInGroup()) { | 
 |         NodeGroup *Group = NI->Group; | 
 |          | 
 |         if (!Group->getDominator()) { | 
 |           NIIterator NGI = Group->group_begin(), NGE = Group->group_end(); | 
 |           NodeInfo *Dominator = *NGI; | 
 |           unsigned Latency = 0; | 
 |            | 
 |           for (NGI++; NGI != NGE; NGI++) { | 
 |             NodeInfo* NGNI = *NGI; | 
 |             Latency += NGNI->Latency; | 
 |             if (Dominator->Latency < NGNI->Latency) Dominator = NGNI; | 
 |           } | 
 |            | 
 |           Dominator->Latency = Latency; | 
 |           Group->setDominator(Dominator); | 
 |         } | 
 |       } | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | /// VisitAll - Visit each node breadth-wise to produce an initial ordering. | 
 | /// Note that the ordering in the Nodes vector is reversed. | 
 | void ScheduleDAGSimple::VisitAll() { | 
 |   // Add first element to list | 
 |   NodeInfo *NI = getNI(DAG.getRoot().Val); | 
 |   if (NI->isInGroup()) { | 
 |     Ordering.push_back(NI->Group->getDominator()); | 
 |   } else { | 
 |     Ordering.push_back(NI); | 
 |   } | 
 |  | 
 |   // Iterate through all nodes that have been added | 
 |   for (unsigned i = 0; i < Ordering.size(); i++) { // note: size() varies | 
 |     // Visit all operands | 
 |     NodeGroupOpIterator NGI(Ordering[i]); | 
 |     while (!NGI.isEnd()) { | 
 |       // Get next operand | 
 |       SDOperand Op = NGI.next(); | 
 |       // Get node | 
 |       SDNode *Node = Op.Val; | 
 |       // Ignore passive nodes | 
 |       if (isPassiveNode(Node)) continue; | 
 |       // Check out node | 
 |       IncludeNode(getNI(Node)); | 
 |     } | 
 |   } | 
 |  | 
 |   // Add entry node last (IncludeNode filters entry nodes) | 
 |   if (DAG.getEntryNode().Val != DAG.getRoot().Val) | 
 |     Ordering.push_back(getNI(DAG.getEntryNode().Val)); | 
 |      | 
 |   // Reverse the order | 
 |   std::reverse(Ordering.begin(), Ordering.end()); | 
 | } | 
 |  | 
 | /// FakeGroupDominators - Set dominators for non-scheduling. | 
 | ///  | 
 | void ScheduleDAGSimple::FakeGroupDominators() { | 
 |   for (unsigned i = 0, N = NodeCount; i < N; i++) { | 
 |     NodeInfo* NI = &Info[i]; | 
 |      | 
 |     if (NI->isInGroup()) { | 
 |       NodeGroup *Group = NI->Group; | 
 |        | 
 |       if (!Group->getDominator()) { | 
 |         Group->setDominator(NI); | 
 |       } | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | /// isStrongDependency - Return true if node A has results used by node B.  | 
 | /// I.E., B must wait for latency of A. | 
 | bool ScheduleDAGSimple::isStrongDependency(NodeInfo *A, NodeInfo *B) { | 
 |   // If A defines for B then it's a strong dependency or | 
 |   // if a load follows a store (may be dependent but why take a chance.) | 
 |   return isDefiner(A, B) || (A->IsStore && B->IsLoad); | 
 | } | 
 |  | 
 | /// isWeakDependency Return true if node A produces a result that will | 
 | /// conflict with operands of B.  It is assumed that we have called | 
 | /// isStrongDependency prior. | 
 | bool ScheduleDAGSimple::isWeakDependency(NodeInfo *A, NodeInfo *B) { | 
 |   // TODO check for conflicting real registers and aliases | 
 | #if 0 // FIXME - Since we are in SSA form and not checking register aliasing | 
 |   return A->Node->getOpcode() == ISD::EntryToken || isStrongDependency(B, A); | 
 | #else | 
 |   return A->Node->getOpcode() == ISD::EntryToken; | 
 | #endif | 
 | } | 
 |  | 
 | /// ScheduleBackward - Schedule instructions so that any long latency | 
 | /// instructions and the critical path get pushed back in time. Time is run in | 
 | /// reverse to allow code reuse of the Tally and eliminate the overhead of | 
 | /// biasing every slot indices against NSlots. | 
 | void ScheduleDAGSimple::ScheduleBackward() { | 
 |   // Size and clear the resource tally | 
 |   Tally.Initialize(NSlots); | 
 |   // Get number of nodes to schedule | 
 |   unsigned N = Ordering.size(); | 
 |    | 
 |   // For each node being scheduled | 
 |   for (unsigned i = N; 0 < i--;) { | 
 |     NodeInfo *NI = Ordering[i]; | 
 |     // Track insertion | 
 |     unsigned Slot = NotFound; | 
 |      | 
 |     // Compare against those previously scheduled nodes | 
 |     unsigned j = i + 1; | 
 |     for (; j < N; j++) { | 
 |       // Get following instruction | 
 |       NodeInfo *Other = Ordering[j]; | 
 |        | 
 |       // Check dependency against previously inserted nodes | 
 |       if (isStrongDependency(NI, Other)) { | 
 |         Slot = Other->Slot + Other->Latency; | 
 |         break; | 
 |       } else if (isWeakDependency(NI, Other)) { | 
 |         Slot = Other->Slot; | 
 |         break; | 
 |       } | 
 |     } | 
 |      | 
 |     // If independent of others (or first entry) | 
 |     if (Slot == NotFound) Slot = 0; | 
 |      | 
 | #if 0 // FIXME - measure later | 
 |     // Find a slot where the needed resources are available | 
 |     if (NI->StageBegin != NI->StageEnd) | 
 |       Slot = Tally.FindAndReserve(Slot, NI->StageBegin, NI->StageEnd); | 
 | #endif | 
 |        | 
 |     // Set node slot | 
 |     NI->Slot = Slot; | 
 |      | 
 |     // Insert sort based on slot | 
 |     j = i + 1; | 
 |     for (; j < N; j++) { | 
 |       // Get following instruction | 
 |       NodeInfo *Other = Ordering[j]; | 
 |       // Should we look further (remember slots are in reverse time) | 
 |       if (Slot >= Other->Slot) break; | 
 |       // Shuffle other into ordering | 
 |       Ordering[j - 1] = Other; | 
 |     } | 
 |     // Insert node in proper slot | 
 |     if (j != i + 1) Ordering[j - 1] = NI; | 
 |   } | 
 | } | 
 |  | 
 | /// ScheduleForward - Schedule instructions to maximize packing. | 
 | /// | 
 | void ScheduleDAGSimple::ScheduleForward() { | 
 |   // Size and clear the resource tally | 
 |   Tally.Initialize(NSlots); | 
 |   // Get number of nodes to schedule | 
 |   unsigned N = Ordering.size(); | 
 |    | 
 |   // For each node being scheduled | 
 |   for (unsigned i = 0; i < N; i++) { | 
 |     NodeInfo *NI = Ordering[i]; | 
 |     // Track insertion | 
 |     unsigned Slot = NotFound; | 
 |      | 
 |     // Compare against those previously scheduled nodes | 
 |     unsigned j = i; | 
 |     for (; 0 < j--;) { | 
 |       // Get following instruction | 
 |       NodeInfo *Other = Ordering[j]; | 
 |        | 
 |       // Check dependency against previously inserted nodes | 
 |       if (isStrongDependency(Other, NI)) { | 
 |         Slot = Other->Slot + Other->Latency; | 
 |         break; | 
 |       } else if (Other->IsCall || isWeakDependency(Other, NI)) { | 
 |         Slot = Other->Slot; | 
 |         break; | 
 |       } | 
 |     } | 
 |      | 
 |     // If independent of others (or first entry) | 
 |     if (Slot == NotFound) Slot = 0; | 
 |      | 
 |     // Find a slot where the needed resources are available | 
 |     if (NI->StageBegin != NI->StageEnd) | 
 |       Slot = Tally.FindAndReserve(Slot, NI->StageBegin, NI->StageEnd); | 
 |        | 
 |     // Set node slot | 
 |     NI->Slot = Slot; | 
 |      | 
 |     // Insert sort based on slot | 
 |     j = i; | 
 |     for (; 0 < j--;) { | 
 |       // Get prior instruction | 
 |       NodeInfo *Other = Ordering[j]; | 
 |       // Should we look further | 
 |       if (Slot >= Other->Slot) break; | 
 |       // Shuffle other into ordering | 
 |       Ordering[j + 1] = Other; | 
 |     } | 
 |     // Insert node in proper slot | 
 |     if (j != i) Ordering[j + 1] = NI; | 
 |   } | 
 | } | 
 |  | 
 | /// Schedule - Order nodes according to selected style. | 
 | /// | 
 | void ScheduleDAGSimple::Schedule() { | 
 |   // Test to see if scheduling should occur | 
 |   bool ShouldSchedule = NodeCount > 3 && Heuristic != noScheduling; | 
 |   // Don't waste time if is only entry and return | 
 |   if (ShouldSchedule) { | 
 |     // Get latency and resource requirements | 
 |     GatherSchedulingInfo(); | 
 |   } else if (HasGroups) { | 
 |     // Make sure all the groups have dominators | 
 |     FakeGroupDominators(); | 
 |   } | 
 |  | 
 |   // Breadth first walk of DAG | 
 |   VisitAll(); | 
 |  | 
 | #ifndef NDEBUG | 
 |   static unsigned Count = 0; | 
 |   Count++; | 
 |   for (unsigned i = 0, N = Ordering.size(); i < N; i++) { | 
 |     NodeInfo *NI = Ordering[i]; | 
 |     NI->Preorder = i; | 
 |   } | 
 | #endif   | 
 |    | 
 |   // Don't waste time if is only entry and return | 
 |   if (ShouldSchedule) { | 
 |     // Push back long instructions and critical path | 
 |     ScheduleBackward(); | 
 |      | 
 |     // Pack instructions to maximize resource utilization | 
 |     ScheduleForward(); | 
 |   } | 
 |    | 
 |   DEBUG(printChanges(Count)); | 
 |    | 
 |   // Emit in scheduled order | 
 |   EmitAll(); | 
 | } | 
 |  | 
 |  | 
 | /// createSimpleDAGScheduler - This creates a simple two pass instruction | 
 | /// scheduler. | 
 | llvm::ScheduleDAG* llvm::createSimpleDAGScheduler(SchedHeuristics Heuristic, | 
 |                                                   SelectionDAG &DAG, | 
 |                                                   MachineBasicBlock *BB) { | 
 |   return new ScheduleDAGSimple(Heuristic, DAG, BB,  DAG.getTarget()); | 
 | } |