Move can be used only when both the compared operand and the operand on switch are move operands. This commit directly changes to Copy, because I don't know if Move has beneficial.
228 lines
6.5 KiB
Rust
228 lines
6.5 KiB
Rust
//@ test-mir-pass: SimplifyComparisonIntegral
|
|
// 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 {
|
|
1
|
|
} else {
|
|
2
|
|
}
|
|
}
|
|
|
|
// 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,
|
|
true => 100 + b as 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');
|
|
opt_i8(22);
|
|
dont_opt_bool(false);
|
|
opt_negative(0);
|
|
opt_multiple_ifs(0);
|
|
dont_remove_comparison(11);
|
|
dont_opt_floats(1.0);
|
|
on_non_ssa_switch(42);
|
|
}
|