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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits