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>) {
}
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();
}
--- /dev/null
+- // 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
+ }
+ }
+
--- /dev/null
+- // 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
+ }
+ }
+
+ // 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
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
+ // + literal: Const { ty: isize, val: Value(Scalar(0x00000000)) }
-+ goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:5:22: 5:26
++ goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
}
bb1: {
}
bb3: {
- switchInt(_2) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:5:5: 7:6
+ switchInt(_2) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
}
bb4: {
- _0 = const (); // scope 0 at $DIR/matches_reduce_branches.rs:5:5: 7:6
+ _0 = const (); // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
// ty::Const
// + ty: ()
// + val: Value(Scalar(<ZST>))
// mir::Constant
- // + span: $DIR/matches_reduce_branches.rs:5:5: 7:6
+ // + span: $DIR/matches_reduce_branches.rs:6:5: 8:6
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
- goto -> bb5; // scope 0 at $DIR/matches_reduce_branches.rs:5:5: 7:6
+ goto -> bb5; // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
}
bb5: {
- StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:8:1: 8:2
- return; // scope 0 at $DIR/matches_reduce_branches.rs:8:2: 8:2
+ StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:9:1: 9:2
+ return; // scope 0 at $DIR/matches_reduce_branches.rs:9:2: 9:2
}
}
+ // 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
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
+ // + literal: Const { ty: isize, val: Value(Scalar(0x0000000000000000)) }
-+ goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:5:22: 5:26
++ goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
}
bb1: {
}
bb3: {
- switchInt(_2) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:5:5: 7:6
+ switchInt(_2) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
}
bb4: {
- _0 = const (); // scope 0 at $DIR/matches_reduce_branches.rs:5:5: 7:6
+ _0 = const (); // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
// ty::Const
// + ty: ()
// + val: Value(Scalar(<ZST>))
// mir::Constant
- // + span: $DIR/matches_reduce_branches.rs:5:5: 7:6
+ // + span: $DIR/matches_reduce_branches.rs:6:5: 8:6
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
- goto -> bb5; // scope 0 at $DIR/matches_reduce_branches.rs:5:5: 7:6
+ goto -> bb5; // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
}
bb5: {
- StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:8:1: 8:2
- return; // scope 0 at $DIR/matches_reduce_branches.rs:8:2: 8:2
+ StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:9:1: 9:2
+ return; // scope 0 at $DIR/matches_reduce_branches.rs:9:2: 9:2
}
}
// 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) {
}
}
+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);
}