Be a bit more efficient when processing the active and inactive
[oota-llvm.git] / include / Support / DepthFirstIterator.h
1 //===- Support/DepthFirstIterator.h - Depth First iterator ------*- C++ -*-===//
2 // 
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 // 
8 //===----------------------------------------------------------------------===//
9 //
10 // This file builds on the Support/GraphTraits.h file to build generic depth
11 // first graph iterator.  This file exposes the following functions/types:
12 //
13 // df_begin/df_end/df_iterator
14 //   * Normal depth-first iteration - visit a node and then all of its children.
15 //
16 // idf_begin/idf_end/idf_iterator
17 //   * Depth-first iteration on the 'inverse' graph.
18 //
19 // df_ext_begin/df_ext_end/df_ext_iterator
20 //   * Normal depth-first iteration - visit a node and then all of its children.
21 //     This iterator stores the 'visited' set in an external set, which allows
22 //     it to be more efficient, and allows external clients to use the set for
23 //     other purposes.
24 //
25 // idf_ext_begin/idf_ext_end/idf_ext_iterator
26 //   * Depth-first iteration on the 'inverse' graph.
27 //     This iterator stores the 'visited' set in an external set, which allows
28 //     it to be more efficient, and allows external clients to use the set for
29 //     other purposes.
30 //
31 //===----------------------------------------------------------------------===//
32
33 #ifndef SUPPORT_DEPTHFIRSTITERATOR_H
34 #define SUPPORT_DEPTHFIRSTITERATOR_H
35
36 #include "Support/GraphTraits.h"
37 #include "Support/iterator"
38 #include <vector>
39 #include <set>
40
41 namespace llvm {
42
43 // df_iterator_storage - A private class which is used to figure out where to
44 // store the visited set.
45 template<class SetType, bool External>   // Non-external set
46 class df_iterator_storage {
47 public:
48   SetType Visited;
49 };
50
51 template<class SetType>
52 class df_iterator_storage<SetType, true> {
53 public:
54   df_iterator_storage(SetType &VSet) : Visited(VSet) {}
55   df_iterator_storage(const df_iterator_storage &S) : Visited(S.Visited) {}
56   SetType &Visited;
57 };
58
59
60 // Generic Depth First Iterator
61 template<class GraphT, class SetType = 
62                             std::set<typename GraphTraits<GraphT>::NodeType*>,
63          bool ExtStorage = false, class GT = GraphTraits<GraphT> >
64 class df_iterator : public forward_iterator<typename GT::NodeType, ptrdiff_t>,
65                     public df_iterator_storage<SetType, ExtStorage> {
66   typedef forward_iterator<typename GT::NodeType, ptrdiff_t> super;
67
68   typedef typename GT::NodeType          NodeType;
69   typedef typename GT::ChildIteratorType ChildItTy;
70
71   // VisitStack - Used to maintain the ordering.  Top = current block
72   // First element is node pointer, second is the 'next child' to visit
73   std::vector<std::pair<NodeType *, ChildItTy> > VisitStack;
74 private:
75   inline df_iterator(NodeType *Node) {
76     this->Visited.insert(Node);
77     VisitStack.push_back(std::make_pair(Node, GT::child_begin(Node)));
78   }
79   inline df_iterator() { /* End is when stack is empty */ }
80
81   inline df_iterator(NodeType *Node, SetType &S)
82     : df_iterator_storage<SetType, ExtStorage>(S) {
83     if (!S.count(Node)) {
84       this->Visited.insert(Node);
85       VisitStack.push_back(std::make_pair(Node, GT::child_begin(Node)));
86     }
87   }
88   inline df_iterator(SetType &S) 
89     : df_iterator_storage<SetType, ExtStorage>(S) {
90     // End is when stack is empty
91   }
92
93 public:
94   typedef typename super::pointer pointer;
95   typedef df_iterator<GraphT, SetType, ExtStorage, GT> _Self;
96
97   // Provide static begin and end methods as our public "constructors"
98   static inline _Self begin(GraphT G) {
99     return _Self(GT::getEntryNode(G));
100   }
101   static inline _Self end(GraphT G) { return _Self(); }
102
103   // Static begin and end methods as our public ctors for external iterators
104   static inline _Self begin(GraphT G, SetType &S) {
105     return _Self(GT::getEntryNode(G), S);
106   }
107   static inline _Self end(GraphT G, SetType &S) { return _Self(S); }
108
109   inline bool operator==(const _Self& x) const { 
110     return VisitStack.size() == x.VisitStack.size() &&
111            VisitStack == x.VisitStack;
112   }
113   inline bool operator!=(const _Self& x) const { return !operator==(x); }
114
115   inline pointer operator*() const { 
116     return VisitStack.back().first;
117   }
118
119   // This is a nonstandard operator-> that dereferences the pointer an extra
120   // time... so that you can actually call methods ON the Node, because
121   // the contained type is a pointer.  This allows BBIt->getTerminator() f.e.
122   //
123   inline NodeType *operator->() const { return operator*(); }
124
125   inline _Self& operator++() {   // Preincrement
126     do {
127       std::pair<NodeType *, ChildItTy> &Top = VisitStack.back();
128       NodeType *Node = Top.first;
129       ChildItTy &It  = Top.second;
130       
131       while (It != GT::child_end(Node)) {
132         NodeType *Next = *It++;
133         if (!this->Visited.count(Next)) {  // Has our next sibling been visited?
134           // No, do it now.
135           this->Visited.insert(Next);
136           VisitStack.push_back(std::make_pair(Next, GT::child_begin(Next)));
137           return *this;
138         }
139       }
140       
141       // Oops, ran out of successors... go up a level on the stack.
142       VisitStack.pop_back();
143     } while (!VisitStack.empty());
144     return *this; 
145   }
146
147   inline _Self operator++(int) { // Postincrement
148     _Self tmp = *this; ++*this; return tmp; 
149   }
150
151   // nodeVisited - return true if this iterator has already visited the
152   // specified node.  This is public, and will probably be used to iterate over
153   // nodes that a depth first iteration did not find: ie unreachable nodes.
154   //
155   inline bool nodeVisited(NodeType *Node) const { 
156     return this->Visited.count(Node) != 0;
157   }
158 };
159
160
161 // Provide global constructors that automatically figure out correct types...
162 //
163 template <class T>
164 df_iterator<T> df_begin(T G) {
165   return df_iterator<T>::begin(G);
166 }
167
168 template <class T>
169 df_iterator<T> df_end(T G) {
170   return df_iterator<T>::end(G);
171 }
172
173 // Provide global definitions of external depth first iterators...
174 template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeType*> >
175 struct df_ext_iterator : public df_iterator<T, SetTy, true> {
176   df_ext_iterator(const df_iterator<T, SetTy, true> &V)
177     : df_iterator<T, SetTy, true>(V) {}
178 };
179
180 template <class T, class SetTy>
181 df_ext_iterator<T, SetTy> df_ext_begin(T G, SetTy &S) {
182   return df_ext_iterator<T, SetTy>::begin(G, S);
183 }
184
185 template <class T, class SetTy>
186 df_ext_iterator<T, SetTy> df_ext_end(T G, SetTy &S) {
187   return df_ext_iterator<T, SetTy>::end(G, S);
188 }
189
190
191 // Provide global definitions of inverse depth first iterators...
192 template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeType*>,
193           bool External = false>
194 struct idf_iterator : public df_iterator<Inverse<T>, SetTy, External> {
195   idf_iterator(const df_iterator<Inverse<T>, SetTy, External> &V)
196     : df_iterator<Inverse<T>, SetTy, External>(V) {}
197 };
198
199 template <class T>
200 idf_iterator<T> idf_begin(T G) {
201   return idf_iterator<T>::begin(G);
202 }
203
204 template <class T>
205 idf_iterator<T> idf_end(T G){
206   return idf_iterator<T>::end(G);
207 }
208
209 // Provide global definitions of external inverse depth first iterators...
210 template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeType*> >
211 struct idf_ext_iterator : public idf_iterator<T, SetTy, true> {
212   idf_ext_iterator(const idf_iterator<T, SetTy, true> &V)
213     : idf_iterator<T, SetTy, true>(V) {}
214   idf_ext_iterator(const df_iterator<Inverse<T>, SetTy, true> &V)
215     : idf_iterator<T, SetTy, true>(V) {}
216 };
217
218 template <class T, class SetTy>
219 idf_ext_iterator<T, SetTy> idf_ext_begin(T G, SetTy &S) {
220   return idf_ext_iterator<T, SetTy>::begin(G, S);
221 }
222
223 template <class T, class SetTy>
224 idf_ext_iterator<T, SetTy> idf_ext_end(T G, SetTy &S) {
225   return idf_ext_iterator<T, SetTy>::end(G, S);
226 }
227
228 } // End llvm namespace
229
230 #endif