diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index ed4e0bc8a4a..43b07f9d420 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// // -// This 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. +/// \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. // //===----------------------------------------------------------------------===// @@ -40,11 +40,11 @@ namespace llvm { class TargetRegisterClass; template class GraphWriter; - /// SDep - Scheduling dependency. This represents one direction of an - /// edge in the scheduling DAG. + /// Scheduling dependency. This represents one direction of an edge in the + /// scheduling DAG. class SDep { public: - /// Kind - These are the different kinds of scheduling dependencies. + /// These are the different kinds of scheduling dependencies. enum Kind { Data, ///< Regular data dependence (aka true-dependence). Anti, ///< A register anti-dependedence (aka WAR). @@ -71,33 +71,32 @@ namespace llvm { }; private: - /// Dep - A pointer to the depending/depended-on SUnit, and an enum + /// \brief A pointer to the depending/depended-on SUnit, and an enum /// indicating the kind of the dependency. PointerIntPair Dep; - /// Contents - A union discriminated by the dependence kind. + /// A union discriminated by the dependence kind. union { - /// Reg - 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. + /// 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; - /// Order - Additional information about Order dependencies. + /// Additional information about Order dependencies. unsigned OrdKind; // enum OrderKind } Contents; - /// Latency - 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. + /// 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: - /// SDep - Construct a null SDep. This is only for use by container - /// classes which require default constructors. SUnits may not - /// have null SDep edges. + /// 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) {} - /// SDep - Construct an SDep with the specified values. + /// Constructs an SDep with the specified values. SDep(SUnit *S, Kind kind, unsigned Reg) : Dep(S, kind), Contents() { switch (kind) { @@ -121,7 +120,7 @@ namespace llvm { Contents.OrdKind = kind; } - /// Return true if the specified SDep is equivalent except for latency. + /// Returns true if the specified SDep is equivalent except for latency. bool overlaps(const SDep &Other) const; bool operator==(const SDep &Other) const { @@ -132,100 +131,95 @@ namespace llvm { return !operator==(Other); } - /// getLatency - Return 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. + /// \brief 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; } - /// setLatency - Set the latency for this edge. + /// Sets the latency for this edge. void setLatency(unsigned Lat) { Latency = Lat; } - //// getSUnit - Return the SUnit to which this edge points. + //// Returns the SUnit to which this edge points. SUnit *getSUnit() const; - //// setSUnit - Assign the SUnit to which this edge points. + //// Assigns the SUnit to which this edge points. void setSUnit(SUnit *SU); - /// getKind - Return an enum value representing the kind of the dependence. + /// Returns an enum value representing the kind of the dependence. Kind getKind() const; - /// isCtrl - Shorthand for getKind() != SDep::Data. + /// Shorthand for getKind() != SDep::Data. bool isCtrl() const { return getKind() != Data; } - /// isNormalMemory - Test 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. + /// \brief 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); } - /// isBarrier - Test if this is an Order dependence that is marked - /// as a barrier. + /// Tests if this is an Order dependence that is marked as a barrier. bool isBarrier() const { return getKind() == Order && Contents.OrdKind == Barrier; } - /// isNormalMemoryOrBarrier - Test if this is could be any kind of memory - /// dependence. + /// Tests if this is could be any kind of memory dependence. bool isNormalMemoryOrBarrier() const { return (isNormalMemory() || isBarrier()); } - /// isMustAlias - Test 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. + /// \brief 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; } - /// isWeak - Test 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. + /// 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; } - /// isArtificial - Test if this is an Order dependence that is marked - /// as "artificial", meaning it isn't necessary for correctness. + /// \brief 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; } - /// isCluster - Test if this is an Order dependence that is marked - /// as "cluster", meaning it is artificial and wants to be adjacent. + /// \brief 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; } - /// isAssignedRegDep - Test if this is a Data dependence that is - /// associated with a register. + /// Tests if this is a Data dependence that is associated with a register. bool isAssignedRegDep() const { return getKind() == Data && Contents.Reg != 0; } - /// getReg - Return 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. + /// 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; } - /// setReg - Assign 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. + /// 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!"); @@ -240,71 +234,70 @@ namespace llvm { template <> struct isPodLike { static const bool value = true; }; - /// SUnit - Scheduling unit. This is a node in the scheduling DAG. + /// Scheduling unit. This is a node in the scheduling DAG. class SUnit { private: enum : unsigned { BoundaryID = ~0u }; - SDNode *Node; // Representative node. - MachineInstr *Instr; // Alternatively, a MachineInstr. + SDNode *Node; ///< Representative node. + MachineInstr *Instr; ///< Alternatively, a MachineInstr. public: - SUnit *OrigNode; // If not this, the node from which - // this node was cloned. - // (SD scheduling only) + SUnit *OrigNode; ///< If not this, the node from which + /// this node was cloned. + /// (SD scheduling only) - const MCSchedClassDesc *SchedClass; // NULL or resolved SchedClass. + const MCSchedClassDesc *SchedClass; ///< nullptr or resolved SchedClass. - // Preds/Succs - The SUnits before/after us in the graph. - SmallVector Preds; // All sunit predecessors. - SmallVector Succs; // All sunit successors. + SmallVector Preds; ///< All sunit predecessors. + SmallVector Succs; ///< All sunit successors. typedef SmallVectorImpl::iterator pred_iterator; typedef SmallVectorImpl::iterator succ_iterator; typedef SmallVectorImpl::const_iterator const_pred_iterator; typedef SmallVectorImpl::const_iterator const_succ_iterator; - unsigned NodeNum; // Entry # of node in the node vector. - unsigned NodeQueueId; // Queue id of node. - unsigned NumPreds; // # of SDep::Data preds. - unsigned NumSuccs; // # of SDep::Data sucss. - unsigned NumPredsLeft; // # of preds not scheduled. - unsigned NumSuccsLeft; // # of succs not scheduled. - unsigned WeakPredsLeft; // # of weak preds not scheduled. - unsigned WeakSuccsLeft; // # of weak succs not scheduled. - unsigned short NumRegDefsLeft; // # of reg defs with no scheduled use. - unsigned short Latency; // 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; // Scheduling preference. + unsigned NodeNum; ///< Entry # of node in the node vector. + unsigned NodeQueueId; ///< Queue id of node. + unsigned NumPreds; ///< # of SDep::Data preds. + unsigned NumSuccs; ///< # of SDep::Data sucss. + unsigned NumPredsLeft; ///< # of preds not scheduled. + unsigned NumSuccsLeft; ///< # of succs not scheduled. + unsigned WeakPredsLeft; ///< # of weak preds not scheduled. + unsigned WeakSuccsLeft; ///< # of weak succs not scheduled. + unsigned short NumRegDefsLeft; ///< # of reg defs with no scheduled use. + unsigned short Latency; ///< 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; ///< Scheduling preference. private: - bool isDepthCurrent : 1; // True if Depth is current. - bool isHeightCurrent : 1; // True if Height is current. - unsigned Depth; // Node depth. - unsigned Height; // Node height. + bool isDepthCurrent : 1; ///< True if Depth is current. + bool isHeightCurrent : 1; ///< True if Height is current. + unsigned Depth; ///< Node depth. + unsigned Height; ///< Node height. public: - unsigned TopReadyCycle; // Cycle relative to start when node is ready. - unsigned BotReadyCycle; // Cycle relative to end when node is ready. + unsigned TopReadyCycle; ///< Cycle relative to start when node is ready. + unsigned BotReadyCycle; ///< Cycle relative to end when node is ready. - const TargetRegisterClass *CopyDstRC; // Is a special copy node if not null. + const TargetRegisterClass *CopyDstRC; ///< Is a special copy node if !=null. const TargetRegisterClass *CopySrcRC; - /// SUnit - Construct an SUnit for pre-regalloc scheduling to represent - /// an SDNode and any nodes flagged to it. + /// \brief Constructs an SUnit for pre-regalloc scheduling to represent an + /// SDNode and any nodes flagged to it. SUnit(SDNode *node, unsigned nodenum) : Node(node), Instr(nullptr), OrigNode(nullptr), SchedClass(nullptr), NodeNum(nodenum), NodeQueueId(0), NumPreds(0), NumSuccs(0), @@ -319,8 +312,8 @@ namespace llvm { isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0), BotReadyCycle(0), CopyDstRC(nullptr), CopySrcRC(nullptr) {} - /// SUnit - Construct an SUnit for post-regalloc scheduling to represent - /// a MachineInstr. + /// \brief Constructs an SUnit for post-regalloc scheduling to represent a + /// MachineInstr. SUnit(MachineInstr *instr, unsigned nodenum) : Node(nullptr), Instr(instr), OrigNode(nullptr), SchedClass(nullptr), NodeNum(nodenum), NodeQueueId(0), NumPreds(0), NumSuccs(0), @@ -335,7 +328,7 @@ namespace llvm { isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0), BotReadyCycle(0), CopyDstRC(nullptr), CopySrcRC(nullptr) {} - /// SUnit - Construct a placeholder SUnit. + /// \brief Constructs a placeholder SUnit. SUnit() : Node(nullptr), Instr(nullptr), OrigNode(nullptr), SchedClass(nullptr), NodeNum(BoundaryID), NodeQueueId(0), NumPreds(0), NumSuccs(0), @@ -359,46 +352,44 @@ namespace llvm { /// an assoicative data structure keyed on node ID. bool isBoundaryNode() const { return NodeNum == BoundaryID; } - /// setNode - Assign the representative SDNode for this SUnit. - /// This may be used during pre-regalloc scheduling. + /// 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; } - /// getNode - Return the representative SDNode for this SUnit. - /// This may be used during pre-regalloc scheduling. + /// 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; } - /// isInstr - Return true if this SUnit refers to a machine instruction as + /// \brief Returns true if this SUnit refers to a machine instruction as /// opposed to an SDNode. bool isInstr() const { return Instr; } - /// setInstr - Assign the instruction for the SUnit. - /// This may be used during post-regalloc scheduling. + /// 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; } - /// getInstr - Return the representative MachineInstr for this SUnit. - /// This may be used during post-regalloc scheduling. + /// 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; } - /// addPred - This 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. + /// 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); - /// addPredBarrier - This adds a barrier edge to SU by calling - /// addPred(), with latency 0 generally or latency 1 for a store - /// followed by a load. + /// \brief 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 = @@ -407,20 +398,19 @@ namespace llvm { return addPred(Dep); } - /// removePred - This 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. + /// 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); - /// getDepth - Return the depth of this node, which is the length of the - /// maximum path up to any node which has no predecessors. + /// 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(this)->ComputeDepth(); return Depth; } - /// getHeight - Return the height of this node, which is the length of the + /// \brief 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) @@ -428,38 +418,36 @@ namespace llvm { return Height; } - /// setDepthToAtLeast - If NewDepth is greater than this node's - /// depth value, set it to be the new depth value. This also - /// recursively marks successor nodes dirty. + /// \brief 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); - /// setDepthToAtLeast - 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. + /// \brief 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); - /// setDepthDirty - Set a flag in this node to indicate that its - /// stored Depth value will require recomputation the next time - /// getDepth() is called. + /// \brief Sets a flag in this node to indicate that its stored Depth value + /// will require recomputation the next time getDepth() is called. void setDepthDirty(); - /// setHeightDirty - Set a flag in this node to indicate that its - /// stored Height value will require recomputation the next time - /// getHeight() is called. + /// \brief Sets a flag in this node to indicate that its stored Height value + /// will require recomputation the next time getHeight() is called. void setHeightDirty(); - /// isPred - Test if node N is a predecessor of this node. - bool isPred(SUnit *N) { - for (unsigned i = 0, e = (unsigned)Preds.size(); i != e; ++i) - if (Preds[i].getSUnit() == N) + /// 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; } - /// isSucc - Test if node N is a successor of this node. - bool isSucc(SUnit *N) { - for (unsigned i = 0, e = (unsigned)Succs.size(); i != e; ++i) - if (Succs[i].getSUnit() == N) + /// 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; } @@ -471,7 +459,7 @@ namespace llvm { return NumSuccsLeft == 0; } - /// \brief Order this node's predecessor edges such that the critical path + /// \brief Orders this node's predecessor edges such that the critical path /// edge occurs first. void biasCriticalPath(); @@ -484,7 +472,7 @@ namespace llvm { void ComputeHeight(); }; - /// Return true if the specified SDep is equivalent except for latency. + /// 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; @@ -499,23 +487,23 @@ namespace llvm { llvm_unreachable("Invalid dependency kind!"); } - //// getSUnit - Return the SUnit to which this edge points. + //// Returns the SUnit to which this edge points. inline SUnit *SDep::getSUnit() const { return Dep.getPointer(); } - //// setSUnit - Assign the SUnit to which this edge points. + //// Assigns the SUnit to which this edge points. inline void SDep::setSUnit(SUnit *SU) { Dep.setPointer(SU); } - /// getKind - Return an enum value representing the kind of the dependence. + /// Returns an enum value representing the kind of the dependence. inline SDep::Kind SDep::getKind() const { return Dep.getInt(); } //===--------------------------------------------------------------------===// - /// SchedulingPriorityQueue - 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. - /// + + /// \brief 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; @@ -556,10 +544,9 @@ namespace llvm { virtual void dump(ScheduleDAG *) const {} - /// scheduledNode - As each node is scheduled, this method is invoked. This - /// allows the priority function to adjust the priority of related - /// unscheduled nodes, for example. - /// + /// 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 *) {} @@ -575,14 +562,14 @@ namespace llvm { class ScheduleDAG { public: - const TargetMachine &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 SUnits; // The scheduling units. - SUnit EntrySU; // Special node for the region entry. - SUnit ExitSU; // Special node for the region exit. + const TargetMachine &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 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; @@ -594,43 +581,39 @@ namespace llvm { virtual ~ScheduleDAG(); - /// clearDAG - clear the DAG state (between regions). + /// Clears the DAG state (between regions). void clearDAG(); - /// getInstrDesc - Return the MCInstrDesc of this SUnit. - /// Return NULL for SDNodes without a machine opcode. + /// 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()); } - /// viewGraph - Pop up a GraphViz/gv window with the ScheduleDAG rendered - /// using 'dot'. - /// + /// 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; - /// getGraphNodeLabel - Return a label for an SUnit node in a visualization - /// of the ScheduleDAG. + /// Returns a label for an SUnit node in a visualization of the ScheduleDAG. virtual std::string getGraphNodeLabel(const SUnit *SU) const = 0; - /// getDAGLabel - Return a label for the region of code covered by the DAG. + /// Returns a label for the region of code covered by the DAG. virtual std::string getDAGName() const = 0; - /// addCustomGraphFeatures - Add custom features for a visualization of - /// the ScheduleDAG. + /// Adds custom features for a visualization of the ScheduleDAG. virtual void addCustomGraphFeatures(GraphWriter &) const {} #ifndef NDEBUG - /// VerifyScheduledDAG - Verify that all SUnits were scheduled and that - /// their state is consistent. Return the number of scheduled SUnits. + /// \brief Verifies that all SUnits were scheduled and that their state is + /// consistent. Returns the number of scheduled SUnits. unsigned VerifyScheduledDAG(bool isBottomUp); #endif private: - // Return the MCInstrDesc of this SDNode or NULL. + /// Returns the MCInstrDesc of this SDNode or NULL. const MCInstrDesc *getNodeDesc(const SDNode *Node) const; }; @@ -666,7 +649,7 @@ namespace llvm { unsigned getOperand() const { return Operand; } const SUnit *getNode() const { return Node; } - /// isCtrlDep - Test if this is not an SDep::Data dependence. + /// Tests if this is not an SDep::Data dependence. bool isCtrlDep() const { return getSDep().isCtrl(); } @@ -700,56 +683,53 @@ namespace llvm { } }; - /// ScheduleDAGTopologicalSort is a class that computes a topological - /// ordering for SUnits and provides methods for dynamically updating - /// the ordering as new edges are added. + /// 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 { - /// SUnits - A reference to the ScheduleDAG's SUnits. + /// A reference to the ScheduleDAG's SUnits. std::vector &SUnits; SUnit *ExitSU; - /// Index2Node - Maps topological index to the node number. + /// Maps topological index to the node number. std::vector Index2Node; - /// Node2Index - Maps the node number to its topological index. + /// Maps the node number to its topological index. std::vector Node2Index; - /// Visited - a set of nodes visited during a DFS traversal. + /// a set of nodes visited during a DFS traversal. BitVector Visited; - /// DFS - make 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. + /// 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); - /// Shift - reassign topological indexes for the nodes in the DAG - /// to preserve the topological ordering. + /// \brief Reassigns topological indexes for the nodes in the DAG to + /// preserve the topological ordering. void Shift(BitVector& Visited, int LowerBound, int UpperBound); - /// Allocate - assign the topological index to the node n. + /// Assigns the topological index to the node n. void Allocate(int n, int index); public: ScheduleDAGTopologicalSort(std::vector &SUnits, SUnit *ExitSU); - /// InitDAGTopologicalSorting - create the initial topological - /// ordering from the DAG to be scheduled. + /// Creates the initial topological ordering from the DAG to be scheduled. void InitDAGTopologicalSorting(); - /// IsReachable - Checks if SU is reachable from TargetSU. + /// Checks if \p SU is reachable from \p TargetSU. bool IsReachable(const SUnit *SU, const SUnit *TargetSU); - /// WillCreateCycle - Return true if addPred(TargetSU, SU) creates a cycle. + /// Returns true if addPred(TargetSU, SU) creates a cycle. bool WillCreateCycle(SUnit *TargetSU, SUnit *SU); - /// AddPred - Updates the topological ordering to accommodate an edge - /// to be added from SUnit X to SUnit Y. + /// \brief 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); - /// RemovePred - Updates the topological ordering to accommodate an - /// an edge to be removed from the specified node N from the predecessors - /// of the current node M. + /// \brief 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::iterator iterator; diff --git a/lib/CodeGen/ScheduleDAG.cpp b/lib/CodeGen/ScheduleDAG.cpp index 5c177463a5d..01c056caa62 100644 --- a/lib/CodeGen/ScheduleDAG.cpp +++ b/lib/CodeGen/ScheduleDAG.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// // -// This implements the ScheduleDAG class, which is a base class used by -// scheduling implementation classes. +/// \file Implements the ScheduleDAG class, which is a base class used by +/// scheduling implementation classes. // //===----------------------------------------------------------------------===// @@ -46,45 +46,39 @@ ScheduleDAG::ScheduleDAG(MachineFunction &mf) ScheduleDAG::~ScheduleDAG() {} -/// Clear the DAG state (e.g. between scheduling regions). void ScheduleDAG::clearDAG() { SUnits.clear(); EntrySU = SUnit(); ExitSU = SUnit(); } -/// getInstrDesc helper to handle SDNodes. const MCInstrDesc *ScheduleDAG::getNodeDesc(const SDNode *Node) const { if (!Node || !Node->isMachineOpcode()) return nullptr; return &TII->get(Node->getMachineOpcode()); } -/// addPred - This 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 SUnit::addPred(const SDep &D, bool Required) { // If this node already has this dependence, don't add a redundant one. - for (SmallVectorImpl::iterator I = Preds.begin(), E = Preds.end(); - I != E; ++I) { + for (SDep &PredDep : Preds) { // Zero-latency weak edges may be added purely for heuristic ordering. Don't // add them if another kind of edge already exists. - if (!Required && I->getSUnit() == D.getSUnit()) + if (!Required && PredDep.getSUnit() == D.getSUnit()) return false; - if (I->overlaps(D)) { - // Extend the latency if needed. Equivalent to removePred(I) + addPred(D). - if (I->getLatency() < D.getLatency()) { - SUnit *PredSU = I->getSUnit(); + if (PredDep.overlaps(D)) { + // Extend the latency if needed. Equivalent to + // removePred(PredDep) + addPred(D). + if (PredDep.getLatency() < D.getLatency()) { + SUnit *PredSU = PredDep.getSUnit(); // Find the corresponding successor in N. - SDep ForwardD = *I; + SDep ForwardD = PredDep; ForwardD.setSUnit(this); - for (SmallVectorImpl::iterator II = PredSU->Succs.begin(), - EE = PredSU->Succs.end(); II != EE; ++II) { - if (*II == ForwardD) { - II->setLatency(D.getLatency()); + for (SDep &SuccDep : PredSU->Succs) { + if (SuccDep == ForwardD) { + SuccDep.setLatency(D.getLatency()); break; } } - I->setLatency(D.getLatency()); + PredDep.setLatency(D.getLatency()); } return false; } @@ -127,51 +121,46 @@ bool SUnit::addPred(const SDep &D, bool Required) { return true; } -/// removePred - This 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 SUnit::removePred(const SDep &D) { // Find the matching predecessor. - for (SmallVectorImpl::iterator I = Preds.begin(), E = Preds.end(); - I != E; ++I) - if (*I == D) { - // Find the corresponding successor in N. - SDep P = D; - P.setSUnit(this); - SUnit *N = D.getSUnit(); - SmallVectorImpl::iterator Succ = find(N->Succs, P); - assert(Succ != N->Succs.end() && "Mismatching preds / succs lists!"); - N->Succs.erase(Succ); - Preds.erase(I); - // Update the bookkeeping. - if (P.getKind() == SDep::Data) { - assert(NumPreds > 0 && "NumPreds will underflow!"); - assert(N->NumSuccs > 0 && "NumSuccs will underflow!"); - --NumPreds; - --N->NumSuccs; - } - if (!N->isScheduled) { - if (D.isWeak()) - --WeakPredsLeft; - else { - assert(NumPredsLeft > 0 && "NumPredsLeft will underflow!"); - --NumPredsLeft; - } - } - if (!isScheduled) { - if (D.isWeak()) - --N->WeakSuccsLeft; - else { - assert(N->NumSuccsLeft > 0 && "NumSuccsLeft will underflow!"); - --N->NumSuccsLeft; - } - } - if (P.getLatency() != 0) { - this->setDepthDirty(); - N->setHeightDirty(); - } - return; + SmallVectorImpl::iterator I = find(Preds, D); + if (I == Preds.end()) + return; + // Find the corresponding successor in N. + SDep P = D; + P.setSUnit(this); + SUnit *N = D.getSUnit(); + SmallVectorImpl::iterator Succ = find(N->Succs, P); + assert(Succ != N->Succs.end() && "Mismatching preds / succs lists!"); + N->Succs.erase(Succ); + Preds.erase(I); + // Update the bookkeeping. + if (P.getKind() == SDep::Data) { + assert(NumPreds > 0 && "NumPreds will underflow!"); + assert(N->NumSuccs > 0 && "NumSuccs will underflow!"); + --NumPreds; + --N->NumSuccs; + } + if (!N->isScheduled) { + if (D.isWeak()) + --WeakPredsLeft; + else { + assert(NumPredsLeft > 0 && "NumPredsLeft will underflow!"); + --NumPredsLeft; } + } + if (!isScheduled) { + if (D.isWeak()) + --N->WeakSuccsLeft; + else { + assert(N->NumSuccsLeft > 0 && "NumSuccsLeft will underflow!"); + --N->NumSuccsLeft; + } + } + if (P.getLatency() != 0) { + this->setDepthDirty(); + N->setHeightDirty(); + } } void SUnit::setDepthDirty() { @@ -181,9 +170,8 @@ void SUnit::setDepthDirty() { do { SUnit *SU = WorkList.pop_back_val(); SU->isDepthCurrent = false; - for (SUnit::const_succ_iterator I = SU->Succs.begin(), - E = SU->Succs.end(); I != E; ++I) { - SUnit *SuccSU = I->getSUnit(); + for (SDep &SuccDep : SU->Succs) { + SUnit *SuccSU = SuccDep.getSUnit(); if (SuccSU->isDepthCurrent) WorkList.push_back(SuccSU); } @@ -197,18 +185,14 @@ void SUnit::setHeightDirty() { do { SUnit *SU = WorkList.pop_back_val(); SU->isHeightCurrent = false; - for (SUnit::const_pred_iterator I = SU->Preds.begin(), - E = SU->Preds.end(); I != E; ++I) { - SUnit *PredSU = I->getSUnit(); + for (SDep &PredDep : SU->Preds) { + SUnit *PredSU = PredDep.getSUnit(); if (PredSU->isHeightCurrent) WorkList.push_back(PredSU); } } while (!WorkList.empty()); } -/// setDepthToAtLeast - Update this node's successors to reflect the -/// fact that this node's depth just increased. -/// void SUnit::setDepthToAtLeast(unsigned NewDepth) { if (NewDepth <= getDepth()) return; @@ -217,9 +201,6 @@ void SUnit::setDepthToAtLeast(unsigned NewDepth) { isDepthCurrent = true; } -/// setHeightToAtLeast - Update this node's predecessors to reflect the -/// fact that this node's height just increased. -/// void SUnit::setHeightToAtLeast(unsigned NewHeight) { if (NewHeight <= getHeight()) return; @@ -228,8 +209,7 @@ void SUnit::setHeightToAtLeast(unsigned NewHeight) { isHeightCurrent = true; } -/// ComputeDepth - Calculate the maximal path from the node to the exit. -/// +/// Calculates the maximal path from the node to the exit. void SUnit::ComputeDepth() { SmallVector WorkList; WorkList.push_back(this); @@ -238,12 +218,11 @@ void SUnit::ComputeDepth() { bool Done = true; unsigned MaxPredDepth = 0; - for (SUnit::const_pred_iterator I = Cur->Preds.begin(), - E = Cur->Preds.end(); I != E; ++I) { - SUnit *PredSU = I->getSUnit(); + for (const SDep &PredDep : Cur->Preds) { + SUnit *PredSU = PredDep.getSUnit(); if (PredSU->isDepthCurrent) MaxPredDepth = std::max(MaxPredDepth, - PredSU->Depth + I->getLatency()); + PredSU->Depth + PredDep.getLatency()); else { Done = false; WorkList.push_back(PredSU); @@ -261,8 +240,7 @@ void SUnit::ComputeDepth() { } while (!WorkList.empty()); } -/// ComputeHeight - Calculate the maximal path from the node to the entry. -/// +/// Calculates the maximal path from the node to the entry. void SUnit::ComputeHeight() { SmallVector WorkList; WorkList.push_back(this); @@ -271,12 +249,11 @@ void SUnit::ComputeHeight() { bool Done = true; unsigned MaxSuccHeight = 0; - for (SUnit::const_succ_iterator I = Cur->Succs.begin(), - E = Cur->Succs.end(); I != E; ++I) { - SUnit *SuccSU = I->getSUnit(); + for (const SDep &SuccDep : Cur->Succs) { + SUnit *SuccSU = SuccDep.getSUnit(); if (SuccSU->isHeightCurrent) MaxSuccHeight = std::max(MaxSuccHeight, - SuccSU->Height + I->getLatency()); + SuccSU->Height + SuccDep.getLatency()); else { Done = false; WorkList.push_back(SuccSU); @@ -320,8 +297,6 @@ void SUnit::print(raw_ostream &OS, const ScheduleDAG *DAG) const { OS << "SU(" << NodeNum << ")"; } -/// SUnit - Scheduling unit. It's an wrapper around either a single SDNode or -/// a group of nodes flagged together. LLVM_DUMP_METHOD void SUnit::dump(const ScheduleDAG *G) const { print(dbgs(), G); dbgs() << ": "; @@ -344,41 +319,39 @@ LLVM_DUMP_METHOD void SUnit::dumpAll(const ScheduleDAG *G) const { if (Preds.size() != 0) { dbgs() << " Predecessors:\n"; - for (SUnit::const_succ_iterator I = Preds.begin(), E = Preds.end(); - I != E; ++I) { + for (const SDep &SuccDep : Preds) { dbgs() << " "; - switch (I->getKind()) { + switch (SuccDep.getKind()) { case SDep::Data: dbgs() << "data "; break; case SDep::Anti: dbgs() << "anti "; break; case SDep::Output: dbgs() << "out "; break; case SDep::Order: dbgs() << "ord "; break; } - I->getSUnit()->print(dbgs(), G); - if (I->isArtificial()) + SuccDep.getSUnit()->print(dbgs(), G); + if (SuccDep.isArtificial()) dbgs() << " *"; - dbgs() << ": Latency=" << I->getLatency(); - if (I->isAssignedRegDep()) - dbgs() << " Reg=" << PrintReg(I->getReg(), G->TRI); + dbgs() << ": Latency=" << SuccDep.getLatency(); + if (SuccDep.isAssignedRegDep()) + dbgs() << " Reg=" << PrintReg(SuccDep.getReg(), G->TRI); dbgs() << "\n"; } } if (Succs.size() != 0) { dbgs() << " Successors:\n"; - for (SUnit::const_succ_iterator I = Succs.begin(), E = Succs.end(); - I != E; ++I) { + for (const SDep &SuccDep : Succs) { dbgs() << " "; - switch (I->getKind()) { + switch (SuccDep.getKind()) { case SDep::Data: dbgs() << "data "; break; case SDep::Anti: dbgs() << "anti "; break; case SDep::Output: dbgs() << "out "; break; case SDep::Order: dbgs() << "ord "; break; } - I->getSUnit()->print(dbgs(), G); - if (I->isArtificial()) + SuccDep.getSUnit()->print(dbgs(), G); + if (SuccDep.isArtificial()) dbgs() << " *"; - dbgs() << ": Latency=" << I->getLatency(); - if (I->isAssignedRegDep()) - dbgs() << " Reg=" << PrintReg(I->getReg(), G->TRI); + dbgs() << ": Latency=" << SuccDep.getLatency(); + if (SuccDep.isAssignedRegDep()) + dbgs() << " Reg=" << PrintReg(SuccDep.getReg(), G->TRI); dbgs() << "\n"; } } @@ -386,47 +359,44 @@ LLVM_DUMP_METHOD void SUnit::dumpAll(const ScheduleDAG *G) const { #endif #ifndef NDEBUG -/// VerifyScheduledDAG - Verify that all SUnits were scheduled and that -/// their state is consistent. Return the number of scheduled nodes. -/// unsigned ScheduleDAG::VerifyScheduledDAG(bool isBottomUp) { bool AnyNotSched = false; unsigned DeadNodes = 0; - for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { - if (!SUnits[i].isScheduled) { - if (SUnits[i].NumPreds == 0 && SUnits[i].NumSuccs == 0) { + for (const SUnit &SUnit : SUnits) { + if (!SUnit.isScheduled) { + if (SUnit.NumPreds == 0 && SUnit.NumSuccs == 0) { ++DeadNodes; continue; } if (!AnyNotSched) dbgs() << "*** Scheduling failed! ***\n"; - SUnits[i].dump(this); + SUnit.dump(this); dbgs() << "has not been scheduled!\n"; AnyNotSched = true; } - if (SUnits[i].isScheduled && - (isBottomUp ? SUnits[i].getHeight() : SUnits[i].getDepth()) > + if (SUnit.isScheduled && + (isBottomUp ? SUnit.getHeight() : SUnit.getDepth()) > unsigned(INT_MAX)) { if (!AnyNotSched) dbgs() << "*** Scheduling failed! ***\n"; - SUnits[i].dump(this); + SUnit.dump(this); dbgs() << "has an unexpected " << (isBottomUp ? "Height" : "Depth") << " value!\n"; AnyNotSched = true; } if (isBottomUp) { - if (SUnits[i].NumSuccsLeft != 0) { + if (SUnit.NumSuccsLeft != 0) { if (!AnyNotSched) dbgs() << "*** Scheduling failed! ***\n"; - SUnits[i].dump(this); + SUnit.dump(this); dbgs() << "has successors left!\n"; AnyNotSched = true; } } else { - if (SUnits[i].NumPredsLeft != 0) { + if (SUnit.NumPredsLeft != 0) { if (!AnyNotSched) dbgs() << "*** Scheduling failed! ***\n"; - SUnits[i].dump(this); + SUnit.dump(this); dbgs() << "has predecessors left!\n"; AnyNotSched = true; } @@ -437,36 +407,33 @@ unsigned ScheduleDAG::VerifyScheduledDAG(bool isBottomUp) { } #endif -/// InitDAGTopologicalSorting - create the initial topological -/// ordering from the DAG to be scheduled. -/// -/// The idea of the algorithm is taken from -/// "Online algorithms for managing the topological order of -/// a directed acyclic graph" by David J. Pearce and Paul H.J. Kelly -/// This is the MNR algorithm, which was first introduced by -/// A. Marchetti-Spaccamela, U. Nanni and H. Rohnert in -/// "Maintaining a topological order under edge insertions". -/// -/// Short description of the algorithm: -/// -/// Topological ordering, ord, of a DAG maps each node to a topological -/// index so that for all edges X->Y it is the case that ord(X) < ord(Y). -/// -/// This means that if there is a path from the node X to the node Z, -/// then ord(X) < ord(Z). -/// -/// This property can be used to check for reachability of nodes: -/// if Z is reachable from X, then an insertion of the edge Z->X would -/// create a cycle. -/// -/// The algorithm first computes a topological ordering for the DAG by -/// initializing the Index2Node and Node2Index arrays and then tries to keep -/// the ordering up-to-date after edge insertions by reordering the DAG. -/// -/// On insertion of the edge X->Y, the algorithm first marks by calling DFS -/// the nodes reachable from Y, and then shifts them using Shift to lie -/// immediately after X in Index2Node. void ScheduleDAGTopologicalSort::InitDAGTopologicalSorting() { + // The idea of the algorithm is taken from + // "Online algorithms for managing the topological order of + // a directed acyclic graph" by David J. Pearce and Paul H.J. Kelly + // This is the MNR algorithm, which was first introduced by + // A. Marchetti-Spaccamela, U. Nanni and H. Rohnert in + // "Maintaining a topological order under edge insertions". + // + // Short description of the algorithm: + // + // Topological ordering, ord, of a DAG maps each node to a topological + // index so that for all edges X->Y it is the case that ord(X) < ord(Y). + // + // This means that if there is a path from the node X to the node Z, + // then ord(X) < ord(Z). + // + // This property can be used to check for reachability of nodes: + // if Z is reachable from X, then an insertion of the edge Z->X would + // create a cycle. + // + // The algorithm first computes a topological ordering for the DAG by + // initializing the Index2Node and Node2Index arrays and then tries to keep + // the ordering up-to-date after edge insertions by reordering the DAG. + // + // On insertion of the edge X->Y, the algorithm first marks by calling DFS + // the nodes reachable from Y, and then shifts them using Shift to lie + // immediately after X in Index2Node. unsigned DAGSize = SUnits.size(); std::vector WorkList; WorkList.reserve(DAGSize); @@ -477,18 +444,17 @@ void ScheduleDAGTopologicalSort::InitDAGTopologicalSorting() { // Initialize the data structures. if (ExitSU) WorkList.push_back(ExitSU); - for (unsigned i = 0, e = DAGSize; i != e; ++i) { - SUnit *SU = &SUnits[i]; - int NodeNum = SU->NodeNum; - unsigned Degree = SU->Succs.size(); + for (SUnit &SU : SUnits) { + int NodeNum = SU.NodeNum; + unsigned Degree = SU.Succs.size(); // Temporarily use the Node2Index array as scratch space for degree counts. Node2Index[NodeNum] = Degree; // Is it a node without dependencies? if (Degree == 0) { - assert(SU->Succs.empty() && "SUnit should have no successors"); + assert(SU.Succs.empty() && "SUnit should have no successors"); // Collect leaf nodes. - WorkList.push_back(SU); + WorkList.push_back(&SU); } } @@ -498,9 +464,8 @@ void ScheduleDAGTopologicalSort::InitDAGTopologicalSorting() { WorkList.pop_back(); if (SU->NodeNum < DAGSize) Allocate(SU->NodeNum, --Id); - for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); - I != E; ++I) { - SUnit *SU = I->getSUnit(); + for (const SDep &PredDep : SU->Preds) { + SUnit *SU = PredDep.getSUnit(); if (SU->NodeNum < DAGSize && !--Node2Index[SU->NodeNum]) // If all dependencies of the node are processed already, // then the node can be computed now. @@ -512,19 +477,15 @@ void ScheduleDAGTopologicalSort::InitDAGTopologicalSorting() { #ifndef NDEBUG // Check correctness of the ordering - for (unsigned i = 0, e = DAGSize; i != e; ++i) { - SUnit *SU = &SUnits[i]; - for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); - I != E; ++I) { - assert(Node2Index[SU->NodeNum] > Node2Index[I->getSUnit()->NodeNum] && + for (SUnit &SU : SUnits) { + for (const SDep &PD : SU.Preds) { + assert(Node2Index[SU.NodeNum] > Node2Index[PD.getSUnit()->NodeNum] && "Wrong topological sorting"); } } #endif } -/// AddPred - Updates the topological ordering to accommodate an edge -/// to be added from SUnit X to SUnit Y. void ScheduleDAGTopologicalSort::AddPred(SUnit *Y, SUnit *X) { int UpperBound, LowerBound; LowerBound = Node2Index[Y->NodeNum]; @@ -541,16 +502,10 @@ void ScheduleDAGTopologicalSort::AddPred(SUnit *Y, SUnit *X) { } } -/// RemovePred - Updates the topological ordering to accommodate an -/// an edge to be removed from the specified node N from the predecessors -/// of the current node M. void ScheduleDAGTopologicalSort::RemovePred(SUnit *M, SUnit *N) { // InitDAGTopologicalSorting(); } -/// DFS - Make a DFS traversal to mark all nodes reachable from SU and mark -/// all nodes affected by the edge insertion. These nodes will later get new -/// topological indexes by means of the Shift method. void ScheduleDAGTopologicalSort::DFS(const SUnit *SU, int UpperBound, bool &HasLoop) { std::vector WorkList; @@ -561,8 +516,9 @@ void ScheduleDAGTopologicalSort::DFS(const SUnit *SU, int UpperBound, SU = WorkList.back(); WorkList.pop_back(); Visited.set(SU->NodeNum); - for (int I = SU->Succs.size()-1; I >= 0; --I) { - unsigned s = SU->Succs[I].getSUnit()->NodeNum; + for (const SDep &SuccDep + : make_range(SU->Succs.rbegin(), SU->Succs.rend())) { + unsigned s = SuccDep.getSUnit()->NodeNum; // Edges to non-SUnits are allowed but ignored (e.g. ExitSU). if (s >= Node2Index.size()) continue; @@ -572,14 +528,12 @@ void ScheduleDAGTopologicalSort::DFS(const SUnit *SU, int UpperBound, } // Visit successors if not already and in affected region. if (!Visited.test(s) && Node2Index[s] < UpperBound) { - WorkList.push_back(SU->Succs[I].getSUnit()); + WorkList.push_back(SuccDep.getSUnit()); } } } while (!WorkList.empty()); } -/// Shift - Renumber the nodes so that the topological ordering is -/// preserved. void ScheduleDAGTopologicalSort::Shift(BitVector& Visited, int LowerBound, int UpperBound) { std::vector L; @@ -599,28 +553,24 @@ void ScheduleDAGTopologicalSort::Shift(BitVector& Visited, int LowerBound, } } - for (unsigned j = 0; j < L.size(); ++j) { - Allocate(L[j], i - shift); + for (unsigned LI : L) { + Allocate(LI, i - shift); i = i + 1; } } -/// WillCreateCycle - Returns true if adding an edge to TargetSU from SU will -/// create a cycle. If so, it is not safe to call AddPred(TargetSU, SU). bool ScheduleDAGTopologicalSort::WillCreateCycle(SUnit *TargetSU, SUnit *SU) { // Is SU reachable from TargetSU via successor edges? if (IsReachable(SU, TargetSU)) return true; - for (SUnit::pred_iterator - I = TargetSU->Preds.begin(), E = TargetSU->Preds.end(); I != E; ++I) - if (I->isAssignedRegDep() && - IsReachable(SU, I->getSUnit())) + for (const SDep &PredDep : TargetSU->Preds) + if (PredDep.isAssignedRegDep() && + IsReachable(SU, PredDep.getSUnit())) return true; return false; } -/// IsReachable - Checks if SU is reachable from TargetSU. bool ScheduleDAGTopologicalSort::IsReachable(const SUnit *SU, const SUnit *TargetSU) { // If insertion of the edge SU->TargetSU would create a cycle @@ -638,7 +588,6 @@ bool ScheduleDAGTopologicalSort::IsReachable(const SUnit *SU, return HasLoop; } -/// Allocate - assign the topological index to the node n. void ScheduleDAGTopologicalSort::Allocate(int n, int index) { Node2Index[n] = index; Index2Node[index] = n;