From 7fa69ef109b5cf5d719ac9384ede721d5e6d53f6 Mon Sep 17 00:00:00 2001 From: Devang Patel Date: Tue, 31 Mar 2009 17:36:12 +0000 Subject: [PATCH] Update call graph after inlining invoke. Patch by Jay Foad. llvm-svn: 68120 --- lib/Transforms/Utils/InlineFunction.cpp | 21 +++++++++++++++-- test/Other/2009-03-31-CallGraph.ll | 31 +++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 test/Other/2009-03-31-CallGraph.ll diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp index a96c7ceaa8e..1b677fbc2bc 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 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(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 00000000000..43578be2d92 --- /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() +