diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index c1f8c46baddbe..adaac3d7ffc2f 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -374,6 +374,12 @@ impl<'tcx> Place<'tcx> { self.projection.iter().any(|elem| elem.is_indirect()) } + /// Returns `true` if the `Place` always refers to the same memory region + /// whatever the state of the program. + pub fn is_stable_offset(&self) -> bool { + self.projection.iter().all(|elem| elem.is_stable_offset()) + } + /// Returns `true` if this `Place`'s first projection is `Deref`. /// /// This is useful because for MIR phases `AnalysisPhase::PostCleanup` and later, diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index 2643d78990e57..58b5e45672a2f 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -9,6 +9,8 @@ use rustc_middle::mir::{ use rustc_middle::ty::{Ty, TyCtxt}; use tracing::trace; +use crate::ssa::SsaLocals; + /// Pass to convert `if` conditions on integrals into switches on the integral. /// For an example, it turns something like /// @@ -27,17 +29,18 @@ pub(super) struct SimplifyComparisonIntegral; impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() > 0 + sess.mir_opt_level() > 1 } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("Running SimplifyComparisonIntegral on {:?}", body.source); + let typing_env = body.typing_env(tcx); + let ssa = SsaLocals::new(tcx, body, typing_env); let helper = OptimizationFinder { body }; - let opts = helper.find_optimizations(); + let opts = helper.find_optimizations(&ssa); let mut storage_deads_to_insert = vec![]; let mut storage_deads_to_remove: Vec<(usize, BasicBlock)> = vec![]; - let typing_env = body.typing_env(tcx); for opt in opts { trace!("SUCCESS: Applying {:?}", opt); // replace terminator with a switchInt that switches on the integer directly @@ -132,7 +135,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { let terminator = bb.terminator_mut(); terminator.kind = - TerminatorKind::SwitchInt { discr: Operand::Move(opt.to_switch_on), targets }; + TerminatorKind::SwitchInt { discr: Operand::Copy(opt.to_switch_on), targets }; } for (idx, bb_idx) in storage_deads_to_remove { @@ -154,19 +157,18 @@ struct OptimizationFinder<'a, 'tcx> { } impl<'tcx> OptimizationFinder<'_, 'tcx> { - fn find_optimizations(&self) -> Vec> { + fn find_optimizations(&self, ssa: &SsaLocals) -> Vec> { self.body .basic_blocks .iter_enumerated() .filter_map(|(bb_idx, bb)| { // find switch - let (place_switched_on, targets, place_switched_on_moved) = - match &bb.terminator().kind { - rustc_middle::mir::TerminatorKind::SwitchInt { discr, targets, .. } => { - Some((discr.place()?, targets, discr.is_move())) - } - _ => None, - }?; + let (discr, targets) = bb.terminator().kind.as_switch()?; + let place_switched_on = discr.place()?; + // Make sure that the place is not modified. + if !ssa.is_ssa(place_switched_on.local) || !place_switched_on.is_stable_offset() { + return None; + } // find the statement that assigns the place being switched on bb.statements.iter().enumerate().rev().find_map(|(stmt_idx, stmt)| { @@ -180,12 +182,12 @@ impl<'tcx> OptimizationFinder<'_, 'tcx> { box (left, right), ) => { let (branch_value_scalar, branch_value_ty, to_switch_on) = - find_branch_value_info(left, right)?; + find_branch_value_info(left, right, ssa)?; Some(OptimizationInfo { bin_op_stmt_idx: stmt_idx, bb_idx, - can_remove_bin_op_stmt: place_switched_on_moved, + can_remove_bin_op_stmt: discr.is_move(), to_switch_on, branch_value_scalar, branch_value_ty, @@ -207,6 +209,7 @@ impl<'tcx> OptimizationFinder<'_, 'tcx> { fn find_branch_value_info<'tcx>( left: &Operand<'tcx>, right: &Operand<'tcx>, + ssa: &SsaLocals, ) -> Option<(Scalar, Ty<'tcx>, Place<'tcx>)> { // check that either left or right is a constant. // if any are, we can use the other to switch on, and the constant as a value in a switch @@ -214,6 +217,10 @@ fn find_branch_value_info<'tcx>( match (left, right) { (Constant(branch_value), Copy(to_switch_on) | Move(to_switch_on)) | (Copy(to_switch_on) | Move(to_switch_on), Constant(branch_value)) => { + // Make sure that the place is not modified. + if !ssa.is_ssa(to_switch_on.local) || !to_switch_on.is_stable_offset() { + return None; + } let branch_value_ty = branch_value.const_.ty(); // we only want to apply this optimization if we are matching on integrals (and chars), // as it is not possible to switch on floats diff --git a/tests/debuginfo/dummy_span.rs b/tests/debuginfo/dummy_span.rs index fec4f33e3d569..6cf79c46d9a9e 100644 --- a/tests/debuginfo/dummy_span.rs +++ b/tests/debuginfo/dummy_span.rs @@ -1,6 +1,8 @@ //@ min-lldb-version: 310 //@ compile-flags:-g +// FIXME: Investigate why test fails without SimplifyComparisonIntegral pass. +//@ compile-flags: -Zmir-enable-passes=+SimplifyComparisonIntegral //@ ignore-backends: gcc // === GDB TESTS =================================================================================== diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff index 6baa902b6f4bd..2b77aa380a0fe 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff @@ -74,7 +74,7 @@ _23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); _22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG); StorageDead(_23); - switchInt(move _22) -> [0: bb10, otherwise: bb11]; + switchInt(copy _22) -> [0: bb10, otherwise: bb11]; } bb4: { diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff index 36540e038654f..ba6d2f3e155c8 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff @@ -74,7 +74,7 @@ _23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); _22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG); StorageDead(_23); - switchInt(move _22) -> [0: bb10, otherwise: bb11]; + switchInt(copy _22) -> [0: bb10, otherwise: bb11]; } bb4: { diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff index 41c350f3eaeb5..bf6d9d864d578 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff @@ -74,7 +74,7 @@ _23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); _22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG); StorageDead(_23); - switchInt(move _22) -> [0: bb10, otherwise: bb11]; + switchInt(copy _22) -> [0: bb10, otherwise: bb11]; } bb4: { diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff index b839bf81eaf45..01c87fd5317a9 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff @@ -74,7 +74,7 @@ _23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); _22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG); StorageDead(_23); - switchInt(move _22) -> [0: bb10, otherwise: bb11]; + switchInt(copy _22) -> [0: bb10, otherwise: bb11]; } bb4: { diff --git a/tests/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff index 2350faa05d3f0..f2d527326592e 100644 --- a/tests/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff @@ -9,7 +9,7 @@ bb0: { StorageLive(_2); _2 = copy _1; - switchInt(move _2) -> [0: bb2, otherwise: bb1]; + switchInt(copy _1) -> [0: bb2, otherwise: bb1]; } bb1: { diff --git a/tests/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff index 94570017730df..c72a58a145f4e 100644 --- a/tests/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff @@ -11,7 +11,7 @@ StorageLive(_2); StorageLive(_3); _3 = copy _1; - _2 = Eq(move _3, const -42f32); + _2 = Eq(copy _1, const -42f32); switchInt(move _2) -> [0: bb2, otherwise: bb1]; } diff --git a/tests/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff index d19b4148405e2..f5f2e0317ead1 100644 --- a/tests/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff @@ -15,23 +15,20 @@ } bb0: { - StorageLive(_2); + nop; StorageLive(_3); _3 = copy _1; -- _2 = Eq(move _3, const 17_i8); -- StorageDead(_3); + _2 = Eq(copy _1, const 17_i8); + StorageDead(_3); - switchInt(copy _2) -> [0: bb2, otherwise: bb1]; -+ _2 = Eq(copy _3, const 17_i8); -+ nop; -+ switchInt(move _3) -> [17: bb1, otherwise: bb2]; ++ switchInt(copy _1) -> [17: bb1, otherwise: bb2]; } bb1: { -+ StorageDead(_3); StorageLive(_6); StorageLive(_7); _7 = copy _2; - _6 = move _7 as i32 (IntToInt); + _6 = copy _2 as i32 (IntToInt); StorageDead(_7); _0 = Add(const 100_i32, move _6); StorageDead(_6); @@ -39,11 +36,10 @@ } bb2: { -+ StorageDead(_3); StorageLive(_4); StorageLive(_5); _5 = copy _2; - _4 = move _5 as i32 (IntToInt); + _4 = copy _2 as i32 (IntToInt); StorageDead(_5); _0 = Add(const 10_i32, move _4); StorageDead(_4); @@ -51,7 +47,7 @@ } bb3: { - StorageDead(_2); + nop; return; } } diff --git a/tests/mir-opt/if_condition_int.on_non_ssa_cmp.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.on_non_ssa_cmp.SimplifyComparisonIntegral.diff new file mode 100644 index 0000000000000..ce5a2bf172a97 --- /dev/null +++ b/tests/mir-opt/if_condition_int.on_non_ssa_cmp.SimplifyComparisonIntegral.diff @@ -0,0 +1,24 @@ +- // MIR for `on_non_ssa_cmp` before SimplifyComparisonIntegral ++ // MIR for `on_non_ssa_cmp` after SimplifyComparisonIntegral + + fn on_non_ssa_cmp(_1: u64) -> i32 { + let mut _0: i32; + let mut _2: bool; + + bb0: { + _2 = Eq(copy _1, const 42_u64); + _1 = const 43_u64; + switchInt(copy _2) -> [1: bb1, otherwise: bb2]; + } + + bb1: { + _0 = const 0_i32; + return; + } + + bb2: { + _0 = const 1_i32; + return; + } + } + diff --git a/tests/mir-opt/if_condition_int.on_non_ssa_place.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.on_non_ssa_place.SimplifyComparisonIntegral.diff new file mode 100644 index 0000000000000..7ad0a87f1cdd9 --- /dev/null +++ b/tests/mir-opt/if_condition_int.on_non_ssa_place.SimplifyComparisonIntegral.diff @@ -0,0 +1,24 @@ +- // MIR for `on_non_ssa_place` before SimplifyComparisonIntegral ++ // MIR for `on_non_ssa_place` after SimplifyComparisonIntegral + + fn on_non_ssa_place(_1: [u64; 10], _2: usize) -> i32 { + let mut _0: i32; + let mut _3: bool; + + bb0: { + _3 = Eq(copy _1[_2], const 42_u64); + _2 = const 10_usize; + switchInt(copy _3) -> [1: bb1, otherwise: bb2]; + } + + bb1: { + _0 = const 0_i32; + return; + } + + bb2: { + _0 = const 1_i32; + return; + } + } + diff --git a/tests/mir-opt/if_condition_int.on_non_ssa_switch.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.on_non_ssa_switch.SimplifyComparisonIntegral.diff new file mode 100644 index 0000000000000..e2dc97f76b5c8 --- /dev/null +++ b/tests/mir-opt/if_condition_int.on_non_ssa_switch.SimplifyComparisonIntegral.diff @@ -0,0 +1,24 @@ +- // MIR for `on_non_ssa_switch` before SimplifyComparisonIntegral ++ // MIR for `on_non_ssa_switch` after SimplifyComparisonIntegral + + fn on_non_ssa_switch(_1: u64) -> i32 { + let mut _0: i32; + let mut _2: bool; + + bb0: { + _2 = Eq(copy _1, const 42_u64); + _2 = const false; + switchInt(copy _2) -> [1: bb1, otherwise: bb2]; + } + + bb1: { + _0 = const 0_i32; + return; + } + + bb2: { + _0 = const 1_i32; + return; + } + } + diff --git a/tests/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff index e47b7e5225983..22f6443a6c0f9 100644 --- a/tests/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff @@ -11,10 +11,10 @@ StorageLive(_2); StorageLive(_3); _3 = copy _1; -- _2 = Eq(move _3, const 'x'); +- _2 = Eq(copy _1, const 'x'); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; + nop; -+ switchInt(move _3) -> [120: bb1, otherwise: bb2]; ++ switchInt(copy _1) -> [120: bb1, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff index b6cdc6af8bf48..d5c48fd04ca60 100644 --- a/tests/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff @@ -11,10 +11,10 @@ StorageLive(_2); StorageLive(_3); _3 = copy _1; -- _2 = Eq(move _3, const 42_i8); +- _2 = Eq(copy _1, const 42_i8); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; + nop; -+ switchInt(move _3) -> [42: bb1, otherwise: bb2]; ++ switchInt(copy _1) -> [42: bb1, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff index 31745ac732a22..84d62b8136078 100644 --- a/tests/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff @@ -13,10 +13,10 @@ StorageLive(_2); StorageLive(_3); _3 = copy _1; -- _2 = Eq(move _3, const 42_u32); +- _2 = Eq(copy _1, const 42_u32); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; + nop; -+ switchInt(move _3) -> [42: bb1, otherwise: bb2]; ++ switchInt(copy _1) -> [42: bb1, otherwise: bb2]; } bb1: { @@ -30,10 +30,10 @@ StorageLive(_4); StorageLive(_5); _5 = copy _1; -- _4 = Ne(move _5, const 21_u32); +- _4 = Ne(copy _1, const 21_u32); - switchInt(move _4) -> [0: bb4, otherwise: bb3]; + nop; -+ switchInt(move _5) -> [21: bb4, otherwise: bb3]; ++ switchInt(copy _1) -> [21: bb4, otherwise: bb3]; } bb3: { diff --git a/tests/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff index d747985f6e135..a1cbaff796b35 100644 --- a/tests/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff @@ -11,10 +11,10 @@ StorageLive(_2); StorageLive(_3); _3 = copy _1; -- _2 = Eq(move _3, const -42_i32); +- _2 = Eq(copy _1, const -42_i32); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; + nop; -+ switchInt(move _3) -> [4294967254: bb1, otherwise: bb2]; ++ switchInt(copy _1) -> [4294967254: bb1, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff index 1d6809a9438a0..8101de8cbf381 100644 --- a/tests/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff @@ -11,10 +11,10 @@ StorageLive(_2); StorageLive(_3); _3 = copy _1; -- _2 = Eq(move _3, const 42_u32); +- _2 = Eq(copy _1, const 42_u32); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; + nop; -+ switchInt(move _3) -> [42: bb1, otherwise: bb2]; ++ switchInt(copy _1) -> [42: bb1, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/if_condition_int.rs b/tests/mir-opt/if_condition_int.rs index 4cc2c2b902102..5e0961da3ccea 100644 --- a/tests/mir-opt/if_condition_int.rs +++ b/tests/mir-opt/if_condition_int.rs @@ -1,36 +1,80 @@ -// skip-filecheck //@ test-mir-pass: SimplifyComparisonIntegral -// EMIT_MIR if_condition_int.opt_u32.SimplifyComparisonIntegral.diff -// EMIT_MIR if_condition_int.opt_negative.SimplifyComparisonIntegral.diff -// EMIT_MIR if_condition_int.opt_char.SimplifyComparisonIntegral.diff -// EMIT_MIR if_condition_int.opt_i8.SimplifyComparisonIntegral.diff -// EMIT_MIR if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff -// EMIT_MIR if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff -// EMIT_MIR if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff -// EMIT_MIR if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff +// GVN simplifies FileCheck. +//@ compile-flags: -Zmir-enable-passes=+GVN +#![feature(custom_mir, core_intrinsics)] + +extern crate core; +use core::intrinsics::mir::*; + +// EMIT_MIR if_condition_int.opt_u32.SimplifyComparisonIntegral.diff fn opt_u32(x: u32) -> u32 { + // CHECK-LABEL: fn opt_u32( + // CHECK: switchInt(copy _1) -> [42: [[BB1:bb.*]], otherwise: [[BB2:bb.*]]]; + // CHECK: [[BB1]]: + // CHECK: _0 = const 0_u32; + // CHECK: [[BB2]]: + // CHECK: _0 = const 1_u32; if x == 42 { 0 } else { 1 } } +// EMIT_MIR if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff // don't opt: it is already optimal to switch on the bool fn dont_opt_bool(x: bool) -> u32 { + // CHECK-LABEL: fn dont_opt_bool( + // CHECK: switchInt(copy _1) -> [0: [[BB2:bb.*]], otherwise: [[BB1:bb.*]]]; + // CHECK: [[BB1]]: + // CHECK: _0 = const 0_u32; + // CHECK: [[BB2]]: + // CHECK: _0 = const 1_u32; if x { 0 } else { 1 } } +// EMIT_MIR if_condition_int.opt_char.SimplifyComparisonIntegral.diff fn opt_char(x: char) -> u32 { + // CHECK-LABEL: fn opt_char( + // CHECK: switchInt(copy _1) -> [120: [[BB1:bb.*]], otherwise: [[BB2:bb.*]]]; + // CHECK: [[BB1]]: + // CHECK: _0 = const 0_u32; + // CHECK: [[BB2]]: + // CHECK: _0 = const 1_u32; if x == 'x' { 0 } else { 1 } } +// EMIT_MIR if_condition_int.opt_i8.SimplifyComparisonIntegral.diff fn opt_i8(x: i8) -> u32 { + // CHECK-LABEL: fn opt_i8( + // CHECK: switchInt(copy _1) -> [42: [[BB1:bb.*]], otherwise: [[BB2:bb.*]]]; + // CHECK: [[BB1]]: + // CHECK: _0 = const 0_u32; + // CHECK: [[BB2]]: + // CHECK: _0 = const 1_u32; if x == 42 { 0 } else { 1 } } +// EMIT_MIR if_condition_int.opt_negative.SimplifyComparisonIntegral.diff fn opt_negative(x: i32) -> u32 { + // CHECK-LABEL: fn opt_negative( + // CHECK: switchInt(copy _1) -> [4294967254: [[BB1:bb.*]], otherwise: [[BB2:bb.*]]]; + // CHECK: [[BB1]]: + // CHECK: _0 = const 0_u32; + // CHECK: [[BB2]]: + // CHECK: _0 = const 1_u32; if x == -42 { 0 } else { 1 } } +// EMIT_MIR if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff fn opt_multiple_ifs(x: u32) -> u32 { + // CHECK-LABEL: fn opt_multiple_ifs( + // CHECK: switchInt(copy _1) -> [42: [[BB1:bb.*]], otherwise: [[BB2:bb.*]]]; + // CHECK: [[BB1]]: + // CHECK: _0 = const 0_u32; + // CHECK: [[BB2]]: + // CHECK: switchInt(copy _1) -> [21: [[BB4:bb.*]], otherwise: [[BB3:bb.*]]]; + // CHECK: [[BB3]]: + // CHECK: _0 = const 1_u32; + // CHECK: [[BB4]]: + // CHECK: _0 = const 2_u32; if x == 42 { 0 } else if x != 21 { @@ -40,8 +84,18 @@ fn opt_multiple_ifs(x: u32) -> u32 { } } +// EMIT_MIR if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff // test that we optimize, but do not remove the b statement, as that is used later on fn dont_remove_comparison(a: i8) -> i32 { + // CHECK-LABEL: fn dont_remove_comparison( + // CHECK: [[b:_.*]] = Eq(copy _1, const 17_i8); + // CHECK: switchInt(copy _1) -> [17: [[BB1:bb.*]], otherwise: [[BB2:bb.*]]]; + // CHECK: [[BB1]]: + // CHECK: [[cast_1:_.*]] = copy [[b]] as i32 (IntToInt); + // CHECK: _0 = Add(const 100_i32, move [[cast_1]]); + // CHECK: [[BB2]]: + // CHECK: [[cast_2:_.*]] = copy [[b]] as i32 (IntToInt); + // CHECK: _0 = Add(const 10_i32, move [[cast_2]]); let b = a == 17; match b { false => 10 + b as i32, @@ -49,11 +103,118 @@ fn dont_remove_comparison(a: i8) -> i32 { } } +// EMIT_MIR if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff // test that we do not optimize on floats fn dont_opt_floats(a: f32) -> i32 { + // CHECK-LABEL: fn dont_opt_floats( + // CHECK: [[cmp:_.*]] = Eq(copy _1, const -42f32); + // CHECK: switchInt(move [[cmp]]) -> [0: [[BB2:bb.*]], otherwise: [[BB1:bb.*]]]; + // CHECK: [[BB1]]: + // CHECK: _0 = const 0_i32; + // CHECK: [[BB2]]: + // CHECK: _0 = const 1_i32; if a == -42.0 { 0 } else { 1 } } +// EMIT_MIR if_condition_int.on_non_ssa_switch.SimplifyComparisonIntegral.diff +#[custom_mir(dialect = "runtime")] +pub fn on_non_ssa_switch(mut v: u64) -> i32 { + // CHECK-LABEL: fn on_non_ssa_switch( + // CHECK: [[cmp:_.*]] = Eq(copy _1, const 42_u64); + // CHECK: [[cmp]] = const false; + // CHECK: switchInt(copy [[cmp]]) -> [1: [[BB1:bb.*]], otherwise: [[BB2:bb.*]]]; + // CHECK: [[BB1]]: + // CHECK: _0 = const 0_i32; + // CHECK: [[BB2]]: + // CHECK: _0 = const 1_i32; + mir! { + let a: bool; + { + a = v == 42; + a = false; + match a { + true => bb1, + _ => bb2, + } + + } + bb1 = { + RET = 0; + Return() + } + bb2 = { + RET = 1; + Return() + } + } +} + +// EMIT_MIR if_condition_int.on_non_ssa_cmp.SimplifyComparisonIntegral.diff +#[custom_mir(dialect = "runtime")] +pub fn on_non_ssa_cmp(mut v: u64) -> i32 { + // CHECK-LABEL: fn on_non_ssa_cmp( + // CHECK: [[cmp:_.*]] = Eq(copy _1, const 42_u64); + // CHECK: _1 = const 43_u64; + // CHECK: switchInt(copy [[cmp]]) -> [1: [[BB1:bb.*]], otherwise: [[BB2:bb.*]]]; + // CHECK: [[BB1]]: + // CHECK: _0 = const 0_i32; + // CHECK: [[BB2]]: + // CHECK: _0 = const 1_i32; + mir! { + let a: bool; + { + a = v == 42; + v = 43; + match a { + true => bb1, + _ => bb2, + } + + } + bb1 = { + RET = 0; + Return() + } + bb2 = { + RET = 1; + Return() + } + } +} + +// EMIT_MIR if_condition_int.on_non_ssa_place.SimplifyComparisonIntegral.diff +#[custom_mir(dialect = "runtime")] +pub fn on_non_ssa_place(mut v: [u64; 10], mut i: usize) -> i32 { + // CHECK-LABEL: fn on_non_ssa_place( + // CHECK: [[cmp:_.*]] = Eq(copy _1[_2], const 42_u64); + // CHECK: _2 = const 10_usize; + // CHECK: switchInt(copy [[cmp]]) -> [1: [[BB1:bb.*]], otherwise: [[BB2:bb.*]]]; + // CHECK: [[BB1]]: + // CHECK: _0 = const 0_i32; + // CHECK: [[BB2]]: + // CHECK: _0 = const 1_i32; + mir! { + let a: bool; + { + a = v[i] == 42; + i = 10; + match a { + true => bb1, + _ => bb2, + } + + } + bb1 = { + RET = 0; + Return() + } + bb2 = { + RET = 1; + Return() + } + } +} + fn main() { opt_u32(0); opt_char('0'); @@ -63,4 +224,5 @@ fn main() { opt_multiple_ifs(0); dont_remove_comparison(11); dont_opt_floats(1.0); + on_non_ssa_switch(42); } diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.32bit.panic-abort.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.32bit.panic-abort.mir index b5c23822162c9..f3c83f62edf61 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.32bit.panic-abort.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.32bit.panic-abort.mir @@ -28,7 +28,7 @@ fn num_to_digit(_1: char) -> u32 { StorageLive(_3); _3 = discriminant(_2); StorageDead(_2); - switchInt(move _3) -> [1: bb2, otherwise: bb7]; + switchInt(copy _3) -> [1: bb2, otherwise: bb7]; } bb2: { diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.32bit.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.32bit.panic-unwind.mir index f22b8835735d1..0e55df24cc57b 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.32bit.panic-unwind.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.32bit.panic-unwind.mir @@ -28,7 +28,7 @@ fn num_to_digit(_1: char) -> u32 { StorageLive(_3); _3 = discriminant(_2); StorageDead(_2); - switchInt(move _3) -> [1: bb2, otherwise: bb7]; + switchInt(copy _3) -> [1: bb2, otherwise: bb7]; } bb2: { diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-abort.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-abort.mir index b5c23822162c9..f3c83f62edf61 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-abort.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-abort.mir @@ -28,7 +28,7 @@ fn num_to_digit(_1: char) -> u32 { StorageLive(_3); _3 = discriminant(_2); StorageDead(_2); - switchInt(move _3) -> [1: bb2, otherwise: bb7]; + switchInt(copy _3) -> [1: bb2, otherwise: bb7]; } bb2: { diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-unwind.mir index f22b8835735d1..0e55df24cc57b 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-unwind.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-unwind.mir @@ -28,7 +28,7 @@ fn num_to_digit(_1: char) -> u32 { StorageLive(_3); _3 = discriminant(_2); StorageDead(_2); - switchInt(move _3) -> [1: bb2, otherwise: bb7]; + switchInt(copy _3) -> [1: bb2, otherwise: bb7]; } bb2: {