move some simple scheduler methods into the simple scheduler
[oota-llvm.git] / include / llvm / CodeGen / ScheduleDAG.h
index 3401c7d812249d6d13e3aa7c51ff66ca74937aae..49acf41818c53e67fca0318308a135898ee97c87 100644 (file)
@@ -34,21 +34,65 @@ namespace llvm {
   typedef std::vector<NodeInfoPtr>           NIVector;
   typedef std::vector<NodeInfoPtr>::iterator NIIterator;
 
-
   // Scheduling heuristics
   enum SchedHeuristics {
-    noScheduling,           // No scheduling, emit breath first sequence.
+    defaultScheduling,      // Let the target specify its preference.
+    noScheduling,           // No scheduling, emit breadth first sequence.
     simpleScheduling,       // Two pass, min. critical path, max. utilization.
     simpleNoItinScheduling, // Same as above exact using generic latency.
     listSchedulingBURR,     // Bottom up reg reduction list scheduling.
+    listSchedulingTD        // Top-down list scheduler.
+  };
+  
+  /// HazardRecognizer - This determines whether or not an instruction can be
+  /// issued this cycle, and whether or not a noop needs to be inserted to handle
+  /// the hazard.
+  class HazardRecognizer {
+  public:
+    virtual ~HazardRecognizer();
+    
+    enum HazardType {
+      NoHazard,      // This instruction can be emitted at this cycle.
+      Hazard,        // This instruction can't be emitted at this cycle.
+      NoopHazard,    // This instruction can't be emitted, and needs noops.
+    };
+    
+    /// getHazardType - Return the hazard type of emitting this node.  There are
+    /// three possible results.  Either:
+    ///  * NoHazard: it is legal to issue this instruction on this cycle.
+    ///  * Hazard: issuing this instruction would stall the machine.  If some
+    ///     other instruction is available, issue it first.
+    ///  * NoopHazard: issuing this instruction would break the program.  If
+    ///     some other instruction can be issued, do so, otherwise issue a noop.
+    virtual HazardType getHazardType(SDNode *Node) {
+      return NoHazard;
+    }
+    
+    /// EmitInstruction - This callback is invoked when an instruction is
+    /// emitted, to advance the hazard state.
+    virtual void EmitInstruction(SDNode *Node) {
+    }
+    
+    /// AdvanceCycle - This callback is invoked when no instructions can be
+    /// issued on this cycle without a hazard.  This should increment the
+    /// internal state of the hazard recognizer so that previously "Hazard"
+    /// instructions will now not be hazards.
+    virtual void AdvanceCycle() {
+    }
+    
+    /// EmitNoop - This callback is invoked when a noop was added to the
+    /// instruction stream.
+    virtual void EmitNoop() {
+    }
   };
-
 
   //===--------------------------------------------------------------------===//
   ///
   /// 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
@@ -58,10 +102,12 @@ namespace llvm {
 
   public:
     // Ctor.
-    NodeGroup() : Dominator(NULL), Pending(0) {}
+    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; }
@@ -94,7 +140,7 @@ namespace llvm {
   class NodeInfo {
   private:
     int           Pending;                // Number of visits pending before
-    //    adding to order
+                                          // adding to order
   public:
     SDNode        *Node;                  // DAG node
     InstrStage    *StageBegin;            // First stage in itinerary
@@ -105,7 +151,6 @@ namespace llvm {
     bool          IsStore : 1;            // Is memory store
     unsigned      Slot;                   // Node's time slot
     NodeGroup     *Group;                 // Grouping information
-    unsigned      VRBase;                 // Virtual register base
 #ifndef NDEBUG
     unsigned      Preorder;               // Index before scheduling
 #endif
@@ -120,7 +165,6 @@ namespace llvm {
       , IsCall(false)
       , Slot(0)
       , Group(NULL)
-      , VRBase(0)
 #ifndef NDEBUG
       , Preorder(0)
 #endif
@@ -253,13 +297,24 @@ namespace llvm {
     bool HasGroups;                       // True if there are any groups
     NodeInfo *Info;                       // Info for nodes being scheduled
     NIVector Ordering;                    // Emit ordering of nodes
+    NodeGroup *HeadNG, *TailNG;           // Keep track of allocated NodeGroups
 
     ScheduleDAG(SchedHeuristics hstc, SelectionDAG &dag, MachineBasicBlock *bb,
                 const TargetMachine &tm)
-      : Heuristic(hstc), DAG(dag), BB(bb), TM(tm),
-        NodeCount(0), HasGroups(false), Info(NULL) {}
-
-    virtual ~ScheduleDAG() {};
+      : Heuristic(hstc), DAG(dag), BB(bb), TM(tm), NodeCount(0),
+        HasGroups(false), Info(NULL), HeadNG(NULL), TailNG(NULL) {}
+
+    virtual ~ScheduleDAG() {
+      if (Info)
+        delete[] Info;
+
+      NodeGroup *NG = HeadNG;
+      while (NG) {
+        NodeGroup *NextSU = NG->Next;
+        delete NG;
+        NG = NextSU;
+      }
+    };
 
     /// Run - perform scheduling.
     ///
@@ -269,17 +324,9 @@ namespace llvm {
     ///
     NodeInfo *getNI(SDNode *Node) { return Map[Node]; }
   
-    /// getVR - Returns the virtual register number of the node.
-    ///
-    unsigned getVR(SDOperand Op) {
-      NodeInfo *NI = getNI(Op.Val);
-      assert(NI->VRBase != 0 && "Node emitted out of order - late");
-      return NI->VRBase + Op.ResNo;
-    }
-
     /// isPassiveNode - Return true if the node is a non-scheduled leaf.
     ///
-    bool isPassiveNode(SDNode *Node) {
+    static bool isPassiveNode(SDNode *Node) {
       if (isa<ConstantSDNode>(Node))       return true;
       if (isa<RegisterSDNode>(Node))       return true;
       if (isa<GlobalAddressSDNode>(Node))  return true;
@@ -291,41 +338,24 @@ namespace llvm {
     }
 
     /// EmitNode - Generate machine code for an node and needed dependencies.
+    /// VRBaseMap contains, for each already emitted node, the first virtual
+    /// register number for the results of the node.
     ///
-    void EmitNode(NodeInfo *NI);
-
-    /// EmitAll - Emit all nodes in schedule sorted order.
+    void EmitNode(SDNode *Node, std::map<SDNode*, unsigned> &VRBaseMap);
+    
+    /// EmitNoop - Emit a noop instruction.
     ///
-    void EmitAll();
+    void EmitNoop();
+    
 
     /// Schedule - Order nodes according to selected style.
     ///
-    virtual void Schedule() {};
-
-    /// printNI - Print node info.
-    ///
-    void printNI(std::ostream &O, NodeInfo *NI) const;
-
-    /// printChanges - Hilight changes in order caused by scheduling.
-    ///
-    void printChanges(unsigned Index) const;
-
-    /// print - Print ordering to specified output stream.
-    ///
-    void print(std::ostream &O) const;
-
-    void dump(const char *tag) const;
-
-    void dump() const;
+    virtual void Schedule() {}
 
   private:
-    /// PrepareNodeInfo - Set up the basic minimum node info for scheduling.
-    /// 
-    void PrepareNodeInfo();
-
-    /// IdentifyGroups - Put flagged nodes into groups.
-    ///
-    void IdentifyGroups();
+    void AddOperand(MachineInstr *MI, SDOperand Op, unsigned IIOpNum,
+                    const TargetInstrDescriptor *II,
+                    std::map<SDNode*, unsigned> &VRBaseMap);
   };
 
   /// createSimpleDAGScheduler - This creates a simple two pass instruction
@@ -338,6 +368,13 @@ namespace llvm {
   /// reduction list scheduler.
   ScheduleDAG* createBURRListDAGScheduler(SelectionDAG &DAG,
                                           MachineBasicBlock *BB);
+  
+  /// createTDListDAGScheduler - This creates a top-down list scheduler with
+  /// the specified hazard recognizer.  This takes ownership of the hazard
+  /// recognizer and deletes it when done.
+  ScheduleDAG* createTDListDAGScheduler(SelectionDAG &DAG,
+                                        MachineBasicBlock *BB,
+                                        HazardRecognizer *HR);
 }
 
 #endif