blob: 967a0e145ac2ba8c1c284643a5241b3c54831033 [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
4// first graph iterator.
5//
6//===----------------------------------------------------------------------===//
7
Brian Gaekea7a50132003-06-17 00:35:55 +00008#ifndef SUPPORT_DEPTHFIRSTITERATOR_H
9#define SUPPORT_DEPTHFIRSTITERATOR_H
Chris Lattner409bbec2001-09-28 22:59:14 +000010
Chris Lattner5de22042001-11-27 00:03:19 +000011#include "Support/GraphTraits.h"
Chris Lattner94a4f222002-10-28 02:11:53 +000012#include "Support/iterator"
Chris Lattner409bbec2001-09-28 22:59:14 +000013#include <stack>
14#include <set>
15
16// Generic Depth First Iterator
17template<class GraphT, class GT = GraphTraits<GraphT> >
Chris Lattner889cddf2002-07-24 22:08:36 +000018class df_iterator : public forward_iterator<typename GT::NodeType, ptrdiff_t> {
19 typedef forward_iterator<typename GT::NodeType, ptrdiff_t> super;
Chris Lattner889cddf2002-07-24 22:08:36 +000020
Chris Lattner409bbec2001-09-28 22:59:14 +000021 typedef typename GT::NodeType NodeType;
22 typedef typename GT::ChildIteratorType ChildItTy;
23
Chris Lattner7f74a562002-01-20 22:54:45 +000024 std::set<NodeType *> Visited; // All of the blocks visited so far...
Chris Lattner409bbec2001-09-28 22:59:14 +000025 // VisitStack - Used to maintain the ordering. Top = current block
26 // First element is node pointer, second is the 'next child' to visit
Chris Lattner7f74a562002-01-20 22:54:45 +000027 std::stack<std::pair<NodeType *, ChildItTy> > VisitStack;
Chris Lattner409bbec2001-09-28 22:59:14 +000028 const bool Reverse; // Iterate over children before self?
29private:
30 void reverseEnterNode() {
Chris Lattner7f74a562002-01-20 22:54:45 +000031 std::pair<NodeType *, ChildItTy> &Top = VisitStack.top();
Chris Lattner409bbec2001-09-28 22:59:14 +000032 NodeType *Node = Top.first;
33 ChildItTy &It = Top.second;
34 for (; It != GT::child_end(Node); ++It) {
35 NodeType *Child = *It;
36 if (!Visited.count(Child)) {
37 Visited.insert(Child);
Chris Lattner7f74a562002-01-20 22:54:45 +000038 VisitStack.push(std::make_pair(Child, GT::child_begin(Child)));
Chris Lattner409bbec2001-09-28 22:59:14 +000039 reverseEnterNode();
40 return;
41 }
42 }
43 }
44
45 inline df_iterator(NodeType *Node, bool reverse) : Reverse(reverse) {
46 Visited.insert(Node);
Chris Lattner7f74a562002-01-20 22:54:45 +000047 VisitStack.push(std::make_pair(Node, GT::child_begin(Node)));
Chris Lattner409bbec2001-09-28 22:59:14 +000048 if (Reverse) reverseEnterNode();
49 }
50 inline df_iterator() { /* End is when stack is empty */ }
51
52public:
Chris Lattner33d51022003-07-25 17:49:28 +000053 typedef typename super::pointer pointer;
Chris Lattner409bbec2001-09-28 22:59:14 +000054 typedef df_iterator<GraphT, GT> _Self;
55
56 // Provide static begin and end methods as our public "constructors"
57 static inline _Self begin(GraphT G, bool Reverse = false) {
58 return _Self(GT::getEntryNode(G), Reverse);
59 }
60 static inline _Self end(GraphT G) { return _Self(); }
61
62
63 inline bool operator==(const _Self& x) const {
64 return VisitStack == x.VisitStack;
65 }
66 inline bool operator!=(const _Self& x) const { return !operator==(x); }
67
68 inline pointer operator*() const {
69 return VisitStack.top().first;
70 }
71
72 // This is a nonstandard operator-> that dereferences the pointer an extra
73 // time... so that you can actually call methods ON the Node, because
74 // the contained type is a pointer. This allows BBIt->getTerminator() f.e.
75 //
76 inline NodeType *operator->() const { return operator*(); }
77
78 inline _Self& operator++() { // Preincrement
79 if (Reverse) { // Reverse Depth First Iterator
80 if (VisitStack.top().second == GT::child_end(VisitStack.top().first))
81 VisitStack.pop();
82 if (!VisitStack.empty())
83 reverseEnterNode();
84 } else { // Normal Depth First Iterator
85 do {
Chris Lattner7f74a562002-01-20 22:54:45 +000086 std::pair<NodeType *, ChildItTy> &Top = VisitStack.top();
Chris Lattner409bbec2001-09-28 22:59:14 +000087 NodeType *Node = Top.first;
88 ChildItTy &It = Top.second;
89
90 while (It != GT::child_end(Node)) {
91 NodeType *Next = *It++;
92 if (!Visited.count(Next)) { // Has our next sibling been visited?
93 // No, do it now.
94 Visited.insert(Next);
Chris Lattner7f74a562002-01-20 22:54:45 +000095 VisitStack.push(std::make_pair(Next, GT::child_begin(Next)));
Chris Lattner409bbec2001-09-28 22:59:14 +000096 return *this;
97 }
98 }
99
100 // Oops, ran out of successors... go up a level on the stack.
101 VisitStack.pop();
102 } while (!VisitStack.empty());
103 }
104 return *this;
105 }
106
107 inline _Self operator++(int) { // Postincrement
108 _Self tmp = *this; ++*this; return tmp;
109 }
110
111 // nodeVisited - return true if this iterator has already visited the
112 // specified node. This is public, and will probably be used to iterate over
113 // nodes that a depth first iteration did not find: ie unreachable nodes.
114 //
115 inline bool nodeVisited(NodeType *Node) const {
116 return Visited.count(Node) != 0;
117 }
118};
119
120
121// Provide global constructors that automatically figure out correct types...
122//
123template <class T>
124df_iterator<T> df_begin(T G, bool Reverse = false) {
125 return df_iterator<T>::begin(G, Reverse);
126}
127
128template <class T>
129df_iterator<T> df_end(T G) {
130 return df_iterator<T>::end(G);
131}
132
133// Provide global definitions of inverse depth first iterators...
134template <class T>
135struct idf_iterator : public df_iterator<Inverse<T> > {
136 idf_iterator(const df_iterator<Inverse<T> > &V) :df_iterator<Inverse<T> >(V){}
137};
138
139template <class T>
140idf_iterator<T> idf_begin(T G, bool Reverse = false) {
141 return idf_iterator<T>::begin(G, Reverse);
142}
143
144template <class T>
145idf_iterator<T> idf_end(T G){
146 return idf_iterator<T>::end(G);
147}
148
149#endif