]> git.lizzy.rs Git - rust.git/commitdiff
MatchBranchSimplification: fix equal const bool assignments
authorTomasz Miąsko <tomasz.miasko@gmail.com>
Sat, 15 Aug 2020 00:00:00 +0000 (00:00 +0000)
committerTomasz Miąsko <tomasz.miasko@gmail.com>
Sat, 15 Aug 2020 00:00:00 +0000 (00:00 +0000)
The match branch simplification is applied when target blocks contain
statements that are either equal or perform a const bool assignment with
different values to the same place.

Previously, when constructing new statements, only statements from a
single block had been examined. This lead to a misoptimization when
statements are equal because the assign the *same* const bool value to
the same place.

Fix the issue by examining statements from both blocks when deciding on
replacement.

src/librustc_mir/transform/match_branches.rs
src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.32bit [new file with mode: 0644]
src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.64bit [new file with mode: 0644]
src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.32bit
src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.64bit
src/test/mir-opt/matches_reduce_branches.rs

index cdf181aab02dd3cacb9d0fb6ee17e877c48e80c4..b78dee753f85f9f95029c40ea453a488993506ed 100644 (file)
@@ -4,10 +4,37 @@
 
 pub struct MatchBranchSimplification;
 
-// What's the intent of this pass?
-// If one block is found that switches between blocks which both go to the same place
-// AND both of these blocks set a similar const in their ->
-// condense into 1 block based on discriminant AND goto the destination afterwards
+/// If a source block is found that switches between two blocks that are exactly
+/// the same modulo const bool assignments (e.g., one assigns true another false
+/// to the same place), merge a target block statements into the source block,
+/// using Eq / Ne comparison with switch value where const bools value differ.
+///
+/// For example:
+///
+/// ```rust
+/// bb0: {
+///     switchInt(move _3) -> [42_isize: bb1, otherwise: bb2];
+/// }
+///
+/// bb1: {
+///     _2 = const true;
+///     goto -> bb3;
+/// }
+///
+/// bb2: {
+///     _2 = const false;
+///     goto -> bb3;
+/// }
+/// ```
+///
+/// into:
+///
+/// ```rust
+/// bb0: {
+///    _2 = Eq(move _3, const 42_isize);
+///    goto -> bb3;
+/// }
+/// ```
 
 impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
@@ -42,48 +69,68 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx
             }
             for (f, s) in first_stmts.iter().zip(scnd_stmts.iter()) {
                 match (&f.kind, &s.kind) {
-                    // If two statements are exactly the same just ignore them.
-                    (f_s, s_s) if f_s == s_s => (),
+                    // If two statements are exactly the same, we can optimize.
+                    (f_s, s_s) if f_s == s_s => {}
 
+                    // If two statements are const bool assignments to the same place, we can optimize.
                     (
                         StatementKind::Assign(box (lhs_f, Rvalue::Use(Operand::Constant(f_c)))),
                         StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))),
-                    ) if lhs_f == lhs_s && f_c.literal.ty.is_bool() && s_c.literal.ty.is_bool() => {
-                        let f_c = f_c.literal.try_eval_bool(tcx, param_env).unwrap();
-                        let s_c = s_c.literal.try_eval_bool(tcx, param_env).unwrap();
-                        if f_c != s_c {
-                            // have to check this here because f_c & s_c might have
-                            // different spans.
-                            continue;
-                        }
-                        continue 'outer;
-                    }
-                    // If there are not exclusively assignments, then ignore this
+                    ) if lhs_f == lhs_s
+                        && f_c.literal.ty.is_bool()
+                        && s_c.literal.ty.is_bool()
+                        && f_c.literal.try_eval_bool(tcx, param_env).is_some()
+                        && s_c.literal.try_eval_bool(tcx, param_env).is_some() => {}
+
+                    // Otherwise we cannot optimize. Try another block.
                     _ => continue 'outer,
                 }
             }
-            // Take owenership of items now that we know we can optimize.
+            // Take ownership of items now that we know we can optimize.
             let discr = discr.clone();
-            let (from, first) = bbs.pick2_mut(bb_idx, first);
 
-            let new_stmts = first.statements.iter().cloned().map(|mut s| {
-                if let StatementKind::Assign(box (_, ref mut rhs)) = s.kind {
-                    if let Rvalue::Use(Operand::Constant(c)) = rhs {
-                        let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size;
-                        let const_cmp = Operand::const_from_scalar(
-                            tcx,
-                            switch_ty,
-                            crate::interpret::Scalar::from_uint(val, size),
-                            rustc_span::DUMMY_SP,
-                        );
-                        if let Some(c) = c.literal.try_eval_bool(tcx, param_env) {
-                            let op = if c { BinOp::Eq } else { BinOp::Ne };
-                            *rhs = Rvalue::BinaryOp(op, Operand::Copy(discr), const_cmp);
+            let new_stmts = first_stmts
+                .iter()
+                .zip(scnd_stmts.iter())
+                .map(|(f, s)| {
+                    match (&f.kind, &s.kind) {
+                        (f_s, s_s) if f_s == s_s => (*f).clone(),
+
+                        (
+                            StatementKind::Assign(box (lhs, Rvalue::Use(Operand::Constant(f_c)))),
+                            StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(s_c)))),
+                        ) => {
+                            // From earlier loop we know that we are dealing with bool constants only:
+                            let f_b = f_c.literal.try_eval_bool(tcx, param_env).unwrap();
+                            let s_b = s_c.literal.try_eval_bool(tcx, param_env).unwrap();
+                            if f_b == s_b {
+                                // Same value in both blocks. Use statement as is.
+                                (*f).clone()
+                            } else {
+                                // Different value between blocks. Make value conditional on switch condition.
+                                let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size;
+                                let const_cmp = Operand::const_from_scalar(
+                                    tcx,
+                                    switch_ty,
+                                    crate::interpret::Scalar::from_uint(val, size),
+                                    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);
+                                Statement {
+                                    source_info: f.source_info,
+                                    kind: StatementKind::Assign(box (*lhs, rhs)),
+                                }
+                            }
                         }
+
+                        _ => unreachable!(),
                     }
-                }
-                s
-            });
+                })
+                .collect::<Vec<_>>();
+
+            let (from, first) = bbs.pick2_mut(bb_idx, first);
             from.statements.extend(new_stmts);
             from.terminator_mut().kind = first.terminator().kind.clone();
         }
diff --git a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.32bit b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.32bit
new file mode 100644 (file)
index 0000000..968890e
--- /dev/null
@@ -0,0 +1,156 @@
+- // MIR for `bar` before MatchBranchSimplification
++ // MIR for `bar` after MatchBranchSimplification
+  
+  fn bar(_1: i32) -> (bool, bool, bool, bool) {
+      debug i => _1;                       // in scope 0 at $DIR/matches_reduce_branches.rs:11:8: 11:9
+      let mut _0: (bool, bool, bool, bool); // return place in scope 0 at $DIR/matches_reduce_branches.rs:11:19: 11:43
+      let _2: bool;                        // in scope 0 at $DIR/matches_reduce_branches.rs:12:9: 12:10
+      let _6: ();                          // in scope 0 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+      let mut _7: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:34:6: 34:7
+      let mut _8: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:34:9: 34:10
+      let mut _9: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:34:12: 34:13
+      let mut _10: bool;                   // in scope 0 at $DIR/matches_reduce_branches.rs:34:15: 34:16
+      scope 1 {
+          debug a => _2;                   // in scope 1 at $DIR/matches_reduce_branches.rs:12:9: 12:10
+          let _3: bool;                    // in scope 1 at $DIR/matches_reduce_branches.rs:13:9: 13:10
+          scope 2 {
+              debug b => _3;               // in scope 2 at $DIR/matches_reduce_branches.rs:13:9: 13:10
+              let _4: bool;                // in scope 2 at $DIR/matches_reduce_branches.rs:14:9: 14:10
+              scope 3 {
+                  debug c => _4;           // in scope 3 at $DIR/matches_reduce_branches.rs:14:9: 14:10
+                  let _5: bool;            // in scope 3 at $DIR/matches_reduce_branches.rs:15:9: 15:10
+                  scope 4 {
+                      debug d => _5;       // in scope 4 at $DIR/matches_reduce_branches.rs:15:9: 15:10
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:12:9: 12:10
+          StorageLive(_3);                 // scope 1 at $DIR/matches_reduce_branches.rs:13:9: 13:10
+          StorageLive(_4);                 // scope 2 at $DIR/matches_reduce_branches.rs:14:9: 14:10
+          StorageLive(_5);                 // scope 3 at $DIR/matches_reduce_branches.rs:15:9: 15:10
+          StorageLive(_6);                 // scope 4 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+-         switchInt(_1) -> [7_i32: bb2, otherwise: bb1]; // scope 4 at $DIR/matches_reduce_branches.rs:18:9: 18:10
++         _2 = Ne(_1, const 7_i32);        // scope 4 at $DIR/matches_reduce_branches.rs:19:13: 19:22
++                                          // ty::Const
++                                          // + ty: i32
++                                          // + val: Value(Scalar(0x00000007))
++                                          // mir::Constant
++                                          // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
++                                          // + literal: Const { ty: i32, val: Value(Scalar(0x00000007)) }
++         _3 = Eq(_1, const 7_i32);        // scope 4 at $DIR/matches_reduce_branches.rs:20:13: 20:21
++                                          // ty::Const
++                                          // + ty: i32
++                                          // + val: Value(Scalar(0x00000007))
++                                          // mir::Constant
++                                          // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
++                                          // + literal: Const { ty: i32, val: Value(Scalar(0x00000007)) }
++         _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:22
++                                          // ty::Const
++                                          // + ty: bool
++                                          // + val: Value(Scalar(0x00))
++                                          // mir::Constant
++                                          // + span: $DIR/matches_reduce_branches.rs:21:17: 21:22
++                                          // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
++         _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:22:13: 22:21
++                                          // ty::Const
++                                          // + ty: bool
++                                          // + val: Value(Scalar(0x01))
++                                          // mir::Constant
++                                          // + span: $DIR/matches_reduce_branches.rs:22:17: 22:21
++                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
++         goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:18:9: 18:10
+      }
+  
+      bb1: {
+          _2 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:26:13: 26:21
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:26:17: 26:21
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+          _3 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:27:13: 27:22
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:27:17: 27:22
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:28:13: 28:22
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:28:17: 28:22
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:29:13: 29:21
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:29:17: 29:21
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+          goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+      }
+  
+      bb2: {
+          _2 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:19:13: 19:22
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:19:17: 19:22
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          _3 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:20:13: 20:21
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:20:17: 20:21
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+          _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:22
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:21:17: 21:22
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:22:13: 22:21
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:22:17: 22:21
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+          goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+      }
+  
+      bb3: {
+          StorageDead(_6);                 // scope 4 at $DIR/matches_reduce_branches.rs:32:6: 32:7
+          StorageLive(_7);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:6: 34:7
+          _7 = _2;                         // scope 4 at $DIR/matches_reduce_branches.rs:34:6: 34:7
+          StorageLive(_8);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:9: 34:10
+          _8 = _3;                         // scope 4 at $DIR/matches_reduce_branches.rs:34:9: 34:10
+          StorageLive(_9);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:12: 34:13
+          _9 = _4;                         // scope 4 at $DIR/matches_reduce_branches.rs:34:12: 34:13
+          StorageLive(_10);                // scope 4 at $DIR/matches_reduce_branches.rs:34:15: 34:16
+          _10 = _5;                        // scope 4 at $DIR/matches_reduce_branches.rs:34:15: 34:16
+          (_0.0: bool) = move _7;          // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+          (_0.1: bool) = move _8;          // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+          (_0.2: bool) = move _9;          // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+          (_0.3: bool) = move _10;         // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+          StorageDead(_10);                // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+          StorageDead(_9);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+          StorageDead(_8);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+          StorageDead(_7);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+          StorageDead(_5);                 // scope 3 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+          StorageDead(_4);                 // scope 2 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+          StorageDead(_3);                 // scope 1 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+          return;                          // scope 0 at $DIR/matches_reduce_branches.rs:35:2: 35:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.64bit b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.64bit
new file mode 100644 (file)
index 0000000..968890e
--- /dev/null
@@ -0,0 +1,156 @@
+- // MIR for `bar` before MatchBranchSimplification
++ // MIR for `bar` after MatchBranchSimplification
+  
+  fn bar(_1: i32) -> (bool, bool, bool, bool) {
+      debug i => _1;                       // in scope 0 at $DIR/matches_reduce_branches.rs:11:8: 11:9
+      let mut _0: (bool, bool, bool, bool); // return place in scope 0 at $DIR/matches_reduce_branches.rs:11:19: 11:43
+      let _2: bool;                        // in scope 0 at $DIR/matches_reduce_branches.rs:12:9: 12:10
+      let _6: ();                          // in scope 0 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+      let mut _7: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:34:6: 34:7
+      let mut _8: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:34:9: 34:10
+      let mut _9: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:34:12: 34:13
+      let mut _10: bool;                   // in scope 0 at $DIR/matches_reduce_branches.rs:34:15: 34:16
+      scope 1 {
+          debug a => _2;                   // in scope 1 at $DIR/matches_reduce_branches.rs:12:9: 12:10
+          let _3: bool;                    // in scope 1 at $DIR/matches_reduce_branches.rs:13:9: 13:10
+          scope 2 {
+              debug b => _3;               // in scope 2 at $DIR/matches_reduce_branches.rs:13:9: 13:10
+              let _4: bool;                // in scope 2 at $DIR/matches_reduce_branches.rs:14:9: 14:10
+              scope 3 {
+                  debug c => _4;           // in scope 3 at $DIR/matches_reduce_branches.rs:14:9: 14:10
+                  let _5: bool;            // in scope 3 at $DIR/matches_reduce_branches.rs:15:9: 15:10
+                  scope 4 {
+                      debug d => _5;       // in scope 4 at $DIR/matches_reduce_branches.rs:15:9: 15:10
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:12:9: 12:10
+          StorageLive(_3);                 // scope 1 at $DIR/matches_reduce_branches.rs:13:9: 13:10
+          StorageLive(_4);                 // scope 2 at $DIR/matches_reduce_branches.rs:14:9: 14:10
+          StorageLive(_5);                 // scope 3 at $DIR/matches_reduce_branches.rs:15:9: 15:10
+          StorageLive(_6);                 // scope 4 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+-         switchInt(_1) -> [7_i32: bb2, otherwise: bb1]; // scope 4 at $DIR/matches_reduce_branches.rs:18:9: 18:10
++         _2 = Ne(_1, const 7_i32);        // scope 4 at $DIR/matches_reduce_branches.rs:19:13: 19:22
++                                          // ty::Const
++                                          // + ty: i32
++                                          // + val: Value(Scalar(0x00000007))
++                                          // mir::Constant
++                                          // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
++                                          // + literal: Const { ty: i32, val: Value(Scalar(0x00000007)) }
++         _3 = Eq(_1, const 7_i32);        // scope 4 at $DIR/matches_reduce_branches.rs:20:13: 20:21
++                                          // ty::Const
++                                          // + ty: i32
++                                          // + val: Value(Scalar(0x00000007))
++                                          // mir::Constant
++                                          // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
++                                          // + literal: Const { ty: i32, val: Value(Scalar(0x00000007)) }
++         _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:22
++                                          // ty::Const
++                                          // + ty: bool
++                                          // + val: Value(Scalar(0x00))
++                                          // mir::Constant
++                                          // + span: $DIR/matches_reduce_branches.rs:21:17: 21:22
++                                          // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
++         _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:22:13: 22:21
++                                          // ty::Const
++                                          // + ty: bool
++                                          // + val: Value(Scalar(0x01))
++                                          // mir::Constant
++                                          // + span: $DIR/matches_reduce_branches.rs:22:17: 22:21
++                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
++         goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:18:9: 18:10
+      }
+  
+      bb1: {
+          _2 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:26:13: 26:21
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:26:17: 26:21
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+          _3 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:27:13: 27:22
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:27:17: 27:22
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:28:13: 28:22
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:28:17: 28:22
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:29:13: 29:21
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:29:17: 29:21
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+          goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+      }
+  
+      bb2: {
+          _2 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:19:13: 19:22
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:19:17: 19:22
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          _3 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:20:13: 20:21
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:20:17: 20:21
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+          _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:22
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:21:17: 21:22
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:22:13: 22:21
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:22:17: 22:21
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+          goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+      }
+  
+      bb3: {
+          StorageDead(_6);                 // scope 4 at $DIR/matches_reduce_branches.rs:32:6: 32:7
+          StorageLive(_7);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:6: 34:7
+          _7 = _2;                         // scope 4 at $DIR/matches_reduce_branches.rs:34:6: 34:7
+          StorageLive(_8);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:9: 34:10
+          _8 = _3;                         // scope 4 at $DIR/matches_reduce_branches.rs:34:9: 34:10
+          StorageLive(_9);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:12: 34:13
+          _9 = _4;                         // scope 4 at $DIR/matches_reduce_branches.rs:34:12: 34:13
+          StorageLive(_10);                // scope 4 at $DIR/matches_reduce_branches.rs:34:15: 34:16
+          _10 = _5;                        // scope 4 at $DIR/matches_reduce_branches.rs:34:15: 34:16
+          (_0.0: bool) = move _7;          // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+          (_0.1: bool) = move _8;          // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+          (_0.2: bool) = move _9;          // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+          (_0.3: bool) = move _10;         // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+          StorageDead(_10);                // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+          StorageDead(_9);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+          StorageDead(_8);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+          StorageDead(_7);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+          StorageDead(_5);                 // scope 3 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+          StorageDead(_4);                 // scope 2 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+          StorageDead(_3);                 // scope 1 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+          return;                          // scope 0 at $DIR/matches_reduce_branches.rs:35:2: 35:2
+      }
+  }
+  
index 9324762fb0803fb790720db8536a8208e6950a75..a33db001f443825afa04d428fb934cc71d27b2e3 100644 (file)
@@ -2,15 +2,15 @@
 + // MIR for `foo` after MatchBranchSimplification
   
   fn foo(_1: std::option::Option<()>) -> () {
-      debug bar => _1;                     // in scope 0 at $DIR/matches_reduce_branches.rs:4:8: 4:11
-      let mut _0: ();                      // return place in scope 0 at $DIR/matches_reduce_branches.rs:4:25: 4:25
+      debug bar => _1;                     // in scope 0 at $DIR/matches_reduce_branches.rs:5:8: 5:11
+      let mut _0: ();                      // return place in scope 0 at $DIR/matches_reduce_branches.rs:5:25: 5: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:5:22: 5:26
+      let mut _3: isize;                   // in scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6: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:5:22: 5:26
--         switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:5:22: 5:26
+          _3 = discriminant(_1);           // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
+-         switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
 +         _2 = Eq(_3, const 0_isize);      // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 +                                          // ty::Const
 +                                          // + ty: isize
@@ -18,7 +18,7 @@
 +                                          // mir::Constant
 +                                          // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
 +                                          // + literal: Const { ty: isize, val: Value(Scalar(0x00000000)) }
-+         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:5:22: 5:26
++         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
       }
   
       bb1: {
       }
   
       bb3: {
-          switchInt(_2) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:5:5: 7:6
+          switchInt(_2) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
       }
   
       bb4: {
-          _0 = const ();                   // scope 0 at $DIR/matches_reduce_branches.rs:5:5: 7:6
+          _0 = const ();                   // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
                                            // ty::Const
                                            // + ty: ()
                                            // + val: Value(Scalar(<ZST>))
                                            // mir::Constant
-                                           // + span: $DIR/matches_reduce_branches.rs:5:5: 7:6
+                                           // + span: $DIR/matches_reduce_branches.rs:6:5: 8:6
                                            // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
-          goto -> bb5;                     // scope 0 at $DIR/matches_reduce_branches.rs:5:5: 7:6
+          goto -> bb5;                     // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
       }
   
       bb5: {
-          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:8:1: 8:2
-          return;                          // scope 0 at $DIR/matches_reduce_branches.rs:8:2: 8:2
+          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:9:1: 9:2
+          return;                          // scope 0 at $DIR/matches_reduce_branches.rs:9:2: 9:2
       }
   }
   
index 144a71228ad696650d7ba5bc7f187e8c40723046..3eb5b01fbf4960034dc09ef2ce9ff34e9a9394f5 100644 (file)
@@ -2,15 +2,15 @@
 + // MIR for `foo` after MatchBranchSimplification
   
   fn foo(_1: std::option::Option<()>) -> () {
-      debug bar => _1;                     // in scope 0 at $DIR/matches_reduce_branches.rs:4:8: 4:11
-      let mut _0: ();                      // return place in scope 0 at $DIR/matches_reduce_branches.rs:4:25: 4:25
+      debug bar => _1;                     // in scope 0 at $DIR/matches_reduce_branches.rs:5:8: 5:11
+      let mut _0: ();                      // return place in scope 0 at $DIR/matches_reduce_branches.rs:5:25: 5: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:5:22: 5:26
+      let mut _3: isize;                   // in scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6: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:5:22: 5:26
--         switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:5:22: 5:26
+          _3 = discriminant(_1);           // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
+-         switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
 +         _2 = Eq(_3, const 0_isize);      // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 +                                          // ty::Const
 +                                          // + ty: isize
@@ -18,7 +18,7 @@
 +                                          // mir::Constant
 +                                          // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
 +                                          // + literal: Const { ty: isize, val: Value(Scalar(0x0000000000000000)) }
-+         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:5:22: 5:26
++         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
       }
   
       bb1: {
       }
   
       bb3: {
-          switchInt(_2) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:5:5: 7:6
+          switchInt(_2) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
       }
   
       bb4: {
-          _0 = const ();                   // scope 0 at $DIR/matches_reduce_branches.rs:5:5: 7:6
+          _0 = const ();                   // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
                                            // ty::Const
                                            // + ty: ()
                                            // + val: Value(Scalar(<ZST>))
                                            // mir::Constant
-                                           // + span: $DIR/matches_reduce_branches.rs:5:5: 7:6
+                                           // + span: $DIR/matches_reduce_branches.rs:6:5: 8:6
                                            // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
-          goto -> bb5;                     // scope 0 at $DIR/matches_reduce_branches.rs:5:5: 7:6
+          goto -> bb5;                     // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
       }
   
       bb5: {
-          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:8:1: 8:2
-          return;                          // scope 0 at $DIR/matches_reduce_branches.rs:8:2: 8:2
+          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:9:1: 9:2
+          return;                          // scope 0 at $DIR/matches_reduce_branches.rs:9:2: 9:2
       }
   }
   
index 91b6bfc836bd49dafc88c03708df7a070e14675e..ebc88d2fbd1dacb113957cd4ddc1309766cde654 100644 (file)
@@ -1,5 +1,6 @@
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 // EMIT_MIR matches_reduce_branches.foo.MatchBranchSimplification.diff
+// EMIT_MIR matches_reduce_branches.bar.MatchBranchSimplification.diff
 
 fn foo(bar: Option<()>) {
     if matches!(bar, None) {
@@ -7,7 +8,35 @@ fn foo(bar: Option<()>) {
     }
 }
 
+fn bar(i: i32) -> (bool, bool, bool, bool) {
+    let a;
+    let b;
+    let c;
+    let d;
+
+    match i {
+        7 => {
+            a = false;
+            b = true;
+            c = false;
+            d = true;
+            ()
+        }
+        _ => {
+            a = true;
+            b = false;
+            c = false;
+            d = true;
+            ()
+        }
+    };
+
+    (a, b, c, d)
+}
+
+
 fn main() {
   let _ = foo(None);
   let _ = foo(Some(()));
+  let _ = bar(0);
 }