diff options
author | Chris Lattner <sabre@nondot.org> | 2009-08-31 00:19:58 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-08-31 00:19:58 +0000 |
commit | 5095e3d1d1caef8d573534d369e37277c623064c (patch) | |
tree | f6801c8985931a1d161538b2daa7961923a4f15d /lib/Analysis/IPA/CallGraphSCCPass.cpp | |
parent | 52248ff682e13315e5be08824bdd1d340e02d610 (diff) |
Fix some nasty callgraph dangling pointer problems in
argpromotion and structretpromote. Basically, when replacing
a function, they used the 'changeFunction' api which changes
the entry in the function map (and steals/reuses the callgraph
node).
This has some interesting effects: first, the problem is that it doesn't
update the "callee" edges in any callees of the function in the call graph.
Second, this covers for a major problem in all the CGSCC pass stuff, which
is that it is completely broken when functions are deleted if they *don't*
reuse a CGN. (there is a cute little fixme about this though :).
This patch changes the protocol that CGSCC passes must obey: now the CGSCC
pass manager copies the SCC and preincrements its iterator to avoid passes
invalidating it. This allows CGSCC passes to mutate the current SCC. However
multiple passes may be run on that SCC, so if passes do this, they are now
required to *update* the SCC to be current when they return.
Other less interesting parts of this patch are that it makes passes update
the CG more directly, eliminates changeFunction, and requires clients of
replaceCallSite to specify the new callee CGN if they are changing it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@80527 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/IPA/CallGraphSCCPass.cpp')
-rw-r--r-- | lib/Analysis/IPA/CallGraphSCCPass.cpp | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/lib/Analysis/IPA/CallGraphSCCPass.cpp b/lib/Analysis/IPA/CallGraphSCCPass.cpp index 00eddc4de8..4a9bf9fa00 100644 --- a/lib/Analysis/IPA/CallGraphSCCPass.cpp +++ b/lib/Analysis/IPA/CallGraphSCCPass.cpp @@ -84,10 +84,16 @@ bool CGPassManager::runOnModule(Module &M) { CallGraph &CG = getAnalysis<CallGraph>(); bool Changed = doInitialization(CG); + std::vector<CallGraphNode*> CurSCC; + // Walk SCC - for (scc_iterator<CallGraph*> I = scc_begin(&CG), E = scc_end(&CG); - I != E; ++I) { - + for (scc_iterator<CallGraph*> CGI = scc_begin(&CG), E = scc_end(&CG); + CGI != E;) { + // 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. + CurSCC = *CGI; + ++CGI; + // Run all passes on current SCC for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { Pass *P = getContainedPass(Index); @@ -99,16 +105,14 @@ bool CGPassManager::runOnModule(Module &M) { StartPassTimer(P); if (CallGraphSCCPass *CGSP = dynamic_cast<CallGraphSCCPass *>(P)) - Changed |= CGSP->runOnSCC(*I); // TODO : What if CG is changed ? + Changed |= CGSP->runOnSCC(CurSCC); else { FPPassManager *FPP = dynamic_cast<FPPassManager *>(P); assert (FPP && "Invalid CGPassManager member"); // Run pass P on all functions current SCC - std::vector<CallGraphNode*> &SCC = *I; - for (unsigned i = 0, e = SCC.size(); i != e; ++i) { - Function *F = SCC[i]->getFunction(); - if (F) { + for (unsigned i = 0, e = CurSCC.size(); i != e; ++i) { + if (Function *F = CurSCC[i]->getFunction()) { dumpPassInfo(P, EXECUTION_MSG, ON_FUNCTION_MSG, F->getName()); Changed |= FPP->runOnFunction(*F); } |