diff --git a/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp b/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp index b621e8d8aa6f..97441008c46c 100644 --- a/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp +++ b/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp @@ -58,13 +58,20 @@ FunctionPass *llvm::createCFGSimplificationPass() { /// 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) { +static void ChangeToUnreachable(Instruction *I, bool UseLLVMTrap) { 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); + // Insert a call to llvm.trap right before this. This turns the undefined + // behavior into a hard fail instead of falling through into random code. + if (UseLLVMTrap) { + Function *TrapFn = + Intrinsic::getDeclaration(BB->getParent()->getParent(), Intrinsic::trap); + CallInst::Create(TrapFn, "", I); + } new UnreachableInst(I->getContext(), I); // All instructions after this are dead. @@ -118,7 +125,8 @@ static bool MarkAliveBlocks(BasicBlock *BB, // though. ++BBI; if (!isa(BBI)) { - ChangeToUnreachable(BBI); + // Don't insert a call to llvm.trap right before the unreachable. + ChangeToUnreachable(BBI, false); Changed = true; } break; @@ -134,7 +142,7 @@ static bool MarkAliveBlocks(BasicBlock *BB, if (isa(Ptr) || (isa(Ptr) && SI->getPointerAddressSpace() == 0)) { - ChangeToUnreachable(SI); + ChangeToUnreachable(SI, true); Changed = true; break; } diff --git a/llvm/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll b/llvm/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll index 0c9cc8be9251..6956faabc336 100644 --- a/llvm/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll +++ b/llvm/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll @@ -1,19 +1,33 @@ -; RUN: opt < %s -simplifycfg -S | grep {volatile load} +; RUN: opt < %s -simplifycfg -S | FileCheck %s ; PR2967 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32" target triple = "i386-pc-linux-gnu" -define void @foo(i32 %x) nounwind { +define void @test1(i32 %x) nounwind { entry: %0 = icmp eq i32 %x, 0 ; [#uses=1] br i1 %0, label %bb, label %return bb: ; preds = %entry - %1 = volatile load i32* null ; [#uses=0] + %1 = volatile load i32* null unreachable + br label %return return: ; preds = %entry ret void +; CHECK: @test1 +; CHECK: volatile load +} + +; rdar://7958343 +define void @test2() nounwind { +entry: + store i32 4,i32* null + ret void + +; CHECK: @test2 +; CHECK: call void @llvm.trap +; CHECK: unreachable }