From 16e21309bfe72e4846936472f30923c44baccae4 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Wed, 24 Feb 2016 10:02:16 +0000 Subject: [PATCH] [SimplifyCFG] Do not blindly remove unreachable blocks DeleteDeadBlock was called indiscriminately, leading to cleanuprets with undef cleanuppad references. Instead, try to drain the BB of most of it's instructions if it is unreachable. We can then remove the BB if it solely consists of a terminator (and maybe some phis). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@261731 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Utils/SimplifyCFG.cpp | 14 +++++-- .../SimplifyCFG/unreachable-cleanuppad.ll | 40 +++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 test/Transforms/SimplifyCFG/unreachable-cleanuppad.ll diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index dc56ebb08d1..7a3d368f34c 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -5278,9 +5278,17 @@ bool SimplifyCFGOpt::run(BasicBlock *BB) { if ((pred_empty(BB) && BB != &BB->getParent()->getEntryBlock()) || BB->getSinglePredecessor() == BB) { - DEBUG(dbgs() << "Removing BB: \n" << *BB); - DeleteDeadBlock(BB); - return true; + // Get the block mostly empty. + Changed |= removeAllNonTerminatorAndEHPadInstructions(BB) > 0; + // Now, verify that we succeeded getting the block empty. + // This will not be the case if this unreachable BB creates a token which is + // consumed by other unreachable blocks. + Instruction *FirstNonPHI = BB->getFirstNonPHI(); + if (isa(FirstNonPHI) && FirstNonPHI->use_empty()) { + DEBUG(dbgs() << "Removing BB: \n" << *BB); + DeleteDeadBlock(BB); + return true; + } } // Check to see if we can constant propagate this terminator instruction diff --git a/test/Transforms/SimplifyCFG/unreachable-cleanuppad.ll b/test/Transforms/SimplifyCFG/unreachable-cleanuppad.ll new file mode 100644 index 00000000000..9198b2a6ea4 --- /dev/null +++ b/test/Transforms/SimplifyCFG/unreachable-cleanuppad.ll @@ -0,0 +1,40 @@ +; RUN: opt -simplifycfg -S < %s | FileCheck %s +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" +target triple = "i686-pc-win32" + +declare i32 @__CxxFrameHandler3(...) + +declare void @fn_2() + +define void @fn_1(i1 %B) personality i32 (...)* @__CxxFrameHandler3 { +entry: + br i1 %B, label %__Ea.exit, label %lor.lhs.false.i.i + +lor.lhs.false.i.i: + br i1 %B, label %if.end.i.i, label %__Ea.exit + +if.end.i.i: + invoke void @fn_2() + to label %__Ea.exit unwind label %ehcleanup.i + +ehcleanup.i: + %t4 = cleanuppad within none [] + br label %arraydestroy.body.i + +arraydestroy.body.i: + %gep = getelementptr i8, i8* null, i32 -1 + br label %dtor.exit.i + +dtor.exit.i: + br i1 %B, label %arraydestroy.done3.i, label %arraydestroy.body.i + +arraydestroy.done3.i: + cleanupret from %t4 unwind to caller + +__Ea.exit: + ret void +} + +; CHECK-LABEL: define void @fn_1( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret void