LLVM API Documentation
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