//===- llvm/CodeGen/ScheduleDAG.h - Common Base Class -----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// \file Implements the ScheduleDAG class, which is used as the common base
/// class for instruction schedulers. This encapsulates the scheduling DAG,
/// which is shared between SelectionDAG and MachineInstr scheduling.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CODEGEN_SCHEDULEDAG_H
#define LLVM_CODEGEN_SCHEDULEDAG_H

#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
#include <cstddef>
#include <iterator>
#include <string>
#include <vector>

namespace llvm {

template<class Graph> class GraphWriter;
class LLVMTargetMachine;
class MachineFunction;
class MachineRegisterInfo;
class MCInstrDesc;
struct MCSchedClassDesc;
class SDNode;
class SUnit;
class ScheduleDAG;
class TargetInstrInfo;
class TargetRegisterClass;
class TargetRegisterInfo;

  /// Scheduling dependency. This represents one direction of an edge in the
  /// scheduling DAG.
  class SDep {
  public:
    /// These are the different kinds of scheduling dependencies.
    enum Kind {
      Data,        ///< Regular data dependence (aka true-dependence).
      Anti,        ///< A register anti-dependence (aka WAR).
      Output,      ///< A register output-dependence (aka WAW).
      Order        ///< Any other ordering dependency.
    };

    // Strong dependencies must be respected by the scheduler. Artificial
    // dependencies may be removed only if they are redundant with another
    // strong dependence.
    //
    // Weak dependencies may be violated by the scheduling strategy, but only if
    // the strategy can prove it is correct to do so.
    //
    // Strong OrderKinds must occur before "Weak".
    // Weak OrderKinds must occur after "Weak".
    enum OrderKind {
      Barrier,      ///< An unknown scheduling barrier.
      MayAliasMem,  ///< Nonvolatile load/Store instructions that may alias.
      MustAliasMem, ///< Nonvolatile load/Store instructions that must alias.
      Artificial,   ///< Arbitrary strong DAG edge (no real dependence).
      Weak,         ///< Arbitrary weak DAG edge.
      Cluster       ///< Weak DAG edge linking a chain of clustered instrs.
    };

  private:
    /// A pointer to the depending/depended-on SUnit, and an enum
    /// indicating the kind of the dependency.
    PointerIntPair<SUnit *, 2, Kind> Dep;

    /// A union discriminated by the dependence kind.
    union {
      /// For Data, Anti, and Output dependencies, the associated register. For
      /// Data dependencies that don't currently have a register/ assigned, this
      /// is set to zero.
      unsigned Reg;

      /// Additional information about Order dependencies.
      unsigned OrdKind; // enum OrderKind
    } Contents;

    /// The time associated with this edge. Often this is just the value of the
    /// Latency field of the predecessor, however advanced models may provide
    /// additional information about specific edges.
    unsigned Latency;

  public:
    /// Constructs a null SDep. This is only for use by container classes which
    /// require default constructors. SUnits may not/ have null SDep edges.
    SDep() : Dep(nullptr, Data) {}

    /// Constructs an SDep with the specified values.
    SDep(SUnit *S, Kind kind, unsigned Reg)
      : Dep(S, kind), Contents() {
      switch (kind) {
      default:
        llvm_unreachable("Reg given for non-register dependence!");
      case Anti:
      case Output:
        assert(Reg != 0 &&
               "SDep::Anti and SDep::Output must use a non-zero Reg!");
        Contents.Reg = Reg;
        Latency = 0;
        break;
      case Data:
        Contents.Reg = Reg;
        Latency = 1;
        break;
      }
    }

    SDep(SUnit *S, OrderKind kind)
      : Dep(S, Order), Contents(), Latency(0) {
      Contents.OrdKind = kind;
    }

    /// Returns true if the specified SDep is equivalent except for latency.
    bool overlaps(const SDep &Other) const;

    bool operator==(const SDep &Other) const {
      return overlaps(Other) && Latency == Other.Latency;
    }

    bool operator!=(const SDep &Other) const {
      return !operator==(Other);
    }

    /// Returns the latency value for this edge, which roughly means the
    /// minimum number of cycles that must elapse between the predecessor and
    /// the successor, given that they have this edge between them.
    unsigned getLatency() const {
      return Latency;
    }

    /// Sets the latency for this edge.
    void setLatency(unsigned Lat) {
      Latency = Lat;
    }

    //// Returns the SUnit to which this edge points.
    SUnit *getSUnit() const;

    //// Assigns the SUnit to which this edge points.
    void setSUnit(SUnit *SU);

    /// Returns an enum value representing the kind of the dependence.
    Kind getKind() const;

    /// Shorthand for getKind() != SDep::Data.
    bool isCtrl() const {
      return getKind() != Data;
    }

    /// Tests if this is an Order dependence between two memory accesses
    /// where both sides of the dependence access memory in non-volatile and
    /// fully modeled ways.
    bool isNormalMemory() const {
      return getKind() == Order && (Contents.OrdKind == MayAliasMem
                                    || Contents.OrdKind == MustAliasMem);
    }

    /// Tests if this is an Order dependence that is marked as a barrier.
    bool isBarrier() const {
      return getKind() == Order && Contents.OrdKind == Barrier;
    }

    /// Tests if this is could be any kind of memory dependence.
    bool isNormalMemoryOrBarrier() const {
      return (isNormalMemory() || isBarrier());
    }

    /// Tests if this is an Order dependence that is marked as
    /// "must alias", meaning that the SUnits at either end of the edge have a
    /// memory dependence on a known memory location.
    bool isMustAlias() const {
      return getKind() == Order && Contents.OrdKind == MustAliasMem;
    }

    /// Tests if this a weak dependence. Weak dependencies are considered DAG
    /// edges for height computation and other heuristics, but do not force
    /// ordering. Breaking a weak edge may require the scheduler to compensate,
    /// for example by inserting a copy.
    bool isWeak() const {
      return getKind() == Order && Contents.OrdKind >= Weak;
    }

    /// Tests if this is an Order dependence that is marked as
    /// "artificial", meaning it isn't necessary for correctness.
    bool isArtificial() const {
      return getKind() == Order && Contents.OrdKind == Artificial;
    }

    /// Tests if this is an Order dependence that is marked as "cluster",
    /// meaning it is artificial and wants to be adjacent.
    bool isCluster() const {
      return getKind() == Order && Contents.OrdKind == Cluster;
    }

    /// Tests if this is a Data dependence that is associated with a register.
    bool isAssignedRegDep() const {
      return getKind() == Data && Contents.Reg != 0;
    }

    /// Returns the register associated with this edge. This is only valid on
    /// Data, Anti, and Output edges. On Data edges, this value may be zero,
    /// meaning there is no associated register.
    unsigned getReg() const {
      assert((getKind() == Data || getKind() == Anti || getKind() == Output) &&
             "getReg called on non-register dependence edge!");
      return Contents.Reg;
    }

    /// Assigns the associated register for this edge. This is only valid on
    /// Data, Anti, and Output edges. On Anti and Output edges, this value must
    /// not be zero. On Data edges, the value may be zero, which would mean that
    /// no specific register is associated with this edge.
    void setReg(unsigned Reg) {
      assert((getKind() == Data || getKind() == Anti || getKind() == Output) &&
             "setReg called on non-register dependence edge!");
      assert((getKind() != Anti || Reg != 0) &&
             "SDep::Anti edge cannot use the zero register!");
      assert((getKind() != Output || Reg != 0) &&
             "SDep::Output edge cannot use the zero register!");
      Contents.Reg = Reg;
    }

    void dump(const TargetRegisterInfo *TRI = nullptr) const;
  };

  template <>
  struct isPodLike<SDep> { static const bool value = true; };

  /// Scheduling unit. This is a node in the scheduling DAG.
  class SUnit {
  private:
    enum : unsigned { BoundaryID = ~0u };

    SDNode *Node = nullptr;        ///< Representative node.
    MachineInstr *Instr = nullptr; ///< Alternatively, a MachineInstr.

  public:
    SUnit *OrigNode = nullptr; ///< If not this, the node from which this node
                               /// was cloned. (SD scheduling only)

    const MCSchedClassDesc *SchedClass =
        nullptr; ///< nullptr or resolved SchedClass.

    SmallVector<SDep, 4> Preds;  ///< All sunit predecessors.
    SmallVector<SDep, 4> Succs;  ///< All sunit successors.

    typedef SmallVectorImpl<SDep>::iterator pred_iterator;
    typedef SmallVectorImpl<SDep>::iterator succ_iterator;
    typedef SmallVectorImpl<SDep>::const_iterator const_pred_iterator;
    typedef SmallVectorImpl<SDep>::const_iterator const_succ_iterator;

    unsigned NodeNum = BoundaryID;     ///< Entry # of node in the node vector.
    unsigned NodeQueueId = 0;          ///< Queue id of node.
    unsigned NumPreds = 0;             ///< # of SDep::Data preds.
    unsigned NumSuccs = 0;             ///< # of SDep::Data sucss.
    unsigned NumPredsLeft = 0;         ///< # of preds not scheduled.
    unsigned NumSuccsLeft = 0;         ///< # of succs not scheduled.
    unsigned WeakPredsLeft = 0;        ///< # of weak preds not scheduled.
    unsigned WeakSuccsLeft = 0;        ///< # of weak succs not scheduled.
    unsigned short NumRegDefsLeft = 0; ///< # of reg defs with no scheduled use.
    unsigned short Latency = 0;        ///< Node latency.
    bool isVRegCycle      : 1;         ///< May use and def the same vreg.
    bool isCall           : 1;         ///< Is a function call.
    bool isCallOp         : 1;         ///< Is a function call operand.
    bool isTwoAddress     : 1;         ///< Is a two-address instruction.
    bool isCommutable     : 1;         ///< Is a commutable instruction.
    bool hasPhysRegUses   : 1;         ///< Has physreg uses.
    bool hasPhysRegDefs   : 1;         ///< Has physreg defs that are being used.
    bool hasPhysRegClobbers : 1;       ///< Has any physreg defs, used or not.
    bool isPending        : 1;         ///< True once pending.
    bool isAvailable      : 1;         ///< True once available.
    bool isScheduled      : 1;         ///< True once scheduled.
    bool isScheduleHigh   : 1;         ///< True if preferable to schedule high.
    bool isScheduleLow    : 1;         ///< True if preferable to schedule low.
    bool isCloned         : 1;         ///< True if this node has been cloned.
    bool isUnbuffered     : 1;         ///< Uses an unbuffered resource.
    bool hasReservedResource : 1;      ///< Uses a reserved resource.
    Sched::Preference SchedulingPref = Sched::None; ///< Scheduling preference.

  private:
    bool isDepthCurrent   : 1;         ///< True if Depth is current.
    bool isHeightCurrent  : 1;         ///< True if Height is current.
    unsigned Depth = 0;                ///< Node depth.
    unsigned Height = 0;               ///< Node height.

  public:
    unsigned TopReadyCycle = 0; ///< Cycle relative to start when node is ready.
    unsigned BotReadyCycle = 0; ///< Cycle relative to end when node is ready.

    const TargetRegisterClass *CopyDstRC =
        nullptr; ///< Is a special copy node if != nullptr.
    const TargetRegisterClass *CopySrcRC = nullptr;

    /// Constructs an SUnit for pre-regalloc scheduling to represent an
    /// SDNode and any nodes flagged to it.
    SUnit(SDNode *node, unsigned nodenum)
      : Node(node), NodeNum(nodenum), isVRegCycle(false), isCall(false),
        isCallOp(false), isTwoAddress(false), isCommutable(false),
        hasPhysRegUses(false), hasPhysRegDefs(false), hasPhysRegClobbers(false),
        isPending(false), isAvailable(false), isScheduled(false),
        isScheduleHigh(false), isScheduleLow(false), isCloned(false),
        isUnbuffered(false), hasReservedResource(false), isDepthCurrent(false),
        isHeightCurrent(false) {}

    /// Constructs an SUnit for post-regalloc scheduling to represent a
    /// MachineInstr.
    SUnit(MachineInstr *instr, unsigned nodenum)
      : Instr(instr), NodeNum(nodenum), isVRegCycle(false), isCall(false),
        isCallOp(false), isTwoAddress(false), isCommutable(false),
        hasPhysRegUses(false), hasPhysRegDefs(false), hasPhysRegClobbers(false),
        isPending(false), isAvailable(false), isScheduled(false),
        isScheduleHigh(false), isScheduleLow(false), isCloned(false),
        isUnbuffered(false), hasReservedResource(false), isDepthCurrent(false),
        isHeightCurrent(false) {}

    /// Constructs a placeholder SUnit.
    SUnit()
      : isVRegCycle(false), isCall(false), isCallOp(false), isTwoAddress(false),
        isCommutable(false), hasPhysRegUses(false), hasPhysRegDefs(false),
        hasPhysRegClobbers(false), isPending(false), isAvailable(false),
        isScheduled(false), isScheduleHigh(false), isScheduleLow(false),
        isCloned(false), isUnbuffered(false), hasReservedResource(false),
        isDepthCurrent(false), isHeightCurrent(false) {}

    /// Boundary nodes are placeholders for the boundary of the
    /// scheduling region.
    ///
    /// BoundaryNodes can have DAG edges, including Data edges, but they do not
    /// correspond to schedulable entities (e.g. instructions) and do not have a
    /// valid ID. Consequently, always check for boundary nodes before accessing
    /// an associative data structure keyed on node ID.
    bool isBoundaryNode() const { return NodeNum == BoundaryID; }

    /// Assigns the representative SDNode for this SUnit. This may be used
    /// during pre-regalloc scheduling.
    void setNode(SDNode *N) {
      assert(!Instr && "Setting SDNode of SUnit with MachineInstr!");
      Node = N;
    }

    /// Returns the representative SDNode for this SUnit. This may be used
    /// during pre-regalloc scheduling.
    SDNode *getNode() const {
      assert(!Instr && "Reading SDNode of SUnit with MachineInstr!");
      return Node;
    }

    /// Returns true if this SUnit refers to a machine instruction as
    /// opposed to an SDNode.
    bool isInstr() const { return Instr; }

    /// Assigns the instruction for the SUnit. This may be used during
    /// post-regalloc scheduling.
    void setInstr(MachineInstr *MI) {
      assert(!Node && "Setting MachineInstr of SUnit with SDNode!");
      Instr = MI;
    }

    /// Returns the representative MachineInstr for this SUnit. This may be used
    /// during post-regalloc scheduling.
    MachineInstr *getInstr() const {
      assert(!Node && "Reading MachineInstr of SUnit with SDNode!");
      return Instr;
    }

    /// Adds the specified edge as a pred of the current node if not already.
    /// It also adds the current node as a successor of the specified node.
    bool addPred(const SDep &D, bool Required = true);

    /// Adds a barrier edge to SU by calling addPred(), with latency 0
    /// generally or latency 1 for a store followed by a load.
    bool addPredBarrier(SUnit *SU) {
      SDep Dep(SU, SDep::Barrier);
      unsigned TrueMemOrderLatency =
        ((SU->getInstr()->mayStore() && this->getInstr()->mayLoad()) ? 1 : 0);
      Dep.setLatency(TrueMemOrderLatency);
      return addPred(Dep);
    }

    /// Removes the specified edge as a pred of the current node if it exists.
    /// It also removes the current node as a successor of the specified node.
    void removePred(const SDep &D);

    /// Returns the depth of this node, which is the length of the maximum path
    /// up to any node which has no predecessors.
    unsigned getDepth() const {
      if (!isDepthCurrent)
        const_cast<SUnit *>(this)->ComputeDepth();
      return Depth;
    }

    /// Returns the height of this node, which is the length of the
    /// maximum path down to any node which has no successors.
    unsigned getHeight() const {
      if (!isHeightCurrent)
        const_cast<SUnit *>(this)->ComputeHeight();
      return Height;
    }

    /// If NewDepth is greater than this node's depth value, sets it to
    /// be the new depth value. This also recursively marks successor nodes
    /// dirty.
    void setDepthToAtLeast(unsigned NewDepth);

    /// If NewDepth is greater than this node's depth value, set it to be
    /// the new height value. This also recursively marks predecessor nodes
    /// dirty.
    void setHeightToAtLeast(unsigned NewHeight);

    /// Sets a flag in this node to indicate that its stored Depth value
    /// will require recomputation the next time getDepth() is called.
    void setDepthDirty();

    /// Sets a flag in this node to indicate that its stored Height value
    /// will require recomputation the next time getHeight() is called.
    void setHeightDirty();

    /// Tests if node N is a predecessor of this node.
    bool isPred(const SUnit *N) const {
      for (const SDep &Pred : Preds)
        if (Pred.getSUnit() == N)
          return true;
      return false;
    }

    /// Tests if node N is a successor of this node.
    bool isSucc(const SUnit *N) const {
      for (const SDep &Succ : Succs)
        if (Succ.getSUnit() == N)
          return true;
      return false;
    }

    bool isTopReady() const {
      return NumPredsLeft == 0;
    }
    bool isBottomReady() const {
      return NumSuccsLeft == 0;
    }

    /// Orders this node's predecessor edges such that the critical path
    /// edge occurs first.
    void biasCriticalPath();

    void dumpAttributes() const;

  private:
    void ComputeDepth();
    void ComputeHeight();
  };

  /// Returns true if the specified SDep is equivalent except for latency.
  inline bool SDep::overlaps(const SDep &Other) const {
    if (Dep != Other.Dep)
      return false;
    switch (Dep.getInt()) {
    case Data:
    case Anti:
    case Output:
      return Contents.Reg == Other.Contents.Reg;
    case Order:
      return Contents.OrdKind == Other.Contents.OrdKind;
    }
    llvm_unreachable("Invalid dependency kind!");
  }

  //// Returns the SUnit to which this edge points.
  inline SUnit *SDep::getSUnit() const { return Dep.getPointer(); }

  //// Assigns the SUnit to which this edge points.
  inline void SDep::setSUnit(SUnit *SU) { Dep.setPointer(SU); }

  /// Returns an enum value representing the kind of the dependence.
  inline SDep::Kind SDep::getKind() const { return Dep.getInt(); }

  //===--------------------------------------------------------------------===//

  /// This interface is used to plug different priorities computation
  /// algorithms into the list scheduler. It implements the interface of a
  /// standard priority queue, where nodes are inserted in arbitrary order and
  /// returned in priority order.  The computation of the priority and the
  /// representation of the queue are totally up to the implementation to
  /// decide.
  class SchedulingPriorityQueue {
    virtual void anchor();

    unsigned CurCycle = 0;
    bool HasReadyFilter;

  public:
    SchedulingPriorityQueue(bool rf = false) :  HasReadyFilter(rf) {}

    virtual ~SchedulingPriorityQueue() = default;

    virtual bool isBottomUp() const = 0;

    virtual void initNodes(std::vector<SUnit> &SUnits) = 0;
    virtual void addNode(const SUnit *SU) = 0;
    virtual void updateNode(const SUnit *SU) = 0;
    virtual void releaseState() = 0;

    virtual bool empty() const = 0;

    bool hasReadyFilter() const { return HasReadyFilter; }

    virtual bool tracksRegPressure() const { return false; }

    virtual bool isReady(SUnit *) const {
      assert(!HasReadyFilter && "The ready filter must override isReady()");
      return true;
    }

    virtual void push(SUnit *U) = 0;

    void push_all(const std::vector<SUnit *> &Nodes) {
      for (std::vector<SUnit *>::const_iterator I = Nodes.begin(),
           E = Nodes.end(); I != E; ++I)
        push(*I);
    }

    virtual SUnit *pop() = 0;

    virtual void remove(SUnit *SU) = 0;

    virtual void dump(ScheduleDAG *) const {}

    /// As each node is scheduled, this method is invoked.  This allows the
    /// priority function to adjust the priority of related unscheduled nodes,
    /// for example.
    virtual void scheduledNode(SUnit *) {}

    virtual void unscheduledNode(SUnit *) {}

    void setCurCycle(unsigned Cycle) {
      CurCycle = Cycle;
    }

    unsigned getCurCycle() const {
      return CurCycle;
    }
  };

  class ScheduleDAG {
  public:
    const LLVMTargetMachine &TM;        ///< Target processor
    const TargetInstrInfo *TII;         ///< Target instruction information
    const TargetRegisterInfo *TRI;      ///< Target processor register info
    MachineFunction &MF;                ///< Machine function
    MachineRegisterInfo &MRI;           ///< Virtual/real register map
    std::vector<SUnit> SUnits;          ///< The scheduling units.
    SUnit EntrySU;                      ///< Special node for the region entry.
    SUnit ExitSU;                       ///< Special node for the region exit.

#ifdef NDEBUG
    static const bool StressSched = false;
#else
    bool StressSched;
#endif

    explicit ScheduleDAG(MachineFunction &mf);

    virtual ~ScheduleDAG();

    /// Clears the DAG state (between regions).
    void clearDAG();

    /// Returns the MCInstrDesc of this SUnit.
    /// Returns NULL for SDNodes without a machine opcode.
    const MCInstrDesc *getInstrDesc(const SUnit *SU) const {
      if (SU->isInstr()) return &SU->getInstr()->getDesc();
      return getNodeDesc(SU->getNode());
    }

    /// Pops up a GraphViz/gv window with the ScheduleDAG rendered using 'dot'.
    virtual void viewGraph(const Twine &Name, const Twine &Title);
    virtual void viewGraph();

    virtual void dumpNode(const SUnit &SU) const = 0;
    virtual void dump() const = 0;
    void dumpNodeName(const SUnit &SU) const;

    /// Returns a label for an SUnit node in a visualization of the ScheduleDAG.
    virtual std::string getGraphNodeLabel(const SUnit *SU) const = 0;

    /// Returns a label for the region of code covered by the DAG.
    virtual std::string getDAGName() const = 0;

    /// Adds custom features for a visualization of the ScheduleDAG.
    virtual void addCustomGraphFeatures(GraphWriter<ScheduleDAG*> &) const {}

#ifndef NDEBUG
    /// Verifies that all SUnits were scheduled and that their state is
    /// consistent. Returns the number of scheduled SUnits.
    unsigned VerifyScheduledDAG(bool isBottomUp);
#endif

  protected:
    void dumpNodeAll(const SUnit &SU) const;

  private:
    /// Returns the MCInstrDesc of this SDNode or NULL.
    const MCInstrDesc *getNodeDesc(const SDNode *Node) const;
  };

  class SUnitIterator : public std::iterator<std::forward_iterator_tag,
                                             SUnit, ptrdiff_t> {
    SUnit *Node;
    unsigned Operand;

    SUnitIterator(SUnit *N, unsigned Op) : Node(N), Operand(Op) {}

  public:
    bool operator==(const SUnitIterator& x) const {
      return Operand == x.Operand;
    }
    bool operator!=(const SUnitIterator& x) const { return !operator==(x); }

    pointer operator*() const {
      return Node->Preds[Operand].getSUnit();
    }
    pointer operator->() const { return operator*(); }

    SUnitIterator& operator++() {                // Preincrement
      ++Operand;
      return *this;
    }
    SUnitIterator operator++(int) { // Postincrement
      SUnitIterator tmp = *this; ++*this; return tmp;
    }

    static SUnitIterator begin(SUnit *N) { return SUnitIterator(N, 0); }
    static SUnitIterator end  (SUnit *N) {
      return SUnitIterator(N, (unsigned)N->Preds.size());
    }

    unsigned getOperand() const { return Operand; }
    const SUnit *getNode() const { return Node; }

    /// Tests if this is not an SDep::Data dependence.
    bool isCtrlDep() const {
      return getSDep().isCtrl();
    }
    bool isArtificialDep() const {
      return getSDep().isArtificial();
    }
    const SDep &getSDep() const {
      return Node->Preds[Operand];
    }
  };

  template <> struct GraphTraits<SUnit*> {
    typedef SUnit *NodeRef;
    typedef SUnitIterator ChildIteratorType;
    static NodeRef getEntryNode(SUnit *N) { return N; }
    static ChildIteratorType child_begin(NodeRef N) {
      return SUnitIterator::begin(N);
    }
    static ChildIteratorType child_end(NodeRef N) {
      return SUnitIterator::end(N);
    }
  };

  template <> struct GraphTraits<ScheduleDAG*> : public GraphTraits<SUnit*> {
    typedef pointer_iterator<std::vector<SUnit>::iterator> nodes_iterator;
    static nodes_iterator nodes_begin(ScheduleDAG *G) {
      return nodes_iterator(G->SUnits.begin());
    }
    static nodes_iterator nodes_end(ScheduleDAG *G) {
      return nodes_iterator(G->SUnits.end());
    }
  };

  /// This class can compute a topological ordering for SUnits and provides
  /// methods for dynamically updating the ordering as new edges are added.
  ///
  /// This allows a very fast implementation of IsReachable, for example.
  class ScheduleDAGTopologicalSort {
    /// A reference to the ScheduleDAG's SUnits.
    std::vector<SUnit> &SUnits;
    SUnit *ExitSU;

    /// Maps topological index to the node number.
    std::vector<int> Index2Node;
    /// Maps the node number to its topological index.
    std::vector<int> Node2Index;
    /// a set of nodes visited during a DFS traversal.
    BitVector Visited;

    /// Makes a DFS traversal and mark all nodes affected by the edge insertion.
    /// These nodes will later get new topological indexes by means of the Shift
    /// method.
    void DFS(const SUnit *SU, int UpperBound, bool& HasLoop);

    /// Reassigns topological indexes for the nodes in the DAG to
    /// preserve the topological ordering.
    void Shift(BitVector& Visited, int LowerBound, int UpperBound);

    /// Assigns the topological index to the node n.
    void Allocate(int n, int index);

  public:
    ScheduleDAGTopologicalSort(std::vector<SUnit> &SUnits, SUnit *ExitSU);

    /// Creates the initial topological ordering from the DAG to be scheduled.
    void InitDAGTopologicalSorting();

    /// Returns an array of SUs that are both in the successor
    /// subtree of StartSU and in the predecessor subtree of TargetSU.
    /// StartSU and TargetSU are not in the array.
    /// Success is false if TargetSU is not in the successor subtree of
    /// StartSU, else it is true.
    std::vector<int> GetSubGraph(const SUnit &StartSU, const SUnit &TargetSU,
                                 bool &Success);

    /// Checks if \p SU is reachable from \p TargetSU.
    bool IsReachable(const SUnit *SU, const SUnit *TargetSU);

    /// Returns true if addPred(TargetSU, SU) creates a cycle.
    bool WillCreateCycle(SUnit *TargetSU, SUnit *SU);

    /// Updates the topological ordering to accommodate an edge to be
    /// added from SUnit \p X to SUnit \p Y.
    void AddPred(SUnit *Y, SUnit *X);

    /// Updates the topological ordering to accommodate an an edge to be
    /// removed from the specified node \p N from the predecessors of the
    /// current node \p M.
    void RemovePred(SUnit *M, SUnit *N);

    typedef std::vector<int>::iterator iterator;
    typedef std::vector<int>::const_iterator const_iterator;
    iterator begin() { return Index2Node.begin(); }
    const_iterator begin() const { return Index2Node.begin(); }
    iterator end() { return Index2Node.end(); }
    const_iterator end() const { return Index2Node.end(); }

    typedef std::vector<int>::reverse_iterator reverse_iterator;
    typedef std::vector<int>::const_reverse_iterator const_reverse_iterator;
    reverse_iterator rbegin() { return Index2Node.rbegin(); }
    const_reverse_iterator rbegin() const { return Index2Node.rbegin(); }
    reverse_iterator rend() { return Index2Node.rend(); }
    const_reverse_iterator rend() const { return Index2Node.rend(); }
  };

} // end namespace llvm

#endif // LLVM_CODEGEN_SCHEDULEDAG_H
