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.
This commit is contained in:
Tomasz Miąsko 2020-08-15 00:00:00 +00:00
parent 4fae04968e
commit 1fe2e2941d
6 changed files with 447 additions and 59 deletions

View File

@ -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();
}

View File

@ -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
}
}

View File

@ -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
}
}

View 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: {
@ -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
}
}

View 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: {
@ -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
}
}

View 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);
}