From 73d4bb6676ab5730f8b3a7c20cf5fb8f856bdabb Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Thu, 22 Nov 2007 22:24:59 +0000 Subject: [PATCH] Turn invokes of nounwind functions into ordinary calls. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@44280 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/SimplifyCFG.cpp | 50 ++++++++++++++++++- .../SimplifyCFG/2007-11-22-InvokeNoUnwind.ll | 14 ++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 test/Transforms/SimplifyCFG/2007-11-22-InvokeNoUnwind.ll diff --git a/lib/Transforms/Scalar/SimplifyCFG.cpp b/lib/Transforms/Scalar/SimplifyCFG.cpp index 74005757206..692a8af0a2a 100644 --- a/lib/Transforms/Scalar/SimplifyCFG.cpp +++ b/lib/Transforms/Scalar/SimplifyCFG.cpp @@ -71,6 +71,28 @@ static void ChangeToUnreachable(Instruction *I) { } } +/// ChangeToCall - Convert the specified invoke into a normal call. +static void ChangeToCall(InvokeInst *II) { + BasicBlock *BB = II->getParent(); + SmallVector Args(II->op_begin()+3, II->op_end()); + CallInst *NewCall = new CallInst(II->getCalledValue(), Args.begin(), + Args.end(), "", II); + NewCall->takeName(II); + NewCall->setCallingConv(II->getCallingConv()); + NewCall->setParamAttrs(II->getParamAttrs()); + II->replaceAllUsesWith(NewCall); + + // Follow the call by a branch to the normal destination. + new BranchInst(II->getNormalDest(), II); + + // Update PHI nodes in the unwind destination + II->getUnwindDest()->removePredecessor(BB); + BB->getInstList().erase(II); + + if (NewCall->use_empty()) + BB->getInstList().erase(NewCall); +} + /// IsNoReturn - Return true if the specified call is to a no-return function. static bool IsNoReturn(const CallInst *CI) { if (const ParamAttrsList *Attrs = CI->getParamAttrs()) @@ -90,6 +112,25 @@ static bool IsNoReturn(const CallInst *CI) { return false; } +/// IsNoUnwind - Return true if the specified invoke is to a no-unwind function. +static bool IsNoUnwind(const InvokeInst *II) { + if (const ParamAttrsList *Attrs = II->getParamAttrs()) + if (Attrs->paramHasAttr(0, ParamAttr::NoUnwind)) + return true; + + if (const Function *Callee = II->getCalledFunction()) { + if (const ParamAttrsList *Attrs = Callee->getParamAttrs()) + if (Attrs->paramHasAttr(0, ParamAttr::NoUnwind)) + return true; + + const FunctionType *FT = Callee->getFunctionType(); + if (const ParamAttrsList *Attrs = FT->getParamAttrs()) + if (Attrs->paramHasAttr(0, ParamAttr::NoUnwind)) + return true; + } + return false; +} + static bool MarkAliveBlocks(BasicBlock *BB, SmallPtrSet &Reachable) { @@ -106,7 +147,7 @@ static bool MarkAliveBlocks(BasicBlock *BB, // Do a quick scan of the basic block, turning any obviously unreachable // instructions into LLVM unreachable insts. The instruction combining pass - // canonnicalizes unreachable insts into stores to null or undef. + // canonicalizes unreachable insts into stores to null or undef. for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E;++BBI){ if (CallInst *CI = dyn_cast(BBI)) { if (IsNoReturn(CI)) { @@ -131,6 +172,13 @@ static bool MarkAliveBlocks(BasicBlock *BB, } } + // Turn invokes that call 'nounwind' functions into ordinary calls. + if (InvokeInst *II = dyn_cast(BB->getTerminator())) + if (IsNoUnwind(II)) { + ChangeToCall(II); + Changed = true; + } + Changed |= ConstantFoldTerminator(BB); for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) Worklist.push_back(*SI); diff --git a/test/Transforms/SimplifyCFG/2007-11-22-InvokeNoUnwind.ll b/test/Transforms/SimplifyCFG/2007-11-22-InvokeNoUnwind.ll new file mode 100644 index 00000000000..8e8ef43932b --- /dev/null +++ b/test/Transforms/SimplifyCFG/2007-11-22-InvokeNoUnwind.ll @@ -0,0 +1,14 @@ +; RUN: llvm-as < %s | opt -simplifycfg | llvm-dis | not grep invoke + +declare i32 @func(i8*) nounwind + +define i32 @test() { + invoke i32 @func( i8* null ) nounwind + to label %Cont unwind label %Other ; :1 [#uses=0] + +Cont: ; preds = %0 + ret i32 0 + +Other: ; preds = %0 + ret i32 1 +}