about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-03-08 07:18:17 +0000
committerbors <bors@rust-lang.org>2024-03-08 07:18:17 +0000
commit14fbc3c00525b41a3a3ee2c90e9ab6fd3b05274f (patch)
tree81cec2387610314e63c2468b5c3a2d1b797b6529
parent9fb91aa2e70bfcc1c0adaad79711f0321ea81ece (diff)
parent2884230df2bdf6ff23d51808f5e2f270dfbe0d3a (diff)
downloadrust-14fbc3c00525b41a3a3ee2c90e9ab6fd3b05274f.tar.gz
rust-14fbc3c00525b41a3a3ee2c90e9ab6fd3b05274f.zip
Auto merge of #120268 - DianQK:otherwise_is_last_variant_switchs, r=oli-obk
Replace the default branch with an unreachable branch If it is the last variant

Fixes #119520. Fixes #110097.

LLVM currently has limited ability to eliminate dead branches in switches, even with the patch of https://github.com/llvm/llvm-project/issues/73446.

The main reasons are as follows:

- Additional costs are required to calculate the range of values, and there exist many scenarios that cannot be analyzed accurately.
- Matching values by bitwise calculation cannot handle odd branches, nor can it handle values like `-1, 0, 1`. See [SimplifyCFG.cpp#L5424](https://github.com/llvm/llvm-project/blob/llvmorg-17.0.6/llvm/lib/Transforms/Utils/SimplifyCFG.cpp#L5424) and https://llvm.godbolt.org/z/qYMqhvMa8
- The current range information is continuous, even if the metadata for the range is submitted. See [ConstantRange.cpp#L1869-L1870](https://github.com/llvm/llvm-project/blob/llvmorg-17.0.6/llvm/lib/IR/ConstantRange.cpp#L1869-L1870).
- The metadata of the range may be lost in passes such as SROA. See https://rust.godbolt.org/z/e7f87vKMK.

Although we can make improvements, I think it would be more appropriate to put this issue to rustc first. After all, we can easily know the possible values.

Note that we've currently found a slow compilation problem in the presence of unreachable branches. See
https://github.com/llvm/llvm-project/issues/78578.

r? compiler
-rw-r--r--compiler/rustc_middle/src/mir/patch.rs27
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs11
-rw-r--r--compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs84
-rw-r--r--tests/codegen/enum/uninhabited_enum_default_branch.rs24
-rw-r--r--tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff6
-rw-r--r--tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff6
-rw-r--r--tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir22
-rw-r--r--tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir22
-rw-r--r--tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff26
-rw-r--r--tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff20
-rw-r--r--tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff26
-rw-r--r--tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff20
-rw-r--r--tests/mir-opt/separate_const_switch.identity.JumpThreading.diff28
-rw-r--r--tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff34
-rw-r--r--tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff8
-rw-r--r--tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff8
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff (renamed from tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff)8
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff115
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff (renamed from tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.diff)7
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff43
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff53
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff53
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff44
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff44
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff53
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff53
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff48
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff48
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff62
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff62
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff75
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff75
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff66
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff70
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.rs139
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff (renamed from tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.diff)6
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff53
-rw-r--r--tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff2
38 files changed, 1396 insertions, 155 deletions
diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs
index b81e9fa1aab..33412297017 100644
--- a/compiler/rustc_middle/src/mir/patch.rs
+++ b/compiler/rustc_middle/src/mir/patch.rs
@@ -11,6 +11,8 @@ pub struct MirPatch<'tcx> {
     resume_block: Option<BasicBlock>,
     // Only for unreachable in cleanup path.
     unreachable_cleanup_block: Option<BasicBlock>,
+    // Only for unreachable not in cleanup path.
+    unreachable_no_cleanup_block: Option<BasicBlock>,
     // Cached block for UnwindTerminate (with reason)
     terminate_block: Option<(BasicBlock, UnwindTerminateReason)>,
     body_span: Span,
@@ -27,6 +29,7 @@ impl<'tcx> MirPatch<'tcx> {
             next_local: body.local_decls.len(),
             resume_block: None,
             unreachable_cleanup_block: None,
+            unreachable_no_cleanup_block: None,
             terminate_block: None,
             body_span: body.span,
         };
@@ -43,9 +46,12 @@ impl<'tcx> MirPatch<'tcx> {
             // Check if we already have an unreachable block
             if matches!(block.terminator().kind, TerminatorKind::Unreachable)
                 && block.statements.is_empty()
-                && block.is_cleanup
             {
-                result.unreachable_cleanup_block = Some(bb);
+                if block.is_cleanup {
+                    result.unreachable_cleanup_block = Some(bb);
+                } else {
+                    result.unreachable_no_cleanup_block = Some(bb);
+                }
                 continue;
             }
 
@@ -95,6 +101,23 @@ impl<'tcx> MirPatch<'tcx> {
         bb
     }
 
+    pub fn unreachable_no_cleanup_block(&mut self) -> BasicBlock {
+        if let Some(bb) = self.unreachable_no_cleanup_block {
+            return bb;
+        }
+
+        let bb = self.new_block(BasicBlockData {
+            statements: vec![],
+            terminator: Some(Terminator {
+                source_info: SourceInfo::outermost(self.body_span),
+                kind: TerminatorKind::Unreachable,
+            }),
+            is_cleanup: false,
+        });
+        self.unreachable_no_cleanup_block = Some(bb);
+        bb
+    }
+
     pub fn terminate_block(&mut self, reason: UnwindTerminateReason) -> BasicBlock {
         if let Some((cached_bb, cached_reason)) = self.terminate_block
             && reason == cached_reason
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 6c92dfa3cd8..ae3daa77b1c 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -74,6 +74,17 @@ impl SwitchTargets {
     pub fn target_for_value(&self, value: u128) -> BasicBlock {
         self.iter().find_map(|(v, t)| (v == value).then_some(t)).unwrap_or_else(|| self.otherwise())
     }
+
+    /// Adds a new target to the switch. But You cannot add an already present value.
+    #[inline]
+    pub fn add_target(&mut self, value: u128, bb: BasicBlock) {
+        let value = Pu128(value);
+        if self.values.contains(&value) {
+            bug!("target value {:?} already present", value);
+        }
+        self.values.push(value);
+        self.targets.insert(self.targets.len() - 1, bb);
+    }
 }
 
 pub struct SwitchTargetsIter<'a> {
diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
index e68d37f4c70..57fe46ad75a 100644
--- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
@@ -2,8 +2,10 @@
 
 use crate::MirPass;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::{
-    BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, Terminator, TerminatorKind,
+    BasicBlock, BasicBlockData, BasicBlocks, Body, Local, Operand, Rvalue, StatementKind,
+    TerminatorKind,
 };
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_middle::ty::{Ty, TyCtxt};
@@ -77,7 +79,8 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         trace!("UninhabitedEnumBranching starting for {:?}", body.source);
 
-        let mut removable_switchs = Vec::new();
+        let mut unreachable_targets = Vec::new();
+        let mut patch = MirPatch::new(body);
 
         for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
             trace!("processing block {:?}", bb);
@@ -92,46 +95,73 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
                 tcx.param_env_reveal_all_normalized(body.source.def_id()).and(discriminant_ty),
             );
 
-            let allowed_variants = if let Ok(layout) = layout {
+            let mut allowed_variants = if let Ok(layout) = layout {
                 variant_discriminants(&layout, discriminant_ty, tcx)
+            } else if let Some(variant_range) = discriminant_ty.variant_range(tcx) {
+                variant_range
+                    .map(|variant| {
+                        discriminant_ty.discriminant_for_variant(tcx, variant).unwrap().val
+                    })
+                    .collect()
             } else {
                 continue;
             };
 
             trace!("allowed_variants = {:?}", allowed_variants);
 
-            let terminator = bb_data.terminator();
-            let TerminatorKind::SwitchInt { targets, .. } = &terminator.kind else { bug!() };
+            unreachable_targets.clear();
+            let TerminatorKind::SwitchInt { targets, discr } = &bb_data.terminator().kind else {
+                bug!()
+            };
 
-            let mut reachable_count = 0;
             for (index, (val, _)) in targets.iter().enumerate() {
-                if allowed_variants.contains(&val) {
-                    reachable_count += 1;
-                } else {
-                    removable_switchs.push((bb, index));
+                if !allowed_variants.remove(&val) {
+                    unreachable_targets.push(index);
+                }
+            }
+            let otherwise_is_empty_unreachable =
+                body.basic_blocks[targets.otherwise()].is_empty_unreachable();
+            // After resolving https://github.com/llvm/llvm-project/issues/78578,
+            // we can remove the limit on the number of successors.
+            fn check_successors(basic_blocks: &BasicBlocks<'_>, bb: BasicBlock) -> bool {
+                let mut successors = basic_blocks[bb].terminator().successors();
+                let Some(first_successor) = successors.next() else { return true };
+                if successors.next().is_some() {
+                    return true;
                 }
+                if let TerminatorKind::SwitchInt { .. } =
+                    &basic_blocks[first_successor].terminator().kind
+                {
+                    return false;
+                };
+                true
             }
+            let otherwise_is_last_variant = !otherwise_is_empty_unreachable
+                && allowed_variants.len() == 1
+                && check_successors(&body.basic_blocks, targets.otherwise());
+            let replace_otherwise_to_unreachable = otherwise_is_last_variant
+                || !otherwise_is_empty_unreachable && allowed_variants.is_empty();
 
-            if reachable_count == allowed_variants.len() {
-                removable_switchs.push((bb, targets.iter().count()));
+            if unreachable_targets.is_empty() && !replace_otherwise_to_unreachable {
+                continue;
             }
-        }
 
-        if removable_switchs.is_empty() {
-            return;
+            let unreachable_block = patch.unreachable_no_cleanup_block();
+            let mut targets = targets.clone();
+            if replace_otherwise_to_unreachable {
+                if otherwise_is_last_variant {
+                    #[allow(rustc::potential_query_instability)]
+                    let last_variant = *allowed_variants.iter().next().unwrap();
+                    targets.add_target(last_variant, targets.otherwise());
+                }
+                unreachable_targets.push(targets.iter().count());
+            }
+            for index in unreachable_targets.iter() {
+                targets.all_targets_mut()[*index] = unreachable_block;
+            }
+            patch.patch_terminator(bb, TerminatorKind::SwitchInt { targets, discr: discr.clone() });
         }
 
-        let new_block = BasicBlockData::new(Some(Terminator {
-            source_info: body.basic_blocks[removable_switchs[0].0].terminator().source_info,
-            kind: TerminatorKind::Unreachable,
-        }));
-        let unreachable_block = body.basic_blocks.as_mut().push(new_block);
-
-        for (bb, index) in removable_switchs {
-            let bb = &mut body.basic_blocks.as_mut()[bb];
-            let terminator = bb.terminator_mut();
-            let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind else { bug!() };
-            targets.all_targets_mut()[index] = unreachable_block;
-        }
+        patch.apply(body);
     }
 }
diff --git a/tests/codegen/enum/uninhabited_enum_default_branch.rs b/tests/codegen/enum/uninhabited_enum_default_branch.rs
new file mode 100644
index 00000000000..5f318f18dec
--- /dev/null
+++ b/tests/codegen/enum/uninhabited_enum_default_branch.rs
@@ -0,0 +1,24 @@
+//@ compile-flags: -O
+
+#![crate_type = "lib"]
+
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Int(u32);
+
+const A: Int = Int(201);
+const B: Int = Int(270);
+const C: Int = Int(153);
+
+// CHECK-LABEL: @foo(
+// CHECK-SAME: [[TMP0:%.*]])
+// CHECK-NEXT:  start:
+// CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[TMP0]], -201
+// CHECK-NEXT:    icmp ult i32 [[TMP1]], 70
+// CHECK-NEXT:    icmp eq i32 [[TMP0]], 153
+// CHECK-NEXT:    [[SPEC_SELECT:%.*]] = or i1
+// CHECK-NEXT:    ret i1 [[SPEC_SELECT]]
+#[no_mangle]
+pub fn foo(x: Int) -> bool {
+    (x >= A && x <= B)
+        || x == C
+}
diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff
index 080478ea884..bd346af6d16 100644
--- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff
+++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff
@@ -69,7 +69,7 @@
           StorageLive(_6);
           _6 = ((*_1).4: std::option::Option<usize>);
           _7 = discriminant(_6);
-          switchInt(move _7) -> [1: bb4, otherwise: bb6];
+          switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9];
       }
   
       bb4: {
@@ -135,5 +135,9 @@
           StorageDead(_6);
           return;
       }
+  
+      bb9: {
+          unreachable;
+      }
   }
   
diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff
index ff8933fca8b..422cbeaa224 100644
--- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff
+++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff
@@ -69,7 +69,7 @@
           StorageLive(_6);
           _6 = ((*_1).4: std::option::Option<usize>);
           _7 = discriminant(_6);
-          switchInt(move _7) -> [1: bb4, otherwise: bb6];
+          switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9];
       }
   
       bb4: {
@@ -135,5 +135,9 @@
           StorageDead(_6);
           return;
       }
+  
+      bb9: {
+          unreachable;
+      }
   }
   
diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir
index f7be8b75db7..bc12002490a 100644
--- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir
@@ -33,13 +33,13 @@ fn num_to_digit(_1: char) -> u32 {
         _3 = &_2;
         StorageLive(_4);
         _4 = discriminant(_2);
-        StorageDead(_3);
-        StorageDead(_2);
-        switchInt(move _4) -> [1: bb2, otherwise: bb7];
+        switchInt(move _4) -> [1: bb2, 0: bb6, otherwise: bb8];
     }
 
     bb2: {
         StorageDead(_4);
+        StorageDead(_3);
+        StorageDead(_2);
         StorageLive(_5);
         _5 = char::methods::<impl char>::to_digit(move _1, const 8_u32) -> [return: bb3, unwind unreachable];
     }
@@ -47,7 +47,7 @@ fn num_to_digit(_1: char) -> u32 {
     bb3: {
         StorageLive(_6);
         _6 = discriminant(_5);
-        switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb6];
+        switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb8];
     }
 
     bb4: {
@@ -58,20 +58,22 @@ fn num_to_digit(_1: char) -> u32 {
         _0 = move ((_5 as Some).0: u32);
         StorageDead(_6);
         StorageDead(_5);
-        goto -> bb8;
+        goto -> bb7;
     }
 
     bb6: {
-        unreachable;
+        StorageDead(_4);
+        StorageDead(_3);
+        StorageDead(_2);
+        _0 = const 0_u32;
+        goto -> bb7;
     }
 
     bb7: {
-        StorageDead(_4);
-        _0 = const 0_u32;
-        goto -> bb8;
+        return;
     }
 
     bb8: {
-        return;
+        unreachable;
     }
 }
diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir
index e76fe992ac7..6c7e10a4525 100644
--- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir
@@ -33,13 +33,13 @@ fn num_to_digit(_1: char) -> u32 {
         _3 = &_2;
         StorageLive(_4);
         _4 = discriminant(_2);
-        StorageDead(_3);
-        StorageDead(_2);
-        switchInt(move _4) -> [1: bb2, otherwise: bb7];
+        switchInt(move _4) -> [1: bb2, 0: bb6, otherwise: bb8];
     }
 
     bb2: {
         StorageDead(_4);
+        StorageDead(_3);
+        StorageDead(_2);
         StorageLive(_5);
         _5 = char::methods::<impl char>::to_digit(move _1, const 8_u32) -> [return: bb3, unwind continue];
     }
@@ -47,7 +47,7 @@ fn num_to_digit(_1: char) -> u32 {
     bb3: {
         StorageLive(_6);
         _6 = discriminant(_5);
-        switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb6];
+        switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb8];
     }
 
     bb4: {
@@ -58,20 +58,22 @@ fn num_to_digit(_1: char) -> u32 {
         _0 = move ((_5 as Some).0: u32);
         StorageDead(_6);
         StorageDead(_5);
-        goto -> bb8;
+        goto -> bb7;
     }
 
     bb6: {
-        unreachable;
+        StorageDead(_4);
+        StorageDead(_3);
+        StorageDead(_2);
+        _0 = const 0_u32;
+        goto -> bb7;
     }
 
     bb7: {
-        StorageDead(_4);
-        _0 = const 0_u32;
-        goto -> bb8;
+        return;
     }
 
     bb8: {
-        return;
+        unreachable;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
index 5c586fbc2fc..84181462f67 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
@@ -58,16 +58,20 @@
 +         _2 = const Option::<Layout>::None;
           StorageLive(_10);
 -         _10 = discriminant(_2);
--         switchInt(move _10) -> [0: bb1, 1: bb2, otherwise: bb6];
+-         switchInt(move _10) -> [0: bb2, 1: bb3, otherwise: bb1];
 +         _10 = const 0_isize;
-+         switchInt(const 0_isize) -> [0: bb1, 1: bb2, otherwise: bb6];
++         switchInt(const 0_isize) -> [0: bb2, 1: bb3, otherwise: bb1];
       }
   
       bb1: {
-          _11 = option::unwrap_failed() -> unwind unreachable;
+          unreachable;
       }
   
       bb2: {
+          _11 = option::unwrap_failed() -> unwind unreachable;
+      }
+  
+      bb3: {
 -         _1 = move ((_2 as Some).0: std::alloc::Layout);
 +         _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }};
           StorageDead(_10);
@@ -82,21 +86,21 @@
 +         _7 = const {ALLOC1<imm>: &std::alloc::Global};
           StorageLive(_8);
 -         _8 = _1;
--         _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb3, unwind unreachable];
+-         _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind unreachable];
 +         _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }};
-+         _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb3, unwind unreachable];
++         _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable];
       }
   
-      bb3: {
+      bb4: {
           StorageDead(_8);
           StorageDead(_7);
           StorageLive(_12);
           StorageLive(_15);
           _12 = discriminant(_6);
-          switchInt(move _12) -> [0: bb5, 1: bb4, otherwise: bb6];
+          switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb1];
       }
   
-      bb4: {
+      bb5: {
           _15 = const "called `Result::unwrap()` on an `Err` value";
           StorageLive(_16);
           StorageLive(_17);
@@ -106,7 +110,7 @@
           _14 = result::unwrap_failed(move _15, move _16) -> unwind unreachable;
       }
   
-      bb5: {
+      bb6: {
           _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>);
           StorageDead(_15);
           StorageDead(_12);
@@ -127,10 +131,6 @@
 +         nop;
           return;
       }
-  
-      bb6: {
-          unreachable;
-      }
   }
 + 
 + ALLOC0 (size: 8, align: 4) {
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff
index bfb2319dac1..820d02e26cd 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff
@@ -43,9 +43,9 @@
 +         _2 = const Option::<Layout>::None;
           StorageLive(_10);
 -         _10 = discriminant(_2);
--         switchInt(move _10) -> [0: bb2, 1: bb3, otherwise: bb5];
+-         switchInt(move _10) -> [0: bb3, 1: bb4, otherwise: bb2];
 +         _10 = const 0_isize;
-+         switchInt(const 0_isize) -> [0: bb2, 1: bb3, otherwise: bb5];
++         switchInt(const 0_isize) -> [0: bb3, 1: bb4, otherwise: bb2];
       }
   
       bb1: {
@@ -68,10 +68,14 @@
       }
   
       bb2: {
-          _11 = option::unwrap_failed() -> unwind continue;
+          unreachable;
       }
   
       bb3: {
+          _11 = option::unwrap_failed() -> unwind continue;
+      }
+  
+      bb4: {
 -         _1 = move ((_2 as Some).0: std::alloc::Layout);
 +         _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }};
           StorageDead(_10);
@@ -86,20 +90,16 @@
 +         _7 = const {ALLOC1<imm>: &std::alloc::Global};
           StorageLive(_8);
 -         _8 = _1;
--         _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind continue];
+-         _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb5, unwind continue];
 +         _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }};
-+         _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind continue];
++         _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue];
       }
   
-      bb4: {
+      bb5: {
           StorageDead(_8);
           StorageDead(_7);
           _5 = Result::<NonNull<[u8]>, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue];
       }
-  
-      bb5: {
-          unreachable;
-      }
   }
 + 
 + ALLOC0 (size: 8, align: 4) {
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
index ce55a8265e5..f478f7cb903 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
@@ -58,16 +58,20 @@
 +         _2 = const Option::<Layout>::None;
           StorageLive(_10);
 -         _10 = discriminant(_2);
--         switchInt(move _10) -> [0: bb1, 1: bb2, otherwise: bb6];
+-         switchInt(move _10) -> [0: bb2, 1: bb3, otherwise: bb1];
 +         _10 = const 0_isize;
-+         switchInt(const 0_isize) -> [0: bb1, 1: bb2, otherwise: bb6];
++         switchInt(const 0_isize) -> [0: bb2, 1: bb3, otherwise: bb1];
       }
   
       bb1: {
-          _11 = option::unwrap_failed() -> unwind unreachable;
+          unreachable;
       }
   
       bb2: {
+          _11 = option::unwrap_failed() -> unwind unreachable;
+      }
+  
+      bb3: {
 -         _1 = move ((_2 as Some).0: std::alloc::Layout);
 +         _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }};
           StorageDead(_10);
@@ -82,21 +86,21 @@
 +         _7 = const {ALLOC1<imm>: &std::alloc::Global};
           StorageLive(_8);
 -         _8 = _1;
--         _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb3, unwind unreachable];
+-         _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind unreachable];
 +         _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }};
-+         _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb3, unwind unreachable];
++         _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable];
       }
   
-      bb3: {
+      bb4: {
           StorageDead(_8);
           StorageDead(_7);
           StorageLive(_12);
           StorageLive(_15);
           _12 = discriminant(_6);
-          switchInt(move _12) -> [0: bb5, 1: bb4, otherwise: bb6];
+          switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb1];
       }
   
-      bb4: {
+      bb5: {
           _15 = const "called `Result::unwrap()` on an `Err` value";
           StorageLive(_16);
           StorageLive(_17);
@@ -106,7 +110,7 @@
           _14 = result::unwrap_failed(move _15, move _16) -> unwind unreachable;
       }
   
-      bb5: {
+      bb6: {
           _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>);
           StorageDead(_15);
           StorageDead(_12);
@@ -127,10 +131,6 @@
 +         nop;
           return;
       }
-  
-      bb6: {
-          unreachable;
-      }
   }
 + 
 + ALLOC0 (size: 16, align: 8) {
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff
index ddf4223bb49..1fba8b5059a 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff
@@ -43,9 +43,9 @@
 +         _2 = const Option::<Layout>::None;
           StorageLive(_10);
 -         _10 = discriminant(_2);
--         switchInt(move _10) -> [0: bb2, 1: bb3, otherwise: bb5];
+-         switchInt(move _10) -> [0: bb3, 1: bb4, otherwise: bb2];
 +         _10 = const 0_isize;
-+         switchInt(const 0_isize) -> [0: bb2, 1: bb3, otherwise: bb5];
++         switchInt(const 0_isize) -> [0: bb3, 1: bb4, otherwise: bb2];
       }
   
       bb1: {
@@ -68,10 +68,14 @@
       }
   
       bb2: {
-          _11 = option::unwrap_failed() -> unwind continue;
+          unreachable;
       }
   
       bb3: {
+          _11 = option::unwrap_failed() -> unwind continue;
+      }
+  
+      bb4: {
 -         _1 = move ((_2 as Some).0: std::alloc::Layout);
 +         _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }};
           StorageDead(_10);
@@ -86,20 +90,16 @@
 +         _7 = const {ALLOC1<imm>: &std::alloc::Global};
           StorageLive(_8);
 -         _8 = _1;
--         _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind continue];
+-         _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb5, unwind continue];
 +         _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }};
-+         _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind continue];
++         _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue];
       }
   
-      bb4: {
+      bb5: {
           StorageDead(_8);
           StorageDead(_7);
           _5 = Result::<NonNull<[u8]>, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue];
       }
-  
-      bb5: {
-          unreachable;
-      }
   }
 + 
 + ALLOC0 (size: 16, align: 8) {
diff --git a/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff b/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff
index ab3d91ab918..d0abebff214 100644
--- a/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff
+++ b/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff
@@ -52,17 +52,21 @@
           StorageLive(_9);
           StorageLive(_10);
           _8 = discriminant(_1);
-          switchInt(move _8) -> [0: bb5, 1: bb4, otherwise: bb6];
+          switchInt(move _8) -> [0: bb6, 1: bb5, otherwise: bb1];
       }
   
       bb1: {
+          unreachable;
+      }
+  
+      bb2: {
           _7 = ((_2 as Continue).0: i32);
           _0 = Result::<i32, i32>::Ok(_7);
           StorageDead(_2);
           return;
       }
   
-      bb2: {
+      bb3: {
           _5 = ((_2 as Break).0: std::result::Result<std::convert::Infallible, i32>);
           StorageLive(_6);
           _6 = _5;
@@ -73,34 +77,30 @@
           return;
       }
   
-      bb3: {
+      bb4: {
           StorageDead(_10);
           StorageDead(_9);
           StorageDead(_8);
           StorageDead(_3);
           _4 = discriminant(_2);
--         switchInt(move _4) -> [0: bb1, 1: bb2, otherwise: bb6];
-+         goto -> bb1;
+-         switchInt(move _4) -> [0: bb2, 1: bb3, otherwise: bb1];
++         goto -> bb2;
       }
   
-      bb4: {
+      bb5: {
           _10 = ((_1 as Err).0: i32);
           StorageLive(_11);
           _11 = Result::<Infallible, i32>::Err(_10);
           _2 = ControlFlow::<Result<Infallible, i32>, i32>::Break(move _11);
           StorageDead(_11);
--         goto -> bb3;
+-         goto -> bb4;
 +         goto -> bb7;
       }
   
-      bb5: {
+      bb6: {
           _9 = ((_1 as Ok).0: i32);
           _2 = ControlFlow::<Result<Infallible, i32>, i32>::Continue(_9);
-          goto -> bb3;
-      }
-  
-      bb6: {
-          unreachable;
+          goto -> bb4;
 +     }
 + 
 +     bb7: {
@@ -109,7 +109,7 @@
 +         StorageDead(_8);
 +         StorageDead(_3);
 +         _4 = discriminant(_2);
-+         goto -> bb2;
++         goto -> bb3;
       }
   }
   
diff --git a/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff b/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff
index 1ac527e9338..f7495862992 100644
--- a/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff
+++ b/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff
@@ -27,54 +27,54 @@
       bb0: {
           StorageLive(_2);
           _3 = discriminant(_1);
-          switchInt(move _3) -> [0: bb2, 1: bb1, otherwise: bb7];
+          switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1];
       }
   
       bb1: {
+          unreachable;
+      }
+  
+      bb2: {
           _5 = ((_1 as Err).0: usize);
           _2 = ControlFlow::<usize, i32>::Break(_5);
--         goto -> bb3;
+-         goto -> bb4;
 +         goto -> bb8;
       }
   
-      bb2: {
+      bb3: {
           _4 = ((_1 as Ok).0: i32);
           _2 = ControlFlow::<usize, i32>::Continue(_4);
-          goto -> bb3;
+          goto -> bb4;
       }
   
-      bb3: {
+      bb4: {
           _6 = discriminant(_2);
--         switchInt(move _6) -> [0: bb5, 1: bb4, otherwise: bb7];
-+         goto -> bb5;
+-         switchInt(move _6) -> [0: bb6, 1: bb5, otherwise: bb1];
++         goto -> bb6;
       }
   
-      bb4: {
+      bb5: {
           StorageLive(_8);
           _8 = ((_2 as Break).0: usize);
           _0 = const Option::<i32>::None;
           StorageDead(_8);
-          goto -> bb6;
+          goto -> bb7;
       }
   
-      bb5: {
+      bb6: {
           _7 = ((_2 as Continue).0: i32);
           _0 = Option::<i32>::Some(_7);
-          goto -> bb6;
+          goto -> bb7;
       }
   
-      bb6: {
+      bb7: {
           StorageDead(_2);
           return;
-      }
-  
-      bb7: {
-          unreachable;
 +     }
 + 
 +     bb8: {
 +         _6 = discriminant(_2);
-+         goto -> bb4;
++         goto -> bb5;
       }
   }
   
diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff
index 1566d7197ac..c520a159f47 100644
--- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff
+++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff
@@ -23,12 +23,12 @@
           StorageDead(_3);
           StorageDead(_2);
           _5 = discriminant((_1.0: std::option::Option<u8>));
-          switchInt(move _5) -> [1: bb1, otherwise: bb3];
+          switchInt(move _5) -> [1: bb1, 0: bb3, otherwise: bb5];
       }
   
       bb1: {
           _4 = discriminant((_1.1: std::option::Option<T>));
-          switchInt(move _4) -> [0: bb2, otherwise: bb3];
+          switchInt(move _4) -> [0: bb2, 1: bb3, otherwise: bb5];
       }
   
       bb2: {
@@ -46,5 +46,9 @@
           StorageDead(_1);
           return;
       }
+  
+      bb5: {
+          unreachable;
+      }
   }
   
diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff
index ba5262b0ee1..686581591fc 100644
--- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff
+++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff
@@ -23,12 +23,12 @@
           StorageDead(_3);
           StorageDead(_2);
           _5 = discriminant((_1.0: std::option::Option<u8>));
-          switchInt(move _5) -> [1: bb1, otherwise: bb3];
+          switchInt(move _5) -> [1: bb1, 0: bb3, otherwise: bb5];
       }
   
       bb1: {
           _4 = discriminant((_1.1: std::option::Option<T>));
-          switchInt(move _4) -> [0: bb2, otherwise: bb3];
+          switchInt(move _4) -> [0: bb2, 1: bb3, otherwise: bb5];
       }
   
       bb2: {
@@ -46,5 +46,9 @@
           StorageDead(_1);
           return;
       }
+  
+      bb5: {
+          unreachable;
+      }
   }
   
diff --git a/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff
index 5a3544f8538..1b7517c8d01 100644
--- a/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff
+++ b/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff
@@ -31,7 +31,7 @@
           _4 = &(_1.1: Test3);
           _5 = discriminant((*_4));
 -         switchInt(move _5) -> [0: bb3, 1: bb4, 2: bb5, 3: bb2, otherwise: bb1];
-+         switchInt(move _5) -> [0: bb12, 1: bb12, 2: bb5, 3: bb2, otherwise: bb12];
++         switchInt(move _5) -> [0: bb1, 1: bb1, 2: bb5, 3: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -73,7 +73,7 @@
           StorageLive(_9);
           _10 = discriminant((_1.1: Test3));
 -         switchInt(move _10) -> [0: bb8, 1: bb9, 2: bb10, 3: bb7, otherwise: bb1];
-+         switchInt(move _10) -> [0: bb12, 1: bb12, 2: bb10, 3: bb7, otherwise: bb12];
++         switchInt(move _10) -> [0: bb1, 1: bb1, 2: bb10, 3: bb7, otherwise: bb1];
       }
   
       bb7: {
@@ -110,10 +110,6 @@
           _0 = const ();
           StorageDead(_1);
           return;
-+     }
-+ 
-+     bb12: {
-+         unreachable;
       }
   }
   
diff --git a/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..1b7517c8d01
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,115 @@
+- // MIR for `byref` before UninhabitedEnumBranching
++ // MIR for `byref` after UninhabitedEnumBranching
+  
+  fn byref() -> () {
+      let mut _0: ();
+      let _1: Plop;
+      let mut _2: Test3;
+      let _3: &str;
+      let mut _4: &Test3;
+      let mut _5: isize;
+      let _6: &str;
+      let _7: &str;
+      let _8: &str;
+      let _9: &str;
+      let mut _10: isize;
+      let _11: &str;
+      let _12: &str;
+      let _13: &str;
+      scope 1 {
+          debug plop => _1;
+      }
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test3::C;
+          _1 = Plop { xx: const 51_u32, test3: move _2 };
+          StorageDead(_2);
+          StorageLive(_3);
+          StorageLive(_4);
+          _4 = &(_1.1: Test3);
+          _5 = discriminant((*_4));
+-         switchInt(move _5) -> [0: bb3, 1: bb4, 2: bb5, 3: bb2, otherwise: bb1];
++         switchInt(move _5) -> [0: bb1, 1: bb1, 2: bb5, 3: bb2, otherwise: bb1];
+      }
+  
+      bb1: {
+          unreachable;
+      }
+  
+      bb2: {
+          StorageLive(_8);
+          _8 = const "D";
+          _3 = &(*_8);
+          StorageDead(_8);
+          goto -> bb6;
+      }
+  
+      bb3: {
+          _3 = const "A(Empty)";
+          goto -> bb6;
+      }
+  
+      bb4: {
+          StorageLive(_6);
+          _6 = const "B(Empty)";
+          _3 = &(*_6);
+          StorageDead(_6);
+          goto -> bb6;
+      }
+  
+      bb5: {
+          StorageLive(_7);
+          _7 = const "C";
+          _3 = &(*_7);
+          StorageDead(_7);
+          goto -> bb6;
+      }
+  
+      bb6: {
+          StorageDead(_4);
+          StorageDead(_3);
+          StorageLive(_9);
+          _10 = discriminant((_1.1: Test3));
+-         switchInt(move _10) -> [0: bb8, 1: bb9, 2: bb10, 3: bb7, otherwise: bb1];
++         switchInt(move _10) -> [0: bb1, 1: bb1, 2: bb10, 3: bb7, otherwise: bb1];
+      }
+  
+      bb7: {
+          StorageLive(_13);
+          _13 = const "D";
+          _9 = &(*_13);
+          StorageDead(_13);
+          goto -> bb11;
+      }
+  
+      bb8: {
+          _9 = const "A(Empty)";
+          goto -> bb11;
+      }
+  
+      bb9: {
+          StorageLive(_11);
+          _11 = const "B(Empty)";
+          _9 = &(*_11);
+          StorageDead(_11);
+          goto -> bb11;
+      }
+  
+      bb10: {
+          StorageLive(_12);
+          _12 = const "C";
+          _9 = &(*_12);
+          StorageDead(_12);
+          goto -> bb11;
+      }
+  
+      bb11: {
+          StorageDead(_9);
+          _0 = const ();
+          StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff
index 121374553ed..f9a43480917 100644
--- a/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.diff
+++ b/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff
@@ -13,8 +13,7 @@
           StorageLive(_2);
           _2 = Test2::D;
           _3 = discriminant(_2);
--         switchInt(move _3) -> [4: bb3, 5: bb2, otherwise: bb1];
-+         switchInt(move _3) -> [4: bb3, 5: bb2, otherwise: bb5];
+          switchInt(move _3) -> [4: bb3, 5: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -39,10 +38,6 @@
           StorageDead(_1);
           _0 = const ();
           return;
-+     }
-+ 
-+     bb5: {
-+         unreachable;
       }
   }
   
diff --git a/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..f9a43480917
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,43 @@
+- // MIR for `custom_discriminant` before UninhabitedEnumBranching
++ // MIR for `custom_discriminant` after UninhabitedEnumBranching
+  
+  fn custom_discriminant() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test2;
+      let mut _3: isize;
+      let _4: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test2::D;
+          _3 = discriminant(_2);
+          switchInt(move _3) -> [4: bb3, 5: bb2, otherwise: bb1];
+      }
+  
+      bb1: {
+          unreachable;
+      }
+  
+      bb2: {
+          StorageLive(_4);
+          _4 = const "E";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb4;
+      }
+  
+      bb3: {
+          _1 = const "D";
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff
new file mode 100644
index 00000000000..383fde4d787
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff
@@ -0,0 +1,53 @@
+- // MIR for `otherwise_t1` before UninhabitedEnumBranching
++ // MIR for `otherwise_t1` after UninhabitedEnumBranching
+  
+  fn otherwise_t1() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test1;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test1::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
++         switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5];
+      }
+  
+      bb1: {
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb4;
+      }
+  
+      bb2: {
+          _1 = const "A(Empty)";
+          goto -> bb4;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(Empty)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb5: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..383fde4d787
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,53 @@
+- // MIR for `otherwise_t1` before UninhabitedEnumBranching
++ // MIR for `otherwise_t1` after UninhabitedEnumBranching
+  
+  fn otherwise_t1() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test1;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test1::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
++         switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5];
+      }
+  
+      bb1: {
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb4;
+      }
+  
+      bb2: {
+          _1 = const "A(Empty)";
+          goto -> bb4;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(Empty)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb5: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff
new file mode 100644
index 00000000000..3a2dc19db71
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff
@@ -0,0 +1,44 @@
+- // MIR for `otherwise_t2` before UninhabitedEnumBranching
++ // MIR for `otherwise_t2` after UninhabitedEnumBranching
+  
+  fn otherwise_t2() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test2;
+      let mut _3: isize;
+      let _4: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test2::D;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [4: bb2, otherwise: bb1];
++         switchInt(move _3) -> [4: bb2, 5: bb1, otherwise: bb4];
+      }
+  
+      bb1: {
+          StorageLive(_4);
+          _4 = const "E";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb3;
+      }
+  
+      bb2: {
+          _1 = const "D";
+          goto -> bb3;
+      }
+  
+      bb3: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb4: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..3a2dc19db71
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,44 @@
+- // MIR for `otherwise_t2` before UninhabitedEnumBranching
++ // MIR for `otherwise_t2` after UninhabitedEnumBranching
+  
+  fn otherwise_t2() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test2;
+      let mut _3: isize;
+      let _4: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test2::D;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [4: bb2, otherwise: bb1];
++         switchInt(move _3) -> [4: bb2, 5: bb1, otherwise: bb4];
+      }
+  
+      bb1: {
+          StorageLive(_4);
+          _4 = const "E";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb3;
+      }
+  
+      bb2: {
+          _1 = const "D";
+          goto -> bb3;
+      }
+  
+      bb3: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb4: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff
new file mode 100644
index 00000000000..5dc1e2b73f6
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff
@@ -0,0 +1,53 @@
+- // MIR for `otherwise_t3` before UninhabitedEnumBranching
++ // MIR for `otherwise_t3` after UninhabitedEnumBranching
+  
+  fn otherwise_t3() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test3;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test3::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
++         switchInt(move _3) -> [0: bb5, 1: bb5, otherwise: bb1];
+      }
+  
+      bb1: {
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb4;
+      }
+  
+      bb2: {
+          _1 = const "A(Empty)";
+          goto -> bb4;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(Empty)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb5: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..5dc1e2b73f6
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,53 @@
+- // MIR for `otherwise_t3` before UninhabitedEnumBranching
++ // MIR for `otherwise_t3` after UninhabitedEnumBranching
+  
+  fn otherwise_t3() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test3;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test3::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
++         switchInt(move _3) -> [0: bb5, 1: bb5, otherwise: bb1];
+      }
+  
+      bb1: {
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb4;
+      }
+  
+      bb2: {
+          _1 = const "A(Empty)";
+          goto -> bb4;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(Empty)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb5: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff
new file mode 100644
index 00000000000..1352dda4971
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff
@@ -0,0 +1,48 @@
+- // MIR for `otherwise_t4` before UninhabitedEnumBranching
++ // MIR for `otherwise_t4` after UninhabitedEnumBranching
+  
+  fn otherwise_t4() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test4;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test4::C;
+          _3 = discriminant(_2);
+          switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
+      }
+  
+      bb1: {
+          StorageLive(_5);
+          _5 = const "CD";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb4;
+      }
+  
+      bb2: {
+          _1 = const "A(i32)";
+          goto -> bb4;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(i32)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..1352dda4971
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,48 @@
+- // MIR for `otherwise_t4` before UninhabitedEnumBranching
++ // MIR for `otherwise_t4` after UninhabitedEnumBranching
+  
+  fn otherwise_t4() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test4;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test4::C;
+          _3 = discriminant(_2);
+          switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
+      }
+  
+      bb1: {
+          StorageLive(_5);
+          _5 = const "CD";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb4;
+      }
+  
+      bb2: {
+          _1 = const "A(i32)";
+          goto -> bb4;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(i32)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff
new file mode 100644
index 00000000000..40dd961fbac
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff
@@ -0,0 +1,62 @@
+- // MIR for `otherwise_t4_uninhabited_default` before UninhabitedEnumBranching
++ // MIR for `otherwise_t4_uninhabited_default` after UninhabitedEnumBranching
+  
+  fn otherwise_t4_uninhabited_default() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test4;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+      let _6: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test4::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1];
++         switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: bb6];
+      }
+  
+      bb1: {
+          StorageLive(_6);
+          _6 = const "D";
+          _1 = &(*_6);
+          StorageDead(_6);
+          goto -> bb5;
+      }
+  
+      bb2: {
+          _1 = const "A(i32)";
+          goto -> bb5;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(i32)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb5;
+      }
+  
+      bb4: {
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb5;
+      }
+  
+      bb5: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb6: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..40dd961fbac
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,62 @@
+- // MIR for `otherwise_t4_uninhabited_default` before UninhabitedEnumBranching
++ // MIR for `otherwise_t4_uninhabited_default` after UninhabitedEnumBranching
+  
+  fn otherwise_t4_uninhabited_default() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test4;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+      let _6: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test4::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1];
++         switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: bb6];
+      }
+  
+      bb1: {
+          StorageLive(_6);
+          _6 = const "D";
+          _1 = &(*_6);
+          StorageDead(_6);
+          goto -> bb5;
+      }
+  
+      bb2: {
+          _1 = const "A(i32)";
+          goto -> bb5;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(i32)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb5;
+      }
+  
+      bb4: {
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb5;
+      }
+  
+      bb5: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb6: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff
new file mode 100644
index 00000000000..ac39f6be6c6
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff
@@ -0,0 +1,75 @@
+- // MIR for `otherwise_t4_uninhabited_default_2` before UninhabitedEnumBranching
++ // MIR for `otherwise_t4_uninhabited_default_2` after UninhabitedEnumBranching
+  
+  fn otherwise_t4_uninhabited_default_2() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test4;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+      let _6: &str;
+      let _7: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test4::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, otherwise: bb1];
++         switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: bb8];
+      }
+  
+      bb1: {
+          StorageLive(_7);
+          _7 = const "A(other)D";
+          _1 = &(*_7);
+          StorageDead(_7);
+          goto -> bb7;
+      }
+  
+      bb2: {
+          switchInt(((_2 as A).0: i32)) -> [1: bb3, 2: bb4, otherwise: bb1];
+      }
+  
+      bb3: {
+          _1 = const "A(1)";
+          goto -> bb7;
+      }
+  
+      bb4: {
+          StorageLive(_4);
+          _4 = const "A(2)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb7;
+      }
+  
+      bb5: {
+          StorageLive(_5);
+          _5 = const "B(i32)";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb7;
+      }
+  
+      bb6: {
+          StorageLive(_6);
+          _6 = const "C";
+          _1 = &(*_6);
+          StorageDead(_6);
+          goto -> bb7;
+      }
+  
+      bb7: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb8: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..ac39f6be6c6
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,75 @@
+- // MIR for `otherwise_t4_uninhabited_default_2` before UninhabitedEnumBranching
++ // MIR for `otherwise_t4_uninhabited_default_2` after UninhabitedEnumBranching
+  
+  fn otherwise_t4_uninhabited_default_2() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test4;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+      let _6: &str;
+      let _7: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test4::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, otherwise: bb1];
++         switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: bb8];
+      }
+  
+      bb1: {
+          StorageLive(_7);
+          _7 = const "A(other)D";
+          _1 = &(*_7);
+          StorageDead(_7);
+          goto -> bb7;
+      }
+  
+      bb2: {
+          switchInt(((_2 as A).0: i32)) -> [1: bb3, 2: bb4, otherwise: bb1];
+      }
+  
+      bb3: {
+          _1 = const "A(1)";
+          goto -> bb7;
+      }
+  
+      bb4: {
+          StorageLive(_4);
+          _4 = const "A(2)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb7;
+      }
+  
+      bb5: {
+          StorageLive(_5);
+          _5 = const "B(i32)";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb7;
+      }
+  
+      bb6: {
+          StorageLive(_6);
+          _6 = const "C";
+          _1 = &(*_6);
+          StorageDead(_6);
+          goto -> bb7;
+      }
+  
+      bb7: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb8: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff
new file mode 100644
index 00000000000..8180428a6f4
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff
@@ -0,0 +1,66 @@
+- // MIR for `otherwise_t5_uninhabited_default` before UninhabitedEnumBranching
++ // MIR for `otherwise_t5_uninhabited_default` after UninhabitedEnumBranching
+  
+  fn otherwise_t5_uninhabited_default() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test5<T>;
+      let mut _3: i8;
+      let _4: &str;
+      let _5: &str;
+      let _6: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test5::<T>::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, otherwise: bb1];
++         switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: bb7];
+      }
+  
+      bb1: {
+          StorageLive(_6);
+          _6 = const "D";
+          _1 = &(*_6);
+          StorageDead(_6);
+          goto -> bb5;
+      }
+  
+      bb2: {
+          _1 = const "A(T)";
+          goto -> bb5;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(T)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb5;
+      }
+  
+      bb4: {
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb5;
+      }
+  
+      bb5: {
+          drop(_2) -> [return: bb6, unwind unreachable];
+      }
+  
+      bb6: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb7: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..b13d5816aed
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,70 @@
+- // MIR for `otherwise_t5_uninhabited_default` before UninhabitedEnumBranching
++ // MIR for `otherwise_t5_uninhabited_default` after UninhabitedEnumBranching
+  
+  fn otherwise_t5_uninhabited_default() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test5<T>;
+      let mut _3: i8;
+      let _4: &str;
+      let _5: &str;
+      let _6: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test5::<T>::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, otherwise: bb1];
++         switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: bb8];
+      }
+  
+      bb1: {
+          StorageLive(_6);
+          _6 = const "D";
+          _1 = &(*_6);
+          StorageDead(_6);
+          goto -> bb5;
+      }
+  
+      bb2: {
+          _1 = const "A(T)";
+          goto -> bb5;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(T)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb5;
+      }
+  
+      bb4: {
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb5;
+      }
+  
+      bb5: {
+          drop(_2) -> [return: bb6, unwind: bb7];
+      }
+  
+      bb6: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
+      }
+  
+      bb7 (cleanup): {
+          resume;
++     }
++ 
++     bb8: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.rs b/tests/mir-opt/uninhabited_enum_branching.rs
index 08eca57afc6..6de001be979 100644
--- a/tests/mir-opt/uninhabited_enum_branching.rs
+++ b/tests/mir-opt/uninhabited_enum_branching.rs
@@ -1,4 +1,6 @@
 //@ unit-test: UninhabitedEnumBranching
+// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+
 enum Empty {}
 
 // test matching an enum with uninhabited variants
@@ -23,6 +25,21 @@ enum Test3 {
     D,
 }
 
+enum Test4 {
+    A(i32),
+    B(i32),
+    C,
+    D,
+}
+
+#[repr(i8)]
+enum Test5<T> {
+    A(T) = -1,
+    B(T) = 0,
+    C = 5,
+    D = 3,
+}
+
 struct Plop {
     xx: u32,
     test3: Test3,
@@ -46,8 +63,8 @@ fn simple() {
 fn custom_discriminant() {
     // CHECK-LABEL: fn custom_discriminant(
     // CHECK: [[discr:_.*]] = discriminant(
-    // CHECK: switchInt(move [[discr]]) -> [4: bb3, 5: bb2, otherwise: bb5];
-    // CHECK: bb5: {
+    // CHECK: switchInt(move [[discr]]) -> [4: bb3, 5: bb2, otherwise: [[unreachable:bb.*]]];
+    // CHECK: [[unreachable]]: {
     // CHECK-NEXT: unreachable;
     match Test2::D {
         Test2::D => "D",
@@ -55,6 +72,111 @@ fn custom_discriminant() {
     };
 }
 
+// EMIT_MIR uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.diff
+fn otherwise_t1() {
+    // CHECK-LABEL: fn otherwise_t1(
+    // CHECK: [[discr:_.*]] = discriminant(
+    // CHECK: switchInt(move [[discr]]) -> [0: bb5, 1: bb5, 2: bb1, otherwise: [[unreachable:bb.*]]];
+    // CHECK: [[unreachable]]: {
+    // CHECK-NEXT: unreachable;
+    match Test1::C {
+        Test1::A(_) => "A(Empty)",
+        Test1::B(_) => "B(Empty)",
+        _ => "C",
+    };
+}
+
+// EMIT_MIR uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.diff
+fn otherwise_t2() {
+    // CHECK-LABEL: fn otherwise_t2(
+    // CHECK: [[discr:_.*]] = discriminant(
+    // CHECK: switchInt(move [[discr]]) -> [4: bb2, 5: bb1, otherwise: [[unreachable:bb.*]]];
+    // CHECK: [[unreachable]]: {
+    // CHECK-NEXT: unreachable;
+    match Test2::D {
+        Test2::D => "D",
+        _ => "E",
+    };
+}
+
+// EMIT_MIR uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.diff
+fn otherwise_t3() {
+    // CHECK-LABEL: fn otherwise_t3(
+    // CHECK: [[discr:_.*]] = discriminant(
+    // CHECK: switchInt(move [[discr]]) -> [0: bb5, 1: bb5, otherwise: bb1];
+    // CHECK: bb1: {
+    // CHECK-NOT: unreachable;
+    // CHECK: }
+    // CHECK: bb5: {
+    // CHECK-NEXT: unreachable;
+    match Test3::C {
+        Test3::A(_) => "A(Empty)",
+        Test3::B(_) => "B(Empty)",
+        _ => "C",
+    };
+}
+
+// EMIT_MIR uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.diff
+fn otherwise_t4_uninhabited_default() {
+    // CHECK-LABEL: fn otherwise_t4_uninhabited_default(
+    // CHECK: [[discr:_.*]] = discriminant(
+    // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: [[unreachable:bb.*]]];
+    // CHECK: [[unreachable]]: {
+    // CHECK-NEXT: unreachable;
+    match Test4::C {
+        Test4::A(_) => "A(i32)",
+        Test4::B(_) => "B(i32)",
+        Test4::C => "C",
+        _ => "D",
+    };
+}
+
+// EMIT_MIR uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.diff
+fn otherwise_t4_uninhabited_default_2() {
+    // CHECK-LABEL: fn otherwise_t4_uninhabited_default_2(
+    // CHECK: [[discr:_.*]] = discriminant(
+    // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: [[unreachable:bb.*]]];
+    // CHECK: [[unreachable]]: {
+    // CHECK-NEXT: unreachable;
+    match Test4::C {
+        Test4::A(1) => "A(1)",
+        Test4::A(2) => "A(2)",
+        Test4::B(_) => "B(i32)",
+        Test4::C => "C",
+        _ => "A(other)D",
+    };
+}
+
+// EMIT_MIR uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.diff
+fn otherwise_t4() {
+    // CHECK-LABEL: fn otherwise_t4(
+    // CHECK: [[discr:_.*]] = discriminant(
+    // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb3, otherwise: [[unreachable:bb.*]]];
+    // CHECK: [[unreachable]]: {
+    // CHECK-NOT: unreachable;
+    // CHECK: }
+    match Test4::C {
+        Test4::A(_) => "A(i32)",
+        Test4::B(_) => "B(i32)",
+        _ => "CD",
+    };
+}
+
+// EMIT_MIR uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.diff
+fn otherwise_t5_uninhabited_default<T>() {
+    // CHECK-LABEL: fn otherwise_t5_uninhabited_default(
+    // CHECK: [[discr:_.*]] = discriminant(
+    // CHECK: switchInt(move [[discr]]) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: [[unreachable:bb.*]]];
+    // CHECK: [[unreachable]]: {
+    // CHECK-NEXT: unreachable;
+    match Test5::<T>::C {
+        Test5::A(_) => "A(T)",
+        Test5::B(_) => "B(T)",
+        Test5::C => "C",
+        _ => "D",
+    };
+}
+
 // EMIT_MIR uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff
 fn byref() {
     // CHECK-LABEL: fn byref(
@@ -69,6 +191,9 @@ fn byref() {
         Test3::D => "D",
     };
 
+    // CHECK: [[unreachable]]: {
+    // CHECK-NEXT: unreachable;
+
     // CHECK: [[discr:_.*]] = discriminant(
     // CHECK: switchInt(move [[discr]]) -> [0: [[unreachable]], 1: [[unreachable]], 2: bb10, 3: bb7, otherwise: [[unreachable]]];
     match plop.test3 {
@@ -77,13 +202,17 @@ fn byref() {
         Test3::C => "C",
         Test3::D => "D",
     };
-
-    // CHECK: [[unreachable]]: {
-    // CHECK-NEXT: unreachable;
 }
 
 fn main() {
     simple();
     custom_discriminant();
+    otherwise_t1();
+    otherwise_t2();
+    otherwise_t3();
+    otherwise_t4_uninhabited_default();
+    otherwise_t4_uninhabited_default_2();
+    otherwise_t4();
+    otherwise_t5_uninhabited_default::<i32>();
     byref();
 }
diff --git a/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff
index 6ce61e15287..674d3a25504 100644
--- a/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.diff
+++ b/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff
@@ -15,7 +15,7 @@
           _2 = Test1::C;
           _3 = discriminant(_2);
 -         switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb2, otherwise: bb1];
-+         switchInt(move _3) -> [0: bb6, 1: bb6, 2: bb2, otherwise: bb6];
++         switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -48,10 +48,6 @@
           StorageDead(_1);
           _0 = const ();
           return;
-+     }
-+ 
-+     bb6: {
-+         unreachable;
       }
   }
   
diff --git a/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..674d3a25504
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,53 @@
+- // MIR for `simple` before UninhabitedEnumBranching
++ // MIR for `simple` after UninhabitedEnumBranching
+  
+  fn simple() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test1;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test1::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb2, otherwise: bb1];
++         switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1];
+      }
+  
+      bb1: {
+          unreachable;
+      }
+  
+      bb2: {
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb5;
+      }
+  
+      bb3: {
+          _1 = const "A(Empty)";
+          goto -> bb5;
+      }
+  
+      bb4: {
+          StorageLive(_4);
+          _4 = const "B(Empty)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb5;
+      }
+  
+      bb5: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff
index 79948139f88..28a8c251d95 100644
--- a/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff
+++ b/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff
@@ -9,7 +9,7 @@
       bb0: {
           _2 = discriminant(_1);
 -         switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1];
-+         switchInt(move _2) -> [0: bb5, 1: bb3, otherwise: bb1];
++         switchInt(move _2) -> [0: bb5, 1: bb3, 2: bb1, otherwise: bb5];
       }
   
       bb1: {