X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FCodeGen%2FScheduleDAG.h;h=e032df89018cf35d5204dce6d30d73e3b089a0bc;hb=3627e34486db088661bc7fb6c0dde6a18a543217;hp=2394c5865b1144952cdd932b32dfec28578ae7c8;hpb=7593639df672018d90331774f45b5ef06da2f385;p=oota-llvm.git diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 2394c5865b1..e032df89018 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by Evan Cheng and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -15,35 +15,29 @@ #ifndef LLVM_CODEGEN_SCHEDULEDAG_H #define LLVM_CODEGEN_SCHEDULEDAG_H +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SmallSet.h" namespace llvm { struct InstrStage; + struct SUnit; class MachineConstantPool; - class MachineDebugInfo; + class MachineFunction; + class MachineModuleInfo; + class MachineRegisterInfo; class MachineInstr; - class MRegisterInfo; + class TargetRegisterInfo; class SelectionDAG; - class SSARegMap; + class SelectionDAGISel; class TargetInstrInfo; - class TargetInstrDescriptor; + class TargetInstrDesc; + class TargetLowering; class TargetMachine; + class TargetRegisterClass; - class NodeInfo; - typedef NodeInfo *NodeInfoPtr; - typedef std::vector NIVector; - typedef std::vector::iterator NIIterator; - - // Scheduling heuristics - enum SchedHeuristics { - 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. @@ -54,7 +48,7 @@ namespace llvm { 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. + NoopHazard // This instruction can't be emitted, and needs noops. }; /// getHazardType - Return the hazard type of emitting this node. There are @@ -64,346 +58,426 @@ namespace llvm { /// 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) { + virtual HazardType getHazardType(SDNode *) { return NoHazard; } /// EmitInstruction - This callback is invoked when an instruction is /// emitted, to advance the hazard state. - virtual void EmitInstruction(SDNode *Node) { - } + virtual void EmitInstruction(SDNode *) {} /// 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() { - } + virtual void AdvanceCycle() {} /// EmitNoop - This callback is invoked when a noop was added to the /// instruction stream. - virtual void EmitNoop() { - } + 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 - 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); + /// SDep - Scheduling dependency. It keeps track of dependent nodes, + /// cost of the depdenency, etc. + struct SDep { + SUnit *Dep; // Dependent - either a predecessor or a successor. + unsigned Reg; // If non-zero, this dep is a phy register dependency. + int Cost; // Cost of the dependency. + bool isCtrl : 1; // True iff it's a control dependency. + bool isSpecial : 1; // True iff it's a special ctrl dep added during sched. + SDep(SUnit *d, unsigned r, int t, bool c, bool s) + : Dep(d), Reg(r), Cost(t), isCtrl(c), isSpecial(s) {} }; - //===--------------------------------------------------------------------===// - /// - /// 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 + /// SUnit - Scheduling unit. It's an wrapper around either a single SDNode or + /// a group of nodes flagged together. + struct SUnit { + SDNode *Node; // Representative node. + SmallVector FlaggedNodes;// All nodes flagged to Node. + SUnit *OrigNode; // If not this, the node from which + // this node was cloned. + + // Preds/Succs - The SUnits before/after us in the graph. The boolean value + // is true if the edge is a token chain edge, false if it is a value edge. + SmallVector Preds; // All sunit predecessors. + SmallVector Succs; // All sunit successors. - // 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; + typedef SmallVector::iterator pred_iterator; + typedef SmallVector::iterator succ_iterator; + typedef SmallVector::const_iterator const_pred_iterator; + typedef SmallVector::const_iterator const_succ_iterator; + + unsigned NodeNum; // Entry # of node in the node vector. + unsigned NodeQueueId; // Queue id of node. + unsigned short Latency; // Node latency. + short NumPreds; // # of preds. + short NumSuccs; // # of sucss. + short NumPredsLeft; // # of preds not scheduled. + short NumSuccsLeft; // # of succs not scheduled. + bool isTwoAddress : 1; // Is a two-address instruction. + bool isCommutable : 1; // Is a commutable instruction. + bool hasPhysRegDefs : 1; // Has physreg defs that are being used. + bool isPending : 1; // True once pending. + bool isAvailable : 1; // True once available. + bool isScheduled : 1; // True once scheduled. + unsigned CycleBound; // Upper/lower cycle to be scheduled at. + unsigned Cycle; // Once scheduled, the cycle of the op. + unsigned Depth; // Node depth; + unsigned Height; // Node height; + const TargetRegisterClass *CopyDstRC; // Is a special copy node if not null. + const TargetRegisterClass *CopySrcRC; + + SUnit(SDNode *node, unsigned nodenum) + : Node(node), OrigNode(0), NodeNum(nodenum), NodeQueueId(0), Latency(0), + NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0), + isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), + isPending(false), isAvailable(false), isScheduled(false), + CycleBound(0), Cycle(0), Depth(0), Height(0), + CopyDstRC(NULL), CopySrcRC(NULL) {} + + /// addPred - This adds the specified node as a pred of the current node if + /// not already. This returns true if this is a new pred. + bool addPred(SUnit *N, bool isCtrl, bool isSpecial, + unsigned PhyReg = 0, int Cost = 1) { + for (unsigned i = 0, e = (unsigned)Preds.size(); i != e; ++i) + if (Preds[i].Dep == N && + Preds[i].isCtrl == isCtrl && Preds[i].isSpecial == isSpecial) + return false; + Preds.push_back(SDep(N, PhyReg, Cost, isCtrl, isSpecial)); + N->Succs.push_back(SDep(this, PhyReg, Cost, isCtrl, isSpecial)); + if (!isCtrl) { + ++NumPreds; + ++N->NumSuccs; + } + if (!N->isScheduled) + ++NumPredsLeft; + if (!isScheduled) + ++N->NumSuccsLeft; + return true; } - inline int addPending(int I) { - if (Group) return Group->addPending(I); - else return Pending += I; + + bool removePred(SUnit *N, bool isCtrl, bool isSpecial) { + for (SmallVector::iterator I = Preds.begin(), E = Preds.end(); + I != E; ++I) + if (I->Dep == N && I->isCtrl == isCtrl && I->isSpecial == isSpecial) { + bool FoundSucc = false; + for (SmallVector::iterator II = N->Succs.begin(), + EE = N->Succs.end(); II != EE; ++II) + if (II->Dep == this && + II->isCtrl == isCtrl && II->isSpecial == isSpecial) { + FoundSucc = true; + N->Succs.erase(II); + break; + } + assert(FoundSucc && "Mismatching preds / succs lists!"); + Preds.erase(I); + if (!isCtrl) { + --NumPreds; + --N->NumSuccs; + } + if (!N->isScheduled) + --NumPredsLeft; + if (!isScheduled) + --N->NumSuccsLeft; + return true; + } + return false; } - }; - //===--------------------------------------------------------------------===// - /// - /// 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; - } + bool isPred(SUnit *N) { + for (unsigned i = 0, e = (unsigned)Preds.size(); i != e; ++i) + if (Preds[i].Dep == N) + return true; + return false; } - - /// 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; + + bool isSucc(SUnit *N) { + for (unsigned i = 0, e = (unsigned)Succs.size(); i != e; ++i) + if (Succs[i].Dep == N) + return true; + return false; } + + void dump(const SelectionDAG *G) const; + void dumpAll(const SelectionDAG *G) const; }; - //===--------------------------------------------------------------------===// - //===--------------------------------------------------------------------===// - /// - /// 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(); - } - } - + /// 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. + /// + class SchedulingPriorityQueue { public: - // Ctor. - NodeGroupOpIterator(NodeInfo *N) - : NI(N), GI(N), OI(SDNode::op_iterator()), OE(SDNode::op_iterator()) {} + virtual ~SchedulingPriorityQueue() {} - /// isEnd - Returns true when not more operands are available. - /// - inline bool isEnd() { CheckNode(); return OI == OE; } + virtual void initNodes(DenseMap &SUMap, + std::vector &SUnits) = 0; + virtual void addNode(const SUnit *SU) = 0; + virtual void updateNode(const SUnit *SU) = 0; + virtual void releaseState() = 0; + + virtual unsigned size() const = 0; + virtual bool empty() const = 0; + virtual void push(SUnit *U) = 0; - /// next - Returns the next available operand. - /// - inline SDOperand next() { - assert(OI != OE && - "Not checking for end of NodeGroupOpIterator correctly"); - return *OI++; - } + virtual void push_all(const std::vector &Nodes) = 0; + virtual SUnit *pop() = 0; + + virtual void remove(SUnit *SU) = 0; + + /// ScheduledNode - As each node is scheduled, this method is invoked. This + /// allows the priority function to adjust the priority of node that have + /// already been emitted. + virtual void ScheduledNode(SUnit *) {} + + virtual void UnscheduledNode(SUnit *) {} }; class ScheduleDAG { public: - SchedHeuristics Heuristic; // Scheduling heuristic SelectionDAG &DAG; // DAG of the current basic block MachineBasicBlock *BB; // Current basic block const TargetMachine &TM; // Target processor const TargetInstrInfo *TII; // Target instruction information - const MRegisterInfo *MRI; // Target processor register info - SSARegMap *RegMap; // Virtual/real register map + const TargetRegisterInfo *TRI; // Target processor register info + TargetLowering *TLI; // Target lowering info + MachineFunction *MF; // Machine function + MachineRegisterInfo &MRI; // Virtual/real register map MachineConstantPool *ConstPool; // Target constant pool - std::map Map; // Map nodes to info - unsigned NodeCount; // Number of nodes in DAG - 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), HeadNG(NULL), TailNG(NULL) {} - - virtual ~ScheduleDAG() { - if (Info) - delete[] Info; - - NodeGroup *NG = HeadNG; - while (NG) { - NodeGroup *NextSU = NG->Next; - delete NG; - NG = NextSU; - } - }; + std::vector Sequence; // The schedule. Null SUnit*'s + // represent noop instructions. + DenseMap SUnitMap; // SDNode to SUnit mapping (n -> n). + std::vector SUnits; // The scheduling units. + SmallSet CommuteSet; // Nodes that should be commuted. + + ScheduleDAG(SelectionDAG &dag, MachineBasicBlock *bb, + const TargetMachine &tm); + virtual ~ScheduleDAG() {} + + /// viewGraph - Pop up a GraphViz/gv window with the ScheduleDAG rendered + /// using 'dot'. + /// + void viewGraph(); + /// Run - perform scheduling. /// MachineBasicBlock *Run(); - /// getNI - Returns the node info for the specified node. - /// - NodeInfo *getNI(SDNode *Node) { return Map[Node]; } - /// isPassiveNode - Return true if the node is a non-scheduled leaf. /// static bool isPassiveNode(SDNode *Node) { if (isa(Node)) return true; + if (isa(Node)) return true; if (isa(Node)) return true; if (isa(Node)) return true; if (isa(Node)) return true; if (isa(Node)) return true; if (isa(Node)) return true; + if (isa(Node)) return true; if (isa(Node)) return true; + if (isa(Node)) return true; + if (Node->getOpcode() == ISD::EntryToken) return true; return false; } + /// NewSUnit - Creates a new SUnit and return a ptr to it. + /// + SUnit *NewSUnit(SDNode *N) { + SUnits.push_back(SUnit(N, (unsigned)SUnits.size())); + SUnits.back().OrigNode = &SUnits.back(); + return &SUnits.back(); + } + + /// Clone - Creates a clone of the specified SUnit. It does not copy the + /// predecessors / successors info nor the temporary scheduling states. + SUnit *Clone(SUnit *N); + + /// BuildSchedUnits - Build SUnits from the selection dag that we are input. + /// This SUnit graph is similar to the SelectionDAG, but represents flagged + /// together nodes with a single SUnit. + void BuildSchedUnits(); + + /// ComputeLatency - Compute node latency. + /// + void ComputeLatency(SUnit *SU); + + /// CalculateDepths, CalculateHeights - Calculate node depth / height. + /// + void CalculateDepths(); + void CalculateHeights(); + + /// CountResults - The results of target nodes have register or immediate + /// operands first, then an optional chain, and optional flag operands + /// (which do not go into the machine instrs.) + static unsigned CountResults(SDNode *Node); + + /// CountOperands - The inputs to target nodes have any actual inputs first, + /// followed by special operands that describe memory references, then an + /// optional chain operand, then flag operands. Compute the number of + /// actual operands that will go into the resulting MachineInstr. + static unsigned CountOperands(SDNode *Node); + + /// ComputeMemOperandsEnd - Find the index one past the last + /// MemOperandSDNode operand + static unsigned ComputeMemOperandsEnd(SDNode *Node); + /// 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, std::map &VRBaseMap); + void EmitNode(SDNode *Node, bool IsClone, + DenseMap &VRBaseMap); /// EmitNoop - Emit a noop instruction. /// void EmitNoop(); - - /// EmitAll - Emit all nodes in schedule sorted order. - /// - void EmitAll(); + + void EmitSchedule(); + + void dumpSchedule() const; /// Schedule - Order nodes according to selected style. /// virtual void Schedule() {} - /// printNI - Print node info. + private: + /// EmitSubregNode - Generate machine code for subreg nodes. /// - void printNI(std::ostream &O, NodeInfo *NI) const; + void EmitSubregNode(SDNode *Node, + DenseMap &VRBaseMap); - /// printChanges - Hilight changes in order caused by scheduling. - /// - void printChanges(unsigned Index) const; + /// getVR - Return the virtual register corresponding to the specified result + /// of the specified node. + unsigned getVR(SDOperand Op, DenseMap &VRBaseMap); + + /// getDstOfCopyToRegUse - If the only use of the specified result number of + /// node is a CopyToReg, return its destination register. Return 0 otherwise. + unsigned getDstOfOnlyCopyToRegUse(SDNode *Node, unsigned ResNo) const; - /// print - Print ordering to specified output stream. - /// - void print(std::ostream &O) const; + void AddOperand(MachineInstr *MI, SDOperand Op, unsigned IIOpNum, + const TargetInstrDesc *II, + DenseMap &VRBaseMap); - void dump(const char *tag) const; + void AddMemOperand(MachineInstr *MI, const MachineMemOperand &MO); - virtual void dump() const; + void EmitCrossRCCopy(SUnit *SU, DenseMap &VRBaseMap); - private: - void AddOperand(MachineInstr *MI, SDOperand Op, unsigned IIOpNum, - const TargetInstrDescriptor *II, - std::map &VRBaseMap); - - void AddToGroup(NodeInfo *D, NodeInfo *U); -protected: - /// PrepareNodeInfo - Set up the basic minimum node info for scheduling. - /// - void PrepareNodeInfo(); + /// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an + /// implicit physical register output. + void EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone, + unsigned SrcReg, + DenseMap &VRBaseMap); - /// IdentifyGroups - Put flagged nodes into groups. - /// - void IdentifyGroups(); - }; + void CreateVirtualRegisters(SDNode *Node, MachineInstr *MI, + const TargetInstrDesc &II, + DenseMap &VRBaseMap); - /// createSimpleDAGScheduler - This creates a simple two pass instruction - /// scheduler. - ScheduleDAG* createSimpleDAGScheduler(SchedHeuristics Heuristic, - SelectionDAG &DAG, - MachineBasicBlock *BB); + /// EmitLiveInCopy - Emit a copy for a live in physical register. If the + /// physical register has only a single copy use, then coalesced the copy + /// if possible. + void EmitLiveInCopy(MachineBasicBlock *MBB, + MachineBasicBlock::iterator &InsertPos, + unsigned VirtReg, unsigned PhysReg, + const TargetRegisterClass *RC, + DenseMap &CopyRegMap); + + /// EmitLiveInCopies - 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. + void EmitLiveInCopies(MachineBasicBlock *MBB); + }; /// createBURRListDAGScheduler - This creates a bottom up register usage /// reduction list scheduler. - ScheduleDAG* createBURRListDAGScheduler(SelectionDAG &DAG, + ScheduleDAG* createBURRListDAGScheduler(SelectionDAGISel *IS, + SelectionDAG *DAG, + MachineBasicBlock *BB); + + /// createTDRRListDAGScheduler - This creates a top down register usage + /// reduction list scheduler. + ScheduleDAG* createTDRRListDAGScheduler(SelectionDAGISel *IS, + 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); + /// a hazard recognizer. + ScheduleDAG* createTDListDAGScheduler(SelectionDAGISel *IS, + SelectionDAG *DAG, + MachineBasicBlock *BB); + + /// createDefaultScheduler - This creates an instruction scheduler appropriate + /// for the target. + ScheduleDAG* createDefaultScheduler(SelectionDAGISel *IS, + SelectionDAG *DAG, + MachineBasicBlock *BB); + + class SUnitIterator : public forward_iterator { + 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); } + + const SUnitIterator &operator=(const SUnitIterator &I) { + assert(I.Node == Node && "Cannot assign iterators to two different nodes!"); + Operand = I.Operand; + return *this; + } + + pointer operator*() const { + return Node->Preds[Operand].Dep; + } + 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; } + bool isCtrlDep() const { return Node->Preds[Operand].isCtrl; } + bool isSpecialDep() const { return Node->Preds[Operand].isSpecial; } + }; + + template <> struct GraphTraits { + typedef SUnit NodeType; + typedef SUnitIterator ChildIteratorType; + static inline NodeType *getEntryNode(SUnit *N) { return N; } + static inline ChildIteratorType child_begin(NodeType *N) { + return SUnitIterator::begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return SUnitIterator::end(N); + } + }; + + template <> struct GraphTraits : public GraphTraits { + typedef std::vector::iterator nodes_iterator; + static nodes_iterator nodes_begin(ScheduleDAG *G) { + return G->SUnits.begin(); + } + static nodes_iterator nodes_end(ScheduleDAG *G) { + return G->SUnits.end(); + } + }; } #endif