]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/ADT/SCCIterator.h
Update tcpdump to 4.9.0.
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / ADT / SCCIterator.h
1 //===---- ADT/SCCIterator.h - Strongly Connected Comp. Iter. ----*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 ///
11 /// This builds on the llvm/ADT/GraphTraits.h file to find the strongly
12 /// connected components (SCCs) of a graph in O(N+E) time using Tarjan's DFS
13 /// algorithm.
14 ///
15 /// The SCC iterator has the important property that if a node in SCC S1 has an
16 /// edge to a node in SCC S2, then it visits S1 *after* S2.
17 ///
18 /// To visit S1 *before* S2, use the scc_iterator on the Inverse graph. (NOTE:
19 /// This requires some simple wrappers and is not supported yet.)
20 ///
21 //===----------------------------------------------------------------------===//
22
23 #ifndef LLVM_ADT_SCCITERATOR_H
24 #define LLVM_ADT_SCCITERATOR_H
25
26 #include "llvm/ADT/DenseMap.h"
27 #include "llvm/ADT/GraphTraits.h"
28 #include "llvm/ADT/iterator.h"
29 #include <vector>
30
31 namespace llvm {
32
33 /// \brief Enumerate the SCCs of a directed graph in reverse topological order
34 /// of the SCC DAG.
35 ///
36 /// This is implemented using Tarjan's DFS algorithm using an internal stack to
37 /// build up a vector of nodes in a particular SCC. Note that it is a forward
38 /// iterator and thus you cannot backtrack or re-visit nodes.
39 template <class GraphT, class GT = GraphTraits<GraphT>>
40 class scc_iterator : public iterator_facade_base<
41                          scc_iterator<GraphT, GT>, std::forward_iterator_tag,
42                          const std::vector<typename GT::NodeRef>, ptrdiff_t> {
43   typedef typename GT::NodeRef NodeRef;
44   typedef typename GT::ChildIteratorType ChildItTy;
45   typedef std::vector<NodeRef> SccTy;
46   typedef typename scc_iterator::reference reference;
47
48   /// Element of VisitStack during DFS.
49   struct StackElement {
50     NodeRef Node;         ///< The current node pointer.
51     ChildItTy NextChild;  ///< The next child, modified inplace during DFS.
52     unsigned MinVisited;  ///< Minimum uplink value of all children of Node.
53
54     StackElement(NodeRef Node, const ChildItTy &Child, unsigned Min)
55         : Node(Node), NextChild(Child), MinVisited(Min) {}
56
57     bool operator==(const StackElement &Other) const {
58       return Node == Other.Node &&
59              NextChild == Other.NextChild &&
60              MinVisited == Other.MinVisited;
61     }
62   };
63
64   /// The visit counters used to detect when a complete SCC is on the stack.
65   /// visitNum is the global counter.
66   ///
67   /// nodeVisitNumbers are per-node visit numbers, also used as DFS flags.
68   unsigned visitNum;
69   DenseMap<NodeRef, unsigned> nodeVisitNumbers;
70
71   /// Stack holding nodes of the SCC.
72   std::vector<NodeRef> SCCNodeStack;
73
74   /// The current SCC, retrieved using operator*().
75   SccTy CurrentSCC;
76
77   /// DFS stack, Used to maintain the ordering.  The top contains the current
78   /// node, the next child to visit, and the minimum uplink value of all child
79   std::vector<StackElement> VisitStack;
80
81   /// A single "visit" within the non-recursive DFS traversal.
82   void DFSVisitOne(NodeRef N);
83
84   /// The stack-based DFS traversal; defined below.
85   void DFSVisitChildren();
86
87   /// Compute the next SCC using the DFS traversal.
88   void GetNextSCC();
89
90   scc_iterator(NodeRef entryN) : visitNum(0) {
91     DFSVisitOne(entryN);
92     GetNextSCC();
93   }
94
95   /// End is when the DFS stack is empty.
96   scc_iterator() {}
97
98 public:
99   static scc_iterator begin(const GraphT &G) {
100     return scc_iterator(GT::getEntryNode(G));
101   }
102   static scc_iterator end(const GraphT &) { return scc_iterator(); }
103
104   /// \brief Direct loop termination test which is more efficient than
105   /// comparison with \c end().
106   bool isAtEnd() const {
107     assert(!CurrentSCC.empty() || VisitStack.empty());
108     return CurrentSCC.empty();
109   }
110
111   bool operator==(const scc_iterator &x) const {
112     return VisitStack == x.VisitStack && CurrentSCC == x.CurrentSCC;
113   }
114
115   scc_iterator &operator++() {
116     GetNextSCC();
117     return *this;
118   }
119
120   reference operator*() const {
121     assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!");
122     return CurrentSCC;
123   }
124
125   /// \brief Test if the current SCC has a loop.
126   ///
127   /// If the SCC has more than one node, this is trivially true.  If not, it may
128   /// still contain a loop if the node has an edge back to itself.
129   bool hasLoop() const;
130
131   /// This informs the \c scc_iterator that the specified \c Old node
132   /// has been deleted, and \c New is to be used in its place.
133   void ReplaceNode(NodeRef Old, NodeRef New) {
134     assert(nodeVisitNumbers.count(Old) && "Old not in scc_iterator?");
135     nodeVisitNumbers[New] = nodeVisitNumbers[Old];
136     nodeVisitNumbers.erase(Old);
137   }
138 };
139
140 template <class GraphT, class GT>
141 void scc_iterator<GraphT, GT>::DFSVisitOne(NodeRef N) {
142   ++visitNum;
143   nodeVisitNumbers[N] = visitNum;
144   SCCNodeStack.push_back(N);
145   VisitStack.push_back(StackElement(N, GT::child_begin(N), visitNum));
146 #if 0 // Enable if needed when debugging.
147   dbgs() << "TarjanSCC: Node " << N <<
148         " : visitNum = " << visitNum << "\n";
149 #endif
150 }
151
152 template <class GraphT, class GT>
153 void scc_iterator<GraphT, GT>::DFSVisitChildren() {
154   assert(!VisitStack.empty());
155   while (VisitStack.back().NextChild != GT::child_end(VisitStack.back().Node)) {
156     // TOS has at least one more child so continue DFS
157     NodeRef childN = *VisitStack.back().NextChild++;
158     typename DenseMap<NodeRef, unsigned>::iterator Visited =
159         nodeVisitNumbers.find(childN);
160     if (Visited == nodeVisitNumbers.end()) {
161       // this node has never been seen.
162       DFSVisitOne(childN);
163       continue;
164     }
165
166     unsigned childNum = Visited->second;
167     if (VisitStack.back().MinVisited > childNum)
168       VisitStack.back().MinVisited = childNum;
169   }
170 }
171
172 template <class GraphT, class GT> void scc_iterator<GraphT, GT>::GetNextSCC() {
173   CurrentSCC.clear(); // Prepare to compute the next SCC
174   while (!VisitStack.empty()) {
175     DFSVisitChildren();
176
177     // Pop the leaf on top of the VisitStack.
178     NodeRef visitingN = VisitStack.back().Node;
179     unsigned minVisitNum = VisitStack.back().MinVisited;
180     assert(VisitStack.back().NextChild == GT::child_end(visitingN));
181     VisitStack.pop_back();
182
183     // Propagate MinVisitNum to parent so we can detect the SCC starting node.
184     if (!VisitStack.empty() && VisitStack.back().MinVisited > minVisitNum)
185       VisitStack.back().MinVisited = minVisitNum;
186
187 #if 0 // Enable if needed when debugging.
188     dbgs() << "TarjanSCC: Popped node " << visitingN <<
189           " : minVisitNum = " << minVisitNum << "; Node visit num = " <<
190           nodeVisitNumbers[visitingN] << "\n";
191 #endif
192
193     if (minVisitNum != nodeVisitNumbers[visitingN])
194       continue;
195
196     // A full SCC is on the SCCNodeStack!  It includes all nodes below
197     // visitingN on the stack.  Copy those nodes to CurrentSCC,
198     // reset their minVisit values, and return (this suspends
199     // the DFS traversal till the next ++).
200     do {
201       CurrentSCC.push_back(SCCNodeStack.back());
202       SCCNodeStack.pop_back();
203       nodeVisitNumbers[CurrentSCC.back()] = ~0U;
204     } while (CurrentSCC.back() != visitingN);
205     return;
206   }
207 }
208
209 template <class GraphT, class GT>
210 bool scc_iterator<GraphT, GT>::hasLoop() const {
211     assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!");
212     if (CurrentSCC.size() > 1)
213       return true;
214     NodeRef N = CurrentSCC.front();
215     for (ChildItTy CI = GT::child_begin(N), CE = GT::child_end(N); CI != CE;
216          ++CI)
217       if (*CI == N)
218         return true;
219     return false;
220   }
221
222 /// \brief Construct the begin iterator for a deduced graph type T.
223 template <class T> scc_iterator<T> scc_begin(const T &G) {
224   return scc_iterator<T>::begin(G);
225 }
226
227 /// \brief Construct the end iterator for a deduced graph type T.
228 template <class T> scc_iterator<T> scc_end(const T &G) {
229   return scc_iterator<T>::end(G);
230 }
231
232 /// \brief Construct the begin iterator for a deduced graph type T's Inverse<T>.
233 template <class T> scc_iterator<Inverse<T> > scc_begin(const Inverse<T> &G) {
234   return scc_iterator<Inverse<T> >::begin(G);
235 }
236
237 /// \brief Construct the end iterator for a deduced graph type T's Inverse<T>.
238 template <class T> scc_iterator<Inverse<T> > scc_end(const Inverse<T> &G) {
239   return scc_iterator<Inverse<T> >::end(G);
240 }
241
242 } // End llvm namespace
243
244 #endif