diff options
| author | Duncan Sands <baldrick@free.fr> | 2007-12-19 21:13:37 +0000 |
|---|---|---|
| committer | Duncan Sands <baldrick@free.fr> | 2007-12-19 21:13:37 +0000 |
| commit | aa31b92508bf121b5a58be4cd794f16225f07f2d (patch) | |
| tree | ebdbd951790a83af69a87d51cc4e71b049da6458 /llvm/lib/Transforms/Utils | |
| parent | a246e09aa019e2048063dfd28765cf46417fc7f1 (diff) | |
| download | bcm5719-llvm-aa31b92508bf121b5a58be4cd794f16225f07f2d.tar.gz bcm5719-llvm-aa31b92508bf121b5a58be4cd794f16225f07f2d.zip | |
When inlining through an 'nounwind' call, mark inlined
calls 'nounwind'. It is important for correct C++
exception handling that nounwind markings do not get
lost, so this transformation is actually needed for
correctness.
llvm-svn: 45218
Diffstat (limited to 'llvm/lib/Transforms/Utils')
| -rw-r--r-- | llvm/lib/Transforms/Utils/InlineFunction.cpp | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp index a2b834b5869..dba0e69a355 100644 --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -194,6 +194,10 @@ bool llvm::InlineFunction(CallSite CS, CallGraph *CG, const TargetData *TD) { bool MustClearTailCallFlags = isa<CallInst>(TheCall) && !cast<CallInst>(TheCall)->isTailCall(); + // If the call to the callee cannot throw, set the 'nounwind' flag on any + // calls that we inline. + bool MarkNoUnwind = CS.doesNotThrow(); + BasicBlock *OrigBB = TheCall->getParent(); Function *Caller = OrigBB->getParent(); @@ -207,7 +211,7 @@ bool llvm::InlineFunction(CallSite CS, CallGraph *CG, const TargetData *TD) { std::vector<ReturnInst*> Returns; ClonedCodeInfo InlinedFunctionInfo; Function::iterator FirstNewBlock; - + { // Scope to destroy ValueMap after cloning. DenseMap<const Value*, Value*> ValueMap; @@ -323,15 +327,33 @@ bool llvm::InlineFunction(CallSite CS, CallGraph *CG, const TargetData *TD) { // If we are inlining tail call instruction through a call site that isn't // marked 'tail', we must remove the tail marker for any calls in the inlined - // code. - if (MustClearTailCallFlags && InlinedFunctionInfo.ContainsCalls) { + // code. Also, calls inlined through a 'nounwind' call site should be marked + // 'nounwind'. + if (InlinedFunctionInfo.ContainsCalls && + (MustClearTailCallFlags || MarkNoUnwind)) { for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E; ++BB) for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) - if (CallInst *CI = dyn_cast<CallInst>(I)) - CI->setTailCall(false); + if (CallInst *CI = dyn_cast<CallInst>(I)) { + if (MustClearTailCallFlags) + CI->setTailCall(false); + if (MarkNoUnwind) + CI->setDoesNotThrow(); + } } + // If we are inlining through a 'nounwind' call site then any inlined 'unwind' + // instructions are unreachable. + if (InlinedFunctionInfo.ContainsUnwinds && MarkNoUnwind) + for (Function::iterator BB = FirstNewBlock, E = Caller->end(); + BB != E; ++BB) { + TerminatorInst *Term = BB->getTerminator(); + if (isa<UnwindInst>(Term)) { + new UnreachableInst(Term); + BB->getInstList().erase(Term); + } + } + // If we are inlining for an invoke instruction, we must make sure to rewrite // any inlined 'unwind' instructions into branches to the invoke exception // destination, and call instructions into invoke instructions. |

