REALLY fix PR324: don't delete linkonce functions until after the SCC traversal

is done, which avoids invalidating iterators in the SCC traversal routines


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@13088 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2004-04-20 22:06:53 +00:00
parent 72035995d5
commit 68d57e7ae8
2 changed files with 33 additions and 7 deletions

View File

@ -117,7 +117,7 @@ bool Inliner::runOnSCC(const 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 != Caller &&
(Callee->hasInternalLinkage() || Callee->hasLinkOnceLinkage())) {
Callee->hasInternalLinkage()) {
DEBUG(std::cerr << " -> Deleting dead function: "
<< Callee->getName() << "\n");
SCCFunctions.erase(Callee); // Remove function from this SCC.
@ -126,12 +126,6 @@ bool Inliner::runOnSCC(const std::vector<CallGraphNode*> &SCC) {
while (CalleeNode->begin() != CalleeNode->end())
CalleeNode->removeCallEdgeTo(*(CalleeNode->end()-1));
// If the function has external linkage (basically if it's a
// linkonce function) remove the edge from the external node to the
// callee node.
if (!Callee->hasInternalLinkage())
CG.getExternalCallingNode()->removeCallEdgeTo(CalleeNode);
// Removing the node for callee from the call graph and delete it.
delete CG.removeFunctionFromModule(CalleeNode);
++NumDeleted;
@ -145,3 +139,30 @@ bool Inliner::runOnSCC(const std::vector<CallGraphNode*> &SCC) {
return Changed;
}
// doFinalization - Remove now-dead linkonce functions at the end of
// processing to avoid breaking the SCC traversal.
bool Inliner::doFinalization(CallGraph &CG) {
bool Changed = false;
for (CallGraph::iterator I = CG.begin(), E = CG.end(); I != E; ) {
CallGraphNode *CGN = (++I)->second;
Function *F = CGN ? CGN->getFunction() : 0;
if (F && (F->hasLinkOnceLinkage() || F->hasInternalLinkage()) &&
F->use_empty()) {
// Remove any call graph edges from the callee to its callees.
while (CGN->begin() != CGN->end())
CGN->removeCallEdgeTo(*(CGN->end()-1));
// If the function has external linkage (basically if it's a
// linkonce function) remove the edge from the external node to the
// callee node.
if (!F->hasInternalLinkage())
CG.getExternalCallingNode()->removeCallEdgeTo(CGN);
// Removing the node for callee from the call graph and delete it.
delete CG.removeFunctionFromModule(CGN);
++NumDeleted;
Changed = true;
}
}
return Changed;
}

View File

@ -35,6 +35,11 @@ struct Inliner : public CallGraphSCCPass {
// Pass class.
virtual bool runOnSCC(const std::vector<CallGraphNode *> &SCC);
// doFinalization - Remove now-dead linkonce functions at the end of
// processing to avoid breaking the SCC traversal.
virtual bool doFinalization(CallGraph &CG);
/// This method returns the value specified by the -inline-threshold value,
/// specified on the command line. This is typically not directly needed.
///