aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/Utils/InlineFunction.cpp21
-rw-r--r--test/Other/2009-03-31-CallGraph.ll31
2 files changed, 50 insertions, 2 deletions
diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp
index a96c7ceaa8..1b677fbc2b 100644
--- a/lib/Transforms/Utils/InlineFunction.cpp
+++ b/lib/Transforms/Utils/InlineFunction.cpp
@@ -41,7 +41,8 @@ bool llvm::InlineFunction(InvokeInst *II, CallGraph *CG, const TargetData *TD) {
/// block of the inlined code (the last block is the end of the function),
/// and InlineCodeInfo is information about the code that got inlined.
static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
- ClonedCodeInfo &InlinedCodeInfo) {
+ ClonedCodeInfo &InlinedCodeInfo,
+ CallGraph *CG) {
BasicBlock *InvokeDest = II->getUnwindDest();
std::vector<Value*> InvokeDestPHIValues;
@@ -93,6 +94,22 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
// Make sure that anything using the call now uses the invoke!
CI->replaceAllUsesWith(II);
+ // Update the callgraph.
+ if (CG) {
+ // We should be able to do this:
+ // (*CG)[Caller]->replaceCallSite(CI, II);
+ // but that fails if the old call site isn't in the call graph,
+ // which, because of LLVM bug 3601, it sometimes isn't.
+ CallGraphNode *CGN = (*CG)[Caller];
+ for (CallGraphNode::iterator NI = CGN->begin(), NE = CGN->end();
+ NI != NE; ++NI) {
+ if (NI->first == CI) {
+ NI->first = II;
+ break;
+ }
+ }
+ }
+
// Delete the unconditional branch inserted by splitBasicBlock
BB->getInstList().pop_back();
Split->getInstList().pop_front(); // Delete the original call
@@ -433,7 +450,7 @@ bool llvm::InlineFunction(CallSite CS, CallGraph *CG, const TargetData *TD) {
// any inlined 'unwind' instructions into branches to the invoke exception
// destination, and call instructions into invoke instructions.
if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall))
- HandleInlinedInvoke(II, FirstNewBlock, InlinedFunctionInfo);
+ HandleInlinedInvoke(II, FirstNewBlock, InlinedFunctionInfo, CG);
// If we cloned in _exactly one_ basic block, and if that block ends in a
// return instruction, we splice the body of the inlined callee directly into
diff --git a/test/Other/2009-03-31-CallGraph.ll b/test/Other/2009-03-31-CallGraph.ll
new file mode 100644
index 0000000000..43578be2d9
--- /dev/null
+++ b/test/Other/2009-03-31-CallGraph.ll
@@ -0,0 +1,31 @@
+; RUN: llvm-as < %s | opt -inline -prune-eh -disable-output
+define void @f2() {
+ invoke void @f6()
+ to label %ok1 unwind label %lpad1
+
+ok1:
+ ret void
+
+lpad1:
+ invoke void @f4()
+ to label %ok2 unwind label %lpad2
+
+ok2:
+ call void @f8()
+ unreachable
+
+lpad2:
+ unreachable
+}
+
+declare void @f3()
+
+define void @f4() {
+ call void @f3()
+ ret void
+}
+
+declare void @f6() nounwind
+
+declare void @f8()
+