about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/codegen/enum/enum-early-otherwise-branch.rs26
-rw-r--r--tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff39
-rw-r--r--tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff57
-rw-r--r--tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff105
-rw-r--r--tests/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff107
-rw-r--r--tests/mir-opt/early_otherwise_branch.rs63
-rw-r--r--tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff91
-rw-r--r--tests/mir-opt/early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff141
-rw-r--r--tests/mir-opt/early_otherwise_branch_3_element_tuple.rs37
-rw-r--r--tests/mir-opt/early_otherwise_branch_68867.rs9
-rw-r--r--tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff6
-rw-r--r--tests/mir-opt/early_otherwise_branch_noopt.rs9
-rw-r--r--tests/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff8
-rw-r--r--tests/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff8
-rw-r--r--tests/mir-opt/early_otherwise_branch_soundness.rs16
15 files changed, 563 insertions, 159 deletions
diff --git a/tests/codegen/enum/enum-early-otherwise-branch.rs b/tests/codegen/enum/enum-early-otherwise-branch.rs
new file mode 100644
index 00000000000..6c7548912da
--- /dev/null
+++ b/tests/codegen/enum/enum-early-otherwise-branch.rs
@@ -0,0 +1,26 @@
+//@ compile-flags: -O
+//@ min-llvm-version: 18
+
+#![crate_type = "lib"]
+
+pub enum Enum {
+    A(u32),
+    B(u32),
+    C(u32),
+}
+
+#[no_mangle]
+pub fn foo(lhs: &Enum, rhs: &Enum) -> bool {
+    // CHECK-LABEL: define{{.*}}i1 @foo(
+    // CHECK-NOT: switch
+    // CHECK-NOT: br
+    // CHECK: [[SELECT:%.*]] = select
+    // CHECK-NEXT: ret i1 [[SELECT]]
+    // CHECK-NEXT: }
+    match (lhs, rhs) {
+        (Enum::A(lhs), Enum::A(rhs)) => lhs == rhs,
+        (Enum::B(lhs), Enum::B(rhs)) => lhs == rhs,
+        (Enum::C(lhs), Enum::C(rhs)) => lhs == rhs,
+        _ => false,
+    }
+}
diff --git a/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
index 7a374c5675a..4af3ed3e1d1 100644
--- a/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
@@ -12,8 +12,6 @@
       let mut _7: isize;
       let _8: u32;
       let _9: u32;
-+     let mut _10: isize;
-+     let mut _11: bool;
       scope 1 {
           debug a => _8;
           debug b => _9;
@@ -29,28 +27,20 @@
           StorageDead(_5);
           StorageDead(_4);
           _7 = discriminant((_3.0: std::option::Option<u32>));
--         switchInt(move _7) -> [1: bb2, otherwise: bb1];
-+         StorageLive(_10);
-+         _10 = discriminant((_3.1: std::option::Option<u32>));
-+         StorageLive(_11);
-+         _11 = Ne(_7, move _10);
-+         StorageDead(_10);
-+         switchInt(move _11) -> [0: bb4, otherwise: bb1];
+          switchInt(move _7) -> [1: bb2, 0: bb1, otherwise: bb5];
       }
   
       bb1: {
-+         StorageDead(_11);
           _0 = const 1_u32;
--         goto -> bb4;
-+         goto -> bb3;
+          goto -> bb4;
       }
   
       bb2: {
--         _6 = discriminant((_3.1: std::option::Option<u32>));
--         switchInt(move _6) -> [1: bb3, otherwise: bb1];
--     }
-- 
--     bb3: {
+          _6 = discriminant((_3.1: std::option::Option<u32>));
+          switchInt(move _6) -> [1: bb3, 0: bb1, otherwise: bb5];
+      }
+  
+      bb3: {
           StorageLive(_8);
           _8 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
           StorageLive(_9);
@@ -58,19 +48,16 @@
           _0 = const 0_u32;
           StorageDead(_9);
           StorageDead(_8);
--         goto -> bb4;
-+         goto -> bb3;
+          goto -> bb4;
       }
   
--     bb4: {
-+     bb3: {
+      bb4: {
           StorageDead(_3);
           return;
-+     }
-+ 
-+     bb4: {
-+         StorageDead(_11);
-+         switchInt(_7) -> [1: bb2, otherwise: bb1];
+      }
+  
+      bb5: {
+          unreachable;
       }
   }
   
diff --git a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
index 1348bdd739a..7776ff0fde7 100644
--- a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
@@ -13,8 +13,6 @@
       let mut _8: isize;
       let _9: u32;
       let _10: u32;
-+     let mut _11: isize;
-+     let mut _12: bool;
       scope 1 {
           debug a => _9;
           debug b => _10;
@@ -30,33 +28,25 @@
           StorageDead(_5);
           StorageDead(_4);
           _8 = discriminant((_3.0: std::option::Option<u32>));
--         switchInt(move _8) -> [0: bb3, 1: bb2, otherwise: bb1];
-+         StorageLive(_11);
-+         _11 = discriminant((_3.1: std::option::Option<u32>));
-+         StorageLive(_12);
-+         _12 = Ne(_8, move _11);
-+         StorageDead(_11);
-+         switchInt(move _12) -> [0: bb5, otherwise: bb1];
+          switchInt(move _8) -> [0: bb3, 1: bb2, otherwise: bb7];
       }
   
       bb1: {
-+         StorageDead(_12);
           _0 = const 1_u32;
--         goto -> bb6;
-+         goto -> bb4;
+          goto -> bb6;
       }
   
       bb2: {
--         _6 = discriminant((_3.1: std::option::Option<u32>));
--         switchInt(move _6) -> [1: bb4, otherwise: bb1];
--     }
-- 
--     bb3: {
--         _7 = discriminant((_3.1: std::option::Option<u32>));
--         switchInt(move _7) -> [0: bb5, otherwise: bb1];
--     }
-- 
--     bb4: {
+          _6 = discriminant((_3.1: std::option::Option<u32>));
+          switchInt(move _6) -> [1: bb4, 0: bb1, otherwise: bb7];
+      }
+  
+      bb3: {
+          _7 = discriminant((_3.1: std::option::Option<u32>));
+          switchInt(move _7) -> [0: bb5, 1: bb1, otherwise: bb7];
+      }
+  
+      bb4: {
           StorageLive(_9);
           _9 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
           StorageLive(_10);
@@ -64,26 +54,21 @@
           _0 = const 0_u32;
           StorageDead(_10);
           StorageDead(_9);
--         goto -> bb6;
-+         goto -> bb4;
+          goto -> bb6;
       }
   
--     bb5: {
-+     bb3: {
-          _0 = const 0_u32;
--         goto -> bb6;
-+         goto -> bb4;
+      bb5: {
+          _0 = const 2_u32;
+          goto -> bb6;
       }
   
--     bb6: {
-+     bb4: {
+      bb6: {
           StorageDead(_3);
           return;
-+     }
-+ 
-+     bb5: {
-+         StorageDead(_12);
-+         switchInt(_8) -> [0: bb3, 1: bb2, otherwise: bb1];
+      }
+  
+      bb7: {
+          unreachable;
       }
   }
   
diff --git a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
index e058c409cb5..b41e952d80f 100644
--- a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
@@ -1,76 +1,107 @@
 - // MIR for `opt3` before EarlyOtherwiseBranch
 + // MIR for `opt3` after EarlyOtherwiseBranch
   
-  fn opt3(_1: Option<u32>, _2: Option<bool>) -> u32 {
+  fn opt3(_1: Option2<u32>, _2: Option2<bool>) -> u32 {
       debug x => _1;
       debug y => _2;
       let mut _0: u32;
-      let mut _3: (std::option::Option<u32>, std::option::Option<bool>);
-      let mut _4: std::option::Option<u32>;
-      let mut _5: std::option::Option<bool>;
+      let mut _3: (Option2<u32>, Option2<bool>);
+      let mut _4: Option2<u32>;
+      let mut _5: Option2<bool>;
       let mut _6: isize;
       let mut _7: isize;
-      let _8: u32;
-      let _9: bool;
-+     let mut _10: isize;
-+     let mut _11: bool;
+      let mut _8: isize;
+      let mut _9: isize;
+      let _10: u32;
+      let _11: bool;
++     let mut _12: isize;
++     let mut _13: bool;
       scope 1 {
-          debug a => _8;
-          debug b => _9;
+          debug a => _10;
+          debug b => _11;
       }
   
       bb0: {
           StorageLive(_3);
           StorageLive(_4);
-          _4 = _1;
+          _4 = move _1;
           StorageLive(_5);
-          _5 = _2;
+          _5 = move _2;
           _3 = (move _4, move _5);
           StorageDead(_5);
           StorageDead(_4);
-          _7 = discriminant((_3.0: std::option::Option<u32>));
--         switchInt(move _7) -> [1: bb2, otherwise: bb1];
-+         StorageLive(_10);
-+         _10 = discriminant((_3.1: std::option::Option<bool>));
-+         StorageLive(_11);
-+         _11 = Ne(_7, move _10);
-+         StorageDead(_10);
-+         switchInt(move _11) -> [0: bb4, otherwise: bb1];
+          _9 = discriminant((_3.0: Option2<u32>));
+-         switchInt(move _9) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb9];
++         StorageLive(_12);
++         _12 = discriminant((_3.1: Option2<bool>));
++         StorageLive(_13);
++         _13 = Ne(_9, move _12);
++         StorageDead(_12);
++         switchInt(move _13) -> [0: bb7, otherwise: bb1];
       }
   
       bb1: {
-+         StorageDead(_11);
++         StorageDead(_13);
           _0 = const 1_u32;
--         goto -> bb4;
-+         goto -> bb3;
+-         goto -> bb8;
++         goto -> bb5;
       }
   
       bb2: {
--         _6 = discriminant((_3.1: std::option::Option<bool>));
--         switchInt(move _6) -> [1: bb3, otherwise: bb1];
+-         _6 = discriminant((_3.1: Option2<bool>));
+-         switchInt(move _6) -> [0: bb5, otherwise: bb1];
 -     }
 - 
 -     bb3: {
-          StorageLive(_8);
-          _8 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
-          StorageLive(_9);
-          _9 = (((_3.1: std::option::Option<bool>) as Some).0: bool);
+-         _7 = discriminant((_3.1: Option2<bool>));
+-         switchInt(move _7) -> [1: bb6, otherwise: bb1];
+-     }
+- 
+-     bb4: {
+-         _8 = discriminant((_3.1: Option2<bool>));
+-         switchInt(move _8) -> [2: bb7, otherwise: bb1];
+-     }
+- 
+-     bb5: {
+          StorageLive(_10);
+          _10 = (((_3.0: Option2<u32>) as Some).0: u32);
+          StorageLive(_11);
+          _11 = (((_3.1: Option2<bool>) as Some).0: bool);
           _0 = const 0_u32;
-          StorageDead(_9);
-          StorageDead(_8);
--         goto -> bb4;
-+         goto -> bb3;
+          StorageDead(_11);
+          StorageDead(_10);
+-         goto -> bb8;
++         goto -> bb5;
       }
   
--     bb4: {
+-     bb6: {
 +     bb3: {
+          _0 = const 2_u32;
+-         goto -> bb8;
++         goto -> bb5;
+      }
+  
+-     bb7: {
++     bb4: {
+          _0 = const 3_u32;
+-         goto -> bb8;
++         goto -> bb5;
+      }
+  
+-     bb8: {
++     bb5: {
           StorageDead(_3);
           return;
+      }
+  
+-     bb9: {
++     bb6: {
+          unreachable;
 +     }
 + 
-+     bb4: {
-+         StorageDead(_11);
-+         switchInt(_7) -> [1: bb2, otherwise: bb1];
++     bb7: {
++         StorageDead(_13);
++         switchInt(_9) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb6];
       }
   }
   
diff --git a/tests/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff
new file mode 100644
index 00000000000..18dea56f430
--- /dev/null
+++ b/tests/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff
@@ -0,0 +1,107 @@
+- // MIR for `opt4` before EarlyOtherwiseBranch
++ // MIR for `opt4` after EarlyOtherwiseBranch
+  
+  fn opt4(_1: Option2<u32>, _2: Option2<u32>) -> u32 {
+      debug x => _1;
+      debug y => _2;
+      let mut _0: u32;
+      let mut _3: (Option2<u32>, Option2<u32>);
+      let mut _4: Option2<u32>;
+      let mut _5: Option2<u32>;
+      let mut _6: isize;
+      let mut _7: isize;
+      let mut _8: isize;
+      let mut _9: isize;
+      let _10: u32;
+      let _11: u32;
++     let mut _12: isize;
++     let mut _13: bool;
+      scope 1 {
+          debug a => _10;
+          debug b => _11;
+      }
+  
+      bb0: {
+          StorageLive(_3);
+          StorageLive(_4);
+          _4 = move _1;
+          StorageLive(_5);
+          _5 = move _2;
+          _3 = (move _4, move _5);
+          StorageDead(_5);
+          StorageDead(_4);
+          _9 = discriminant((_3.0: Option2<u32>));
+-         switchInt(move _9) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb9];
++         StorageLive(_12);
++         _12 = discriminant((_3.1: Option2<u32>));
++         StorageLive(_13);
++         _13 = Ne(_9, move _12);
++         StorageDead(_12);
++         switchInt(move _13) -> [0: bb7, otherwise: bb1];
+      }
+  
+      bb1: {
++         StorageDead(_13);
+          _0 = const 1_u32;
+-         goto -> bb8;
++         goto -> bb5;
+      }
+  
+      bb2: {
+-         _6 = discriminant((_3.1: Option2<u32>));
+-         switchInt(move _6) -> [0: bb5, otherwise: bb1];
+-     }
+- 
+-     bb3: {
+-         _7 = discriminant((_3.1: Option2<u32>));
+-         switchInt(move _7) -> [1: bb6, otherwise: bb1];
+-     }
+- 
+-     bb4: {
+-         _8 = discriminant((_3.1: Option2<u32>));
+-         switchInt(move _8) -> [2: bb7, otherwise: bb1];
+-     }
+- 
+-     bb5: {
+          StorageLive(_10);
+          _10 = (((_3.0: Option2<u32>) as Some).0: u32);
+          StorageLive(_11);
+          _11 = (((_3.1: Option2<u32>) as Some).0: u32);
+          _0 = const 0_u32;
+          StorageDead(_11);
+          StorageDead(_10);
+-         goto -> bb8;
++         goto -> bb5;
+      }
+  
+-     bb6: {
++     bb3: {
+          _0 = const 2_u32;
+-         goto -> bb8;
++         goto -> bb5;
+      }
+  
+-     bb7: {
++     bb4: {
+          _0 = const 3_u32;
+-         goto -> bb8;
++         goto -> bb5;
+      }
+  
+-     bb8: {
++     bb5: {
+          StorageDead(_3);
+          return;
+      }
+  
+-     bb9: {
++     bb6: {
+          unreachable;
++     }
++ 
++     bb7: {
++         StorageDead(_13);
++         switchInt(_9) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb6];
+      }
+  }
+  
diff --git a/tests/mir-opt/early_otherwise_branch.rs b/tests/mir-opt/early_otherwise_branch.rs
index c984c271ccd..bfeb1f7bbc6 100644
--- a/tests/mir-opt/early_otherwise_branch.rs
+++ b/tests/mir-opt/early_otherwise_branch.rs
@@ -1,27 +1,79 @@
-// skip-filecheck
 //@ unit-test: EarlyOtherwiseBranch
+//@ compile-flags: -Zmir-enable-passes=+UnreachableEnumBranching
+
+enum Option2<T> {
+    Some(T),
+    None,
+    Other,
+}
+
+// We can't optimize it because y may be an invalid value.
 // EMIT_MIR early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
 fn opt1(x: Option<u32>, y: Option<u32>) -> u32 {
+    // CHECK-LABEL: fn opt1(
+    // CHECK: bb0: {
+    // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}});
+    // CHECK-NOT: Ne
+    // CHECK-NOT: discriminant
+    // CHECK: switchInt(move [[LOCAL1]]) -> [
+    // CHECK-NEXT: }
     match (x, y) {
         (Some(a), Some(b)) => 0,
         _ => 1,
     }
 }
 
+// FIXME: `switchInt` will have three targets after `UnreachableEnumBranching`,
+// otherwise is unreachable. We can consume the UB fact to transform back to if else pattern.
 // EMIT_MIR early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
 fn opt2(x: Option<u32>, y: Option<u32>) -> u32 {
+    // CHECK-LABEL: fn opt2(
+    // CHECK: bb0: {
+    // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}});
+    // CHECK-NOT: Ne
+    // CHECK-NOT: discriminant
+    // CHECK: switchInt(move [[LOCAL1]]) -> [
+    // CHECK-NEXT: }
     match (x, y) {
         (Some(a), Some(b)) => 0,
-        (None, None) => 0,
+        (None, None) => 2,
         _ => 1,
     }
 }
 
 // optimize despite different types
 // EMIT_MIR early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
-fn opt3(x: Option<u32>, y: Option<bool>) -> u32 {
+fn opt3(x: Option2<u32>, y: Option2<bool>) -> u32 {
+    // CHECK-LABEL: fn opt3(
+    // CHECK: let mut [[CMP_LOCAL:_.*]]: bool;
+    // CHECK: bb0: {
+    // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}});
+    // CHECK: [[LOCAL2:_.*]] = discriminant({{.*}});
+    // CHECK: [[CMP_LOCAL]] = Ne([[LOCAL1]], move [[LOCAL2]]);
+    // CHECK: switchInt(move [[CMP_LOCAL]]) -> [
+    // CHECK-NEXT: }
     match (x, y) {
-        (Some(a), Some(b)) => 0,
+        (Option2::Some(a), Option2::Some(b)) => 0,
+        (Option2::None, Option2::None) => 2,
+        (Option2::Other, Option2::Other) => 3,
+        _ => 1,
+    }
+}
+
+// EMIT_MIR early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff
+fn opt4(x: Option2<u32>, y: Option2<u32>) -> u32 {
+    // CHECK-LABEL: fn opt4(
+    // CHECK: let mut [[CMP_LOCAL:_.*]]: bool;
+    // CHECK: bb0: {
+    // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}});
+    // CHECK: [[LOCAL2:_.*]] = discriminant({{.*}});
+    // CHECK: [[CMP_LOCAL]] = Ne([[LOCAL1]], move [[LOCAL2]]);
+    // CHECK: switchInt(move [[CMP_LOCAL]]) -> [
+    // CHECK-NEXT: }
+    match (x, y) {
+        (Option2::Some(a), Option2::Some(b)) => 0,
+        (Option2::None, Option2::None) => 2,
+        (Option2::Other, Option2::Other) => 3,
         _ => 1,
     }
 }
@@ -29,5 +81,6 @@ fn opt3(x: Option<u32>, y: Option<bool>) -> u32 {
 fn main() {
     opt1(None, Some(0));
     opt2(None, Some(0));
-    opt3(None, Some(false));
+    opt3(Option2::None, Option2::Some(false));
+    opt4(Option2::None, Option2::Some(0));
 }
diff --git a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
index f98d68e6ffc..4c3c717b522 100644
--- a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
@@ -13,17 +13,15 @@
       let mut _8: isize;
       let mut _9: isize;
       let mut _10: isize;
-      let _11: u32;
-      let _12: u32;
+      let mut _11: isize;
+      let mut _12: isize;
       let _13: u32;
-+     let mut _14: isize;
-+     let mut _15: bool;
-+     let mut _16: isize;
-+     let mut _17: bool;
+      let _14: u32;
+      let _15: u32;
       scope 1 {
-          debug a => _11;
-          debug b => _12;
-          debug c => _13;
+          debug a => _13;
+          debug b => _14;
+          debug c => _15;
       }
   
       bb0: {
@@ -38,60 +36,61 @@
           StorageDead(_7);
           StorageDead(_6);
           StorageDead(_5);
-          _10 = discriminant((_4.0: std::option::Option<u32>));
--         switchInt(move _10) -> [1: bb2, otherwise: bb1];
-+         StorageLive(_14);
-+         _14 = discriminant((_4.1: std::option::Option<u32>));
-+         StorageLive(_15);
-+         _15 = Ne(_10, move _14);
-+         StorageDead(_14);
-+         switchInt(move _15) -> [0: bb5, otherwise: bb1];
+          _12 = discriminant((_4.0: std::option::Option<u32>));
+          switchInt(move _12) -> [0: bb4, 1: bb2, otherwise: bb9];
       }
   
       bb1: {
-+         StorageDead(_17);
-+         StorageDead(_15);
           _0 = const 1_u32;
--         goto -> bb5;
-+         goto -> bb4;
+          goto -> bb8;
       }
   
       bb2: {
--         _9 = discriminant((_4.1: std::option::Option<u32>));
--         switchInt(move _9) -> [1: bb3, otherwise: bb1];
--     }
-- 
--     bb3: {
+          _9 = discriminant((_4.1: std::option::Option<u32>));
+          switchInt(move _9) -> [1: bb3, 0: bb1, otherwise: bb9];
+      }
+  
+      bb3: {
           _8 = discriminant((_4.2: std::option::Option<u32>));
--         switchInt(move _8) -> [1: bb4, otherwise: bb1];
-+         switchInt(move _8) -> [1: bb3, otherwise: bb1];
+          switchInt(move _8) -> [1: bb6, 0: bb1, otherwise: bb9];
+      }
+  
+      bb4: {
+          _11 = discriminant((_4.1: std::option::Option<u32>));
+          switchInt(move _11) -> [0: bb5, 1: bb1, otherwise: bb9];
+      }
+  
+      bb5: {
+          _10 = discriminant((_4.2: std::option::Option<u32>));
+          switchInt(move _10) -> [0: bb7, 1: bb1, otherwise: bb9];
       }
   
--     bb4: {
-+     bb3: {
-          StorageLive(_11);
-          _11 = (((_4.0: std::option::Option<u32>) as Some).0: u32);
-          StorageLive(_12);
-          _12 = (((_4.1: std::option::Option<u32>) as Some).0: u32);
+      bb6: {
           StorageLive(_13);
-          _13 = (((_4.2: std::option::Option<u32>) as Some).0: u32);
+          _13 = (((_4.0: std::option::Option<u32>) as Some).0: u32);
+          StorageLive(_14);
+          _14 = (((_4.1: std::option::Option<u32>) as Some).0: u32);
+          StorageLive(_15);
+          _15 = (((_4.2: std::option::Option<u32>) as Some).0: u32);
           _0 = const 0_u32;
+          StorageDead(_15);
+          StorageDead(_14);
           StorageDead(_13);
-          StorageDead(_12);
-          StorageDead(_11);
--         goto -> bb5;
-+         goto -> bb4;
+          goto -> bb8;
+      }
+  
+      bb7: {
+          _0 = const 2_u32;
+          goto -> bb8;
       }
   
--     bb5: {
-+     bb4: {
+      bb8: {
           StorageDead(_4);
           return;
-+     }
-+ 
-+     bb5: {
-+         StorageDead(_15);
-+         switchInt(_10) -> [1: bb2, otherwise: bb1];
+      }
+  
+      bb9: {
+          unreachable;
       }
   }
   
diff --git a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff
new file mode 100644
index 00000000000..0ea7a10baaa
--- /dev/null
+++ b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff
@@ -0,0 +1,141 @@
+- // MIR for `opt2` before EarlyOtherwiseBranch
++ // MIR for `opt2` after EarlyOtherwiseBranch
+  
+  fn opt2(_1: Option2<u32>, _2: Option2<u32>, _3: Option2<u32>) -> u32 {
+      debug x => _1;
+      debug y => _2;
+      debug z => _3;
+      let mut _0: u32;
+      let mut _4: (Option2<u32>, Option2<u32>, Option2<u32>);
+      let mut _5: Option2<u32>;
+      let mut _6: Option2<u32>;
+      let mut _7: Option2<u32>;
+      let mut _8: isize;
+      let mut _9: isize;
+      let mut _10: isize;
+      let mut _11: isize;
+      let mut _12: isize;
+      let mut _13: isize;
+      let mut _14: isize;
+      let _15: u32;
+      let _16: u32;
+      let _17: u32;
++     let mut _18: isize;
++     let mut _19: bool;
+      scope 1 {
+          debug a => _15;
+          debug b => _16;
+          debug c => _17;
+      }
+  
+      bb0: {
+          StorageLive(_4);
+          StorageLive(_5);
+          _5 = move _1;
+          StorageLive(_6);
+          _6 = move _2;
+          StorageLive(_7);
+          _7 = move _3;
+          _4 = (move _5, move _6, move _7);
+          StorageDead(_7);
+          StorageDead(_6);
+          StorageDead(_5);
+          _14 = discriminant((_4.0: Option2<u32>));
+-         switchInt(move _14) -> [0: bb2, 1: bb4, 2: bb6, otherwise: bb12];
++         StorageLive(_18);
++         _18 = discriminant((_4.1: Option2<u32>));
++         StorageLive(_19);
++         _19 = Ne(_14, move _18);
++         StorageDead(_18);
++         switchInt(move _19) -> [0: bb10, otherwise: bb1];
+      }
+  
+      bb1: {
++         StorageDead(_19);
+          _0 = const 1_u32;
+-         goto -> bb11;
++         goto -> bb8;
+      }
+  
+      bb2: {
+-         _9 = discriminant((_4.1: Option2<u32>));
+-         switchInt(move _9) -> [0: bb3, otherwise: bb1];
+-     }
+- 
+-     bb3: {
+          _8 = discriminant((_4.2: Option2<u32>));
+-         switchInt(move _8) -> [0: bb8, otherwise: bb1];
++         switchInt(move _8) -> [0: bb5, otherwise: bb1];
+      }
+  
+-     bb4: {
+-         _11 = discriminant((_4.1: Option2<u32>));
+-         switchInt(move _11) -> [1: bb5, otherwise: bb1];
+-     }
+- 
+-     bb5: {
++     bb3: {
+          _10 = discriminant((_4.2: Option2<u32>));
+-         switchInt(move _10) -> [1: bb9, otherwise: bb1];
++         switchInt(move _10) -> [1: bb6, otherwise: bb1];
+      }
+  
+-     bb6: {
+-         _13 = discriminant((_4.1: Option2<u32>));
+-         switchInt(move _13) -> [2: bb7, otherwise: bb1];
+-     }
+- 
+-     bb7: {
++     bb4: {
+          _12 = discriminant((_4.2: Option2<u32>));
+-         switchInt(move _12) -> [2: bb10, otherwise: bb1];
++         switchInt(move _12) -> [2: bb7, otherwise: bb1];
+      }
+  
+-     bb8: {
++     bb5: {
+          StorageLive(_15);
+          _15 = (((_4.0: Option2<u32>) as Some).0: u32);
+          StorageLive(_16);
+          _16 = (((_4.1: Option2<u32>) as Some).0: u32);
+          StorageLive(_17);
+          _17 = (((_4.2: Option2<u32>) as Some).0: u32);
+          _0 = const 0_u32;
+          StorageDead(_17);
+          StorageDead(_16);
+          StorageDead(_15);
+-         goto -> bb11;
++         goto -> bb8;
+      }
+  
+-     bb9: {
++     bb6: {
+          _0 = const 2_u32;
+-         goto -> bb11;
++         goto -> bb8;
+      }
+  
+-     bb10: {
++     bb7: {
+          _0 = const 3_u32;
+-         goto -> bb11;
++         goto -> bb8;
+      }
+  
+-     bb11: {
++     bb8: {
+          StorageDead(_4);
+          return;
+      }
+  
+-     bb12: {
++     bb9: {
+          unreachable;
++     }
++ 
++     bb10: {
++         StorageDead(_19);
++         switchInt(_14) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb9];
+      }
+  }
+  
diff --git a/tests/mir-opt/early_otherwise_branch_3_element_tuple.rs b/tests/mir-opt/early_otherwise_branch_3_element_tuple.rs
index 32081347558..2d215621bbd 100644
--- a/tests/mir-opt/early_otherwise_branch_3_element_tuple.rs
+++ b/tests/mir-opt/early_otherwise_branch_3_element_tuple.rs
@@ -1,14 +1,49 @@
-// skip-filecheck
 //@ unit-test: EarlyOtherwiseBranch
+//@ compile-flags: -Zmir-enable-passes=+UnreachableEnumBranching
 
+enum Option2<T> {
+    Some(T),
+    None,
+    Other,
+}
+
+// FIXME: `switchInt` will have three targets after `UnreachableEnumBranching`,
+// otherwise is unreachable. We can consume the UB fact to transform back to if else pattern.
 // EMIT_MIR early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
 fn opt1(x: Option<u32>, y: Option<u32>, z: Option<u32>) -> u32 {
+    // CHECK-LABEL: fn opt1(
+    // CHECK: bb0: {
+    // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}});
+    // CHECK-NOT: Ne
+    // CHECK-NOT: discriminant
+    // CHECK: switchInt(move [[LOCAL1]]) -> [
+    // CHECK-NEXT: }
     match (x, y, z) {
         (Some(a), Some(b), Some(c)) => 0,
+        (None, None, None) => 2,
+        _ => 1,
+    }
+}
+
+// EMIT_MIR early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff
+fn opt2(x: Option2<u32>, y: Option2<u32>, z: Option2<u32>) -> u32 {
+    // CHECK-LABEL: fn opt2(
+    // CHECK: let mut [[CMP_LOCAL:_.*]]: bool;
+    // CHECK: bb0: {
+    // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}});
+    // CHECK: [[LOCAL2:_.*]] = discriminant({{.*}});
+    // CHECK: [[CMP_LOCAL]] = Ne([[LOCAL1]], move [[LOCAL2]]);
+    // CHECK: switchInt(move [[CMP_LOCAL]]) -> [
+    // CHECK-NEXT: }
+    match (x, y, z) {
+        (Option2::Some(a), Option2::Some(b), Option2::Some(c)) => 0,
+        (Option2::None, Option2::None, Option2::None) => 2,
+        (Option2::Other, Option2::Other, Option2::Other) => 3,
         _ => 1,
     }
 }
 
 fn main() {
     opt1(None, Some(0), None);
+    opt2(Option2::None, Option2::Some(0), Option2::None);
 }
diff --git a/tests/mir-opt/early_otherwise_branch_68867.rs b/tests/mir-opt/early_otherwise_branch_68867.rs
index 805d21533c5..59bc19ceecc 100644
--- a/tests/mir-opt/early_otherwise_branch_68867.rs
+++ b/tests/mir-opt/early_otherwise_branch_68867.rs
@@ -1,5 +1,5 @@
-// skip-filecheck
 //@ unit-test: EarlyOtherwiseBranch
+//@ compile-flags: -Zmir-enable-passes=+UnreachableEnumBranching
 
 // FIXME: This test was broken by the derefer change.
 
@@ -19,6 +19,13 @@ pub extern "C" fn try_sum(
     x: &ViewportPercentageLength,
     other: &ViewportPercentageLength,
 ) -> Result<ViewportPercentageLength, ()> {
+    // CHECK-LABEL: fn try_sum(
+    // CHECK: bb0: {
+    // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}});
+    // CHECK-NOT: Ne
+    // CHECK-NOT: discriminant
+    // CHECK: switchInt(move [[LOCAL1]]) -> [
+    // CHECK-NEXT: }
     use self::ViewportPercentageLength::*;
     Ok(match (x, other) {
         (&Vw(one), &Vw(other)) => Vw(one + other),
diff --git a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
index a5b5659a31a..de12fe8f120 100644
--- a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
@@ -78,7 +78,7 @@
           StorageDead(_5);
           _34 = deref_copy (_4.0: &ViewportPercentageLength);
           _11 = discriminant((*_34));
-          switchInt(move _11) -> [0: bb2, 1: bb3, 2: bb4, 3: bb5, otherwise: bb1];
+          switchInt(move _11) -> [0: bb2, 1: bb3, 2: bb4, 3: bb5, otherwise: bb12];
       }
   
       bb1: {
@@ -213,5 +213,9 @@
       bb11: {
           return;
       }
+  
+      bb12: {
+          unreachable;
+      }
   }
   
diff --git a/tests/mir-opt/early_otherwise_branch_noopt.rs b/tests/mir-opt/early_otherwise_branch_noopt.rs
index 648089e2df1..6b48393e6b9 100644
--- a/tests/mir-opt/early_otherwise_branch_noopt.rs
+++ b/tests/mir-opt/early_otherwise_branch_noopt.rs
@@ -1,11 +1,18 @@
-// skip-filecheck
 //@ unit-test: EarlyOtherwiseBranch
+//@ compile-flags: -Zmir-enable-passes=+UnreachableEnumBranching
 
 // must not optimize as it does not follow the pattern of
 // left and right hand side being the same variant
 
 // EMIT_MIR early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
 fn noopt1(x: Option<u32>, y: Option<u32>) -> u32 {
+    // CHECK-LABEL: fn noopt1(
+    // CHECK: bb0: {
+    // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}});
+    // CHECK-NOT: Ne
+    // CHECK-NOT: discriminant
+    // CHECK: switchInt(move [[LOCAL1]]) -> [
+    // CHECK-NEXT: }
     match (x, y) {
         (Some(a), Some(b)) => 0,
         (Some(a), None) => 1,
diff --git a/tests/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff
index b24ff6ec74b..8eab59823f4 100644
--- a/tests/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff
@@ -14,7 +14,7 @@
   
       bb0: {
           _3 = discriminant(_1);
-          switchInt(move _3) -> [1: bb2, otherwise: bb1];
+          switchInt(move _3) -> [1: bb2, 0: bb1, otherwise: bb6];
       }
   
       bb1: {
@@ -24,7 +24,7 @@
   
       bb2: {
           _4 = discriminant((*_2));
-          switchInt(move _4) -> [1: bb4, otherwise: bb3];
+          switchInt(move _4) -> [1: bb4, 0: bb3, otherwise: bb6];
       }
   
       bb3: {
@@ -43,5 +43,9 @@
       bb5: {
           return;
       }
+  
+      bb6: {
+          unreachable;
+      }
   }
   
diff --git a/tests/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff
index c3ea975ce03..6a4c947b882 100644
--- a/tests/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff
@@ -12,13 +12,13 @@
   
       bb0: {
           _3 = discriminant((*_1));
-          switchInt(move _3) -> [1: bb1, otherwise: bb3];
+          switchInt(move _3) -> [1: bb1, 0: bb3, otherwise: bb5];
       }
   
       bb1: {
           _4 = deref_copy (((*_1) as Some).0: &E<'_>);
           _2 = discriminant((*_4));
-          switchInt(move _2) -> [1: bb2, otherwise: bb3];
+          switchInt(move _2) -> [1: bb2, 0: bb3, otherwise: bb5];
       }
   
       bb2: {
@@ -34,5 +34,9 @@
       bb4: {
           return;
       }
+  
+      bb5: {
+          unreachable;
+      }
   }
   
diff --git a/tests/mir-opt/early_otherwise_branch_soundness.rs b/tests/mir-opt/early_otherwise_branch_soundness.rs
index b4f5821c420..74a2af884c0 100644
--- a/tests/mir-opt/early_otherwise_branch_soundness.rs
+++ b/tests/mir-opt/early_otherwise_branch_soundness.rs
@@ -1,5 +1,5 @@
-// skip-filecheck
 //@ unit-test: EarlyOtherwiseBranch
+//@ compile-flags: -Zmir-enable-passes=+UnreachableEnumBranching
 
 // Tests various cases that the `early_otherwise_branch` opt should *not* optimize
 
@@ -11,12 +11,26 @@ enum E<'a> {
 
 // EMIT_MIR early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff
 fn no_downcast(e: &E) -> u32 {
+    // CHECK-LABEL: fn no_downcast(
+    // CHECK: bb0: {
+    // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}});
+    // CHECK-NOT: Ne
+    // CHECK-NOT: discriminant
+    // CHECK: switchInt(move [[LOCAL1]]) -> [
+    // CHECK-NEXT: }
     if let E::Some(E::Some(_)) = e { 1 } else { 2 }
 }
 
 // SAFETY: if `a` is `Some`, `b` must point to a valid, initialized value
 // EMIT_MIR early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff
 unsafe fn no_deref_ptr(a: Option<i32>, b: *const Option<i32>) -> i32 {
+    // CHECK-LABEL: fn no_deref_ptr(
+    // CHECK: bb0: {
+    // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}});
+    // CHECK-NOT: Ne
+    // CHECK-NOT: discriminant
+    // CHECK: switchInt(move [[LOCAL1]]) -> [
+    // CHECK-NEXT: }
     match a {
         // `*b` being correct depends on `a == Some(_)`
         Some(_) => match *b {