summaryrefslogtreecommitdiff
path: root/lib/Transforms/IPO/Inliner.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-08-31 03:15:49 +0000
committerChris Lattner <sabre@nondot.org>2009-08-31 03:15:49 +0000
commitb374b90e81d0ce6b5d02041ba4f7b15a945b38d8 (patch)
treec25a672fec1906289c9f27809afc94e17f372657 /lib/Transforms/IPO/Inliner.cpp
parent2adb8306e2256a4d1bef8f21ebb6dba55a108a88 (diff)
downloadllvm-b374b90e81d0ce6b5d02041ba4f7b15a945b38d8.tar.gz
llvm-b374b90e81d0ce6b5d02041ba4f7b15a945b38d8.tar.bz2
llvm-b374b90e81d0ce6b5d02041ba4f7b15a945b38d8.tar.xz
Fix PR4834, a tricky case where the inliner would resolve an
indirect function pointer, inline it, then go to delete the body. The problem is that the callgraph had other references to the function, though the inliner had no way to know it, so we got a dangling pointer and an invalid iterator out of the deal. The fix to this is pretty simple: stop the inliner from deleting the function by knowing that there are references to it. Do this by making CallGraphNodes contain a refcount. This requires moving deletion of available_externally functions to the module-level cleanup sweep where it belongs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@80533 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/IPO/Inliner.cpp')
-rw-r--r--lib/Transforms/IPO/Inliner.cpp15
1 files changed, 9 insertions, 6 deletions
diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp
index d5967fb11c..9b8e0a1fc4 100644
--- a/lib/Transforms/IPO/Inliner.cpp
+++ b/lib/Transforms/IPO/Inliner.cpp
@@ -293,10 +293,12 @@ bool Inliner::runOnSCC(std::vector<CallGraphNode*> &SCC) {
// If we inlined the last possible call site to the function, delete the
// function body now.
- if (Callee->use_empty() &&
- (Callee->hasLocalLinkage() ||
- Callee->hasAvailableExternallyLinkage()) &&
- !SCCFunctions.count(Callee)) {
+ if (Callee->use_empty() && Callee->hasLocalLinkage() &&
+ !SCCFunctions.count(Callee) &&
+ // The function may be apparently dead, but if there are indirect
+ // callgraph references to the node, we cannot delete it yet, this
+ // could invalidate the CGSCC iterator.
+ CG[Callee]->getNumReferences() == 0) {
DEBUG(errs() << " -> Deleting dead function: "
<< Callee->getName() << "\n");
CallGraphNode *CalleeNode = CG[Callee];
@@ -353,7 +355,7 @@ bool Inliner::removeDeadFunctions(CallGraph &CG,
// from the program. Insert the dead ones in the FunctionsToRemove set.
for (CallGraph::iterator I = CG.begin(), E = CG.end(); I != E; ++I) {
CallGraphNode *CGN = I->second;
- if (CGN == 0 || CGN->getFunction() == 0)
+ if (CGN->getFunction() == 0)
continue;
Function *F = CGN->getFunction();
@@ -364,7 +366,8 @@ bool Inliner::removeDeadFunctions(CallGraph &CG,
if (DNR && DNR->count(F))
continue;
- if (!F->hasLinkOnceLinkage() && !F->hasLocalLinkage())
+ if (!F->hasLinkOnceLinkage() && !F->hasLocalLinkage() &&
+ !F->hasAvailableExternallyLinkage())
continue;
if (!F->use_empty())
continue;