Index: llvm/include/llvm/ADT/SCCIterator.h =================================================================== --- llvm/include/llvm/ADT/SCCIterator.h +++ llvm/include/llvm/ADT/SCCIterator.h @@ -99,8 +99,8 @@ scc_iterator() = default; public: - static scc_iterator begin(const GraphT &G) { - return scc_iterator(GT::getEntryNode(G)); + static scc_iterator begin(NodeRef N) { + return scc_iterator(N); } static scc_iterator end(const GraphT &) { return scc_iterator(); } @@ -222,16 +222,25 @@ return false; } -/// Construct the begin iterator for a deduced graph type T. +/// Construct the begin iterator for a deduced graph type T, starting from its +/// entry node. template scc_iterator scc_begin(const T &G) { - return scc_iterator::begin(G); + return scc_iterator::begin(GraphTraits::getEntryNode(G)); } -/// Construct the end iterator for a deduced graph type T. +/// Construct the begin iterator for a graph type T, starting from the specified +/// node. +template > +scc_iterator scc_begin(typename U::NodeRef N) { + return scc_iterator::begin(N); +} + + /// Construct the end iterator for a deduced graph type T. template scc_iterator scc_end(const T &G) { return scc_iterator::end(G); } + } // end namespace llvm #endif // LLVM_ADT_SCCITERATOR_H Index: llvm/lib/Analysis/CallGraphSCCPass.cpp =================================================================== --- llvm/lib/Analysis/CallGraphSCCPass.cpp +++ llvm/lib/Analysis/CallGraphSCCPass.cpp @@ -33,6 +33,7 @@ #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" #include +#include #include #include #include @@ -63,6 +64,9 @@ /// whether any of the passes modifies the module, and if so, return true. bool runOnModule(Module &M) override; + bool runOnNode(CallGraphNode *N, CallGraph &CG, + std::set &Visited); + using ModulePass::doInitialization; using ModulePass::doFinalization; @@ -448,15 +452,34 @@ bool CGPassManager::runOnModule(Module &M) { CallGraph &CG = getAnalysis().getCallGraph(); bool Changed = doInitialization(CG); - + + std::set Visited; + for (auto I = CG.begin(), E = CG.end(); I != E; ++I) { + if (Visited.find(I->first) == Visited.end()) + Changed |= runOnNode(I->second.get(), CG, Visited); + } + + Changed |= doFinalization(CG); + return Changed; +} + +bool CGPassManager::runOnNode(CallGraphNode *N, CallGraph &CG, + std::set &Visited) { + bool Changed = false; // Walk the callgraph in bottom-up SCC order. - scc_iterator CGI = scc_begin(&CG); + scc_iterator CGI = scc_begin(N); 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. const std::vector &NodeVec = *CGI; + + // Record that we've seen this set of functions so we don't run the pass + // twice. + for (auto Elt : NodeVec) + Visited.insert(Elt->getFunction()); + CurSCC.initialize(NodeVec); ++CGI; @@ -489,7 +512,6 @@ MaxSCCIterations.updateMax(Iteration); } - Changed |= doFinalization(CG); return Changed; } Index: llvm/test/Transforms/Inline/always-inline.ll =================================================================== --- llvm/test/Transforms/Inline/always-inline.ll +++ llvm/test/Transforms/Inline/always-inline.ll @@ -316,3 +316,10 @@ call void @inner14() ret void } + +define internal i32 @outer15() { +; CHECK-LABEL: @outer15 +; CHECK: ret i32 1 + %res = call i32 @inner1() + ret i32 %res +}