diff --git a/clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp b/clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp --- a/clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp @@ -261,12 +261,10 @@ // Look for cycles in call graph, // by looking for Strongly Connected Components (SCC's) - for (llvm::scc_iterator SCCI = llvm::scc_begin(&CG), - SCCE = llvm::scc_end(&CG); - SCCI != SCCE; ++SCCI) { - if (!SCCI.hasCycle()) // We only care about cycles, not standalone nodes. + for (auto SCC : llvm::scc_traversal(&CG)) { + if (!SCC.hasCycle()) // We only care about cycles, not standalone nodes. continue; - handleSCC(*SCCI); + handleSCC(*SCC); } } diff --git a/llvm/include/llvm/ADT/BreadthFirstIterator.h b/llvm/include/llvm/ADT/BreadthFirstIterator.h --- a/llvm/include/llvm/ADT/BreadthFirstIterator.h +++ b/llvm/include/llvm/ADT/BreadthFirstIterator.h @@ -22,6 +22,7 @@ #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" #include #include @@ -124,6 +125,10 @@ bool operator!=(const bf_iterator &RHS) const { return !(*this == RHS); } + bool operator==(iterator_sentinel) const { return VisitQueue.empty(); } + + bool operator!=(iterator_sentinel RHS) const { return !(*this == RHS); } + const NodeRef &operator*() const { return VisitQueue.front()->first; } // This is a nonstandard operator-> that dereferences the pointer an extra @@ -155,8 +160,9 @@ } // Provide an accessor method to use them in range-based patterns. -template iterator_range> breadth_first(const T &G) { - return make_range(bf_begin(G), bf_end(G)); +template +iterator_range_with_sentinel> breadth_first(const T &G) { + return make_range_with_sentinel(bf_begin(G)); } } // end namespace llvm diff --git a/llvm/include/llvm/ADT/DepthFirstIterator.h b/llvm/include/llvm/ADT/DepthFirstIterator.h --- a/llvm/include/llvm/ADT/DepthFirstIterator.h +++ b/llvm/include/llvm/ADT/DepthFirstIterator.h @@ -166,6 +166,9 @@ } bool operator!=(const df_iterator &x) const { return !(*this == x); } + bool operator==(iterator_sentinel) const { return VisitStack.empty(); } + bool operator!=(iterator_sentinel x) const { return !(*this == x); } + const NodeRef &operator*() const { return VisitStack.back().first; } // This is a nonstandard operator-> that dereferences the pointer an extra @@ -249,9 +252,9 @@ } template -iterator_range> depth_first_ext(const T& G, - SetTy &S) { - return make_range(df_ext_begin(G, S), df_ext_end(G, S)); +iterator_range_with_sentinel> +depth_first_ext(const T &G, SetTy &S) { + return make_range_with_sentinel(df_ext_begin(G, S)); } // Provide global definitions of inverse depth first iterators... @@ -276,8 +279,9 @@ // Provide an accessor method to use them in range-based patterns. template -iterator_range> inverse_depth_first(const T& G) { - return make_range(idf_begin(G), idf_end(G)); +iterator_range_with_sentinel> +inverse_depth_first(const T &G) { + return make_range_with_sentinel(idf_begin(G)); } // Provide global definitions of external inverse depth first iterators... @@ -300,9 +304,9 @@ } template -iterator_range> inverse_depth_first_ext(const T& G, - SetTy &S) { - return make_range(idf_ext_begin(G, S), idf_ext_end(G, S)); +iterator_range_with_sentinel> +inverse_depth_first_ext(const T &G, SetTy &S) { + return make_range_with_sentinel(idf_ext_begin(G, S)); } } // end namespace llvm diff --git a/llvm/include/llvm/ADT/PostOrderIterator.h b/llvm/include/llvm/ADT/PostOrderIterator.h --- a/llvm/include/llvm/ADT/PostOrderIterator.h +++ b/llvm/include/llvm/ADT/PostOrderIterator.h @@ -156,6 +156,9 @@ } bool operator!=(const po_iterator &x) const { return !(*this == x); } + bool operator==(iterator_sentinel) const { return VisitStack.empty(); } + bool operator!=(iterator_sentinel x) const { return !(*this == x); } + const NodeRef &operator*() const { return VisitStack.back().first; } // This is a nonstandard operator-> that dereferences the pointer an extra @@ -186,8 +189,9 @@ template po_iterator po_end (const T &G) { return po_iterator::end(G); } -template iterator_range> post_order(const T &G) { - return make_range(po_begin(G), po_end(G)); +template +iterator_range_with_sentinel> post_order(const T &G) { + return make_range_with_sentinel(po_begin(G)); } // Provide global definitions of external postorder iterators... @@ -208,8 +212,9 @@ } template -iterator_range> post_order_ext(const T &G, SetType &S) { - return make_range(po_ext_begin(G, S), po_ext_end(G, S)); +iterator_range_with_sentinel> +post_order_ext(const T &G, SetType &S) { + return make_range_with_sentinel(po_ext_begin(G, S)); } // Provide global definitions of inverse post order iterators... @@ -231,8 +236,9 @@ } template -iterator_range> inverse_post_order(const T &G) { - return make_range(ipo_begin(G), ipo_end(G)); +iterator_range_with_sentinel> +inverse_post_order(const T &G) { + return make_range_with_sentinel(ipo_begin(G)); } // Provide global definitions of external inverse postorder iterators... @@ -255,9 +261,9 @@ } template -iterator_range> +iterator_range_with_sentinel> inverse_post_order_ext(const T &G, SetType &S) { - return make_range(ipo_ext_begin(G, S), ipo_ext_end(G, S)); + return make_range_with_sentinel(ipo_ext_begin(G, S)); } //===--------------------------------------------------------------------===// diff --git a/llvm/include/llvm/ADT/SCCIterator.h b/llvm/include/llvm/ADT/SCCIterator.h --- a/llvm/include/llvm/ADT/SCCIterator.h +++ b/llvm/include/llvm/ADT/SCCIterator.h @@ -43,13 +43,12 @@ /// build up a vector of nodes in a particular SCC. Note that it is a forward /// iterator and thus you cannot backtrack or re-visit nodes. template > -class scc_iterator : public iterator_facade_base< - scc_iterator, std::forward_iterator_tag, - const std::vector, ptrdiff_t> { +class scc_iterator { using NodeRef = typename GT::NodeRef; using ChildItTy = typename GT::ChildIteratorType; using SccTy = std::vector; - using reference = typename scc_iterator::reference; + using reference = const SccTy &; + using pointer = const SccTy *; /// Element of VisitStack during DFS. struct StackElement { @@ -118,21 +117,58 @@ return VisitStack == x.VisitStack && CurrentSCC == x.CurrentSCC; } + bool operator!=(const scc_iterator &x) const { return !(*this == x); } + + bool operator==(iterator_sentinel) const { return isAtEnd(); } + + bool operator!=(iterator_sentinel RHS) const { return !(*this == RHS); } + scc_iterator &operator++() { GetNextSCC(); return *this; } - reference operator*() const { + /// A proxy object that is returned from scc_iterator operator* and operator-> + /// member functions. It allows performing implicit conversion to SccTy and + /// provides operator* and operator-> member functions to access underlying + /// object with SccTy type. This class is necessary to provide additional + /// functionality (e.g. hasCycle) that cannot be provided by SccTy object. + class SCCProxy { + friend scc_iterator; + + reference SCC; + + SCCProxy(reference SCC) : SCC(SCC) {} + + public: + operator reference() const { return SCC; } + + reference operator*() const { return SCC; } + pointer operator->() const { return &SCC; } + + /// Test if the current SCC has a cycle. + /// + /// If the SCC has more than one node, this is trivially true. If not, it + /// may still contain a cycle if the node has an edge back to itself. + bool hasCycle() const { + assert(!SCC.empty() && "Dereferencing END SCC iterator!"); + if (SCC.size() > 1) + return true; + NodeRef N = SCC.front(); + for (ChildItTy CI = GT::child_begin(N), CE = GT::child_end(N); CI != CE; + ++CI) + if (*CI == N) + return true; + return false; + } + }; + + SCCProxy operator*() const { assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); return CurrentSCC; } - /// Test if the current SCC has a cycle. - /// - /// If the SCC has more than one node, this is trivially true. If not, it may - /// still contain a cycle if the node has an edge back to itself. - bool hasCycle() const; + SCCProxy operator->() const { return operator*(); } /// This informs the \c scc_iterator that the specified \c Old node /// has been deleted, and \c New is to be used in its place. @@ -215,19 +251,6 @@ } } -template -bool scc_iterator::hasCycle() const { - assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); - if (CurrentSCC.size() > 1) - return true; - NodeRef N = CurrentSCC.front(); - for (ChildItTy CI = GT::child_begin(N), CE = GT::child_end(N); CI != CE; - ++CI) - if (*CI == N) - return true; - return false; - } - /// Construct the begin iterator for a deduced graph type T. template scc_iterator scc_begin(const T &G) { return scc_iterator::begin(G); @@ -238,6 +261,11 @@ return scc_iterator::end(G); } +template +iterator_range_with_sentinel> scc_traversal(const T &G) { + return make_range_with_sentinel(scc_begin(G)); +} + /// Sort the nodes of a directed SCC in the decreasing order of the edge /// weights. The instantiating GraphT type should have weighted edge type /// declared in its graph traits in order to use this iterator. diff --git a/llvm/include/llvm/ADT/iterator_range.h b/llvm/include/llvm/ADT/iterator_range.h --- a/llvm/include/llvm/ADT/iterator_range.h +++ b/llvm/include/llvm/ADT/iterator_range.h @@ -46,6 +46,25 @@ bool empty() const { return begin_iterator == end_iterator; } }; +/// As of C++17, the types of the begin-expr and the end-expr do not have to be +/// the same in 'based-range for loop'. This class represents a tag that should +/// be returned from the 'end' member function of an iterator. +class iterator_sentinel {}; + +/// A range adaptor for an iterator that wants iterator_sentinel as the +/// end iterator. The iterator should provide operator!=(iterator_sentinel) +/// function. +template class iterator_range_with_sentinel { + IteratorT begin_iterator; + +public: + explicit iterator_range_with_sentinel(IteratorT begin_iterator) + : begin_iterator(std::move(begin_iterator)) {} + + IteratorT begin() const { return begin_iterator; } + iterator_sentinel end() const { return iterator_sentinel(); } +}; + /// Convenience function for iterating over sub-ranges. /// /// This provides a bit of syntactic sugar to make using sub-ranges @@ -58,6 +77,10 @@ return iterator_range(std::move(p.first), std::move(p.second)); } +template +iterator_range_with_sentinel make_range_with_sentinel(T begin) { + return iterator_range_with_sentinel(std::move(begin)); +} } #endif diff --git a/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp b/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp --- a/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp +++ b/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp @@ -807,12 +807,12 @@ assert((OuterLoop == nullptr) == (Insert == Loops.begin())); auto Prev = OuterLoop ? std::prev(Insert) : Loops.end(); - for (auto I = scc_begin(G); !I.isAtEnd(); ++I) { - if (I->size() < 2) + for (auto SCC : scc_traversal(G)) { + if (SCC->size() < 2) continue; // Translate the SCC into RPO. - createIrreducibleLoop(*this, G, OuterLoop, Insert, *I); + createIrreducibleLoop(*this, G, OuterLoop, Insert, SCC); } if (OuterLoop) diff --git a/llvm/lib/Analysis/BranchProbabilityInfo.cpp b/llvm/lib/Analysis/BranchProbabilityInfo.cpp --- a/llvm/lib/Analysis/BranchProbabilityInfo.cpp +++ b/llvm/lib/Analysis/BranchProbabilityInfo.cpp @@ -219,16 +219,15 @@ // FIXME: We could only calculate this if the CFG is known to be irreducible // (perhaps cache this info in LoopInfo if we can easily calculate it there?). int SccNum = 0; - for (scc_iterator It = scc_begin(&F); !It.isAtEnd(); - ++It, ++SccNum) { + for (auto SCC : scc_traversal(&F)) { + ++SccNum; // Ignore single-block SCCs since they either aren't loops or LoopInfo will // catch them. - const std::vector &Scc = *It; - if (Scc.size() == 1) + if (SCC->size() == 1) continue; LLVM_DEBUG(dbgs() << "BPI: SCC " << SccNum << ":"); - for (const auto *BB : Scc) { + for (const auto *BB : *SCC) { LLVM_DEBUG(dbgs() << " " << BB->getName()); SccNums[BB] = SccNum; calculateSccBlockType(BB, SccNum); diff --git a/llvm/lib/Analysis/CFGPrinter.cpp b/llvm/lib/Analysis/CFGPrinter.cpp --- a/llvm/lib/Analysis/CFGPrinter.cpp +++ b/llvm/lib/Analysis/CFGPrinter.cpp @@ -311,7 +311,8 @@ }; /// The post order traversal iteration is done to know the status of /// isOnDeoptOrUnreachablePath for all the successors on the current BB. - llvm::for_each(post_order(&F->getEntryBlock()), evaluateBB); + for (auto &BB : post_order(&F->getEntryBlock())) + evaluateBB(BB); } bool DOTGraphTraits::isNodeHidden(const BasicBlock *Node, diff --git a/llvm/lib/Analysis/DDG.cpp b/llvm/lib/Analysis/DDG.cpp --- a/llvm/lib/Analysis/DDG.cpp +++ b/llvm/lib/Analysis/DDG.cpp @@ -188,8 +188,8 @@ // Put the basic blocks in program order for correct dependence // directions. BasicBlockListType BBList; - for (const auto &SCC : make_range(scc_begin(&F), scc_end(&F))) - append_range(BBList, SCC); + for (auto SCC : scc_traversal(&F)) + append_range(BBList, *SCC); std::reverse(BBList.begin(), BBList.end()); DDGBuilder(*this, D, BBList).populate(); } diff --git a/llvm/lib/Analysis/DependenceGraphBuilder.cpp b/llvm/lib/Analysis/DependenceGraphBuilder.cpp --- a/llvm/lib/Analysis/DependenceGraphBuilder.cpp +++ b/llvm/lib/Analysis/DependenceGraphBuilder.cpp @@ -110,9 +110,9 @@ // list of nodes in an SCC. Note: trivial SCCs containing a single node are // ignored. SmallVector ListOfSCCs; - for (auto &SCC : make_range(scc_begin(&Graph), scc_end(&Graph))) { - if (SCC.size() > 1) - ListOfSCCs.emplace_back(SCC.begin(), SCC.end()); + for (auto SCC : scc_traversal(&Graph)) { + if (SCC->size() > 1) + ListOfSCCs.emplace_back(SCC->begin(), SCC->end()); } for (NodeListType &NL : ListOfSCCs) { diff --git a/llvm/lib/Analysis/GlobalsModRef.cpp b/llvm/lib/Analysis/GlobalsModRef.cpp --- a/llvm/lib/Analysis/GlobalsModRef.cpp +++ b/llvm/lib/Analysis/GlobalsModRef.cpp @@ -452,11 +452,10 @@ // We do a bottom-up SCC traversal of the call graph. In other words, we // visit all callees before callers (leaf-first). unsigned SCCID = 0; - for (scc_iterator I = scc_begin(&CG); !I.isAtEnd(); ++I) { - const std::vector &SCC = *I; - assert(!SCC.empty() && "SCC with no functions?"); + for (auto SCC : scc_traversal(&CG)) { + assert(!SCC->empty() && "SCC with no functions?"); - for (auto *CGN : SCC) + for (auto *CGN : *SCC) if (Function *F = CGN->getFunction()) FunctionToSCCMap[F] = SCCID; ++SCCID; @@ -470,8 +469,8 @@ void GlobalsAAResult::AnalyzeCallGraph(CallGraph &CG, Module &M) { // We do a bottom-up SCC traversal of the call graph. In other words, we // visit all callees before callers (leaf-first). - for (scc_iterator I = scc_begin(&CG); !I.isAtEnd(); ++I) { - const std::vector &SCC = *I; + for (auto I : scc_traversal(&CG)) { + const std::vector &SCC = I; assert(!SCC.empty() && "SCC with no functions?"); Function *F = SCC[0]->getFunction(); diff --git a/llvm/lib/Analysis/LoopCacheAnalysis.cpp b/llvm/lib/Analysis/LoopCacheAnalysis.cpp --- a/llvm/lib/Analysis/LoopCacheAnalysis.cpp +++ b/llvm/lib/Analysis/LoopCacheAnalysis.cpp @@ -581,7 +581,7 @@ } LoopVectorTy Loops; - append_range(Loops, breadth_first(&Root)); + append_range(Loops, make_range(bf_begin(&Root), bf_end(&Root))); if (!getInnerMostLoop(Loops)) { LLVM_DEBUG(dbgs() << "Cannot compute cache cost of loop nest with more " diff --git a/llvm/lib/Analysis/LoopNestAnalysis.cpp b/llvm/lib/Analysis/LoopNestAnalysis.cpp --- a/llvm/lib/Analysis/LoopNestAnalysis.cpp +++ b/llvm/lib/Analysis/LoopNestAnalysis.cpp @@ -41,7 +41,7 @@ LoopNest::LoopNest(Loop &Root, ScalarEvolution &SE) : MaxPerfectDepth(getMaxPerfectDepth(Root, SE)) { - append_range(Loops, breadth_first(&Root)); + append_range(Loops, make_range(bf_begin(&Root), bf_end(&Root))); } std::unique_ptr LoopNest::getLoopNest(Loop &Root, diff --git a/llvm/lib/Analysis/MLInlineAdvisor.cpp b/llvm/lib/Analysis/MLInlineAdvisor.cpp --- a/llvm/lib/Analysis/MLInlineAdvisor.cpp +++ b/llvm/lib/Analysis/MLInlineAdvisor.cpp @@ -102,8 +102,8 @@ // heuristic's decisions - and, thus, equally important for training for // improvement. CallGraph CGraph(M); - for (auto I = scc_begin(&CGraph); !I.isAtEnd(); ++I) { - const std::vector &CGNodes = *I; + for (auto SCC : scc_traversal(&CGraph)) { + const std::vector &CGNodes = SCC; unsigned Level = 0; for (auto *CGNode : CGNodes) { Function *F = CGNode->getFunction(); diff --git a/llvm/lib/Analysis/SyntheticCountsUtils.cpp b/llvm/lib/Analysis/SyntheticCountsUtils.cpp --- a/llvm/lib/Analysis/SyntheticCountsUtils.cpp +++ b/llvm/lib/Analysis/SyntheticCountsUtils.cpp @@ -86,8 +86,8 @@ std::vector SCCs; // Collect all the SCCs. - for (auto I = scc_begin(CG); !I.isAtEnd(); ++I) - SCCs.push_back(*I); + for (auto SCC : scc_traversal(CG)) + SCCs.push_back(SCC); // The callgraph-scc needs to be visited in top-down order for propagation. // The scc iterator returns the scc in bottom-up order, so reverse the SCCs diff --git a/llvm/lib/IR/ModuleSummaryIndex.cpp b/llvm/lib/IR/ModuleSummaryIndex.cpp --- a/llvm/lib/IR/ModuleSummaryIndex.cpp +++ b/llvm/lib/IR/ModuleSummaryIndex.cpp @@ -353,17 +353,15 @@ // then delete this function and update its tests LLVM_DUMP_METHOD void ModuleSummaryIndex::dumpSCCs(raw_ostream &O) { - for (scc_iterator I = - scc_begin(this); - !I.isAtEnd(); ++I) { - O << "SCC (" << utostr(I->size()) << " node" << (I->size() == 1 ? "" : "s") - << ") {\n"; - for (const ValueInfo &V : *I) { + for (auto SCC : scc_traversal(this)) { + O << "SCC (" << utostr(SCC->size()) << " node" + << (SCC->size() == 1 ? "" : "s") << ") {\n"; + for (const ValueInfo &V : *SCC) { FunctionSummary *F = nullptr; if (V.getSummaryList().size()) F = cast(V.getSummaryList().front().get()); O << " " << (F == nullptr ? "External" : "") << " " << utostr(V.getGUID()) - << (I.hasCycle() ? " (has cycle)" : "") << "\n"; + << (SCC.hasCycle() ? " (has cycle)" : "") << "\n"; } O << "}\n"; } diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -2847,8 +2847,8 @@ // We use scc_iterator which uses Tarjan algorithm to find all the maximal // SCCs.To detect if there's a cycle, we only need to find the maximal ones. if (!SE || !LI) { - for (scc_iterator SCCI = scc_begin(&F); !SCCI.isAtEnd(); ++SCCI) - if (SCCI.hasCycle()) + for (auto SCC : scc_traversal(&F)) + if (SCC.hasCycle()) return true; return false; } diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp --- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -531,9 +531,8 @@ }; // Call propagation functions on each SCC in the Index - for (scc_iterator I = scc_begin(&Index); !I.isAtEnd(); - ++I) { - std::vector Nodes(*I); + for (auto SCC : scc_traversal(&Index)) { + std::vector Nodes(*SCC); PropagateAttributes(Nodes); } return Changed; @@ -990,8 +989,8 @@ // made. If the definition doesn't have a 'nocapture' attribute by now, it // captures. - for (scc_iterator I = scc_begin(&AG); !I.isAtEnd(); ++I) { - const std::vector &ArgumentSCC = *I; + for (auto SCC : scc_traversal(&AG)) { + const std::vector &ArgumentSCC = SCC; if (ArgumentSCC.size() == 1) { if (!ArgumentSCC[0]->Definition) continue; // synthetic root node @@ -2035,11 +2034,11 @@ // synthesizing norecurse and so we can only save the singular SCCs as SCCs // with multiple functions in them will clearly be recursive. SmallVector Worklist; - for (scc_iterator I = scc_begin(&CG); !I.isAtEnd(); ++I) { - if (I->size() != 1) + for (auto SCC : scc_traversal(&CG)) { + if (SCC->size() != 1) continue; - Function *F = I->front()->getFunction(); + Function *F = SCC->front()->getFunction(); if (F && !F->isDeclaration() && !F->doesNotRecurse() && F->hasInternalLinkage()) Worklist.push_back(F); diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp --- a/llvm/lib/Transforms/IPO/SampleProfile.cpp +++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp @@ -1878,8 +1878,7 @@ // context in the profile. std::unique_ptr ProfiledCG = buildProfiledCallGraph(*CG); - scc_iterator CGI = scc_begin(ProfiledCG.get()); - while (!CGI.isAtEnd()) { + for (auto CGI : scc_traversal(ProfiledCG.get())) { auto Range = *CGI; if (SortProfiledSCC) { // Sort nodes in one SCC based on callsite hotness. @@ -1891,17 +1890,14 @@ if (F && !F->isDeclaration() && F->hasFnAttribute("use-sample-profile")) FunctionOrderList.push_back(F); } - ++CGI; } } else { - scc_iterator CGI = scc_begin(CG); - while (!CGI.isAtEnd()) { + for (auto CGI : scc_traversal(CG)) { for (CallGraphNode *Node : *CGI) { auto *F = Node->getFunction(); if (F && !F->isDeclaration() && F->hasFnAttribute("use-sample-profile")) FunctionOrderList.push_back(F); } - ++CGI; } } diff --git a/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp b/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp --- a/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp +++ b/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp @@ -385,7 +385,7 @@ scc_iterator::begin( EntryNode); !SCCI.isAtEnd(); ++SCCI) { - auto &SCC = *SCCI; + auto &SCC = **SCCI; // An SCC up to the size of 2, can be reduced to an entry (the last node), // and a possible additional node. Therefore, it is already in order, and diff --git a/llvm/lib/Transforms/Utils/FixIrreducible.cpp b/llvm/lib/Transforms/Utils/FixIrreducible.cpp --- a/llvm/lib/Transforms/Utils/FixIrreducible.cpp +++ b/llvm/lib/Transforms/Utils/FixIrreducible.cpp @@ -269,7 +269,7 @@ template static bool makeReducible(LoopInfo &LI, DominatorTree &DT, Graph &&G) { bool Changed = false; - for (auto Scc = scc_begin(G); !Scc.isAtEnd(); ++Scc) { + for (auto Scc : scc_traversal(G)) { if (Scc->size() < 2) continue; SetVector Blocks; diff --git a/llvm/tools/llvm-profgen/CSPreInliner.cpp b/llvm/tools/llvm-profgen/CSPreInliner.cpp --- a/llvm/tools/llvm-profgen/CSPreInliner.cpp +++ b/llvm/tools/llvm-profgen/CSPreInliner.cpp @@ -78,19 +78,17 @@ // Now that we have a profiled call graph, construct top-down order // by building up SCC and reversing SCC order. - scc_iterator I = scc_begin(&ProfiledCG); - while (!I.isAtEnd()) { - auto Range = *I; + for (auto SCC : scc_traversal(&ProfiledCG)) { + auto Range = *SCC; if (SortProfiledSCC) { // Sort nodes in one SCC based on callsite hotness. - scc_member_iterator SI(*I); + scc_member_iterator SI(*SCC); Range = *SI; } for (auto *Node : Range) { if (Node != ProfiledCG.getEntryNode()) Order.push_back(Node->Name); } - ++I; } std::reverse(Order.begin(), Order.end()); diff --git a/llvm/tools/opt/PrintSCC.cpp b/llvm/tools/opt/PrintSCC.cpp --- a/llvm/tools/opt/PrintSCC.cpp +++ b/llvm/tools/opt/PrintSCC.cpp @@ -73,14 +73,13 @@ bool CFGSCC::runOnFunction(Function &F) { unsigned sccNum = 0; errs() << "SCCs for Function " << F.getName() << " in PostOrder:"; - for (scc_iterator SCCI = scc_begin(&F); !SCCI.isAtEnd(); ++SCCI) { - const std::vector &nextSCC = *SCCI; + for (auto SCC : scc_traversal(&F)) { errs() << "\nSCC #" << ++sccNum << " : "; - for (BasicBlock *BB : nextSCC) { + for (BasicBlock *BB : *SCC) { BB->printAsOperand(errs(), false); errs() << ", "; } - if (nextSCC.size() == 1 && SCCI.hasCycle()) + if (SCC->size() == 1 && SCC.hasCycle()) errs() << " (Has self-loop)."; } errs() << "\n"; @@ -94,15 +93,14 @@ CallGraph &CG = getAnalysis().getCallGraph(); unsigned sccNum = 0; errs() << "SCCs for the program in PostOrder:"; - for (scc_iterator SCCI = scc_begin(&CG); !SCCI.isAtEnd(); - ++SCCI) { - const std::vector &nextSCC = *SCCI; + for (auto SCC : scc_traversal(&CG)) { errs() << "\nSCC #" << ++sccNum << " : "; - for (std::vector::const_iterator I = nextSCC.begin(), - E = nextSCC.end(); I != E; ++I) - errs() << ((*I)->getFunction() ? (*I)->getFunction()->getName() - : "external node") << ", "; - if (nextSCC.size() == 1 && SCCI.hasCycle()) + for (auto *N : *SCC) + errs() << (N->getFunction() ? N->getFunction()->getName() + : "external node") + << ", "; + + if (SCC->size() == 1 && SCC.hasCycle()) errs() << " (Has self-loop)."; } errs() << "\n"; diff --git a/llvm/unittests/ADT/DirectedGraphTest.cpp b/llvm/unittests/ADT/DirectedGraphTest.cpp --- a/llvm/unittests/ADT/DirectedGraphTest.cpp +++ b/llvm/unittests/ADT/DirectedGraphTest.cpp @@ -270,8 +270,8 @@ // 2. {N4} using NodeListTy = SmallPtrSet; SmallVector ListOfSCCs; - for (auto &SCC : make_range(scc_begin(&DG), scc_end(&DG))) - ListOfSCCs.push_back(NodeListTy(SCC.begin(), SCC.end())); + for (auto SCC : scc_traversal(&DG)) + ListOfSCCs.push_back(NodeListTy(SCC->begin(), SCC->end())); EXPECT_TRUE(ListOfSCCs.size() == 2); diff --git a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp --- a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp +++ b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp @@ -428,7 +428,8 @@ // Post-order. FromIterator.clear(); - copy(post_order(Start), std::back_inserter(FromIterator)); + copy(make_range(po_begin(Start), po_end(Start)), + std::back_inserter(FromIterator)); EXPECT_EQ(8u, FromIterator.size()); EXPECT_EQ(R2BB2, FromIterator[0]); EXPECT_EQ(R2BB1, FromIterator[1]); @@ -630,7 +631,8 @@ // Post-order. FromIterator.clear(); - copy(post_order(Start), std::back_inserter(FromIterator)); + copy(make_range(po_begin(Start), po_end(Start)), + std::back_inserter(FromIterator)); EXPECT_EQ(7u, FromIterator.size()); EXPECT_EQ(VPBB2, FromIterator[0]); EXPECT_EQ(R3BB1, FromIterator[1]); @@ -643,7 +645,8 @@ // Post-order, const VPRegionBlocks only. VPBlockRecursiveTraversalWrapper StartConst(VPBB1); SmallVector FromIteratorVPRegion( - VPBlockUtils::blocksOnly(post_order(StartConst))); + VPBlockUtils::blocksOnly( + make_range(po_begin(StartConst), po_end(StartConst)))); EXPECT_EQ(3u, FromIteratorVPRegion.size()); EXPECT_EQ(R3, FromIteratorVPRegion[0]); EXPECT_EQ(R2, FromIteratorVPRegion[1]); @@ -651,7 +654,8 @@ // Post-order, VPBasicBlocks only. FromIterator.clear(); - copy(VPBlockUtils::blocksOnly(post_order(Start)), + copy(VPBlockUtils::blocksOnly( + make_range(po_begin(Start), po_end(Start))), std::back_inserter(FromIterator)); EXPECT_EQ(FromIterator.size(), 4u); EXPECT_EQ(VPBB2, FromIterator[0]);