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 @@ -132,12 +132,21 @@ /// 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. + /// If \c New is null, the node has been deleted without replacement. void ReplaceNode(NodeRef Old, NodeRef New) { auto it = nodeVisitNumbers.find(Old); assert(it != nodeVisitNumbers.end() && "Old not in scc_iterator?"); unsigned OldVisitNumber = it->second; + // Since we're not updating any of our internal book keeping data structures, + // we need to make sure that the node we're replacing belongs to an SCC + // that's already been visited. + assert(OldVisitNumber == ~0U && "Old not in an scc that was already visited"); nodeVisitNumbers.erase(it); - nodeVisitNumbers[New] = OldVisitNumber; + if (New) { + bool Added = nodeVisitNumbers.try_emplace(New, OldVisitNumber).second; + (void)Added; + assert(Added && "New already in scc_iterator?"); + } } }; diff --git a/llvm/include/llvm/Analysis/CallGraphSCCPass.h b/llvm/include/llvm/Analysis/CallGraphSCCPass.h --- a/llvm/include/llvm/Analysis/CallGraphSCCPass.h +++ b/llvm/include/llvm/Analysis/CallGraphSCCPass.h @@ -21,6 +21,7 @@ #define LLVM_ANALYSIS_CALLGRAPHSCCPASS_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SCCIterator.h" #include "llvm/Pass.h" #include @@ -86,11 +87,11 @@ /// CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on. class CallGraphSCC { const CallGraph &CG; // The call graph for this SCC. - void *Context; // The CGPassManager object that is vending this. + scc_iterator &Context; // The CGPassManager object that is vending this. std::vector Nodes; public: - CallGraphSCC(CallGraph &cg, void *context) : CG(cg), Context(context) {} + CallGraphSCC(CallGraph &cg, scc_iterator &context) : CG(cg), Context(context) {} void initialize(ArrayRef NewNodes) { Nodes.assign(NewNodes.begin(), NewNodes.end()); @@ -101,6 +102,7 @@ /// ReplaceNode - This informs the SCC and the pass manager that the specified /// Old node has been deleted, and New is to be used in its place. + /// If New is null, the node has been deleted without replacement. void ReplaceNode(CallGraphNode *Old, CallGraphNode *New); using iterator = std::vector::const_iterator; @@ -109,6 +111,7 @@ iterator end() const { return Nodes.end(); } const CallGraph &getCallGraph() { return CG; } + scc_iterator &getContext() { return Context; } }; void initializeDummyCGSCCPassPass(PassRegistry &); diff --git a/llvm/lib/Analysis/CallGraphSCCPass.cpp b/llvm/lib/Analysis/CallGraphSCCPass.cpp --- a/llvm/lib/Analysis/CallGraphSCCPass.cpp +++ b/llvm/lib/Analysis/CallGraphSCCPass.cpp @@ -467,7 +467,7 @@ // Walk the callgraph in bottom-up SCC order. scc_iterator CGI = scc_begin(&CG); - CallGraphSCC CurSCC(CG, &CGI); + CallGraphSCC CurSCC(CG, CGI); while (!CGI.isAtEnd()) { // Copy the current SCC and increment past it so that the pass can hack // on the SCC if it wants to without invalidating our iterator. @@ -546,17 +546,21 @@ /// Old node has been deleted, and New is to be used in its place. void CallGraphSCC::ReplaceNode(CallGraphNode *Old, CallGraphNode *New) { assert(Old != New && "Should not replace node with self"); - for (unsigned i = 0; ; ++i) { - assert(i != Nodes.size() && "Node not in SCC"); - if (Nodes[i] != Old) continue; - Nodes[i] = New; + for (auto it = Nodes.begin(); ; ++it) { + assert(it != Nodes.end() && "Node not in SCC"); + if (*it != Old) + continue; + if (New) { + *it = New; + } else { + Nodes.erase(it); + } break; } // Update the active scc_iterator so that it doesn't contain dangling // pointers to the old CallGraphNode. - scc_iterator *CGI = (scc_iterator*)Context; - CGI->ReplaceNode(Old, New); + Context.ReplaceNode(Old, New); } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Transforms/IPO/Inliner.cpp b/llvm/lib/Transforms/IPO/Inliner.cpp --- a/llvm/lib/Transforms/IPO/Inliner.cpp +++ b/llvm/lib/Transforms/IPO/Inliner.cpp @@ -732,6 +732,10 @@ // Removing the node for callee from the call graph and delete it. delete CG.removeFunctionFromModule(CalleeNode); + if (SCCFunctions.count(Callee)) + SCC.ReplaceNode(CalleeNode, nullptr); + else + SCC.getContext().ReplaceNode(CalleeNode, nullptr); ++NumDeleted; }