LLVM API Documentation

SCCIterator.h
Go to the documentation of this file.
00001 //===---- ADT/SCCIterator.h - Strongly Connected Comp. Iter. ----*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 /// \file
00010 ///
00011 /// This builds on the llvm/ADT/GraphTraits.h file to find the strongly
00012 /// connected components (SCCs) of a graph in O(N+E) time using Tarjan's DFS
00013 /// algorithm.
00014 ///
00015 /// The SCC iterator has the important property that if a node in SCC S1 has an
00016 /// edge to a node in SCC S2, then it visits S1 *after* S2.
00017 ///
00018 /// To visit S1 *before* S2, use the scc_iterator on the Inverse graph. (NOTE:
00019 /// This requires some simple wrappers and is not supported yet.)
00020 ///
00021 //===----------------------------------------------------------------------===//
00022 
00023 #ifndef LLVM_ADT_SCCITERATOR_H
00024 #define LLVM_ADT_SCCITERATOR_H
00025 
00026 #include "llvm/ADT/DenseMap.h"
00027 #include "llvm/ADT/GraphTraits.h"
00028 #include "llvm/ADT/iterator.h"
00029 #include <vector>
00030 
00031 namespace llvm {
00032 
00033 /// \brief Enumerate the SCCs of a directed graph in reverse topological order
00034 /// of the SCC DAG.
00035 ///
00036 /// This is implemented using Tarjan's DFS algorithm using an internal stack to
00037 /// build up a vector of nodes in a particular SCC. Note that it is a forward
00038 /// iterator and thus you cannot backtrack or re-visit nodes.
00039 template <class GraphT, class GT = GraphTraits<GraphT>>
00040 class scc_iterator
00041     : public iterator_facade_base<
00042           scc_iterator<GraphT, GT>, std::forward_iterator_tag,
00043           const std::vector<typename GT::NodeType *>, ptrdiff_t> {
00044   typedef typename GT::NodeType NodeType;
00045   typedef typename GT::ChildIteratorType ChildItTy;
00046   typedef std::vector<NodeType *> SccTy;
00047   typedef typename scc_iterator::reference reference;
00048 
00049   /// Element of VisitStack during DFS.
00050   struct StackElement {
00051     NodeType *Node;       ///< The current node pointer.
00052     ChildItTy NextChild;  ///< The next child, modified inplace during DFS.
00053     unsigned MinVisited;  ///< Minimum uplink value of all children of Node.
00054 
00055     StackElement(NodeType *Node, const ChildItTy &Child, unsigned Min)
00056       : Node(Node), NextChild(Child), MinVisited(Min) {}
00057 
00058     bool operator==(const StackElement &Other) const {
00059       return Node == Other.Node &&
00060              NextChild == Other.NextChild &&
00061              MinVisited == Other.MinVisited;
00062     }
00063   };
00064 
00065   /// The visit counters used to detect when a complete SCC is on the stack.
00066   /// visitNum is the global counter.
00067   ///
00068   /// nodeVisitNumbers are per-node visit numbers, also used as DFS flags.
00069   unsigned visitNum;
00070   DenseMap<NodeType *, unsigned> nodeVisitNumbers;
00071 
00072   /// Stack holding nodes of the SCC.
00073   std::vector<NodeType *> SCCNodeStack;
00074 
00075   /// The current SCC, retrieved using operator*().
00076   SccTy CurrentSCC;
00077 
00078   /// DFS stack, Used to maintain the ordering.  The top contains the current
00079   /// node, the next child to visit, and the minimum uplink value of all child
00080   std::vector<StackElement> VisitStack;
00081 
00082   /// A single "visit" within the non-recursive DFS traversal.
00083   void DFSVisitOne(NodeType *N);
00084 
00085   /// The stack-based DFS traversal; defined below.
00086   void DFSVisitChildren();
00087 
00088   /// Compute the next SCC using the DFS traversal.
00089   void GetNextSCC();
00090 
00091   scc_iterator(NodeType *entryN) : visitNum(0) {
00092     DFSVisitOne(entryN);
00093     GetNextSCC();
00094   }
00095 
00096   /// End is when the DFS stack is empty.
00097   scc_iterator() {}
00098 
00099 public:
00100   static scc_iterator begin(const GraphT &G) {
00101     return scc_iterator(GT::getEntryNode(G));
00102   }
00103   static scc_iterator end(const GraphT &) { return scc_iterator(); }
00104 
00105   /// \brief Direct loop termination test which is more efficient than
00106   /// comparison with \c end().
00107   bool isAtEnd() const {
00108     assert(!CurrentSCC.empty() || VisitStack.empty());
00109     return CurrentSCC.empty();
00110   }
00111 
00112   bool operator==(const scc_iterator &x) const {
00113     return VisitStack == x.VisitStack && CurrentSCC == x.CurrentSCC;
00114   }
00115 
00116   scc_iterator &operator++() {
00117     GetNextSCC();
00118     return *this;
00119   }
00120 
00121   reference operator*() const {
00122     assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!");
00123     return CurrentSCC;
00124   }
00125 
00126   /// \brief Test if the current SCC has a loop.
00127   ///
00128   /// If the SCC has more than one node, this is trivially true.  If not, it may
00129   /// still contain a loop if the node has an edge back to itself.
00130   bool hasLoop() const;
00131 
00132   /// This informs the \c scc_iterator that the specified \c Old node
00133   /// has been deleted, and \c New is to be used in its place.
00134   void ReplaceNode(NodeType *Old, NodeType *New) {
00135     assert(nodeVisitNumbers.count(Old) && "Old not in scc_iterator?");
00136     nodeVisitNumbers[New] = nodeVisitNumbers[Old];
00137     nodeVisitNumbers.erase(Old);
00138   }
00139 };
00140 
00141 template <class GraphT, class GT>
00142 void scc_iterator<GraphT, GT>::DFSVisitOne(NodeType *N) {
00143   ++visitNum;
00144   nodeVisitNumbers[N] = visitNum;
00145   SCCNodeStack.push_back(N);
00146   VisitStack.push_back(StackElement(N, GT::child_begin(N), visitNum));
00147 #if 0 // Enable if needed when debugging.
00148   dbgs() << "TarjanSCC: Node " << N <<
00149         " : visitNum = " << visitNum << "\n";
00150 #endif
00151 }
00152 
00153 template <class GraphT, class GT>
00154 void scc_iterator<GraphT, GT>::DFSVisitChildren() {
00155   assert(!VisitStack.empty());
00156   while (VisitStack.back().NextChild != GT::child_end(VisitStack.back().Node)) {
00157     // TOS has at least one more child so continue DFS
00158     NodeType *childN = *VisitStack.back().NextChild++;
00159     typename DenseMap<NodeType *, unsigned>::iterator Visited =
00160         nodeVisitNumbers.find(childN);
00161     if (Visited == nodeVisitNumbers.end()) {
00162       // this node has never been seen.
00163       DFSVisitOne(childN);
00164       continue;
00165     }
00166 
00167     unsigned childNum = Visited->second;
00168     if (VisitStack.back().MinVisited > childNum)
00169       VisitStack.back().MinVisited = childNum;
00170   }
00171 }
00172 
00173 template <class GraphT, class GT> void scc_iterator<GraphT, GT>::GetNextSCC() {
00174   CurrentSCC.clear(); // Prepare to compute the next SCC
00175   while (!VisitStack.empty()) {
00176     DFSVisitChildren();
00177 
00178     // Pop the leaf on top of the VisitStack.
00179     NodeType *visitingN = VisitStack.back().Node;
00180     unsigned minVisitNum = VisitStack.back().MinVisited;
00181     assert(VisitStack.back().NextChild == GT::child_end(visitingN));
00182     VisitStack.pop_back();
00183 
00184     // Propagate MinVisitNum to parent so we can detect the SCC starting node.
00185     if (!VisitStack.empty() && VisitStack.back().MinVisited > minVisitNum)
00186       VisitStack.back().MinVisited = minVisitNum;
00187 
00188 #if 0 // Enable if needed when debugging.
00189     dbgs() << "TarjanSCC: Popped node " << visitingN <<
00190           " : minVisitNum = " << minVisitNum << "; Node visit num = " <<
00191           nodeVisitNumbers[visitingN] << "\n";
00192 #endif
00193 
00194     if (minVisitNum != nodeVisitNumbers[visitingN])
00195       continue;
00196 
00197     // A full SCC is on the SCCNodeStack!  It includes all nodes below
00198     // visitingN on the stack.  Copy those nodes to CurrentSCC,
00199     // reset their minVisit values, and return (this suspends
00200     // the DFS traversal till the next ++).
00201     do {
00202       CurrentSCC.push_back(SCCNodeStack.back());
00203       SCCNodeStack.pop_back();
00204       nodeVisitNumbers[CurrentSCC.back()] = ~0U;
00205     } while (CurrentSCC.back() != visitingN);
00206     return;
00207   }
00208 }
00209 
00210 template <class GraphT, class GT>
00211 bool scc_iterator<GraphT, GT>::hasLoop() const {
00212     assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!");
00213     if (CurrentSCC.size() > 1)
00214       return true;
00215     NodeType *N = CurrentSCC.front();
00216     for (ChildItTy CI = GT::child_begin(N), CE = GT::child_end(N); CI != CE;
00217          ++CI)
00218       if (*CI == N)
00219         return true;
00220     return false;
00221   }
00222 
00223 /// \brief Construct the begin iterator for a deduced graph type T.
00224 template <class T> scc_iterator<T> scc_begin(const T &G) {
00225   return scc_iterator<T>::begin(G);
00226 }
00227 
00228 /// \brief Construct the end iterator for a deduced graph type T.
00229 template <class T> scc_iterator<T> scc_end(const T &G) {
00230   return scc_iterator<T>::end(G);
00231 }
00232 
00233 /// \brief Construct the begin iterator for a deduced graph type T's Inverse<T>.
00234 template <class T> scc_iterator<Inverse<T> > scc_begin(const Inverse<T> &G) {
00235   return scc_iterator<Inverse<T> >::begin(G);
00236 }
00237 
00238 /// \brief Construct the end iterator for a deduced graph type T's Inverse<T>.
00239 template <class T> scc_iterator<Inverse<T> > scc_end(const Inverse<T> &G) {
00240   return scc_iterator<Inverse<T> >::end(G);
00241 }
00242 
00243 } // End llvm namespace
00244 
00245 #endif