LLVM 24.0.0git
DepthFirstIterator.h
Go to the documentation of this file.
1//===- llvm/ADT/DepthFirstIterator.h - Depth First iterator -----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file builds on the ADT/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
15/// children.
16///
17/// idf_begin/idf_end/idf_iterator
18/// * Depth-first iteration on the 'inverse' graph.
19///
20/// df_ext_begin/df_ext_end/df_ext_iterator
21/// * Normal depth-first iteration - visit a node and then all of its
22/// children. This iterator stores the 'visited' set in an external set,
23/// which allows it to be more efficient, and allows external clients to
24/// use the set for other purposes.
25///
26/// idf_ext_begin/idf_ext_end/idf_ext_iterator
27/// * Depth-first iteration on the 'inverse' graph.
28/// This iterator stores the 'visited' set in an external set, which
29/// allows it to be more efficient, and allows external clients to use
30/// the set for other purposes.
31///
32//===----------------------------------------------------------------------===//
33
34#ifndef LLVM_ADT_DEPTHFIRSTITERATOR_H
35#define LLVM_ADT_DEPTHFIRSTITERATOR_H
36
41#include <iterator>
42#include <optional>
43#include <type_traits>
44#include <utility>
45#include <vector>
46
47namespace llvm {
48
49// df_iterator_storage - A private class which is used to figure out where to
50// store the visited set.
51template<class SetType, bool External> // Non-external set
53public:
54 SetType Visited;
55};
56
57template<class SetType>
58class df_iterator_storage<SetType, true> {
59public:
60 df_iterator_storage(SetType &VSet) : Visited(VSet) {}
62
63 SetType &Visited;
64};
65
66// The visited stated for the iteration is a simple set augmented with
67// one more method, completed, which is invoked when all children of a
68// node have been processed. It is intended to distinguish of back and
69// cross edges in the spanning tree but is not used in the common case.
70template <typename NodeRef, unsigned SmallSize = 8>
71struct df_iterator_default_set : SmallPtrSet<NodeRef, SmallSize> {
73 using iterator = typename BaseSet::iterator;
74
75 std::pair<iterator,bool> insert(NodeRef N) { return BaseSet::insert(N); }
76 template <typename IterT>
77 void insert(IterT Begin, IterT End) { BaseSet::insert(Begin,End); }
78
79 void completed(NodeRef) {}
80};
81
82// Generic Depth First Iterator
83template <class GraphT,
84 class SetType =
85 df_iterator_default_set<typename GraphTraits<GraphT>::NodeRef>,
86 bool ExtStorage = false, class GT = GraphTraits<GraphT>>
87class df_iterator : public df_iterator_storage<SetType, ExtStorage> {
88public:
89 // When External storage is used we are not multi-pass safe.
91 std::conditional_t<ExtStorage, std::input_iterator_tag,
92 std::forward_iterator_tag>;
93 using value_type = typename GT::NodeRef;
94 using difference_type = std::ptrdiff_t;
96 using reference = const value_type &;
97
98private:
99 using NodeRef = typename GT::NodeRef;
100 using ChildItTy = typename GT::ChildIteratorType;
101
102 // First element is node reference, second is the 'next child' to visit.
103 // The second child is initialized lazily to pick up graph changes during the
104 // DFS.
105 using StackElement = std::pair<NodeRef, std::optional<ChildItTy>>;
106
107 // VisitStack - Used to maintain the ordering. Top = current block
109
110 inline df_iterator(NodeRef Node) {
111 this->Visited.insert(Node);
112 VisitStack.push_back(StackElement(Node, std::nullopt));
113 }
114
115 inline df_iterator() = default; // End is when stack is empty
116
117 inline df_iterator(NodeRef Node, SetType &S)
118 : df_iterator_storage<SetType, ExtStorage>(S) {
119 if (this->Visited.insert(Node).second)
120 VisitStack.push_back(StackElement(Node, std::nullopt));
121 }
122
123 inline df_iterator(SetType &S)
124 : df_iterator_storage<SetType, ExtStorage>(S) {
125 // End is when stack is empty
126 }
127
128 inline void toNext() {
129 do {
130 NodeRef Node = VisitStack.back().first;
131 std::optional<ChildItTy> &Opt = VisitStack.back().second;
132
133 if (!Opt)
134 Opt.emplace(GT::child_begin(Node));
135
136 // Notice that we directly mutate *Opt here, so that
137 // VisitStack.back().second actually gets updated as the iterator
138 // increases.
139 while (*Opt != GT::child_end(Node)) {
140 NodeRef Next = *(*Opt)++;
141 // Has our next sibling been visited?
142 if (this->Visited.insert(Next).second) {
143 // No, do it now.
144 VisitStack.push_back(StackElement(Next, std::nullopt));
145 return;
146 }
147 }
148 this->Visited.completed(Node);
149
150 // Oops, ran out of successors... go up a level on the stack.
151 VisitStack.pop_back();
152 } while (!VisitStack.empty());
153 }
154
155public:
156 // Provide static begin and end methods as our public "constructors"
157 static df_iterator begin(const GraphT &G) {
158 return df_iterator(GT::getEntryNode(G));
159 }
160 static df_iterator end(const GraphT &G) { return df_iterator(); }
161
162 // Static begin and end methods as our public ctors for external iterators
163 static df_iterator begin(const GraphT &G, SetType &S) {
164 return df_iterator(GT::getEntryNode(G), S);
165 }
166 static df_iterator end(const GraphT &G, SetType &S) { return df_iterator(S); }
167
168 bool operator==(const df_iterator &x) const {
169 return VisitStack == x.VisitStack;
170 }
171 bool operator!=(const df_iterator &x) const { return !(*this == x); }
172
173 reference operator*() const { return VisitStack.back().first; }
174
175 // This is a nonstandard operator-> that dereferences the pointer an extra
176 // time... so that you can actually call methods ON the Node, because
177 // the contained type is a pointer. This allows BBIt->getTerminator() f.e.
178 //
179 NodeRef operator->() const { return **this; }
180
181 df_iterator &operator++() { // Preincrement
182 toNext();
183 return *this;
184 }
185
186 /// Skips all children of the current node and traverses to next node
187 ///
188 /// Note: This function takes care of incrementing the iterator. If you
189 /// always increment and call this function, you risk walking off the end.
190 df_iterator &skipChildren() {
191 VisitStack.pop_back();
192 if (!VisitStack.empty())
193 toNext();
194 return *this;
195 }
196
197 df_iterator operator++(int) { // Postincrement
198 df_iterator tmp = *this;
199 ++*this;
200 return tmp;
201 }
202
203 // nodeVisited - return true if this iterator has already visited the
204 // specified node. This is public, and will probably be used to iterate over
205 // nodes that a depth first iteration did not find: ie unreachable nodes.
206 //
207 bool nodeVisited(NodeRef Node) const {
208 return this->Visited.contains(Node);
209 }
210
211 /// Return the length of the path from the entry node to the current node,
212 /// counting both nodes.
213 unsigned getPathLength() const { return VisitStack.size(); }
214
215 /// Return the n'th node in the path from the entry node to the current node.
216 NodeRef getPath(unsigned n) const { return VisitStack[n].first; }
217};
218
219// Provide global constructors that automatically figure out correct types...
220//
221template <class T>
223 return df_iterator<T>::begin(G);
224}
225
226template <class T>
228 return df_iterator<T>::end(G);
229}
230
231// Provide an accessor method to use them in range-based patterns.
232template <class T>
236
237// Provide global definitions of external depth first iterators...
238template <class T,
239 class SetTy =
240 df_iterator_default_set<typename GraphTraits<T>::NodeRef>>
241struct df_ext_iterator : df_iterator<T, SetTy, true> {
242 df_ext_iterator(const df_iterator<T, SetTy, true> &V)
243 : df_iterator<T, SetTy, true>(V) {}
244};
245
246template <class T, class SetTy>
250
251template <class T, class SetTy>
255
256template <class T, class SetTy>
261
262// Provide global definitions of inverse depth first iterators...
263template <class T,
264 class SetTy =
265 df_iterator_default_set<typename GraphTraits<T>::NodeRef>,
266 bool External = false>
267struct idf_iterator : df_iterator<Inverse<T>, SetTy, External> {
268 idf_iterator(const df_iterator<Inverse<T>, SetTy, External> &V)
269 : df_iterator<Inverse<T>, SetTy, External>(V) {}
270};
271
272template <class T>
276
277template <class T>
281
282// Provide an accessor method to use them in range-based patterns.
283template <class T>
287
288// Provide global definitions of external inverse depth first iterators...
289template <class T,
290 class SetTy =
291 df_iterator_default_set<typename GraphTraits<T>::NodeRef>>
292struct idf_ext_iterator : idf_iterator<T, SetTy, true> {
296 : idf_iterator<T, SetTy, true>(V) {}
297};
298
299template <class T, class SetTy>
303
304template <class T, class SetTy>
308
309template <class T, class SetTy>
314
315} // end namespace llvm
316
317#endif // LLVM_ADT_DEPTHFIRSTITERATOR_H
This file defines the little GraphTraits<X> template class that should be specialized by classes that...
#define G(x, y, z)
Definition MD5.cpp:55
#define T
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
std::pair< iterator, bool > insert(NodeRef Ptr)
SmallPtrSetIterator< NodeRef > iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
df_iterator_storage(const df_iterator_storage &S)
df_iterator & operator++()
static df_iterator begin(const GraphT &G)
NodeRef operator->() const
std::conditional_t< ExtStorage, std::input_iterator_tag, std::forward_iterator_tag > iterator_category
static df_iterator end(const GraphT &G)
const value_type & reference
static df_iterator end(const GraphT &G, SetType &S)
df_iterator & skipChildren()
Skips all children of the current node and traverses to next node.
unsigned getPathLength() const
Return the length of the path from the entry node to the current node, counting both nodes.
bool operator==(const df_iterator &x) const
df_iterator operator++(int)
bool operator!=(const df_iterator &x) const
bool nodeVisited(NodeRef Node) const
NodeRef getPath(unsigned n) const
Return the n'th node in the path from the entry node to the current node.
static df_iterator begin(const GraphT &G, SetType &S)
reference operator*() const
std::ptrdiff_t difference_type
typename GT::NodeRef value_type
A range adaptor for a pair of iterators.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
This is an optimization pass for GlobalISel generic memory operations.
iterator_range< df_ext_iterator< T, SetTy > > depth_first_ext(const T &G, SetTy &S)
idf_ext_iterator< T, SetTy > idf_ext_end(const T &G, SetTy &S)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
df_iterator< T > df_begin(const T &G)
idf_ext_iterator< T, SetTy > idf_ext_begin(const T &G, SetTy &S)
iterator_range< idf_iterator< T > > inverse_depth_first(const T &G)
df_ext_iterator< T, SetTy > df_ext_begin(const T &G, SetTy &S)
idf_iterator< T > idf_end(const T &G)
iterator_range< idf_ext_iterator< T, SetTy > > inverse_depth_first_ext(const T &G, SetTy &S)
idf_iterator< T > idf_begin(const T &G)
df_ext_iterator< T, SetTy > df_ext_end(const T &G, SetTy &S)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
df_iterator< T > df_end(const T &G)
iterator_range< df_iterator< T > > depth_first(const T &G)
#define N
df_ext_iterator(const df_iterator< T, SetTy, true > &V)
void insert(IterT Begin, IterT End)
typename BaseSet::iterator iterator
SmallPtrSet< NodeRef, SmallSize > BaseSet
std::pair< iterator, bool > insert(NodeRef N)
idf_ext_iterator(const idf_iterator< T, SetTy, true > &V)
idf_ext_iterator(const df_iterator< Inverse< T >, SetTy, true > &V)
idf_iterator(const df_iterator< Inverse< T >, SetTy, External > &V)