diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp --- a/llvm/lib/Transforms/Scalar/SCCP.cpp +++ b/llvm/lib/Transforms/Scalar/SCCP.cpp @@ -386,6 +386,24 @@ } else if (FeasibleSuccessors.size() > 1) { SwitchInstProfUpdateWrapper SI(*cast(TI)); SmallVector Updates; + + // If the default destination is unfeasible it will never be taken. Replace + // it with a feasible successor to remove the edge to the original default + // destination. + BasicBlock *DefaultDest = SI->getDefaultDest(); + if (!FeasibleSuccessors.contains(DefaultDest)) { + BasicBlock *FirstFeasible = nullptr; + for (BasicBlock *Succ : successors(BB)) { + if (Solver.isEdgeFeasible(BB, Succ)) { + FirstFeasible = Succ; + break; + } + } + assert(FirstFeasible && "at least one successor must be feasible"); + SI->setDefaultDest(FirstFeasible); + Updates.push_back({DominatorTree::Delete, BB, DefaultDest}); + } + for (auto CI = SI->case_begin(); CI != SI->case_end();) { if (FeasibleSuccessors.contains(CI->getCaseSuccessor())) { ++CI; diff --git a/llvm/test/Transforms/SCCP/switch-constantfold-crash.ll b/llvm/test/Transforms/SCCP/switch-constantfold-crash.ll --- a/llvm/test/Transforms/SCCP/switch-constantfold-crash.ll +++ b/llvm/test/Transforms/SCCP/switch-constantfold-crash.ll @@ -90,3 +90,38 @@ bb4: ; preds = %bb2, %bb2, %bb2 unreachable } + +; Test case from PR49573. %default.bb is unfeasible. Make sure it gets replaced +; by a different feasible successor +define void @pr49573_main() { + %tgt = call i16 @pr49573_fn() + switch i16 %tgt, label %default.bb [ + i16 0, label %case.0 + i16 1, label %case.1 + i16 2, label %case.2 + ] + +case.0: + unreachable + +default.bb: + ret void + +case.1: + ret void + +case.2: + ret void + +} + +define internal i16 @pr49573_fn() { +entry: + br i1 undef, label %then, label %else + +then: + ret i16 0 + +else: + ret i16 2 +}