aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-07-23 06:30:28 +0000
committerChris Lattner <sabre@nondot.org>2009-07-23 06:30:28 +0000
commitf0395160f934eb278aa960de22dada5b297ddd8a (patch)
treef313c01bc9cfb50748426864f0b942e2a9f04736
parent3cd526136a060ccb9798ad442838eb223357b041 (diff)
enhance DepthFirstIterator to support more robust operations in the face
of code mutating the graph while it is being traversed. Patch by Olaf Krzikalla! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@76869 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/ADT/DepthFirstIterator.h72
1 files changed, 49 insertions, 23 deletions
diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h
index 517768f402..c5f246c33e 100644
--- a/include/llvm/ADT/DepthFirstIterator.h
+++ b/include/llvm/ADT/DepthFirstIterator.h
@@ -36,6 +36,7 @@
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/PointerIntPair.h"
#include <set>
#include <vector>
@@ -68,22 +69,27 @@ class df_iterator : public forward_iterator<typename GT::NodeType, ptrdiff_t>,
typedef typename GT::NodeType NodeType;
typedef typename GT::ChildIteratorType ChildItTy;
+ typedef PointerIntPair<NodeType*, 1> PointerIntTy;
// VisitStack - Used to maintain the ordering. Top = current block
// First element is node pointer, second is the 'next child' to visit
- std::vector<std::pair<NodeType *, ChildItTy> > VisitStack;
+ // if the int in PointerIntTy is 0, the 'next child' to visit is invalid
+ std::vector<std::pair<PointerIntTy, ChildItTy> > VisitStack;
private:
inline df_iterator(NodeType *Node) {
this->Visited.insert(Node);
- VisitStack.push_back(std::make_pair(Node, GT::child_begin(Node)));
+ VisitStack.push_back(std::make_pair(PointerIntTy(Node, 0),
+ GT::child_begin(Node)));
+ }
+ inline df_iterator() {
+ // End is when stack is empty
}
- inline df_iterator() { /* End is when stack is empty */ }
-
inline df_iterator(NodeType *Node, SetType &S)
: df_iterator_storage<SetType, ExtStorage>(S) {
if (!S.count(Node)) {
+ VisitStack.push_back(std::make_pair(PointerIntTy(Node, 0),
+ GT::child_begin(Node)));
this->Visited.insert(Node);
- VisitStack.push_back(std::make_pair(Node, GT::child_begin(Node)));
}
}
inline df_iterator(SetType &S)
@@ -91,6 +97,34 @@ private:
// End is when stack is empty
}
+ inline void toNext() {
+ do {
+ std::pair<PointerIntTy, ChildItTy> &Top = VisitStack.back();
+ NodeType *Node = Top.first.getPointer();
+ ChildItTy &It = Top.second;
+ if (!Top.first.getInt()) {
+ // now retrieve the real begin of the children before we dive in
+ It = GT::child_begin(Node);
+ Top.first.setInt(1);
+ }
+
+ while (It != GT::child_end(Node)) {
+ NodeType *Next = *It++;
+ // Has our next sibling been visited?
+ if (Next && !this->Visited.count(Next)) {
+ // No, do it now.
+ this->Visited.insert(Next);
+ VisitStack.push_back(std::make_pair(PointerIntTy(Next, 0),
+ GT::child_begin(Next)));
+ return;
+ }
+ }
+
+ // Oops, ran out of successors... go up a level on the stack.
+ VisitStack.pop_back();
+ } while (!VisitStack.empty());
+ }
+
public:
typedef typename super::pointer pointer;
typedef df_iterator<GraphT, SetType, ExtStorage, GT> _Self;
@@ -114,7 +148,7 @@ public:
inline bool operator!=(const _Self& x) const { return !operator==(x); }
inline pointer operator*() const {
- return VisitStack.back().first;
+ return VisitStack.back().first.getPointer();
}
// This is a nonstandard operator-> that dereferences the pointer an extra
@@ -124,24 +158,16 @@ public:
inline NodeType *operator->() const { return operator*(); }
inline _Self& operator++() { // Preincrement
- do {
- std::pair<NodeType *, ChildItTy> &Top = VisitStack.back();
- NodeType *Node = Top.first;
- ChildItTy &It = Top.second;
-
- while (It != GT::child_end(Node)) {
- NodeType *Next = *It++;
- if (!this->Visited.count(Next)) { // Has our next sibling been visited?
- // No, do it now.
- this->Visited.insert(Next);
- VisitStack.push_back(std::make_pair(Next, GT::child_begin(Next)));
- return *this;
- }
- }
+ toNext();
+ return *this;
+ }
- // Oops, ran out of successors... go up a level on the stack.
- VisitStack.pop_back();
- } while (!VisitStack.empty());
+ // skips all children of the current node and traverses to next node
+ //
+ inline _Self& skipChildren() {
+ VisitStack.pop_back();
+ if (!VisitStack.empty())
+ toNext();
return *this;
}