llvm.org GIT mirror llvm / 161e82b
[ADT] Migrate DepthFirstIterator to use NodeRef Summary: Notice that the data layout is changed: instead of using std::pair<PointerIntPair<NodeType*, 1>, ChildItTy>, now use std::pair<NodeRef, Optional<ChildItTy>>. A NFC but worth noticing change is operator==(), since we only compare an iterator against end(), it's better to put an assert there and make people noticed when it fails. Reviewers: dblaikie, chandlerc Subscribers: mzolotukhin, llvm-commits Differential Revision: https://reviews.llvm.org/D23146 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@278437 91177308-0d34-0410-b5e6-96231b3b80d8 Tim Shen 3 years ago
6 changed file(s) with 73 addition(s) and 68 deletion(s). Raw diff Collapse all Expand all
3333 #define LLVM_ADT_DEPTHFIRSTITERATOR_H
3434
3535 #include "llvm/ADT/GraphTraits.h"
36 #include "llvm/ADT/PointerIntPair.h"
36 #include "llvm/ADT/Optional.h"
3737 #include "llvm/ADT/SmallPtrSet.h"
3838 #include "llvm/ADT/iterator_range.h"
3939 #include
5858 };
5959
6060 // Generic Depth First Iterator
61 template
62 class SetType = llvm::SmallPtrSet::NodeType*, 8>,
63 bool ExtStorage = false, class GT = GraphTraits >
64 class df_iterator : public std::iterator
65 typename GT::NodeType, ptrdiff_t>,
66 public df_iterator_storage {
67 typedef std::iterator
68 typename GT::NodeType, ptrdiff_t> super;
69
70 typedef typename GT::NodeType NodeType;
61 template
62 class SetType =
63 llvm::SmallPtrSet::NodeRef, 8>,
64 bool ExtStorage = false, class GT = GraphTraits>
65 class df_iterator
66 : public std::iterator
67 ptrdiff_t, typename GT::NodeRef,
68 typename GT::NodeRef>,
69 public df_iterator_storage {
70 typedef std::iterator
71 ptrdiff_t, typename GT::NodeRef, typename GT::NodeRef>
72 super;
73
74 typedef typename GT::NodeRef NodeRef;
7175 typedef typename GT::ChildIteratorType ChildItTy;
72 typedef PointerIntPair PointerIntTy;
76
77 // First element is node reference, second is the 'next child' to visit.
78 // The second child is initialized lazily to pick up graph changes during the
79 // DFS.
80 typedef std::pair> StackElement;
7381
7482 // VisitStack - Used to maintain the ordering. Top = current block
75 // First element is node pointer, second is the 'next child' to visit
76 // if the int in PointerIntTy is 0, the 'next child' to visit is invalid
77 std::vector<std::pair> VisitStack;
83 std::vector<StackElement> VisitStack;
7884
7985 private:
80 inline df_iterator(NodeType *Node) {
86 inline df_iterator(NodeRef Node) {
8187 this->Visited.insert(Node);
82 VisitStack.push_back(
83 std::make_pair(PointerIntTy(Node, 0), GT::child_begin(Node)));
88 VisitStack.push_back(StackElement(Node, None));
8489 }
8590 inline df_iterator() {
8691 // End is when stack is empty
8792 }
88 inline df_iterator(NodeType *Node, SetType &S)
89 : df_iterator_storage(S) {
93 inline df_iterator(NodeRef Node, SetType &S)
94 : df_iterator_storage(S) {
9095 if (!S.count(Node)) {
91 VisitStack.push_back(
92 std::make_pair(PointerIntTy(Node, 0), GT::child_begin(Node)));
96 VisitStack.push_back(StackElement(Node, None));
9397 this->Visited.insert(Node);
9498 }
9599 }
100104
101105 inline void toNext() {
102106 do {
103 std::pair &Top = VisitStack.back();
104 NodeType *Node = Top.first.getPointer();
105 ChildItTy &It = Top.second;
106 if (!Top.first.getInt()) {
107 // now retrieve the real begin of the children before we dive in
108 It = GT::child_begin(Node);
109 Top.first.setInt(1);
110 }
111
112 while (It != GT::child_end(Node)) {
113 NodeType *Next = *It++;
107 NodeRef Node = VisitStack.back().first;
108 Optional &Opt = VisitStack.back().second;
109
110 if (!Opt)
111 Opt.emplace(GT::child_begin(Node));
112
113 for (NodeRef Next : make_range(*Opt, GT::child_end(Node))) {
114114 // Has our next sibling been visited?
115 if (Next && this->Visited.insert(Next).second) {
115 if (this->Visited.insert(Next).second) {
116116 // No, do it now.
117 VisitStack.push_back(
118 std::make_pair(PointerIntTy(Next, 0), GT::child_begin(Next)));
117 VisitStack.push_back(StackElement(Next, None));
119118 return;
120119 }
121120 }
145144 }
146145 bool operator!=(const df_iterator &x) const { return !(*this == x); }
147146
148 pointer operator*() const { return VisitStack.back().first.getPointer(); }
147 NodeRef operator*() const { return VisitStack.back().first; }
149148
150149 // This is a nonstandard operator-> that dereferences the pointer an extra
151150 // time... so that you can actually call methods ON the Node, because
152151 // the contained type is a pointer. This allows BBIt->getTerminator() f.e.
153152 //
154 NodeType *operator->() const { return **this; }
153 NodeRef operator->() const { return **this; }
155154
156155 df_iterator &operator++() { // Preincrement
157156 toNext();
179178 // specified node. This is public, and will probably be used to iterate over
180179 // nodes that a depth first iteration did not find: ie unreachable nodes.
181180 //
182 bool nodeVisited(NodeType *Node) const {
181 bool nodeVisited(NodeRef Node) const {
183182 return this->Visited.count(Node) != 0;
184183 }
185184
189188
190189 /// getPath - Return the n'th node in the path from the entry node to the
191190 /// current node.
192 NodeType *getPath(unsigned n) const {
193 return VisitStack[n].first.getPointer();
194 }
191 NodeRef getPath(unsigned n) const { return VisitStack[n].first; }
195192 };
196193
197194 // Provide global constructors that automatically figure out correct types...
213210 }
214211
215212 // Provide global definitions of external depth first iterators...
216 template ::NodeType*> >
213 template ::NodeRef>>
217214 struct df_ext_iterator : public df_iterator {
218215 df_ext_iterator(const df_iterator &V)
219216 : df_iterator(V) {}
237234
238235 // Provide global definitions of inverse depth first iterators...
239236 template
240 class SetTy = llvm::SmallPtrSet::NodeType*, 8>,
237 class SetTy = llvm::SmallPtrSet::NodeRef, 8>,
241238 bool External = false>
242239 struct idf_iterator : public df_iterator, SetTy, External> {
243240 idf_iterator(const df_iterator, SetTy, External> &V)
261258 }
262259
263260 // Provide global definitions of external inverse depth first iterators...
264 template ::NodeType*> >
261 template ::NodeRef>>
265262 struct idf_ext_iterator : public idf_iterator {
266263 idf_ext_iterator(const idf_iterator &V)
267264 : idf_iterator(V) {}
761761 // Allow clients to walk the list of nested loops...
762762 template <> struct GraphTraits {
763763 typedef const Loop NodeType;
764 typedef const Loop *NodeRef;
764765 typedef LoopInfo::iterator ChildIteratorType;
765766
766767 static NodeType *getEntryNode(const Loop *L) { return L; }
774775
775776 template <> struct GraphTraits {
776777 typedef Loop NodeType;
778 typedef Loop *NodeRef;
777779 typedef LoopInfo::iterator ChildIteratorType;
778780
779781 static NodeType *getEntryNode(Loop *L) { return L; }
248248 // NodeT can either be region node or const region node, otherwise child_begin
249249 // and child_end fail.
250250
251 #define RegionNodeGraphTraits(NodeT, BlockT, RegionT) \
252 template<> struct GraphTraits { \
253 typedef NodeT NodeType; \
254 typedef RNSuccIterator ChildIteratorType; \
255 static NodeType *getEntryNode(NodeType* N) { return N; } \
256 static inline ChildIteratorType child_begin(NodeType *N) { \
257 return RNSuccIterator(N); \
258 } \
259 static inline ChildIteratorType child_end(NodeType *N) { \
260 return RNSuccIterator(N, true); \
261 } \
262 }; \
263 template<> struct GraphTraits> { \
264 typedef NodeT NodeType; \
265 typedef RNSuccIterator, BlockT, RegionT > ChildIteratorType; \
266 static NodeType *getEntryNode(NodeType* N) { return N; } \
267 static inline ChildIteratorType child_begin(NodeType *N) { \
268 return RNSuccIterator, BlockT, RegionT>(N); \
269 } \
270 static inline ChildIteratorType child_end(NodeType *N) { \
271 return RNSuccIterator, BlockT, RegionT>(N, true); \
272 } \
273 }
251 #define RegionNodeGraphTraits(NodeT, BlockT, RegionT) \
252 template <> struct GraphTraits { \
253 typedef NodeT NodeType; \
254 typedef NodeT *NodeRef; \
255 typedef RNSuccIterator ChildIteratorType; \
256 static NodeType *getEntryNode(NodeType *N) { return N; } \
257 static inline ChildIteratorType child_begin(NodeType *N) { \
258 return RNSuccIterator(N); \
259 } \
260 static inline ChildIteratorType child_end(NodeType *N) { \
261 return RNSuccIterator(N, true); \
262 } \
263 }; \
264 template <> struct GraphTraits> { \
265 typedef NodeT NodeType; \
266 typedef NodeT *NodeRef; \
267 typedef RNSuccIterator, BlockT, RegionT> ChildIteratorType; \
268 static NodeType *getEntryNode(NodeType *N) { return N; } \
269 static inline ChildIteratorType child_begin(NodeType *N) { \
270 return RNSuccIterator, BlockT, RegionT>(N); \
271 } \
272 static inline ChildIteratorType child_end(NodeType *N) { \
273 return RNSuccIterator, BlockT, RegionT>(N, true); \
274 } \
275 }
274276
275277 #define RegionGraphTraits(RegionT, NodeT) \
276278 template<> struct GraphTraits \
271271 template
272272 struct MachineDomTreeGraphTraitsBase {
273273 typedef Node NodeType;
274 typedef Node *NodeRef;
274275 typedef ChildIterator ChildIteratorType;
275276
276277 static NodeType *getEntryNode(NodeType *N) { return N; }
148148 // Allow clients to walk the list of nested loops...
149149 template <> struct GraphTraits {
150150 typedef const MachineLoop NodeType;
151 typedef const MachineLoop *NodeRef;
151152 typedef MachineLoopInfo::iterator ChildIteratorType;
152153
153154 static NodeType *getEntryNode(const MachineLoop *L) { return L; }
161162
162163 template <> struct GraphTraits {
163164 typedef MachineLoop NodeType;
165 typedef MachineLoop *NodeRef;
164166 typedef MachineLoopInfo::iterator ChildIteratorType;
165167
166168 static NodeType *getEntryNode(MachineLoop *L) { return L; }
155155
156156 template struct DomTreeGraphTraitsBase {
157157 typedef Node NodeType;
158 typedef Node *NodeRef;
158159 typedef ChildIterator ChildIteratorType;
159160 typedef df_iterator> nodes_iterator;
160161