Index: llvm/lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -6609,12 +6609,33 @@ } BI->eraseFromParent(); if (DTU) - DTU->applyUpdates({{DominatorTree::Delete, Predecessor, BB}}); + DTU->applyUpdates({ { DominatorTree::Delete, Predecessor, BB } }); + return true; + } else if (SwitchInst *SI = dyn_cast(T)) { + // Create the new block in which will redirect the edges that + // lead to undefine behavior + BasicBlock *Unreachable = BasicBlock::Create( + Predecessor->getContext(), "unreachable", BB->getParent(), BB); + Builder.SetInsertPoint(Unreachable); + // The new block contains only one instruction: Unreachable + Builder.CreateUnreachable(); + for (auto &Case : SI->cases()) + if (Case.getCaseSuccessor() == BB) { + BB->removePredecessor(Predecessor); + Case.setSuccessor(Unreachable); + } + if (SI->getDefaultDest() == BB) { + BB->removePredecessor(Predecessor); + SI->setDefaultDest(Unreachable); + } + + if (DTU) + DTU->applyUpdates( + { { DominatorTree::Delete, Predecessor, BB }, + { DominatorTree::Insert, Predecessor, Unreachable } }); return true; } - // TODO: SwitchInst. } - return false; } Index: llvm/test/Transforms/SimplifyCFG/switch_ub.ll =================================================================== --- llvm/test/Transforms/SimplifyCFG/switch_ub.ll +++ llvm/test/Transforms/SimplifyCFG/switch_ub.ll @@ -6,19 +6,12 @@ define i32 @test_01(i32* %p, i32 %x, i1 %cond) { ; CHECK-LABEL: @test_01( ; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB:%.*]], label [[PRED:%.*]] -; CHECK: pred: -; CHECK-NEXT: switch i32 [[X:%.*]], label [[COMMON_RET:%.*]] [ -; CHECK-NEXT: i32 42, label [[BB]] -; CHECK-NEXT: i32 123456, label [[BB]] -; CHECK-NEXT: i32 -654321, label [[BB]] -; CHECK-NEXT: ] +; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB:%.*]], label [[COMMON_RET:%.*]] ; CHECK: common.ret: -; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[R:%.*]], [[BB]] ], [ 0, [[PRED]] ] +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[R:%.*]], [[BB]] ], [ 0, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; CHECK: bb: -; CHECK-NEXT: [[PHI:%.*]] = phi i32* [ null, [[PRED]] ], [ null, [[PRED]] ], [ null, [[PRED]] ], [ [[P:%.*]], [[ENTRY:%.*]] ] -; CHECK-NEXT: [[R]] = load i32, i32* [[PHI]], align 4 +; CHECK-NEXT: [[R]] = load i32, i32* [[P:%.*]], align 4 ; CHECK-NEXT: br label [[COMMON_RET]] ; entry: @@ -42,19 +35,12 @@ define i32 @test_02(i32* %p, i32 %x, i1 %cond) { ; CHECK-LABEL: @test_02( ; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB:%.*]], label [[PRED:%.*]] -; CHECK: pred: -; CHECK-NEXT: switch i32 [[X:%.*]], label [[BB]] [ -; CHECK-NEXT: i32 42, label [[COMMON_RET:%.*]] -; CHECK-NEXT: i32 123456, label [[COMMON_RET]] -; CHECK-NEXT: i32 -654321, label [[COMMON_RET]] -; CHECK-NEXT: ] +; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB:%.*]], label [[COMMON_RET:%.*]] ; CHECK: common.ret: -; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[R:%.*]], [[BB]] ], [ 0, [[PRED]] ], [ 0, [[PRED]] ], [ 0, [[PRED]] ] +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[R:%.*]], [[BB]] ], [ 0, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; CHECK: bb: -; CHECK-NEXT: [[PHI:%.*]] = phi i32* [ null, [[PRED]] ], [ [[P:%.*]], [[ENTRY:%.*]] ] -; CHECK-NEXT: [[R]] = load i32, i32* [[PHI]], align 4 +; CHECK-NEXT: [[R]] = load i32, i32* [[P:%.*]], align 4 ; CHECK-NEXT: br label [[COMMON_RET]] ; entry: