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:
parent
4fae04968e
commit
1fe2e2941d
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user