about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_mir/src/transform/match_branches.rs30
-rw-r--r--src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.32bit.diff8
-rw-r--r--src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.64bit.diff8
-rw-r--r--src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff6
-rw-r--r--src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff6
-rw-r--r--src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff116
-rw-r--r--src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff116
-rw-r--r--src/test/mir-opt/matches_reduce_branches.rs10
-rw-r--r--src/test/mir-opt/not_equal_false.opt.InstCombine.diff57
9 files changed, 309 insertions, 48 deletions
diff --git a/compiler/rustc_mir/src/transform/match_branches.rs b/compiler/rustc_mir/src/transform/match_branches.rs
index 0f9b2ff5ab8..06690dcbf6e 100644
--- a/compiler/rustc_mir/src/transform/match_branches.rs
+++ b/compiler/rustc_mir/src/transform/match_branches.rs
@@ -38,19 +38,16 @@ pub struct MatchBranchSimplification;
 
 impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        // FIXME: This optimization can result in unsoundness, because it introduces
-        // additional uses of a place holding the discriminant value without ensuring that
-        // it is valid to do so.
-        if !tcx.sess.opts.debugging_opts.unsound_mir_opts {
+        if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 {
             return;
         }
 
         let param_env = tcx.param_env(body.source.def_id());
-        let bbs = body.basic_blocks_mut();
+        let (bbs, local_decls) = body.basic_blocks_and_local_decls_mut();
         'outer: for bb_idx in bbs.indices() {
             let (discr, val, switch_ty, first, second) = match bbs[bb_idx].terminator().kind {
                 TerminatorKind::SwitchInt {
-                    discr: Operand::Copy(ref place) | Operand::Move(ref place),
+                    discr: ref discr @ (Operand::Copy(_) | Operand::Move(_)),
                     switch_ty,
                     ref targets,
                     ..
@@ -59,7 +56,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
                     if target == targets.otherwise() {
                         continue;
                     }
-                    (place, value, switch_ty, target, targets.otherwise())
+                    (discr, value, switch_ty, target, targets.otherwise())
                 }
                 // Only optimize switch int statements
                 _ => continue,
@@ -99,6 +96,10 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
             // Take ownership of items now that we know we can optimize.
             let discr = discr.clone();
 
+            // Introduce a temporary for the discriminant value.
+            let source_info = bbs[bb_idx].terminator().source_info;
+            let discr_local = local_decls.push(LocalDecl::new(switch_ty, source_info.span));
+
             // We already checked that first and second are different blocks,
             // and bb_idx has a different terminator from both of them.
             let (from, first, second) = bbs.pick3_mut(bb_idx, first, second);
@@ -127,7 +128,11 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
                                 rustc_span::DUMMY_SP,
                             );
                             let op = if f_b { BinOp::Eq } else { BinOp::Ne };
-                            let rhs = Rvalue::BinaryOp(op, Operand::Copy(discr.clone()), const_cmp);
+                            let rhs = Rvalue::BinaryOp(
+                                op,
+                                Operand::Copy(Place::from(discr_local)),
+                                const_cmp,
+                            );
                             Statement {
                                 source_info: f.source_info,
                                 kind: StatementKind::Assign(box (*lhs, rhs)),
@@ -138,7 +143,16 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
                     _ => unreachable!(),
                 }
             });
+
+            from.statements
+                .push(Statement { source_info, kind: StatementKind::StorageLive(discr_local) });
+            from.statements.push(Statement {
+                source_info,
+                kind: StatementKind::Assign(box (Place::from(discr_local), Rvalue::Use(discr))),
+            });
             from.statements.extend(new_stmts);
+            from.statements
+                .push(Statement { source_info, kind: StatementKind::StorageDead(discr_local) });
             from.terminator_mut().kind = first.terminator().kind.clone();
         }
     }
diff --git a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.32bit.diff b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.32bit.diff
index 648cf241cba..d3a29aa5d51 100644
--- a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.32bit.diff
+++ b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.32bit.diff
@@ -10,6 +10,7 @@
       let mut _8: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:35:9: 35:10
       let mut _9: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:35:12: 35:13
       let mut _10: bool;                   // in scope 0 at $DIR/matches_reduce_branches.rs:35:15: 35:16
++     let mut _11: i32;                    // in scope 0 at $DIR/matches_reduce_branches.rs:19:9: 19:10
       scope 1 {
           debug a => _2;                   // in scope 1 at $DIR/matches_reduce_branches.rs:13:9: 13:10
           let _3: bool;                    // in scope 1 at $DIR/matches_reduce_branches.rs:14:9: 14:10
@@ -33,10 +34,13 @@
           StorageLive(_5);                 // scope 3 at $DIR/matches_reduce_branches.rs:16:9: 16:10
           StorageLive(_6);                 // scope 4 at $DIR/matches_reduce_branches.rs:18:5: 33:6
 -         switchInt(_1) -> [7_i32: bb2, otherwise: bb1]; // scope 4 at $DIR/matches_reduce_branches.rs:19:9: 19:10
-+         _2 = Ne(_1, const 7_i32);        // scope 4 at $DIR/matches_reduce_branches.rs:20:13: 20:22
-+         _3 = Eq(_1, const 7_i32);        // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:21
++         StorageLive(_11);                // scope 4 at $DIR/matches_reduce_branches.rs:19:9: 19:10
++         _11 = _1;                        // scope 4 at $DIR/matches_reduce_branches.rs:19:9: 19:10
++         _2 = Ne(_11, const 7_i32);       // scope 4 at $DIR/matches_reduce_branches.rs:20:13: 20:22
++         _3 = Eq(_11, const 7_i32);       // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:21
 +         _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:22:13: 22:22
 +         _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:23:13: 23:21
++         StorageDead(_11);                // scope 4 at $DIR/matches_reduce_branches.rs:19:9: 19:10
 +         goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:19:9: 19:10
       }
   
diff --git a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.64bit.diff b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.64bit.diff
index 648cf241cba..d3a29aa5d51 100644
--- a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.64bit.diff
+++ b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.64bit.diff
@@ -10,6 +10,7 @@
       let mut _8: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:35:9: 35:10
       let mut _9: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:35:12: 35:13
       let mut _10: bool;                   // in scope 0 at $DIR/matches_reduce_branches.rs:35:15: 35:16
++     let mut _11: i32;                    // in scope 0 at $DIR/matches_reduce_branches.rs:19:9: 19:10
       scope 1 {
           debug a => _2;                   // in scope 1 at $DIR/matches_reduce_branches.rs:13:9: 13:10
           let _3: bool;                    // in scope 1 at $DIR/matches_reduce_branches.rs:14:9: 14:10
@@ -33,10 +34,13 @@
           StorageLive(_5);                 // scope 3 at $DIR/matches_reduce_branches.rs:16:9: 16:10
           StorageLive(_6);                 // scope 4 at $DIR/matches_reduce_branches.rs:18:5: 33:6
 -         switchInt(_1) -> [7_i32: bb2, otherwise: bb1]; // scope 4 at $DIR/matches_reduce_branches.rs:19:9: 19:10
-+         _2 = Ne(_1, const 7_i32);        // scope 4 at $DIR/matches_reduce_branches.rs:20:13: 20:22
-+         _3 = Eq(_1, const 7_i32);        // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:21
++         StorageLive(_11);                // scope 4 at $DIR/matches_reduce_branches.rs:19:9: 19:10
++         _11 = _1;                        // scope 4 at $DIR/matches_reduce_branches.rs:19:9: 19:10
++         _2 = Ne(_11, const 7_i32);       // scope 4 at $DIR/matches_reduce_branches.rs:20:13: 20:22
++         _3 = Eq(_11, const 7_i32);       // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:21
 +         _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:22:13: 22:22
 +         _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:23:13: 23:21
++         StorageDead(_11);                // scope 4 at $DIR/matches_reduce_branches.rs:19:9: 19:10
 +         goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:19:9: 19:10
       }
   
diff --git a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff
index a52abfb1a72..ba963e3fe92 100644
--- a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff
+++ b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff
@@ -6,12 +6,16 @@
       let mut _0: ();                      // return place in scope 0 at $DIR/matches_reduce_branches.rs:6:25: 6:25
       let mut _2: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let mut _3: isize;                   // in scope 0 at $DIR/matches_reduce_branches.rs:7:22: 7:26
++     let mut _4: isize;                   // in scope 0 at $DIR/matches_reduce_branches.rs:7:22: 7:26
   
       bb0: {
           StorageLive(_2);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _3 = discriminant(_1);           // scope 0 at $DIR/matches_reduce_branches.rs:7:22: 7:26
 -         switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:7:22: 7:26
-+         _2 = Eq(_3, const 0_isize);      // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         StorageLive(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:7:22: 7:26
++         _4 = move _3;                    // scope 0 at $DIR/matches_reduce_branches.rs:7:22: 7:26
++         _2 = Eq(_4, const 0_isize);      // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         StorageDead(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:7:22: 7:26
 +         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:7:22: 7:26
       }
   
diff --git a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff
index a52abfb1a72..ba963e3fe92 100644
--- a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff
+++ b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff
@@ -6,12 +6,16 @@
       let mut _0: ();                      // return place in scope 0 at $DIR/matches_reduce_branches.rs:6:25: 6:25
       let mut _2: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let mut _3: isize;                   // in scope 0 at $DIR/matches_reduce_branches.rs:7:22: 7:26
++     let mut _4: isize;                   // in scope 0 at $DIR/matches_reduce_branches.rs:7:22: 7:26
   
       bb0: {
           StorageLive(_2);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _3 = discriminant(_1);           // scope 0 at $DIR/matches_reduce_branches.rs:7:22: 7:26
 -         switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:7:22: 7:26
-+         _2 = Eq(_3, const 0_isize);      // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         StorageLive(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:7:22: 7:26
++         _4 = move _3;                    // scope 0 at $DIR/matches_reduce_branches.rs:7:22: 7:26
++         _2 = Eq(_4, const 0_isize);      // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         StorageDead(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:7:22: 7:26
 +         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:7:22: 7:26
       }
   
diff --git a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff
new file mode 100644
index 00000000000..1f46d3777be
--- /dev/null
+++ b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff
@@ -0,0 +1,116 @@
+- // MIR for `match_nested_if` before MatchBranchSimplification
++ // MIR for `match_nested_if` after MatchBranchSimplification
+  
+  fn match_nested_if() -> bool {
+      let mut _0: bool;                    // return place in scope 0 at $DIR/matches_reduce_branches.rs:38:25: 38:29
+      let _1: bool;                        // in scope 0 at $DIR/matches_reduce_branches.rs:39:9: 39:12
+      let mut _2: ();                      // in scope 0 at $DIR/matches_reduce_branches.rs:39:21: 39:23
+      let mut _3: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
+      let mut _4: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
+      let mut _5: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
+      let mut _6: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:40:24: 40:28
++     let mut _7: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
++     let mut _8: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
++     let mut _9: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++     let mut _10: bool;                   // in scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
+      scope 1 {
+          debug val => _1;                 // in scope 1 at $DIR/matches_reduce_branches.rs:39:9: 39:12
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/matches_reduce_branches.rs:39:9: 39:12
+          StorageLive(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:39:21: 39:23
+          StorageLive(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
+          StorageLive(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
+          StorageLive(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
+          StorageLive(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:24: 40:28
+          _6 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:24: 40:28
+-         switchInt(_6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
++         StorageLive(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
++         _7 = _6;                         // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
++         _5 = Ne(_7, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:40:42: 40:47
++         StorageDead(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
++         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
+      }
+  
+      bb1: {
+          _5 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:30: 40:34
+          goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
+      }
+  
+      bb2: {
+          _5 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:40:42: 40:47
+          goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
+      }
+  
+      bb3: {
+          StorageDead(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:47: 40:48
+-         switchInt(_5) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
++         StorageLive(_8);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
++         _8 = _5;                         // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
++         _4 = Ne(_8, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:40:62: 40:67
++         StorageDead(_8);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
++         goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
+      }
+  
+      bb4: {
+          _4 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:40:62: 40:67
+          goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
+      }
+  
+      bb5: {
+          _4 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:50: 40:54
+          goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
+      }
+  
+      bb6: {
+          StorageDead(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:67: 40:68
+-         switchInt(_4) -> [false: bb7, otherwise: bb8]; // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++         StorageLive(_9);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++         _9 = _4;                         // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++         _3 = Ne(_9, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:40:82: 40:87
++         StorageDead(_9);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
+      }
+  
+      bb7: {
+          _3 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:40:82: 40:87
+          goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
+      }
+  
+      bb8: {
+          _3 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:70: 40:74
+          goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
+      }
+  
+      bb9: {
+          StorageDead(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:87: 40:88
+-         switchInt(move _3) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++         StorageLive(_10);                // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++         _10 = move _3;                   // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++         StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:95: 40:96
++         _1 = Ne(_10, const false);       // scope 0 at $DIR/matches_reduce_branches.rs:41:14: 41:19
++         StorageDead(_10);                // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++         goto -> bb12;                    // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
+      }
+  
+      bb10: {
+          StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:95: 40:96
+          _1 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:92: 40:96
+          goto -> bb12;                    // scope 0 at $DIR/matches_reduce_branches.rs:39:15: 42:6
+      }
+  
+      bb11: {
+          StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:95: 40:96
+          _1 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:41:14: 41:19
+          goto -> bb12;                    // scope 0 at $DIR/matches_reduce_branches.rs:39:15: 42:6
+      }
+  
+      bb12: {
+          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:42:6: 42:7
+          _0 = _1;                         // scope 1 at $DIR/matches_reduce_branches.rs:43:5: 43:8
+          StorageDead(_1);                 // scope 0 at $DIR/matches_reduce_branches.rs:44:1: 44:2
+          return;                          // scope 0 at $DIR/matches_reduce_branches.rs:44:2: 44:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff
new file mode 100644
index 00000000000..1f46d3777be
--- /dev/null
+++ b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff
@@ -0,0 +1,116 @@
+- // MIR for `match_nested_if` before MatchBranchSimplification
++ // MIR for `match_nested_if` after MatchBranchSimplification
+  
+  fn match_nested_if() -> bool {
+      let mut _0: bool;                    // return place in scope 0 at $DIR/matches_reduce_branches.rs:38:25: 38:29
+      let _1: bool;                        // in scope 0 at $DIR/matches_reduce_branches.rs:39:9: 39:12
+      let mut _2: ();                      // in scope 0 at $DIR/matches_reduce_branches.rs:39:21: 39:23
+      let mut _3: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
+      let mut _4: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
+      let mut _5: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
+      let mut _6: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:40:24: 40:28
++     let mut _7: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
++     let mut _8: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
++     let mut _9: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++     let mut _10: bool;                   // in scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
+      scope 1 {
+          debug val => _1;                 // in scope 1 at $DIR/matches_reduce_branches.rs:39:9: 39:12
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/matches_reduce_branches.rs:39:9: 39:12
+          StorageLive(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:39:21: 39:23
+          StorageLive(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
+          StorageLive(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
+          StorageLive(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
+          StorageLive(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:24: 40:28
+          _6 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:24: 40:28
+-         switchInt(_6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
++         StorageLive(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
++         _7 = _6;                         // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
++         _5 = Ne(_7, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:40:42: 40:47
++         StorageDead(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
++         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
+      }
+  
+      bb1: {
+          _5 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:30: 40:34
+          goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
+      }
+  
+      bb2: {
+          _5 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:40:42: 40:47
+          goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
+      }
+  
+      bb3: {
+          StorageDead(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:47: 40:48
+-         switchInt(_5) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
++         StorageLive(_8);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
++         _8 = _5;                         // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
++         _4 = Ne(_8, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:40:62: 40:67
++         StorageDead(_8);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
++         goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
+      }
+  
+      bb4: {
+          _4 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:40:62: 40:67
+          goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
+      }
+  
+      bb5: {
+          _4 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:50: 40:54
+          goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
+      }
+  
+      bb6: {
+          StorageDead(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:67: 40:68
+-         switchInt(_4) -> [false: bb7, otherwise: bb8]; // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++         StorageLive(_9);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++         _9 = _4;                         // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++         _3 = Ne(_9, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:40:82: 40:87
++         StorageDead(_9);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
+      }
+  
+      bb7: {
+          _3 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:40:82: 40:87
+          goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
+      }
+  
+      bb8: {
+          _3 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:70: 40:74
+          goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
+      }
+  
+      bb9: {
+          StorageDead(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:87: 40:88
+-         switchInt(move _3) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++         StorageLive(_10);                // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++         _10 = move _3;                   // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++         StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:95: 40:96
++         _1 = Ne(_10, const false);       // scope 0 at $DIR/matches_reduce_branches.rs:41:14: 41:19
++         StorageDead(_10);                // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++         goto -> bb12;                    // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
+      }
+  
+      bb10: {
+          StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:95: 40:96
+          _1 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:92: 40:96
+          goto -> bb12;                    // scope 0 at $DIR/matches_reduce_branches.rs:39:15: 42:6
+      }
+  
+      bb11: {
+          StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:95: 40:96
+          _1 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:41:14: 41:19
+          goto -> bb12;                    // scope 0 at $DIR/matches_reduce_branches.rs:39:15: 42:6
+      }
+  
+      bb12: {
+          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:42:6: 42:7
+          _0 = _1;                         // scope 1 at $DIR/matches_reduce_branches.rs:43:5: 43:8
+          StorageDead(_1);                 // scope 0 at $DIR/matches_reduce_branches.rs:44:1: 44:2
+          return;                          // scope 0 at $DIR/matches_reduce_branches.rs:44:2: 44:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/matches_reduce_branches.rs b/src/test/mir-opt/matches_reduce_branches.rs
index 54b79a84263..e95a62aeeb0 100644
--- a/src/test/mir-opt/matches_reduce_branches.rs
+++ b/src/test/mir-opt/matches_reduce_branches.rs
@@ -1,7 +1,7 @@
-// compile-flags: -Zunsound-mir-opts
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 // EMIT_MIR matches_reduce_branches.foo.MatchBranchSimplification.diff
 // EMIT_MIR matches_reduce_branches.bar.MatchBranchSimplification.diff
+// EMIT_MIR matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff
 
 fn foo(bar: Option<()>) {
     if matches!(bar, None) {
@@ -35,9 +35,17 @@ fn bar(i: i32) -> (bool, bool, bool, bool) {
     (a, b, c, d)
 }
 
+fn match_nested_if() -> bool {
+    let val = match () {
+        () if if if if true {true} else {false} {true} else {false} {true} else {false} => true,
+        _ => false,
+    };
+    val
+}
 
 fn main() {
   let _ = foo(None);
   let _ = foo(Some(()));
   let _ = bar(0);
+  let _ = match_nested_if();
 }
diff --git a/src/test/mir-opt/not_equal_false.opt.InstCombine.diff b/src/test/mir-opt/not_equal_false.opt.InstCombine.diff
index 39830946aeb..dc3a6a36d9e 100644
--- a/src/test/mir-opt/not_equal_false.opt.InstCombine.diff
+++ b/src/test/mir-opt/not_equal_false.opt.InstCombine.diff
@@ -8,61 +8,52 @@
       let mut _3: isize;                   // in scope 0 at $DIR/not_equal_false.rs:4:17: 4:21
       let mut _4: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let mut _5: isize;                   // in scope 0 at $DIR/not_equal_false.rs:4:38: 4:45
+      let mut _6: isize;                   // in scope 0 at $DIR/not_equal_false.rs:4:17: 4:21
+      let mut _7: isize;                   // in scope 0 at $DIR/not_equal_false.rs:4:38: 4:45
+      let mut _8: bool;                    // in scope 0 at $DIR/not_equal_false.rs:4:5: 4:46
   
       bb0: {
           StorageLive(_2);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _3 = discriminant(_1);           // scope 0 at $DIR/not_equal_false.rs:4:17: 4:21
-          switchInt(move _3) -> [0_isize: bb6, otherwise: bb5]; // scope 0 at $DIR/not_equal_false.rs:4:17: 4:21
+          StorageLive(_6);                 // scope 0 at $DIR/not_equal_false.rs:4:17: 4:21
+          _6 = move _3;                    // scope 0 at $DIR/not_equal_false.rs:4:17: 4:21
+          _2 = Eq(_6, const 0_isize);      // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_6);                 // scope 0 at $DIR/not_equal_false.rs:4:17: 4:21
+          goto -> bb4;                     // scope 0 at $DIR/not_equal_false.rs:4:17: 4:21
       }
   
       bb1: {
           _0 = const true;                 // scope 0 at $DIR/not_equal_false.rs:4:5: 4:46
-          goto -> bb4;                     // scope 0 at $DIR/not_equal_false.rs:4:5: 4:46
+          goto -> bb3;                     // scope 0 at $DIR/not_equal_false.rs:4:5: 4:46
       }
   
       bb2: {
-          _0 = const false;                // scope 0 at $DIR/not_equal_false.rs:4:5: 4:46
-          goto -> bb4;                     // scope 0 at $DIR/not_equal_false.rs:4:5: 4:46
-      }
-  
-      bb3: {
           StorageLive(_4);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _5 = discriminant(_1);           // scope 0 at $DIR/not_equal_false.rs:4:38: 4:45
-          switchInt(move _5) -> [1_isize: bb9, otherwise: bb8]; // scope 0 at $DIR/not_equal_false.rs:4:38: 4:45
+          StorageLive(_7);                 // scope 0 at $DIR/not_equal_false.rs:4:38: 4:45
+          _7 = move _5;                    // scope 0 at $DIR/not_equal_false.rs:4:38: 4:45
+          _4 = Eq(_7, const 1_isize);      // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_7);                 // scope 0 at $DIR/not_equal_false.rs:4:38: 4:45
+          goto -> bb5;                     // scope 0 at $DIR/not_equal_false.rs:4:38: 4:45
       }
   
-      bb4: {
+      bb3: {
           StorageDead(_4);                 // scope 0 at $DIR/not_equal_false.rs:4:45: 4:46
           StorageDead(_2);                 // scope 0 at $DIR/not_equal_false.rs:4:45: 4:46
           return;                          // scope 0 at $DIR/not_equal_false.rs:5:2: 5:2
       }
   
-      bb5: {
-          _2 = const false;                // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          goto -> bb7;                     // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      }
-  
-      bb6: {
-          _2 = const true;                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          goto -> bb7;                     // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      }
-  
-      bb7: {
-          switchInt(move _2) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/not_equal_false.rs:4:5: 4:46
-      }
-  
-      bb8: {
-          _4 = const false;                // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          goto -> bb10;                    // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      }
-  
-      bb9: {
-          _4 = const true;                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          goto -> bb10;                    // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      bb4: {
+          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/not_equal_false.rs:4:5: 4:46
       }
   
-      bb10: {
-          switchInt(move _4) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/not_equal_false.rs:4:5: 4:46
+      bb5: {
+          StorageLive(_8);                 // scope 0 at $DIR/not_equal_false.rs:4:5: 4:46
+          _8 = move _4;                    // scope 0 at $DIR/not_equal_false.rs:4:5: 4:46
+-         _0 = Ne(_8, const false);        // scope 0 at $DIR/not_equal_false.rs:4:5: 4:46
++         _0 = _8;                         // scope 0 at $DIR/not_equal_false.rs:4:5: 4:46
+          StorageDead(_8);                 // scope 0 at $DIR/not_equal_false.rs:4:5: 4:46
+          goto -> bb3;                     // scope 0 at $DIR/not_equal_false.rs:4:5: 4:46
       }
   }