Index: include/llvm/ADT/DepthFirstIterator.h =================================================================== --- include/llvm/ADT/DepthFirstIterator.h +++ include/llvm/ADT/DepthFirstIterator.h @@ -58,10 +58,25 @@ SetType &Visited; }; +// The visited stated for the iteration is a simple set augmented with +// one more method, completed, which is invoked when all children of a +// node have been processed. It is intended to distinguish of back and +// cross edges in the spanning tree but is not used in the common case. +template +struct df_iterator_default_set : public llvm::SmallPtrSet { + typedef llvm::SmallPtrSet BaseSet; + typedef typename BaseSet::iterator iterator; + std::pair insert(NodeRef N) { return BaseSet::insert(N) ; } + template + void insert(IterT Begin, IterT End) { BaseSet::insert(Begin,End); } + + void completed(NodeRef) { } +}; + // Generic Depth First Iterator template ::NodeRef, 8>, + df_iterator_default_set::NodeRef>, bool ExtStorage = false, class GT = GraphTraits> class df_iterator : public std::iterator, @@ -89,10 +104,8 @@ } inline df_iterator(NodeRef Node, SetType &S) : df_iterator_storage(S) { - if (!S.count(Node)) { + if (this->Visited.insert(Node).second) VisitStack.push_back(StackElement(Node, None)); - this->Visited.insert(Node); - } } inline df_iterator(SetType &S) : df_iterator_storage(S) { @@ -119,7 +132,8 @@ return; } } - + this->Visited.completed(Node); + // Oops, ran out of successors... go up a level on the stack. VisitStack.pop_back(); } while (!VisitStack.empty()); @@ -235,7 +249,8 @@ // Provide global definitions of inverse depth first iterators... template ::NodeRef, 8>, + class SetTy = + df_iterator_default_set::NodeRef>, bool External = false> struct idf_iterator : public df_iterator, SetTy, External> { idf_iterator(const df_iterator, SetTy, External> &V) Index: include/llvm/Analysis/LoopInfoImpl.h =================================================================== --- include/llvm/Analysis/LoopInfoImpl.h +++ include/llvm/Analysis/LoopInfoImpl.h @@ -228,9 +228,9 @@ // Setup for using a depth-first iterator to visit every block in the loop. SmallVector ExitBBs; getExitBlocks(ExitBBs); - llvm::SmallPtrSet VisitSet; + df_iterator_default_set VisitSet; VisitSet.insert(ExitBBs.begin(), ExitBBs.end()); - df_ext_iterator > + df_ext_iterator> BI = df_ext_begin(getHeader(), VisitSet), BE = df_ext_end(getHeader(), VisitSet); Index: include/llvm/Analysis/RegionInfo.h =================================================================== --- include/llvm/Analysis/RegionInfo.h +++ include/llvm/Analysis/RegionInfo.h @@ -626,12 +626,14 @@ /// are direct children of this Region. It does not iterate over any /// RegionNodes that are also element of a subregion of this Region. //@{ - typedef df_iterator, false, - GraphTraits> element_iterator; - - typedef df_iterator, - false, - GraphTraits> const_element_iterator; + typedef df_iterator, + false, GraphTraits> + element_iterator; + + typedef df_iterator, false, + GraphTraits> + const_element_iterator; element_iterator element_begin(); element_iterator element_end(); Index: include/llvm/Analysis/RegionIterator.h =================================================================== --- include/llvm/Analysis/RegionIterator.h +++ include/llvm/Analysis/RegionIterator.h @@ -294,7 +294,7 @@ template <> \ struct GraphTraits> \ : public GraphTraits> { \ - typedef df_iterator, false, \ + typedef df_iterator, false, \ GraphTraits>> \ nodes_iterator; \ static NodeRef getEntryNode(RegionT *R) { \ @@ -316,7 +316,7 @@ template <> struct GraphTraits : public GraphTraits > { - typedef df_iterator, false, + typedef df_iterator, false, GraphTraits>> nodes_iterator; @@ -333,7 +333,7 @@ template <> struct GraphTraits : public GraphTraits { - typedef df_iterator, false, + typedef df_iterator, false, GraphTraits>> nodes_iterator; Index: include/llvm/CodeGen/MachineRegionInfo.h =================================================================== --- include/llvm/CodeGen/MachineRegionInfo.h +++ include/llvm/CodeGen/MachineRegionInfo.h @@ -142,7 +142,7 @@ template <> struct GraphTraits : public GraphTraits > { - typedef df_iterator, false, + typedef df_iterator, false, GraphTraits>> nodes_iterator; @@ -159,7 +159,7 @@ template <> struct GraphTraits : public GraphTraits { - typedef df_iterator, false, + typedef df_iterator, false, GraphTraits>> nodes_iterator; Index: include/llvm/IR/Dominators.h =================================================================== --- include/llvm/IR/Dominators.h +++ include/llvm/IR/Dominators.h @@ -157,7 +157,7 @@ template struct DomTreeGraphTraitsBase { typedef Node *NodeRef; typedef ChildIterator ChildIteratorType; - typedef df_iterator> nodes_iterator; + typedef df_iterator> nodes_iterator; static NodeRef getEntryNode(NodeRef N) { return N; } static ChildIteratorType child_begin(NodeRef N) { return N->begin(); } Index: lib/CodeGen/LiveIntervalAnalysis.cpp =================================================================== --- lib/CodeGen/LiveIntervalAnalysis.cpp +++ lib/CodeGen/LiveIntervalAnalysis.cpp @@ -599,7 +599,7 @@ // Find all blocks that are reachable from KillMBB without leaving VNI's live // range. It is possible that KillMBB itself is reachable, so start a DFS // from each successor. - typedef SmallPtrSet VisitedTy; + typedef df_iterator_default_set VisitedTy; VisitedTy Visited; for (MachineBasicBlock::succ_iterator SuccI = KillMBB->succ_begin(), SuccE = KillMBB->succ_end(); Index: lib/CodeGen/LiveVariables.cpp =================================================================== --- lib/CodeGen/LiveVariables.cpp +++ lib/CodeGen/LiveVariables.cpp @@ -643,7 +643,7 @@ // register before its uses due to dominance properties of SSA (except for PHI // nodes, which are treated as a special case). MachineBasicBlock *Entry = &MF->front(); - SmallPtrSet Visited; + df_iterator_default_set Visited; for (MachineBasicBlock *MBB : depth_first_ext(Entry, Visited)) { runOnBlock(MBB, NumRegs); Index: lib/CodeGen/MachineVerifier.cpp =================================================================== --- lib/CodeGen/MachineVerifier.cpp +++ lib/CodeGen/MachineVerifier.cpp @@ -2014,11 +2014,11 @@ SmallVector SPState; SPState.resize(MF->getNumBlockIDs()); - SmallPtrSet Reachable; + df_iterator_default_set Reachable; // Visit the MBBs in DFS order. for (df_ext_iterator > + df_iterator_default_set > DFI = df_ext_begin(MF, Reachable), DFE = df_ext_end(MF, Reachable); DFI != DFE; ++DFI) { const MachineBasicBlock *MBB = *DFI; Index: lib/CodeGen/PrologEpilogInserter.cpp =================================================================== --- lib/CodeGen/PrologEpilogInserter.cpp +++ lib/CodeGen/PrologEpilogInserter.cpp @@ -1008,7 +1008,7 @@ // Store SPAdj at exit of a basic block. SmallVector SPState; SPState.resize(Fn.getNumBlockIDs()); - SmallPtrSet Reachable; + df_iterator_default_set Reachable; // Iterate over the reachable blocks in DFS order. for (auto DFI = df_ext_begin(&Fn, Reachable), DFE = df_ext_end(&Fn, Reachable); Index: lib/CodeGen/UnreachableBlockElim.cpp =================================================================== --- lib/CodeGen/UnreachableBlockElim.cpp +++ lib/CodeGen/UnreachableBlockElim.cpp @@ -40,7 +40,7 @@ using namespace llvm; static bool eliminateUnreachableBlock(Function &F) { - SmallPtrSet Reachable; + df_iterator_default_set Reachable; // Mark all reachable blocks. for (BasicBlock *BB : depth_first_ext(&F, Reachable)) @@ -130,7 +130,7 @@ } bool UnreachableMachineBlockElim::runOnMachineFunction(MachineFunction &F) { - SmallPtrSet Reachable; + df_iterator_default_set Reachable; bool ModifiedPHI = false; MMI = getAnalysisIfAvailable(); Index: lib/Target/X86/X86FloatingPoint.cpp =================================================================== --- lib/Target/X86/X86FloatingPoint.cpp +++ lib/Target/X86/X86FloatingPoint.cpp @@ -326,7 +326,7 @@ // Process the function in depth first order so that we process at least one // of the predecessors for every reachable block in the function. - SmallPtrSet Processed; + df_iterator_default_set Processed; MachineBasicBlock *Entry = &MF.front(); bool Changed = false; Index: lib/Transforms/IPO/ArgumentPromotion.cpp =================================================================== --- lib/Transforms/IPO/ArgumentPromotion.cpp +++ lib/Transforms/IPO/ArgumentPromotion.cpp @@ -600,7 +600,7 @@ // Because there could be several/many load instructions, remember which // blocks we know to be transparent to the load. - SmallPtrSet TranspBlocks; + df_iterator_default_set TranspBlocks; for (LoadInst *Load : Loads) { // Check to see if the load is invalidated from the start of the block to Index: unittests/ADT/DepthFirstIteratorTest.cpp =================================================================== --- unittests/ADT/DepthFirstIteratorTest.cpp +++ unittests/ADT/DepthFirstIteratorTest.cpp @@ -27,6 +27,8 @@ } size_t count(const T &Item) const { return S.count(Item); } + + void completed(T) { } }; template class df_iterator_storage, true> {