From 1b12d8855d8e84c37aeba8c99883e5ada6b5fdca Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 14 Nov 2007 06:19:25 +0000 Subject: [PATCH] Implement PR1796 and Transforms/SimplifyCFG/noreturn-call.ll by inserting unreachable after no-return calls. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@44099 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/SimplifyCFG.cpp | 74 ++++++++++++++++---- test/Transforms/SimplifyCFG/noreturn-call.ll | 11 +++ 2 files changed, 70 insertions(+), 15 deletions(-) create mode 100644 test/Transforms/SimplifyCFG/noreturn-call.ll diff --git a/lib/Transforms/Scalar/SimplifyCFG.cpp b/lib/Transforms/Scalar/SimplifyCFG.cpp index 200264e9174..74005757206 100644 --- a/lib/Transforms/Scalar/SimplifyCFG.cpp +++ b/lib/Transforms/Scalar/SimplifyCFG.cpp @@ -24,6 +24,7 @@ #include "llvm/Constants.h" #include "llvm/Instructions.h" #include "llvm/Module.h" +#include "llvm/ParameterAttributes.h" #include "llvm/Support/CFG.h" #include "llvm/Support/Compiler.h" #include "llvm/Pass.h" @@ -50,6 +51,46 @@ FunctionPass *llvm::createCFGSimplificationPass() { return new CFGSimplifyPass(); } +/// ChangeToUnreachable - Insert an unreachable instruction before the specified +/// instruction, making it and the rest of the code in the block dead. +static void ChangeToUnreachable(Instruction *I) { + BasicBlock *BB = I->getParent(); + // Loop over all of the successors, removing BB's entry from any PHI + // nodes. + for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) + (*SI)->removePredecessor(BB); + + new UnreachableInst(I); + + // All instructions after this are dead. + BasicBlock::iterator BBI = I, BBE = BB->end(); + while (BBI != BBE) { + if (!BBI->use_empty()) + BBI->replaceAllUsesWith(UndefValue::get(BBI->getType())); + BB->getInstList().erase(BBI++); + } +} + +/// 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()) + if (Attrs->paramHasAttr(0, ParamAttr::NoReturn)) + return true; + + if (const Function *Callee = CI->getCalledFunction()) { + if (const ParamAttrsList *Attrs = Callee->getParamAttrs()) + if (Attrs->paramHasAttr(0, ParamAttr::NoReturn)) + return true; + + const FunctionType *FT = Callee->getFunctionType(); + if (const ParamAttrsList *Attrs = FT->getParamAttrs()) + if (Attrs->paramHasAttr(0, ParamAttr::NoReturn)) + return true; + } + return false; +} + + static bool MarkAliveBlocks(BasicBlock *BB, SmallPtrSet &Reachable) { @@ -66,26 +107,29 @@ 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. - for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E; ++BBI) + for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E;++BBI){ + if (CallInst *CI = dyn_cast(BBI)) { + if (IsNoReturn(CI)) { + // If we found a call to a no-return function, insert an unreachable + // instruction after it. Make sure there isn't *already* one there + // though. + ++BBI; + if (!isa(BBI)) { + ChangeToUnreachable(BBI); + Changed = true; + } + break; + } + } + if (StoreInst *SI = dyn_cast(BBI)) if (isa(SI->getOperand(1)) || isa(SI->getOperand(1))) { - // Loop over all of the successors, removing BB's entry from any PHI - // nodes. - for (succ_iterator I = succ_begin(BB), SE = succ_end(BB); I != SE;++I) - (*I)->removePredecessor(BB); - - new UnreachableInst(SI); - - // All instructions after this are dead. - while (BBI != E) { - if (!BBI->use_empty()) - BBI->replaceAllUsesWith(UndefValue::get(BBI->getType())); - BB->getInstList().erase(BBI++); - } + ChangeToUnreachable(SI); + Changed = true; break; } - + } Changed |= ConstantFoldTerminator(BB); for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) diff --git a/test/Transforms/SimplifyCFG/noreturn-call.ll b/test/Transforms/SimplifyCFG/noreturn-call.ll new file mode 100644 index 00000000000..0e1c6327e8b --- /dev/null +++ b/test/Transforms/SimplifyCFG/noreturn-call.ll @@ -0,0 +1,11 @@ +; RUN: llvm-as < %s | opt -simplifycfg | llvm-dis | grep unreachable +; PR1796 + +declare void @Finisher(i32) noreturn + +define void @YYY(i32) { + tail call void @Finisher(i32 %0) noreturn + tail call void @Finisher(i32 %0) noreturn + ret void +} + -- 2.34.1