Mark all calls as "could throw", when exceptions are enabled. Emit necessary LP info...
[oota-llvm.git] / lib / CodeGen / SelectionDAG / ScheduleDAGSimple.cpp
index b22eae499a92cb8c6bb106c5f8dfcdf425c5bc60..c6187f1109f9c950dc3610c721e6d06e87190709 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #define DEBUG_TYPE "sched"
+#include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/ScheduleDAG.h"
+#include "llvm/CodeGen/SchedulerRegistry.h"
 #include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/CodeGen/SSARegMap.h"
+#include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
-#include <iostream>
-#include <ios>
+#include "llvm/Support/Compiler.h"
 #include <algorithm>
 using namespace llvm;
 
 namespace {
-  // Style of scheduling to use.
-  enum ScheduleChoices {
-    noScheduling,
-    simpleScheduling,
-    simpleNoItinScheduling
-  };
-} // namespace
 
-cl::opt<ScheduleChoices> ScheduleStyle("sched",
-  cl::desc("Choose scheduling style"),
-  cl::init(noScheduling),
-  cl::values(
-    clEnumValN(noScheduling, "none",
-              "Trivial emission with no analysis"),
-    clEnumValN(simpleScheduling, "simple",
-              "Minimize critical path and maximize processor utilization"),
-    clEnumValN(simpleNoItinScheduling, "simple-noitin",
-              "Same as simple except using generic latency"),
-   clEnumValEnd));
+static RegisterScheduler
+  bfsDAGScheduler("none", "  No scheduling: breadth first sequencing",
+                  createBFS_DAGScheduler);
+static RegisterScheduler
+  simpleDAGScheduler("simple",
+                     "  Simple two pass scheduling: minimize critical path "
+                     "and maximize processor utilization",
+                      createSimpleDAGScheduler);
+static RegisterScheduler
+  noitinDAGScheduler("simple-noitin",
+                     "  Simple two pass scheduling: Same as simple "
+                     "except using generic latency",
+                     createNoItinsDAGScheduler);
+                     
+class NodeInfo;
+typedef NodeInfo *NodeInfoPtr;
+typedef std::vector<NodeInfoPtr>           NIVector;
+typedef std::vector<NodeInfoPtr>::iterator NIIterator;
+
+//===--------------------------------------------------------------------===//
+///
+/// Node group -  This struct is used to manage flagged node groups.
+///
+class NodeGroup {
+public:
+  NodeGroup     *Next;
+private:
+  NIVector      Members;                // Group member nodes
+  NodeInfo      *Dominator;             // Node with highest latency
+  unsigned      Latency;                // Total latency of the group
+  int           Pending;                // Number of visits pending before
+                                        // adding to order  
+
+public:
+  // Ctor.
+  NodeGroup() : Next(NULL), Dominator(NULL), Pending(0) {}
+
+  // Accessors
+  inline void setDominator(NodeInfo *D) { Dominator = D; }
+  inline NodeInfo *getTop() { return Members.front(); }
+  inline NodeInfo *getBottom() { return Members.back(); }
+  inline NodeInfo *getDominator() { return Dominator; }
+  inline void setLatency(unsigned L) { Latency = L; }
+  inline unsigned getLatency() { return Latency; }
+  inline int getPending() const { return Pending; }
+  inline void setPending(int P)  { Pending = P; }
+  inline int addPending(int I)  { return Pending += I; }
+
+  // Pass thru
+  inline bool group_empty() { return Members.empty(); }
+  inline NIIterator group_begin() { return Members.begin(); }
+  inline NIIterator group_end() { return Members.end(); }
+  inline void group_push_back(const NodeInfoPtr &NI) {
+    Members.push_back(NI);
+  }
+  inline NIIterator group_insert(NIIterator Pos, const NodeInfoPtr &NI) {
+    return Members.insert(Pos, NI);
+  }
+  inline void group_insert(NIIterator Pos, NIIterator First,
+                           NIIterator Last) {
+    Members.insert(Pos, First, Last);
+  }
+
+  static void Add(NodeInfo *D, NodeInfo *U);
+};
+
+//===--------------------------------------------------------------------===//
+///
+/// NodeInfo - This struct tracks information used to schedule the a node.
+///
+class NodeInfo {
+private:
+  int           Pending;                // Number of visits pending before
+                                        // adding to order
+public:
+  SDNode        *Node;                  // DAG node
+  InstrStage    *StageBegin;            // First stage in itinerary
+  InstrStage    *StageEnd;              // Last+1 stage in itinerary
+  unsigned      Latency;                // Total cycles to complete instr
+  bool          IsCall : 1;             // Is function call
+  bool          IsLoad : 1;             // Is memory load
+  bool          IsStore : 1;            // Is memory store
+  unsigned      Slot;                   // Node's time slot
+  NodeGroup     *Group;                 // Grouping information
+#ifndef NDEBUG
+  unsigned      Preorder;               // Index before scheduling
+#endif
+
+  // Ctor.
+  NodeInfo(SDNode *N = NULL)
+    : Pending(0)
+    , Node(N)
+    , StageBegin(NULL)
+    , StageEnd(NULL)
+    , Latency(0)
+    , IsCall(false)
+    , Slot(0)
+    , Group(NULL)
+#ifndef NDEBUG
+    , Preorder(0)
+#endif
+  {}
+
+  // Accessors
+  inline bool isInGroup() const {
+    assert(!Group || !Group->group_empty() && "Group with no members");
+    return Group != NULL;
+  }
+  inline bool isGroupDominator() const {
+    return isInGroup() && Group->getDominator() == this;
+  }
+  inline int getPending() const {
+    return Group ? Group->getPending() : Pending;
+  }
+  inline void setPending(int P) {
+    if (Group) Group->setPending(P);
+    else       Pending = P;
+  }
+  inline int addPending(int I) {
+    if (Group) return Group->addPending(I);
+    else       return Pending += I;
+  }
+};
+
+//===--------------------------------------------------------------------===//
+///
+/// NodeGroupIterator - Iterates over all the nodes indicated by the node
+/// info. If the node is in a group then iterate over the members of the
+/// group, otherwise just the node info.
+///
+class NodeGroupIterator {
+private:
+  NodeInfo   *NI;                       // Node info
+  NIIterator NGI;                       // Node group iterator
+  NIIterator NGE;                       // Node group iterator end
+
+public:
+  // Ctor.
+  NodeGroupIterator(NodeInfo *N) : NI(N) {
+    // If the node is in a group then set up the group iterator.  Otherwise
+    // the group iterators will trip first time out.
+    if (N->isInGroup()) {
+      // get Group
+      NodeGroup *Group = NI->Group;
+      NGI = Group->group_begin();
+      NGE = Group->group_end();
+      // Prevent this node from being used (will be in members list
+      NI = NULL;
+    }
+  }
+
+  /// next - Return the next node info, otherwise NULL.
+  ///
+  NodeInfo *next() {
+    // If members list
+    if (NGI != NGE) return *NGI++;
+    // Use node as the result (may be NULL)
+    NodeInfo *Result = NI;
+    // Only use once
+    NI = NULL;
+    // Return node or NULL
+    return Result;
+  }
+};
+//===--------------------------------------------------------------------===//
+
+
+//===--------------------------------------------------------------------===//
+///
+/// NodeGroupOpIterator - Iterates over all the operands of a node.  If the
+/// node is a member of a group, this iterates over all the operands of all
+/// the members of the group.
+///
+class NodeGroupOpIterator {
+private:
+  NodeInfo            *NI;              // Node containing operands
+  NodeGroupIterator   GI;               // Node group iterator
+  SDNode::op_iterator OI;               // Operand iterator
+  SDNode::op_iterator OE;               // Operand iterator end
+
+  /// CheckNode - Test if node has more operands.  If not get the next node
+  /// skipping over nodes that have no operands.
+  void CheckNode() {
+    // Only if operands are exhausted first
+    while (OI == OE) {
+      // Get next node info
+      NodeInfo *NI = GI.next();
+      // Exit if nodes are exhausted
+      if (!NI) return;
+      // Get node itself
+      SDNode *Node = NI->Node;
+      // Set up the operand iterators
+      OI = Node->op_begin();
+      OE = Node->op_end();
+    }
+  }
+
+public:
+  // Ctor.
+  NodeGroupOpIterator(NodeInfo *N)
+    : NI(N), GI(N), OI(SDNode::op_iterator()), OE(SDNode::op_iterator()) {}
+
+  /// isEnd - Returns true when not more operands are available.
+  ///
+  inline bool isEnd() { CheckNode(); return OI == OE; }
+
+  /// next - Returns the next available operand.
+  ///
+  inline SDOperand next() {
+    assert(OI != OE &&
+           "Not checking for end of NodeGroupOpIterator correctly");
+    return *OI++;
+  }
+};
 
 
-namespace {
 //===----------------------------------------------------------------------===//
 ///
 /// BitsIterator - Provides iteration through individual bits in a bit vector.
@@ -80,7 +277,7 @@ public:
 /// 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 
+/// available.  An assumption is made that the tally is large enough to schedule
 /// all current instructions (asserts otherwise.)
 ///
 template<class T>
@@ -91,9 +288,9 @@ private:
                                         // Tally iterator 
   
   /// SlotsAvailable - Returns true if all units are available.
-       ///
+  ///
   bool SlotsAvailable(Iter Begin, unsigned N, unsigned ResourceSet,
-                                              unsigned &Resource) {
+                      unsigned &Resource) {
     assert(N && "Must check availability with N != 0");
     // Determine end of interval
     Iter End = Begin + N;
@@ -121,23 +318,23 @@ private:
     Resource = 0;
     return false;
   }
-       
-       /// RetrySlot - Finds a good candidate slot to retry search.
+  
+  /// 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;
-       }
+    
+    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.
@@ -180,7 +377,7 @@ private:
       // 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);
+      Cursor = RetrySlot(Cursor + 1, StageBegin->Cycles, StageBegin->Units);
     }
   }
   
@@ -194,13 +391,13 @@ public:
   // 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();
+                          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;
   }
 
@@ -210,53 +407,93 @@ public:
 ///
 /// ScheduleDAGSimple - Simple two pass scheduler.
 ///
-class ScheduleDAGSimple : public ScheduleDAG {
+class VISIBILITY_HIDDEN ScheduleDAGSimple : public ScheduleDAG {
 private:
+  bool NoSched;                         // Just do a BFS schedule, nothing fancy
+  bool NoItins;                         // Don't use itineraries?
+  ResourceTally<unsigned> Tally;        // Resource usage tally
+  unsigned NSlots;                      // Total latency
+  static const unsigned NotFound = ~0U; // Search marker
+
   unsigned NodeCount;                   // Number of nodes in DAG
+  std::map<SDNode *, NodeInfo *> Map;   // Map nodes to info
   bool HasGroups;                       // True if there are any groups
   NodeInfo *Info;                       // Info for nodes being scheduled
   NIVector Ordering;                    // Emit ordering of nodes
-  ResourceTally<unsigned> Tally;        // Resource usage tally
-  unsigned NSlots;                      // Total latency
-  static const unsigned NotFound = ~0U; // Search marker
+  NodeGroup *HeadNG, *TailNG;           // Keep track of allocated NodeGroups
   
 public:
 
   // Ctor.
-  ScheduleDAGSimple(SelectionDAG &dag, MachineBasicBlock *bb,
-                    const TargetMachine &tm)
-    : ScheduleDAG(dag, bb, tm),
-      NodeCount(0), HasGroups(false), Info(NULL), Tally(), NSlots(0) {
+  ScheduleDAGSimple(bool noSched, bool noItins, SelectionDAG &dag,
+                    MachineBasicBlock *bb, const TargetMachine &tm)
+    : ScheduleDAG(dag, bb, tm), NoSched(noSched), NoItins(noItins), NSlots(0),
+    NodeCount(0), HasGroups(false), Info(NULL), HeadNG(NULL), TailNG(NULL) {
     assert(&TII && "Target doesn't provide instr info?");
     assert(&MRI && "Target doesn't provide register info?");
   }
 
-  virtual ~ScheduleDAGSimple() {};
+  virtual ~ScheduleDAGSimple() {
+    if (Info)
+      delete[] Info;
+    
+    NodeGroup *NG = HeadNG;
+    while (NG) {
+      NodeGroup *NextSU = NG->Next;
+      delete NG;
+      NG = NextSU;
+    }
+  }
 
+  void Schedule();
+
+  /// getNI - Returns the node info for the specified node.
+  ///
+  NodeInfo *getNI(SDNode *Node) { return Map[Node]; }
+  
 private:
-  static bool isFlagDefiner(SDNode *A);
-  static bool isFlagUser(SDNode *A);
   static bool isDefiner(NodeInfo *A, NodeInfo *B);
-  static bool isPassiveNode(SDNode *Node);
   void IncludeNode(NodeInfo *NI);
   void VisitAll();
-  void Schedule();
-  void IdentifyGroups();
   void GatherSchedulingInfo();
   void FakeGroupDominators(); 
-  void PrepareNodeInfo();
   bool isStrongDependency(NodeInfo *A, NodeInfo *B);
   bool isWeakDependency(NodeInfo *A, NodeInfo *B);
   void ScheduleBackward();
   void ScheduleForward();
+  
+  void AddToGroup(NodeInfo *D, NodeInfo *U);
+  /// PrepareNodeInfo - Set up the basic minimum node info for scheduling.
+  /// 
+  void PrepareNodeInfo();
+  
+  /// IdentifyGroups - Put flagged nodes into groups.
+  ///
+  void IdentifyGroups();
+  
+  /// print - Print ordering to specified output stream.
+  ///
+  void print(std::ostream &O) const;
+  void print(std::ostream *O) const { if (O) print(*O); }
+  
+  void dump(const char *tag) const;
+  
+  virtual void dump() const;
+  
+  /// EmitAll - Emit all nodes in schedule sorted order.
+  ///
   void EmitAll();
 
-  void printChanges(unsigned Index);
-  void printSI(std::ostream &O, NodeInfo *NI) const;
-  void print(std::ostream &O) const;
+  /// printNI - Print node info.
+  ///
+  void printNI(std::ostream &O, NodeInfo *NI) const;
+  void printNI(std::ostream *O, NodeInfo *NI) const { if (O) printNI(*O, NI); }
+  
+  /// printChanges - Hilight changes in order caused by scheduling.
+  ///
+  void printChanges(unsigned Index) const;
 };
 
-
 //===----------------------------------------------------------------------===//
 /// Special case itineraries.
 ///
@@ -268,25 +505,73 @@ enum {
   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
 
 //===----------------------------------------------------------------------===//
 
-} // namespace
+/// PrepareNodeInfo - Set up the basic minimum node info for scheduling.
+/// 
+void ScheduleDAGSimple::PrepareNodeInfo() {
+  // Allocate node information
+  Info = new NodeInfo[NodeCount];
+  
+  unsigned i = 0;
+  for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
+       E = DAG.allnodes_end(); I != E; ++I, ++i) {
+    // Fast reference to node schedule info
+    NodeInfo* NI = &Info[i];
+    // Set up map
+    Map[I] = NI;
+    // Set node
+    NI->Node = I;
+    // Set pending visit count
+    NI->setPending(I->use_size());
+  }
+}
 
-//===----------------------------------------------------------------------===//
+/// IdentifyGroups - Put flagged nodes into groups.
+///
+void ScheduleDAGSimple::IdentifyGroups() {
+  for (unsigned i = 0, N = NodeCount; i < N; i++) {
+    NodeInfo* NI = &Info[i];
+    SDNode *Node = NI->Node;
+    
+    // For each operand (in reverse to only look at flags)
+    for (unsigned N = Node->getNumOperands(); 0 < N--;) {
+      // Get operand
+      SDOperand Op = Node->getOperand(N);
+      // No more flags to walk
+      if (Op.getValueType() != MVT::Flag) break;
+      // Add to node group
+      AddToGroup(getNI(Op.Val), NI);
+      // Let everyone else know
+      HasGroups = true;
+    }
+  }
+}
 
+/// CountInternalUses - Returns the number of edges between the two nodes.
+///
+static unsigned CountInternalUses(NodeInfo *D, NodeInfo *U) {
+  unsigned N = 0;
+  for (unsigned M = U->Node->getNumOperands(); 0 < M--;) {
+    SDOperand Op = U->Node->getOperand(M);
+    if (Op.Val == D->Node) N++;
+  }
+  
+  return N;
+}
 
 //===----------------------------------------------------------------------===//
 /// Add - Adds a definer and user pair to a node group.
 ///
-void NodeGroup::Add(NodeInfo *D, NodeInfo *U) {
+void ScheduleDAGSimple::AddToGroup(NodeInfo *D, NodeInfo *U) {
   // Get current groups
   NodeGroup *DGroup = D->Group;
   NodeGroup *UGroup = U->Group;
@@ -341,37 +626,145 @@ void NodeGroup::Add(NodeInfo *D, NodeInfo *U) {
                        CountInternalUses(D, U));
     DGroup->group_push_back(D);
     DGroup->group_push_back(U);
+    
+    if (HeadNG == NULL)
+      HeadNG = DGroup;
+    if (TailNG != NULL)
+      TailNG->Next = DGroup;
+    TailNG = DGroup;
   }
 }
 
-/// CountInternalUses - Returns the number of edges between the two nodes.
+
+/// print - Print ordering to specified output stream.
 ///
-unsigned NodeGroup::CountInternalUses(NodeInfo *D, NodeInfo *U) {
-  unsigned N = 0;
-  for (unsigned M = U->Node->getNumOperands(); 0 < M--;) {
-    SDOperand Op = U->Node->getOperand(M);
-    if (Op.Val == D->Node) N++;
+void ScheduleDAGSimple::print(std::ostream &O) const {
+#ifndef NDEBUG
+  O << "Ordering\n";
+  for (unsigned i = 0, N = Ordering.size(); i < N; i++) {
+    NodeInfo *NI = Ordering[i];
+    printNI(O, NI);
+    O << "\n";
+    if (NI->isGroupDominator()) {
+      NodeGroup *Group = NI->Group;
+      for (NIIterator NII = Group->group_begin(), E = Group->group_end();
+           NII != E; NII++) {
+        O << "    ";
+        printNI(O, *NII);
+        O << "\n";
+      }
+    }
   }
+#endif
+}
 
-  return N;
+void ScheduleDAGSimple::dump(const char *tag) const {
+  cerr << tag; dump();
 }
-//===----------------------------------------------------------------------===//
 
+void ScheduleDAGSimple::dump() const {
+  print(cerr);
+}
+
+
+/// EmitAll - Emit all nodes in schedule sorted order.
+///
+void ScheduleDAGSimple::EmitAll() {
+  // If this is the first basic block in the function, and if it has live ins
+  // that need to be copied into vregs, emit the copies into the top of the
+  // block before emitting the code for the block.
+  MachineFunction &MF = DAG.getMachineFunction();
+  if (&MF.front() == BB && MF.livein_begin() != MF.livein_end()) {
+    for (MachineFunction::livein_iterator LI = MF.livein_begin(),
+         E = MF.livein_end(); LI != E; ++LI)
+      if (LI->second)
+        MRI->copyRegToReg(*MF.begin(), MF.begin()->end(), LI->second,
+                          LI->first, RegMap->getRegClass(LI->second));
+  }
+  
+  DenseMap<SDNode*, unsigned> VRBaseMap;
+  
+  // For each node in the ordering
+  for (unsigned i = 0, N = Ordering.size(); i < N; i++) {
+    // Get the scheduling info
+    NodeInfo *NI = Ordering[i];
+    if (NI->isInGroup()) {
+      NodeGroupIterator NGI(Ordering[i]);
+      while (NodeInfo *NI = NGI.next()) EmitNode(NI->Node, VRBaseMap);
+    } else {
+      EmitNode(NI->Node, VRBaseMap);
+    }
+  }
+}
 
-//===----------------------------------------------------------------------===//
 /// isFlagDefiner - Returns true if the node defines a flag result.
-bool ScheduleDAGSimple::isFlagDefiner(SDNode *A) {
+static bool isFlagDefiner(SDNode *A) {
   unsigned N = A->getNumValues();
   return N && A->getValueType(N - 1) == MVT::Flag;
 }
 
 /// isFlagUser - Returns true if the node uses a flag result.
 ///
-bool ScheduleDAGSimple::isFlagUser(SDNode *A) {
+static bool isFlagUser(SDNode *A) {
   unsigned N = A->getNumOperands();
   return N && A->getOperand(N - 1).getValueType() == MVT::Flag;
 }
 
+/// printNI - Print node info.
+///
+void ScheduleDAGSimple::printNI(std::ostream &O, NodeInfo *NI) const {
+#ifndef NDEBUG
+  SDNode *Node = NI->Node;
+  O << " "
+    << std::hex << Node << std::dec
+    << ", Lat=" << NI->Latency
+    << ", Slot=" << NI->Slot
+    << ", ARITY=(" << Node->getNumOperands() << ","
+    << Node->getNumValues() << ")"
+    << " " << Node->getOperationName(&DAG);
+  if (isFlagDefiner(Node)) O << "<#";
+  if (isFlagUser(Node)) O << ">#";
+#endif
+}
+
+/// printChanges - Hilight changes in order caused by scheduling.
+///
+void ScheduleDAGSimple::printChanges(unsigned Index) const {
+#ifndef NDEBUG
+  // Get the ordered node count
+  unsigned N = Ordering.size();
+  // Determine if any changes
+  unsigned i = 0;
+  for (; i < N; i++) {
+    NodeInfo *NI = Ordering[i];
+    if (NI->Preorder != i) break;
+  }
+  
+  if (i < N) {
+    cerr << Index << ". New Ordering\n";
+    
+    for (i = 0; i < N; i++) {
+      NodeInfo *NI = Ordering[i];
+      cerr << "  " << NI->Preorder << ". ";
+      printNI(cerr, NI);
+      cerr << "\n";
+      if (NI->isGroupDominator()) {
+        NodeGroup *Group = NI->Group;
+        for (NIIterator NII = Group->group_begin(), E = Group->group_end();
+             NII != E; NII++) {
+          cerr << "          ";
+          printNI(cerr, *NII);
+          cerr << "\n";
+        }
+      }
+    }
+  } else {
+    cerr << Index << ". No Changes\n";
+  }
+#endif
+}
+
+//===----------------------------------------------------------------------===//
 /// isDefiner - Return true if node A is a definer for B.
 ///
 bool ScheduleDAGSimple::isDefiner(NodeInfo *A, NodeInfo *B) {
@@ -391,19 +784,6 @@ bool ScheduleDAGSimple::isDefiner(NodeInfo *A, NodeInfo *B) {
   return false;
 }
 
-/// isPassiveNode - Return true if the node is a non-scheduled leaf.
-///
-bool ScheduleDAGSimple::isPassiveNode(SDNode *Node) {
-  if (isa<ConstantSDNode>(Node))       return true;
-  if (isa<RegisterSDNode>(Node))       return true;
-  if (isa<GlobalAddressSDNode>(Node))  return true;
-  if (isa<BasicBlockSDNode>(Node))     return true;
-  if (isa<FrameIndexSDNode>(Node))     return true;
-  if (isa<ConstantPoolSDNode>(Node))   return true;
-  if (isa<ExternalSymbolSDNode>(Node)) return true;
-  return false;
-}
-
 /// IncludeNode - Add node to NodeInfo vector.
 ///
 void ScheduleDAGSimple::IncludeNode(NodeInfo *NI) {
@@ -432,67 +812,11 @@ void ScheduleDAGSimple::IncludeNode(NodeInfo *NI) {
   NI->setPending(Count);
 }
 
-/// 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());
-}
-
-/// IdentifyGroups - Put flagged nodes into groups.
-///
-void ScheduleDAGSimple::IdentifyGroups() {
-  for (unsigned i = 0, N = NodeCount; i < N; i++) {
-    NodeInfo* NI = &Info[i];
-    SDNode *Node = NI->Node;
-
-    // For each operand (in reverse to only look at flags)
-    for (unsigned N = Node->getNumOperands(); 0 < N--;) {
-      // Get operand
-      SDOperand Op = Node->getOperand(N);
-      // No more flags to walk
-      if (Op.getValueType() != MVT::Flag) break;
-      // Add to node group
-      NodeGroup::Add(getNI(Op.Val), NI);
-      // Let evryone else know
-      HasGroups = true;
-    }
-  }
-}
-
 /// GatherSchedulingInfo - Get latency and resource information about each node.
 ///
 void ScheduleDAGSimple::GatherSchedulingInfo() {
   // Get instruction itineraries for the target
-  const InstrItineraryData InstrItins = TM.getInstrItineraryData();
+  const InstrItineraryData &InstrItins = TM.getInstrItineraryData();
   
   // For each node
   for (unsigned i = 0, N = NodeCount; i < N; i++) {
@@ -501,7 +825,7 @@ void ScheduleDAGSimple::GatherSchedulingInfo() {
     SDNode *Node = NI->Node;
     
     // If there are itineraries and it is a machine instruction
-    if (InstrItins.isEmpty() || ScheduleStyle == simpleNoItinScheduling) {
+    if (InstrItins.isEmpty() || NoItins) {
       // If machine opcode
       if (Node->isTargetOpcode()) {
         // Get return type to guess which processing unit 
@@ -572,6 +896,41 @@ void ScheduleDAGSimple::GatherSchedulingInfo() {
   }
 }
 
+/// 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() {
@@ -588,26 +947,6 @@ void ScheduleDAGSimple::FakeGroupDominators() {
   }
 }
 
-/// PrepareNodeInfo - Set up the basic minimum node info for scheduling.
-/// 
-void ScheduleDAGSimple::PrepareNodeInfo() {
-  // Allocate node information
-  Info = new NodeInfo[NodeCount];
-
-  unsigned i = 0;
-  for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
-       E = DAG.allnodes_end(); I != E; ++I, ++i) {
-    // Fast reference to node schedule info
-    NodeInfo* NI = &Info[i];
-    // Set up map
-    Map[I] = NI;
-    // Set node
-    NI->Node = I;
-    // Set pending visit count
-    NI->setPending(I->use_size());
-  }
-}
-
 /// 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) {
@@ -742,34 +1081,19 @@ void ScheduleDAGSimple::ScheduleForward() {
   }
 }
 
-/// EmitAll - Emit all nodes in schedule sorted order.
-///
-void ScheduleDAGSimple::EmitAll() {
-  // For each node in the ordering
-  for (unsigned i = 0, N = Ordering.size(); i < N; i++) {
-    // Get the scheduling info
-    NodeInfo *NI = Ordering[i];
-    if (NI->isInGroup()) {
-      NodeGroupIterator NGI(Ordering[i]);
-      while (NodeInfo *NI = NGI.next()) EmitNode(NI);
-    } else {
-      EmitNode(NI);
-    }
-  }
-}
-
 /// Schedule - Order nodes according to selected style.
 ///
 void ScheduleDAGSimple::Schedule() {
   // Number the nodes
   NodeCount = std::distance(DAG.allnodes_begin(), DAG.allnodes_end());
-  // Test to see if scheduling should occur
-  bool ShouldSchedule = NodeCount > 3 && ScheduleStyle != noScheduling;
+
   // Set up minimum info for scheduling
   PrepareNodeInfo();
   // Construct node groups for flagged nodes
   IdentifyGroups();
-
+  
+  // Test to see if scheduling should occur
+  bool ShouldSchedule = NodeCount > 3 && !NoSched;
   // Don't waste time if is only entry and return
   if (ShouldSchedule) {
     // Get latency and resource requirements
@@ -806,86 +1130,27 @@ void ScheduleDAGSimple::Schedule() {
   EmitAll();
 }
 
-/// printChanges - Hilight changes in order caused by scheduling.
-///
-void ScheduleDAGSimple::printChanges(unsigned Index) {
-#ifndef NDEBUG
-  // Get the ordered node count
-  unsigned N = Ordering.size();
-  // Determine if any changes
-  unsigned i = 0;
-  for (; i < N; i++) {
-    NodeInfo *NI = Ordering[i];
-    if (NI->Preorder != i) break;
-  }
-  
-  if (i < N) {
-    std::cerr << Index << ". New Ordering\n";
-    
-    for (i = 0; i < N; i++) {
-      NodeInfo *NI = Ordering[i];
-      std::cerr << "  " << NI->Preorder << ". ";
-      printSI(std::cerr, NI);
-      std::cerr << "\n";
-      if (NI->isGroupDominator()) {
-        NodeGroup *Group = NI->Group;
-        for (NIIterator NII = Group->group_begin(), E = Group->group_end();
-             NII != E; NII++) {
-          std::cerr << "          ";
-          printSI(std::cerr, *NII);
-          std::cerr << "\n";
-        }
-      }
-    }
-  } else {
-    std::cerr << Index << ". No Changes\n";
-  }
-#endif
-}
 
-/// printSI - Print schedule info.
-///
-void ScheduleDAGSimple::printSI(std::ostream &O, NodeInfo *NI) const {
-#ifndef NDEBUG
-  SDNode *Node = NI->Node;
-  O << " "
-    << std::hex << Node << std::dec
-    << ", Lat=" << NI->Latency
-    << ", Slot=" << NI->Slot
-    << ", ARITY=(" << Node->getNumOperands() << ","
-                   << Node->getNumValues() << ")"
-    << " " << Node->getOperationName(&DAG);
-  if (isFlagDefiner(Node)) O << "<#";
-  if (isFlagUser(Node)) O << ">#";
-#endif
+/// createSimpleDAGScheduler - This creates a simple two pass instruction
+/// scheduler using instruction itinerary.
+llvm::ScheduleDAG* llvm::createSimpleDAGScheduler(SelectionDAGISel *IS,
+                                                  SelectionDAG *DAG,
+                                                  MachineBasicBlock *BB) {
+  return new ScheduleDAGSimple(false, false, *DAG, BB, DAG->getTarget());
 }
 
-/// print - Print ordering to specified output stream.
-///
-void ScheduleDAGSimple::print(std::ostream &O) const {
-#ifndef NDEBUG
-  using namespace std;
-  O << "Ordering\n";
-  for (unsigned i = 0, N = Ordering.size(); i < N; i++) {
-    NodeInfo *NI = Ordering[i];
-    printSI(O, NI);
-    O << "\n";
-    if (NI->isGroupDominator()) {
-      NodeGroup *Group = NI->Group;
-      for (NIIterator NII = Group->group_begin(), E = Group->group_end();
-           NII != E; NII++) {
-        O << "    ";
-        printSI(O, *NII);
-        O << "\n";
-      }
-    }
-  }
-#endif
+/// createNoItinsDAGScheduler - This creates a simple two pass instruction
+/// scheduler without using instruction itinerary.
+llvm::ScheduleDAG* llvm::createNoItinsDAGScheduler(SelectionDAGISel *IS,
+                                                   SelectionDAG *DAG,
+                                                   MachineBasicBlock *BB) {
+  return new ScheduleDAGSimple(false, true, *DAG, BB, DAG->getTarget());
 }
 
-/// createSimpleDAGScheduler - This creates a simple two pass instruction
+/// createBFS_DAGScheduler - This creates a simple breadth first instruction
 /// scheduler.
-llvm::ScheduleDAG* llvm::createSimpleDAGScheduler(SelectionDAG &DAG,
-                                                  MachineBasicBlock *BB) {
-  return new ScheduleDAGSimple(DAG, BB, DAG.getTarget());
+llvm::ScheduleDAG* llvm::createBFS_DAGScheduler(SelectionDAGISel *IS,
+                                                SelectionDAG *DAG,
+                                                MachineBasicBlock *BB) {
+  return new ScheduleDAGSimple(true, false, *DAG, BB,  DAG->getTarget());
 }