rusyaev-roman updated this revision to Diff 451208.
rusyaev-roman added a comment.
Herald added subscribers: bzcheeseman, sdasgup3, wenzhicui, wrengr, cota, 
teijeong, rdzhabarov, tatianashp, msifontes, jurahul, Kayjukh, grosul1, 
Joonsoo, stephenneuendorffer, liufengdb, aartbik, mgester, arpith-jacob, 
nicolasvasilache, antiagainst, shauheen, rriddle, mehdi_amini.
Herald added a reviewer: aartbik.
Herald added a project: MLIR.

Fix mlir build and rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131448/new/

https://reviews.llvm.org/D131448

Files:
  clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp
  llvm/include/llvm/ADT/BreadthFirstIterator.h
  llvm/include/llvm/ADT/DepthFirstIterator.h
  llvm/include/llvm/ADT/PostOrderIterator.h
  llvm/include/llvm/ADT/SCCIterator.h
  llvm/include/llvm/ADT/iterator_range.h
  llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp
  llvm/lib/Analysis/BranchProbabilityInfo.cpp
  llvm/lib/Analysis/CFGPrinter.cpp
  llvm/lib/Analysis/DDG.cpp
  llvm/lib/Analysis/DependenceGraphBuilder.cpp
  llvm/lib/Analysis/GlobalsModRef.cpp
  llvm/lib/Analysis/LoopCacheAnalysis.cpp
  llvm/lib/Analysis/LoopNestAnalysis.cpp
  llvm/lib/Analysis/MLInlineAdvisor.cpp
  llvm/lib/Analysis/SyntheticCountsUtils.cpp
  llvm/lib/IR/ModuleSummaryIndex.cpp
  llvm/lib/Transforms/IPO/AttributorAttributes.cpp
  llvm/lib/Transforms/IPO/FunctionAttrs.cpp
  llvm/lib/Transforms/IPO/SampleProfile.cpp
  llvm/lib/Transforms/Scalar/StructurizeCFG.cpp
  llvm/lib/Transforms/Utils/FixIrreducible.cpp
  llvm/tools/llvm-profgen/CSPreInliner.cpp
  llvm/tools/opt/PrintSCC.cpp
  llvm/unittests/ADT/DirectedGraphTest.cpp
  llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
  mlir/lib/Analysis/CallGraph.cpp

Index: mlir/lib/Analysis/CallGraph.cpp
===================================================================
--- mlir/lib/Analysis/CallGraph.cpp
+++ mlir/lib/Analysis/CallGraph.cpp
@@ -215,9 +215,9 @@
 
   os << "// -- SCCs --\n";
 
-  for (auto &scc : make_range(llvm::scc_begin(this), llvm::scc_end(this))) {
+  for (auto scc : llvm::scc_traversal(this)) {
     os << "// - SCC : \n";
-    for (auto &node : scc) {
+    for (auto &node : *scc) {
       os << "// -- Node :";
       emitNodeName(node);
       os << "\n";
Index: llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
===================================================================
--- llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
+++ 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<const VPBlockBase *> StartConst(VPBB1);
     SmallVector<const VPRegionBlock *> FromIteratorVPRegion(
-        VPBlockUtils::blocksOnly<const VPRegionBlock>(post_order(StartConst)));
+        VPBlockUtils::blocksOnly<const VPRegionBlock>(
+            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<VPBasicBlock>(post_order(Start)),
+    copy(VPBlockUtils::blocksOnly<VPBasicBlock>(
+             make_range(po_begin(Start), po_end(Start))),
          std::back_inserter(FromIterator));
     EXPECT_EQ(FromIterator.size(), 4u);
     EXPECT_EQ(VPBB2, FromIterator[0]);
Index: llvm/unittests/ADT/DirectedGraphTest.cpp
===================================================================
--- llvm/unittests/ADT/DirectedGraphTest.cpp
+++ llvm/unittests/ADT/DirectedGraphTest.cpp
@@ -270,8 +270,8 @@
   // 2. {N4}
   using NodeListTy = SmallPtrSet<DGTestNode *, 3>;
   SmallVector<NodeListTy, 4> 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);
 
Index: llvm/tools/opt/PrintSCC.cpp
===================================================================
--- llvm/tools/opt/PrintSCC.cpp
+++ 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<Function*> SCCI = scc_begin(&F); !SCCI.isAtEnd(); ++SCCI) {
-    const std::vector<BasicBlock *> &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<CallGraphWrapperPass>().getCallGraph();
   unsigned sccNum = 0;
   errs() << "SCCs for the program in PostOrder:";
-  for (scc_iterator<CallGraph*> SCCI = scc_begin(&CG); !SCCI.isAtEnd();
-       ++SCCI) {
-    const std::vector<CallGraphNode*> &nextSCC = *SCCI;
+  for (auto SCC : scc_traversal(&CG)) {
     errs() << "\nSCC #" << ++sccNum << " : ";
-    for (std::vector<CallGraphNode*>::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";
Index: llvm/tools/llvm-profgen/CSPreInliner.cpp
===================================================================
--- llvm/tools/llvm-profgen/CSPreInliner.cpp
+++ 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<ProfiledCallGraph *> 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<ProfiledCallGraph *> SI(*I);
+      scc_member_iterator<ProfiledCallGraph *> SI(*SCC);
       Range = *SI;
     }
     for (auto *Node : Range) {
       if (Node != ProfiledCG.getEntryNode())
         Order.push_back(Node->Name);
     }
-    ++I;
   }
   std::reverse(Order.begin(), Order.end());
 
Index: llvm/lib/Transforms/Utils/FixIrreducible.cpp
===================================================================
--- llvm/lib/Transforms/Utils/FixIrreducible.cpp
+++ llvm/lib/Transforms/Utils/FixIrreducible.cpp
@@ -269,7 +269,7 @@
 template <class Graph>
 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<BasicBlock *> Blocks;
Index: llvm/lib/Transforms/Scalar/StructurizeCFG.cpp
===================================================================
--- llvm/lib/Transforms/Scalar/StructurizeCFG.cpp
+++ llvm/lib/Transforms/Scalar/StructurizeCFG.cpp
@@ -385,7 +385,7 @@
              scc_iterator<SubGraphTraits::NodeRef, SubGraphTraits>::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
Index: llvm/lib/Transforms/IPO/SampleProfile.cpp
===================================================================
--- llvm/lib/Transforms/IPO/SampleProfile.cpp
+++ llvm/lib/Transforms/IPO/SampleProfile.cpp
@@ -1878,8 +1878,7 @@
     // context in the profile.
 
     std::unique_ptr<ProfiledCallGraph> ProfiledCG = buildProfiledCallGraph(*CG);
-    scc_iterator<ProfiledCallGraph *> 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<CallGraph *> 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;
     }
   }
 
Index: llvm/lib/Transforms/IPO/FunctionAttrs.cpp
===================================================================
--- llvm/lib/Transforms/IPO/FunctionAttrs.cpp
+++ llvm/lib/Transforms/IPO/FunctionAttrs.cpp
@@ -531,9 +531,8 @@
   };
 
   // Call propagation functions on each SCC in the Index
-  for (scc_iterator<ModuleSummaryIndex *> I = scc_begin(&Index); !I.isAtEnd();
-       ++I) {
-    std::vector<ValueInfo> Nodes(*I);
+  for (auto SCC : scc_traversal(&Index)) {
+    std::vector<ValueInfo> 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<ArgumentGraph *> I = scc_begin(&AG); !I.isAtEnd(); ++I) {
-    const std::vector<ArgumentGraphNode *> &ArgumentSCC = *I;
+  for (auto SCC : scc_traversal(&AG)) {
+    const std::vector<ArgumentGraphNode *> &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<Function *, 16> Worklist;
-  for (scc_iterator<CallGraph *> 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);
Index: llvm/lib/Transforms/IPO/AttributorAttributes.cpp
===================================================================
--- llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ 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<Function *> SCCI = scc_begin(&F); !SCCI.isAtEnd(); ++SCCI)
-      if (SCCI.hasCycle())
+    for (auto SCC : scc_traversal(&F))
+      if (SCC.hasCycle())
         return true;
     return false;
   }
Index: llvm/lib/IR/ModuleSummaryIndex.cpp
===================================================================
--- llvm/lib/IR/ModuleSummaryIndex.cpp
+++ 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<ModuleSummaryIndex *> I =
-           scc_begin<ModuleSummaryIndex *>(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<FunctionSummary>(V.getSummaryList().front().get());
       O << " " << (F == nullptr ? "External" : "") << " " << utostr(V.getGUID())
-        << (I.hasCycle() ? " (has cycle)" : "") << "\n";
+        << (SCC.hasCycle() ? " (has cycle)" : "") << "\n";
     }
     O << "}\n";
   }
Index: llvm/lib/Analysis/SyntheticCountsUtils.cpp
===================================================================
--- llvm/lib/Analysis/SyntheticCountsUtils.cpp
+++ llvm/lib/Analysis/SyntheticCountsUtils.cpp
@@ -86,8 +86,8 @@
   std::vector<SccTy> 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
Index: llvm/lib/Analysis/MLInlineAdvisor.cpp
===================================================================
--- llvm/lib/Analysis/MLInlineAdvisor.cpp
+++ 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<CallGraphNode *> &CGNodes = *I;
+  for (auto SCC : scc_traversal(&CGraph)) {
+    const std::vector<CallGraphNode *> &CGNodes = SCC;
     unsigned Level = 0;
     for (auto *CGNode : CGNodes) {
       Function *F = CGNode->getFunction();
Index: llvm/lib/Analysis/LoopNestAnalysis.cpp
===================================================================
--- llvm/lib/Analysis/LoopNestAnalysis.cpp
+++ 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> LoopNest::getLoopNest(Loop &Root,
Index: llvm/lib/Analysis/LoopCacheAnalysis.cpp
===================================================================
--- llvm/lib/Analysis/LoopCacheAnalysis.cpp
+++ 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 "
Index: llvm/lib/Analysis/GlobalsModRef.cpp
===================================================================
--- llvm/lib/Analysis/GlobalsModRef.cpp
+++ 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<CallGraph *> I = scc_begin(&CG); !I.isAtEnd(); ++I) {
-    const std::vector<CallGraphNode *> &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<CallGraph *> I = scc_begin(&CG); !I.isAtEnd(); ++I) {
-    const std::vector<CallGraphNode *> &SCC = *I;
+  for (auto I : scc_traversal(&CG)) {
+    const std::vector<CallGraphNode *> &SCC = I;
     assert(!SCC.empty() && "SCC with no functions?");
 
     Function *F = SCC[0]->getFunction();
Index: llvm/lib/Analysis/DependenceGraphBuilder.cpp
===================================================================
--- llvm/lib/Analysis/DependenceGraphBuilder.cpp
+++ 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<NodeListType, 4> 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) {
Index: llvm/lib/Analysis/DDG.cpp
===================================================================
--- llvm/lib/Analysis/DDG.cpp
+++ 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();
 }
Index: llvm/lib/Analysis/CFGPrinter.cpp
===================================================================
--- llvm/lib/Analysis/CFGPrinter.cpp
+++ 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<DOTFuncInfo *>::isNodeHidden(const BasicBlock *Node,
Index: llvm/lib/Analysis/BranchProbabilityInfo.cpp
===================================================================
--- llvm/lib/Analysis/BranchProbabilityInfo.cpp
+++ 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<const Function *> 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<const BasicBlock *> &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);
Index: llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp
===================================================================
--- llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp
+++ 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)
Index: llvm/include/llvm/ADT/iterator_range.h
===================================================================
--- llvm/include/llvm/ADT/iterator_range.h
+++ 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 <typename IteratorT> 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<T>(std::move(p.first), std::move(p.second));
 }
 
+template <typename T>
+iterator_range_with_sentinel<T> make_range_with_sentinel(T begin) {
+  return iterator_range_with_sentinel<T>(std::move(begin));
+}
 }
 
 #endif
Index: llvm/include/llvm/ADT/SCCIterator.h
===================================================================
--- llvm/include/llvm/ADT/SCCIterator.h
+++ llvm/include/llvm/ADT/SCCIterator.h
@@ -42,14 +42,12 @@
 /// This is implemented using Tarjan's DFS algorithm using an internal stack to
 /// 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 GraphT, class GT = GraphTraits<GraphT>>
-class scc_iterator : public iterator_facade_base<
-                         scc_iterator<GraphT, GT>, std::forward_iterator_tag,
-                         const std::vector<typename GT::NodeRef>, ptrdiff_t> {
+template <class GraphT, class GT = GraphTraits<GraphT>> class scc_iterator {
   using NodeRef = typename GT::NodeRef;
   using ChildItTy = typename GT::ChildIteratorType;
   using SccTy = std::vector<NodeRef>;
-  using reference = typename scc_iterator::reference;
+  using reference = const SccTy &;
+  using pointer = const SccTy *;
 
   /// Element of VisitStack during DFS.
   struct StackElement {
@@ -118,21 +116,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 +250,6 @@
   }
 }
 
-template <class GraphT, class GT>
-bool scc_iterator<GraphT, GT>::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 <class T> scc_iterator<T> scc_begin(const T &G) {
   return scc_iterator<T>::begin(G);
@@ -238,6 +260,11 @@
   return scc_iterator<T>::end(G);
 }
 
+template <typename T>
+iterator_range_with_sentinel<scc_iterator<T>> 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.
Index: llvm/include/llvm/ADT/PostOrderIterator.h
===================================================================
--- llvm/include/llvm/ADT/PostOrderIterator.h
+++ 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 <class T>
 po_iterator<T> po_end  (const T &G) { return po_iterator<T>::end(G); }
 
-template <class T> iterator_range<po_iterator<T>> post_order(const T &G) {
-  return make_range(po_begin(G), po_end(G));
+template <typename T>
+iterator_range_with_sentinel<po_iterator<T>> 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 <class T, class SetType>
-iterator_range<po_ext_iterator<T, SetType>> 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<po_ext_iterator<T, SetType>>
+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,8 @@
 }
 
 template <class T>
-iterator_range<ipo_iterator<T>> inverse_post_order(const T &G) {
-  return make_range(ipo_begin(G), ipo_end(G));
+iterator_range_with_sentinel<ipo_iterator<T>> inverse_post_order(const T &G) {
+  return make_range_with_sentinel(ipo_begin(G));
 }
 
 // Provide global definitions of external inverse postorder iterators...
@@ -255,9 +260,9 @@
 }
 
 template <class T, class SetType>
-iterator_range<ipo_ext_iterator<T, SetType>>
+iterator_range_with_sentinel<ipo_ext_iterator<T, SetType>>
 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));
 }
 
 //===--------------------------------------------------------------------===//
Index: llvm/include/llvm/ADT/DepthFirstIterator.h
===================================================================
--- llvm/include/llvm/ADT/DepthFirstIterator.h
+++ 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 <class T, class SetTy>
-iterator_range<df_ext_iterator<T, SetTy>> 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<df_ext_iterator<T, SetTy>>
+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,8 @@
 
 // Provide an accessor method to use them in range-based patterns.
 template <class T>
-iterator_range<idf_iterator<T>> inverse_depth_first(const T& G) {
-  return make_range(idf_begin(G), idf_end(G));
+iterator_range_with_sentinel<idf_iterator<T>> 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 +303,9 @@
 }
 
 template <class T, class SetTy>
-iterator_range<idf_ext_iterator<T, SetTy>> 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<idf_ext_iterator<T, SetTy>>
+inverse_depth_first_ext(const T &G, SetTy &S) {
+  return make_range_with_sentinel(idf_ext_begin(G, S));
 }
 
 } // end namespace llvm
Index: llvm/include/llvm/ADT/BreadthFirstIterator.h
===================================================================
--- llvm/include/llvm/ADT/BreadthFirstIterator.h
+++ 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 <iterator>
 #include <queue>
@@ -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 <class T> iterator_range<bf_iterator<T>> breadth_first(const T &G) {
-  return make_range(bf_begin(G), bf_end(G));
+template <class T>
+iterator_range_with_sentinel<bf_iterator<T>> breadth_first(const T &G) {
+  return make_range_with_sentinel(bf_begin(G));
 }
 
 } // end namespace llvm
Index: clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp
+++ 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<CallGraph *> 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);
   }
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to