diff options
| author | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2020-08-15 00:00:00 +0000 |
|---|---|---|
| committer | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2020-08-15 00:00:00 +0000 |
| commit | 1fe2e2941d93da397c8ace5f410c0ab3dc5a3049 (patch) | |
| tree | d0dc222ef5e016c57c05e9bdc163adffa49e59ea | |
| parent | 4fae04968eccb8797000b5a42760005b35504136 (diff) | |
| download | rust-1fe2e2941d93da397c8ace5f410c0ab3dc5a3049.tar.gz rust-1fe2e2941d93da397c8ace5f410c0ab3dc5a3049.zip | |
MatchBranchSimplification: fix equal const bool assignments
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.
6 files changed, 447 insertions, 59 deletions
diff --git a/src/librustc_mir/transform/match_branches.rs b/src/librustc_mir/transform/match_branches.rs index cdf181aab02..b78dee753f8 100644 --- a/src/librustc_mir/transform/match_branches.rs +++ b/src/librustc_mir/transform/match_branches.rs @@ -4,10 +4,37 @@ use rustc_middle::ty::TyCtxt; 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 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { } 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 index 00000000000..968890e3a29 --- /dev/null +++ b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.32bit @@ -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 index 00000000000..968890e3a29 --- /dev/null +++ b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.64bit @@ -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.foo.MatchBranchSimplification.diff.32bit b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.32bit index 9324762fb08..a33db001f44 100644 --- a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.32bit +++ b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.32bit @@ -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: { @@ -44,23 +44,23 @@ } 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 } } diff --git a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.64bit b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.64bit index 144a71228ad..3eb5b01fbf4 100644 --- a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.64bit +++ b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.64bit @@ -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: { @@ -44,23 +44,23 @@ } 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 } } diff --git a/src/test/mir-opt/matches_reduce_branches.rs b/src/test/mir-opt/matches_reduce_branches.rs index 91b6bfc836b..ebc88d2fbd1 100644 --- a/src/test/mir-opt/matches_reduce_branches.rs +++ b/src/test/mir-opt/matches_reduce_branches.rs @@ -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); } |
