From 368df2bb6f42ef85b08c923a127a516350322609 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 31 Aug 2009 05:46:59 +0000 Subject: [PATCH] fix a crash building SPASS by tolerating a callsite that doesn't exist in the callgraph, see the big comment at the top of the testcase. llvm-svn: 80541 --- lib/Analysis/IPA/CallGraph.cpp | 21 +++++++----- test/Transforms/Inline/crash.ll | 57 +++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 test/Transforms/Inline/crash.ll diff --git a/lib/Analysis/IPA/CallGraph.cpp b/lib/Analysis/IPA/CallGraph.cpp index 9711013bea3..6490642f772 100644 --- a/lib/Analysis/IPA/CallGraph.cpp +++ b/lib/Analysis/IPA/CallGraph.cpp @@ -239,14 +239,19 @@ void CallGraphNode::dump() const { print(errs()); } /// specified call site. Note that this method takes linear time, so it /// should be used sparingly. void CallGraphNode::removeCallEdgeFor(CallSite CS) { - for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) { - assert(I != CalledFunctions.end() && "Cannot find callsite to remove!"); - if (I->first == CS) { - I->second->DropRef(); - *I = CalledFunctions.back(); - CalledFunctions.pop_back(); - return; - } + // Scan for the call site. Note that we aren't guaranteed to find the call + // site in this node, even in reasonable situations. Passes like instcombine + // can adjust callsites (e.g. folding bitcasts into calls to make them direct) + // which can introduce new call sites. Since instcombine is not callgraph + // aware, it doesn't know to tell CallGraph about this change. + for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); + I != CalledFunctions.end(); ++I) { + if (I->first != CS) continue; + + I->second->DropRef(); + *I = CalledFunctions.back(); + CalledFunctions.pop_back(); + return; } } diff --git a/test/Transforms/Inline/crash.ll b/test/Transforms/Inline/crash.ll new file mode 100644 index 00000000000..ebf8147c57f --- /dev/null +++ b/test/Transforms/Inline/crash.ll @@ -0,0 +1,57 @@ +; RUN: llvm-as < %s | opt -inline -argpromotion -instcombine -disable-output + +; This test was failing because the inliner would inline @list_DeleteElement +; into @list_DeleteDuplicates and then into @inf_GetBackwardPartnerLits, +; turning the indirect call into a direct one. This allowed instcombine to see +; the bitcast and eliminate it, deleting the original call and introducing +; another one. This crashed the inliner because the new call was not in the +; callgraph. + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" +target triple = "i386-apple-darwin10.0" + + +define void @list_DeleteElement(i32 (i8*, i8*)* nocapture %Test) nounwind ssp { +entry: + %0 = call i32 %Test(i8* null, i8* undef) nounwind + ret void +} + + +define void @list_DeleteDuplicates(i32 (i8*, i8*)* nocapture %Test) nounwind ssp { +foo: + call void @list_DeleteElement(i32 (i8*, i8*)* %Test) nounwind ssp + call fastcc void @list_Rplacd1284() nounwind ssp + unreachable + +} + +define internal i32 @inf_LiteralsHaveSameSubtermAndAreFromSameClause(i32* nocapture %L1, i32* nocapture %L2) nounwind readonly ssp { +entry: + unreachable +} + + +define internal fastcc void @inf_GetBackwardPartnerLits(i32* nocapture %Flags) nounwind ssp { +test: + call void @list_DeleteDuplicates(i32 (i8*, i8*)* bitcast (i32 (i32*, i32*)* @inf_LiteralsHaveSameSubtermAndAreFromSameClause to i32 (i8*, i8*)*)) nounwind + ret void +} + + +define void @inf_BackwardEmptySortPlusPlus() nounwind ssp { +entry: + call fastcc void @inf_GetBackwardPartnerLits(i32* null) nounwind ssp + unreachable +} + +define void @inf_BackwardWeakening() nounwind ssp { +entry: + call fastcc void @inf_GetBackwardPartnerLits(i32* null) nounwind ssp + unreachable +} + + + + +declare fastcc void @list_Rplacd1284() nounwind ssp