blob: 7df5c26f98d8a3c1a32c20c1f8c2c880ec5376f5 [file] [log] [blame]
Chris Lattner555eaf52003-09-30 18:37:50 +00001//===- Support/DepthFirstIterator.h - Depth First iterator ------*- C++ -*-===//
Chris Lattner409bbec2001-09-28 22:59:14 +00002//
3// This file builds on the Support/GraphTraits.h file to build generic depth
Chris Lattner97b07c22003-10-13 15:45:33 +00004// first graph iterator. This file exposes the following functions/types:
5//
6// df_begin/df_end/df_iterator
7// * Normal depth-first iteration - visit a node and then all of its children.
8//
9// idf_begin/idf_end/idf_iterator
10// * Depth-first iteration on the 'inverse' graph.
Chris Lattner409bbec2001-09-28 22:59:14 +000011//
Chris Lattner514e18c2003-10-13 16:34:26 +000012// df_ext_begin/df_ext_end/df_ext_iterator
13// * Normal depth-first iteration - visit a node and then all of its children.
14// This iterator stores the 'visited' set in an external set, which allows
15// it to be more efficient, and allows external clients to use the set for
16// other purposes.
17//
18// idf_ext_begin/idf_ext_end/idf_ext_iterator
19// * Depth-first iteration on the 'inverse' graph.
20// This iterator stores the 'visited' set in an external set, which allows
21// it to be more efficient, and allows external clients to use the set for
22// other purposes.
23//
Chris Lattner409bbec2001-09-28 22:59:14 +000024//===----------------------------------------------------------------------===//
25
Brian Gaekea7a50132003-06-17 00:35:55 +000026#ifndef SUPPORT_DEPTHFIRSTITERATOR_H
27#define SUPPORT_DEPTHFIRSTITERATOR_H
Chris Lattner409bbec2001-09-28 22:59:14 +000028
Chris Lattner5de22042001-11-27 00:03:19 +000029#include "Support/GraphTraits.h"
Chris Lattner94a4f222002-10-28 02:11:53 +000030#include "Support/iterator"
Chris Lattner97b07c22003-10-13 15:45:33 +000031#include <vector>
Chris Lattner409bbec2001-09-28 22:59:14 +000032#include <set>
33
Chris Lattner514e18c2003-10-13 16:34:26 +000034// df_iterator_storage - A private class which is used to figure out where to
35// store the visited set.
36template<class SetType, bool External> // Non-external set
37class df_iterator_storage {
38public:
39 SetType Visited;
40};
41
42template<class SetType>
43class df_iterator_storage<SetType, true> {
44public:
45 df_iterator_storage(SetType &VSet) : Visited(VSet) {}
46 df_iterator_storage(const df_iterator_storage &S) : Visited(S.Visited) {}
47 SetType &Visited;
48};
49
50
Chris Lattner409bbec2001-09-28 22:59:14 +000051// Generic Depth First Iterator
Chris Lattner514e18c2003-10-13 16:34:26 +000052template<class GraphT, class SetType =
53 std::set<typename GraphTraits<GraphT>::NodeType*>,
54 bool ExtStorage = false, class GT = GraphTraits<GraphT> >
55class df_iterator : public forward_iterator<typename GT::NodeType, ptrdiff_t>,
56 public df_iterator_storage<SetType, ExtStorage> {
Chris Lattner889cddf2002-07-24 22:08:36 +000057 typedef forward_iterator<typename GT::NodeType, ptrdiff_t> super;
Chris Lattner889cddf2002-07-24 22:08:36 +000058
Chris Lattner409bbec2001-09-28 22:59:14 +000059 typedef typename GT::NodeType NodeType;
60 typedef typename GT::ChildIteratorType ChildItTy;
61
Chris Lattner409bbec2001-09-28 22:59:14 +000062 // VisitStack - Used to maintain the ordering. Top = current block
63 // First element is node pointer, second is the 'next child' to visit
Chris Lattner97b07c22003-10-13 15:45:33 +000064 std::vector<std::pair<NodeType *, ChildItTy> > VisitStack;
Chris Lattner409bbec2001-09-28 22:59:14 +000065private:
Chris Lattner97b07c22003-10-13 15:45:33 +000066 inline df_iterator(NodeType *Node) {
Chris Lattner514e18c2003-10-13 16:34:26 +000067 this->Visited.insert(Node);
Chris Lattner97b07c22003-10-13 15:45:33 +000068 VisitStack.push_back(std::make_pair(Node, GT::child_begin(Node)));
Chris Lattner409bbec2001-09-28 22:59:14 +000069 }
70 inline df_iterator() { /* End is when stack is empty */ }
71
Chris Lattner514e18c2003-10-13 16:34:26 +000072 inline df_iterator(NodeType *Node, SetType &S)
73 : df_iterator_storage<SetType, ExtStorage>(S) {
74 if (!S.count(Node)) {
75 this->Visited.insert(Node);
76 VisitStack.push_back(std::make_pair(Node, GT::child_begin(Node)));
77 }
78 }
79 inline df_iterator(SetType &S)
80 : df_iterator_storage<SetType, ExtStorage>(S) {
81 // End is when stack is empty
82 }
83
Chris Lattner409bbec2001-09-28 22:59:14 +000084public:
Chris Lattner33d51022003-07-25 17:49:28 +000085 typedef typename super::pointer pointer;
Chris Lattner514e18c2003-10-13 16:34:26 +000086 typedef df_iterator<GraphT, SetType, ExtStorage, GT> _Self;
Chris Lattner409bbec2001-09-28 22:59:14 +000087
88 // Provide static begin and end methods as our public "constructors"
Chris Lattner97b07c22003-10-13 15:45:33 +000089 static inline _Self begin(GraphT G) {
90 return _Self(GT::getEntryNode(G));
Chris Lattner409bbec2001-09-28 22:59:14 +000091 }
92 static inline _Self end(GraphT G) { return _Self(); }
93
Chris Lattner514e18c2003-10-13 16:34:26 +000094 // Static begin and end methods as our public ctors for external iterators
95 static inline _Self begin(GraphT G, SetType &S) {
96 return _Self(GT::getEntryNode(G), S);
97 }
98 static inline _Self end(GraphT G, SetType &S) { return _Self(S); }
Chris Lattner409bbec2001-09-28 22:59:14 +000099
100 inline bool operator==(const _Self& x) const {
Chris Lattner97b07c22003-10-13 15:45:33 +0000101 return VisitStack.size() == x.VisitStack.size() &&
102 VisitStack == x.VisitStack;
Chris Lattner409bbec2001-09-28 22:59:14 +0000103 }
104 inline bool operator!=(const _Self& x) const { return !operator==(x); }
105
106 inline pointer operator*() const {
Chris Lattner97b07c22003-10-13 15:45:33 +0000107 return VisitStack.back().first;
Chris Lattner409bbec2001-09-28 22:59:14 +0000108 }
109
110 // This is a nonstandard operator-> that dereferences the pointer an extra
111 // time... so that you can actually call methods ON the Node, because
112 // the contained type is a pointer. This allows BBIt->getTerminator() f.e.
113 //
114 inline NodeType *operator->() const { return operator*(); }
115
116 inline _Self& operator++() { // Preincrement
Chris Lattner97b07c22003-10-13 15:45:33 +0000117 do {
118 std::pair<NodeType *, ChildItTy> &Top = VisitStack.back();
119 NodeType *Node = Top.first;
120 ChildItTy &It = Top.second;
121
122 while (It != GT::child_end(Node)) {
123 NodeType *Next = *It++;
Chris Lattner514e18c2003-10-13 16:34:26 +0000124 if (!this->Visited.count(Next)) { // Has our next sibling been visited?
Chris Lattner97b07c22003-10-13 15:45:33 +0000125 // No, do it now.
Chris Lattner514e18c2003-10-13 16:34:26 +0000126 this->Visited.insert(Next);
Chris Lattner97b07c22003-10-13 15:45:33 +0000127 VisitStack.push_back(std::make_pair(Next, GT::child_begin(Next)));
128 return *this;
129 }
130 }
131
132 // Oops, ran out of successors... go up a level on the stack.
133 VisitStack.pop_back();
134 } while (!VisitStack.empty());
Chris Lattner409bbec2001-09-28 22:59:14 +0000135 return *this;
136 }
137
138 inline _Self operator++(int) { // Postincrement
139 _Self tmp = *this; ++*this; return tmp;
140 }
141
142 // nodeVisited - return true if this iterator has already visited the
143 // specified node. This is public, and will probably be used to iterate over
144 // nodes that a depth first iteration did not find: ie unreachable nodes.
145 //
146 inline bool nodeVisited(NodeType *Node) const {
Chris Lattner514e18c2003-10-13 16:34:26 +0000147 return this->Visited.count(Node) != 0;
Chris Lattner409bbec2001-09-28 22:59:14 +0000148 }
149};
150
151
152// Provide global constructors that automatically figure out correct types...
153//
154template <class T>
Chris Lattner97b07c22003-10-13 15:45:33 +0000155df_iterator<T> df_begin(T G) {
156 return df_iterator<T>::begin(G);
Chris Lattner409bbec2001-09-28 22:59:14 +0000157}
158
159template <class T>
160df_iterator<T> df_end(T G) {
161 return df_iterator<T>::end(G);
162}
163
Chris Lattner514e18c2003-10-13 16:34:26 +0000164// Provide global definitions of external depth first iterators...
Chris Lattnera3244bb2003-10-13 16:44:30 +0000165template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeType*> >
Chris Lattner514e18c2003-10-13 16:34:26 +0000166struct df_ext_iterator : public df_iterator<T, SetTy, true> {
167 df_ext_iterator(const df_iterator<T, SetTy, true> &V)
168 : df_iterator<T, SetTy, true>(V) {}
169};
170
171template <class T, class SetTy>
172df_ext_iterator<T, SetTy> df_ext_begin(T G, SetTy &S) {
173 return df_ext_iterator<T, SetTy>::begin(G, S);
174}
175
176template <class T, class SetTy>
177df_ext_iterator<T, SetTy> df_ext_end(T G, SetTy &S) {
178 return df_ext_iterator<T, SetTy>::end(G, S);
179}
180
181
Chris Lattner409bbec2001-09-28 22:59:14 +0000182// Provide global definitions of inverse depth first iterators...
Chris Lattner514e18c2003-10-13 16:34:26 +0000183template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeType*>,
184 bool External = false>
185struct idf_iterator : public df_iterator<Inverse<T>, SetTy, External> {
186 idf_iterator(const df_iterator<Inverse<T>, SetTy, External> &V)
187 : df_iterator<Inverse<T>, SetTy, External>(V) {}
Chris Lattner409bbec2001-09-28 22:59:14 +0000188};
189
190template <class T>
Chris Lattner97b07c22003-10-13 15:45:33 +0000191idf_iterator<T> idf_begin(T G) {
192 return idf_iterator<T>::begin(G);
Chris Lattner409bbec2001-09-28 22:59:14 +0000193}
194
195template <class T>
196idf_iterator<T> idf_end(T G){
197 return idf_iterator<T>::end(G);
198}
199
Chris Lattner514e18c2003-10-13 16:34:26 +0000200// Provide global definitions of external inverse depth first iterators...
201template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeType*> >
202struct idf_ext_iterator : public idf_iterator<T, SetTy, true> {
203 idf_ext_iterator(const idf_iterator<T, SetTy, true> &V)
204 : idf_iterator<T, SetTy, true>(V) {}
205 idf_ext_iterator(const df_iterator<Inverse<T>, SetTy, true> &V)
206 : idf_iterator<T, SetTy, true>(V) {}
207};
208
209template <class T, class SetTy>
210idf_ext_iterator<T, SetTy> idf_ext_begin(T G, SetTy &S) {
211 return idf_ext_iterator<T, SetTy>::begin(G, S);
212}
213
214template <class T, class SetTy>
215idf_ext_iterator<T, SetTy> idf_ext_end(T G, SetTy &S) {
216 return idf_ext_iterator<T, SetTy>::end(G, S);
217}
218
219
Chris Lattner409bbec2001-09-28 22:59:14 +0000220#endif