diff --git a/lib/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp index e75a5dbddba..66885ed57e2 100644 --- a/lib/Transforms/Scalar/SCCP.cpp +++ b/lib/Transforms/Scalar/SCCP.cpp @@ -2083,12 +2083,22 @@ bool llvm::runIPSCCP( // If we have forced an edge for an indeterminate value, then force the // terminator to fold to that edge. forceIndeterminateEdge(I, Solver); - bool Folded = ConstantFoldTerminator(I->getParent(), + BasicBlock *InstBB = I->getParent(); + bool Folded = ConstantFoldTerminator(InstBB, /*DeleteDeadConditions=*/false, /*TLI=*/nullptr, &DTU); assert(Folded && "Expect TermInst on constantint or blockaddress to be folded"); (void) Folded; + // If we folded the terminator to an unconditional branch to another + // dead block, replace it with Unreachable, to avoid trying to fold that + // branch again. + BranchInst *BI = cast(InstBB->getTerminator()); + if (BI && BI->isUnconditional() && + !Solver.isBlockExecutable(BI->getSuccessor(0))) { + InstBB->getTerminator()->eraseFromParent(); + new UnreachableInst(InstBB->getContext(), InstBB); + } } // Mark dead BB for deletion. DTU.deleteBB(DeadBB); diff --git a/test/Transforms/SCCP/switch-constantfold-crash.ll b/test/Transforms/SCCP/switch-constantfold-crash.ll new file mode 100644 index 00000000000..7596a56b812 --- /dev/null +++ b/test/Transforms/SCCP/switch-constantfold-crash.ll @@ -0,0 +1,92 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -ipsccp < %s -S | FileCheck %s +; RUN: opt -passes=ipsccp < %s -S | FileCheck %s + +define void @barney() { +; CHECK-LABEL: @barney( +; CHECK-NEXT: bb: +; CHECK-NEXT: br label %bb9 +; CHECK: bb6: +; CHECK-NEXT: unreachable +; CHECK: bb9: +; CHECK-NEXT: unreachable +; +bb: + br label %bb9 + +bb6: ; preds = %bb9 + unreachable + +bb7: ; preds = %bb9 + unreachable + +bb9: ; preds = %bb + switch i16 0, label %bb6 [ + i16 61, label %bb7 + ] +} + +define void @blam() { +; CHECK-LABEL: @blam( +; CHECK-NEXT: bb: +; CHECK-NEXT: br label %bb16 +; CHECK: bb16: +; CHECK-NEXT: br label %bb38 +; CHECK: bb38: +; CHECK-NEXT: unreachable +; +bb: + br label %bb16 + +bb16: ; preds = %bb + switch i32 0, label %bb38 [ + i32 66, label %bb17 + i32 63, label %bb18 + i32 86, label %bb19 + ] + +bb17: ; preds = %bb16 + unreachable + +bb18: ; preds = %bb16 + unreachable + +bb19: ; preds = %bb16 + unreachable + +bb38: ; preds = %bb16 + unreachable +} + + +define void @hoge() { +; CHECK-LABEL: @hoge( +; CHECK-NEXT: bb: +; CHECK-NEXT: br label %bb2 +; CHECK: bb2: +; CHECK-NEXT: unreachable +; CHECK: bb3: +; CHECK-NEXT: unreachable +; +bb: + switch i16 undef, label %bb1 [ + i16 135, label %bb2 + i16 66, label %bb2 + ] + +bb1: ; preds = %bb + ret void + +bb2: ; preds = %bb, %bb + switch i16 0, label %bb3 [ + i16 61, label %bb4 + i16 54, label %bb4 + i16 49, label %bb4 + ] + +bb3: ; preds = %bb2 + unreachable + +bb4: ; preds = %bb2, %bb2, %bb2 + unreachable +}