From a4dc92b483420e1975111c8e7a2c5dff49f13845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Wed, 21 Oct 2020 00:00:00 +0000 Subject: [PATCH] Introduce a temporary for discriminant value in MatchBranchSimplification The optimization introduces additional uses of the discriminant operand, but does not ensure that it is still valid to evaluate it or that it still evaluates to the same value. Evaluate it once at original position, and store the result in a new temporary. --- .../rustc_mir/src/transform/match_branches.rs | 30 +++-- ...s.bar.MatchBranchSimplification.32bit.diff | 8 +- ...s.bar.MatchBranchSimplification.64bit.diff | 8 +- ...s.foo.MatchBranchSimplification.32bit.diff | 6 +- ...s.foo.MatchBranchSimplification.64bit.diff | 6 +- ...ed_if.MatchBranchSimplification.32bit.diff | 116 ++++++++++++++++++ ...ed_if.MatchBranchSimplification.64bit.diff | 116 ++++++++++++++++++ src/test/mir-opt/matches_reduce_branches.rs | 10 +- .../not_equal_false.opt.InstCombine.diff | 57 ++++----- 9 files changed, 309 insertions(+), 48 deletions(-) create mode 100644 src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff create mode 100644 src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff diff --git a/compiler/rustc_mir/src/transform/match_branches.rs b/compiler/rustc_mir/src/transform/match_branches.rs index 0f9b2ff5ab81e..06690dcbf6eb7 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 648cf241cbaba..d3a29aa5d51c1 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 648cf241cbaba..d3a29aa5d51c1 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 a52abfb1a727d..ba963e3fe920b 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 a52abfb1a727d..ba963e3fe920b 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 0000000000000..1f46d3777bed8 --- /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 0000000000000..1f46d3777bed8 --- /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 54b79a84263fe..e95a62aeeb0b9 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 39830946aebd6..dc3a6a36d9eef 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 } }