diff --git a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp --- a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp +++ b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp @@ -826,7 +826,9 @@ DTUpdates.push_back({DT.Insert, OldPH, UnswitchedExitBB}); } for (auto SplitUnswitchedPair : SplitExitBBMap) { - DTUpdates.push_back({DT.Delete, ParentBB, SplitUnswitchedPair.first}); + // If the deleted edge was not duplicated in the switch, delete from the DT. + if (!llvm::is_contained(successors(ParentBB), SplitUnswitchedPair.first)) + DTUpdates.push_back({DT.Delete, ParentBB, SplitUnswitchedPair.first}); DTUpdates.push_back({DT.Insert, OldPH, SplitUnswitchedPair.second}); } DT.applyUpdates(DTUpdates); diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll b/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll --- a/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll +++ b/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll @@ -1243,3 +1243,39 @@ ; CHECK: loopexit: ; CHECK-NEXT: ret } + +; PR45355 +define void @test_unswitch_switch_with_duplicate_edge() { +; CHECK-LABEL: @test_unswitch_switch_with_duplicate_edge() +entry: + br label %lbl1 + +lbl1.loopexit: ; preds = %for.cond1 + unreachable + +lbl1: ; preds = %entry + %cleanup.dest.slot.0 = select i1 undef, i32 5, i32 undef + br label %for.cond1 + +for.cond1: ; preds = %for.cond1, %lbl1 + switch i32 %cleanup.dest.slot.0, label %UnifiedUnreachableBlock [ + i32 0, label %for.cond1 + i32 5, label %UnifiedUnreachableBlock + i32 2, label %lbl1.loopexit + ] + +UnifiedUnreachableBlock: ; preds = %for.cond1, %for.cond1 + unreachable + +; CHECK: lbl1: +; CHECK-NEXT: %cleanup.dest.slot.0 = select i1 undef, i32 5, i32 undef +; CHECK-NEXT: switch i32 %cleanup.dest.slot.0, label %lbl1.split [ +; CHECK-NEXT: i32 5, label %UnifiedUnreachableBlock.split +; CHECK-NEXT: i32 2, label %lbl1.loopexit +; CHECK-NEXT: ] + +; CHECK: lbl1.split: +; CHECK-NEXT: switch i32 %cleanup.dest.slot.0, label %UnifiedUnreachableBlock [ +; CHECK-NEXT: i32 0, label %lbl1.split.split +; CHECK-NEXT: ] +}