mirror of https://github.com/rust-lang/rust.git
Fix simd comparison
This commit is contained in:
parent
9e3f2391b8
commit
90f2b12d47
|
@ -57,8 +57,12 @@ unsafe fn test_simd() {
|
||||||
let x = _mm_setzero_si128();
|
let x = _mm_setzero_si128();
|
||||||
let y = _mm_set1_epi16(7);
|
let y = _mm_set1_epi16(7);
|
||||||
let or = _mm_or_si128(x, y);
|
let or = _mm_or_si128(x, y);
|
||||||
|
let cmp_eq = _mm_cmpeq_epi8(y, y);
|
||||||
|
let cmp_lt = _mm_cmplt_epi8(y, y);
|
||||||
|
|
||||||
assert_eq!(std::mem::transmute::<_, [u16; 8]>(or), [7, 7, 7, 7, 7, 7, 7, 7]);
|
assert_eq!(std::mem::transmute::<_, [u16; 8]>(or), [7, 7, 7, 7, 7, 7, 7, 7]);
|
||||||
|
assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_eq), [0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff]);
|
||||||
|
assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_lt), [0, 0, 0, 0, 0, 0, 0, 0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
|
|
|
@ -155,26 +155,40 @@ fn simd_for_each_lane<'tcx, B: Backend>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! simd_binop {
|
fn bool_to_zero_or_max_uint<'tcx>(
|
||||||
($fx:expr, $intrinsic:expr, icmp($cc:ident, $x:ident, $y:ident) -> $ret:ident) => {
|
fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
|
||||||
simd_for_each_lane($fx, $intrinsic, $x, $y, $ret, |fx, _lane_layout, ret_lane_layout, x_lane, y_lane| {
|
layout: TyLayout<'tcx>,
|
||||||
|
val: Value,
|
||||||
|
) -> CValue<'tcx> {
|
||||||
|
let ty = fx.clif_type(layout.ty).unwrap();
|
||||||
|
|
||||||
|
let zero = fx.bcx.ins().iconst(ty, 0);
|
||||||
|
let max = fx.bcx.ins().iconst(ty, (u64::max_value() >> (64 - ty.bits())) as i64);
|
||||||
|
let res = crate::common::codegen_select(&mut fx.bcx, val, max, zero);
|
||||||
|
CValue::by_val(res, layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! simd_cmp {
|
||||||
|
($fx:expr, $intrinsic:expr, $cc:ident($x:ident, $y:ident) -> $ret:ident) => {
|
||||||
|
simd_for_each_lane($fx, $intrinsic, $x, $y, $ret, |fx, _lane_layout, res_lane_layout, x_lane, y_lane| {
|
||||||
let res_lane = fx.bcx.ins().icmp(IntCC::$cc, x_lane, y_lane);
|
let res_lane = fx.bcx.ins().icmp(IntCC::$cc, x_lane, y_lane);
|
||||||
let res_lane = fx.bcx.ins().bint(types::I8, res_lane);
|
bool_to_zero_or_max_uint(fx, res_lane_layout, res_lane)
|
||||||
CValue::by_val(res_lane, ret_lane_layout)
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
($fx:expr, $intrinsic:expr, icmp($cc_u:ident|$cc_s:ident, $x:ident, $y:ident) -> $ret:ident) => {
|
($fx:expr, $intrinsic:expr, $cc_u:ident|$cc_s:ident($x:ident, $y:ident) -> $ret:ident) => {
|
||||||
simd_for_each_lane($fx, $intrinsic, $x, $y, $ret, |fx, lane_layout, ret_lane_layout, x_lane, y_lane| {
|
simd_for_each_lane($fx, $intrinsic, $x, $y, $ret, |fx, lane_layout, res_lane_layout, x_lane, y_lane| {
|
||||||
let res_lane = match lane_layout.ty.sty {
|
let res_lane = match lane_layout.ty.sty {
|
||||||
ty::Uint(_) => fx.bcx.ins().icmp(IntCC::$cc_u, x_lane, y_lane),
|
ty::Uint(_) => fx.bcx.ins().icmp(IntCC::$cc_u, x_lane, y_lane),
|
||||||
ty::Int(_) => fx.bcx.ins().icmp(IntCC::$cc_s, x_lane, y_lane),
|
ty::Int(_) => fx.bcx.ins().icmp(IntCC::$cc_s, x_lane, y_lane),
|
||||||
_ => unreachable!("{:?}", lane_layout.ty),
|
_ => unreachable!("{:?}", lane_layout.ty),
|
||||||
};
|
};
|
||||||
let res_lane = fx.bcx.ins().bint(types::I8, res_lane);
|
bool_to_zero_or_max_uint(fx, res_lane_layout, res_lane)
|
||||||
CValue::by_val(res_lane, ret_lane_layout)
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! simd_binop {
|
||||||
($fx:expr, $intrinsic:expr, $op:ident($x:ident, $y:ident) -> $ret:ident) => {
|
($fx:expr, $intrinsic:expr, $op:ident($x:ident, $y:ident) -> $ret:ident) => {
|
||||||
simd_for_each_lane($fx, $intrinsic, $x, $y, $ret, |fx, _lane_layout, ret_lane_layout, x_lane, y_lane| {
|
simd_for_each_lane($fx, $intrinsic, $x, $y, $ret, |fx, _lane_layout, ret_lane_layout, x_lane, y_lane| {
|
||||||
let res_lane = fx.bcx.ins().$op(x_lane, y_lane);
|
let res_lane = fx.bcx.ins().$op(x_lane, y_lane);
|
||||||
|
@ -773,22 +787,22 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
simd_eq, (c x, c y) {
|
simd_eq, (c x, c y) {
|
||||||
simd_binop!(fx, intrinsic, icmp(Equal, x, y) -> ret);
|
simd_cmp!(fx, intrinsic, Equal(x, y) -> ret);
|
||||||
};
|
};
|
||||||
simd_ne, (c x, c y) {
|
simd_ne, (c x, c y) {
|
||||||
simd_binop!(fx, intrinsic, icmp(NotEqual, x, y) -> ret);
|
simd_cmp!(fx, intrinsic, NotEqual(x, y) -> ret);
|
||||||
};
|
};
|
||||||
simd_lt, (c x, c y) {
|
simd_lt, (c x, c y) {
|
||||||
simd_binop!(fx, intrinsic, icmp(UnsignedLessThan|SignedLessThan, x, y) -> ret);
|
simd_cmp!(fx, intrinsic, UnsignedLessThan|SignedLessThan(x, y) -> ret);
|
||||||
};
|
};
|
||||||
simd_le, (c x, c y) {
|
simd_le, (c x, c y) {
|
||||||
simd_binop!(fx, intrinsic, icmp(UnsignedLessThanOrEqual|SignedLessThanOrEqual, x, y) -> ret);
|
simd_cmp!(fx, intrinsic, UnsignedLessThanOrEqual|SignedLessThanOrEqual(x, y) -> ret);
|
||||||
};
|
};
|
||||||
simd_gt, (c x, c y) {
|
simd_gt, (c x, c y) {
|
||||||
simd_binop!(fx, intrinsic, icmp(UnsignedGreaterThan|SignedGreaterThan, x, y) -> ret);
|
simd_cmp!(fx, intrinsic, UnsignedGreaterThan|SignedGreaterThan(x, y) -> ret);
|
||||||
};
|
};
|
||||||
simd_ge, (c x, c y) {
|
simd_ge, (c x, c y) {
|
||||||
simd_binop!(fx, intrinsic, icmp(UnsignedGreaterThanOrEqual|SignedGreaterThanOrEqual, x, y) -> ret);
|
simd_cmp!(fx, intrinsic, UnsignedGreaterThanOrEqual|SignedGreaterThanOrEqual(x, y) -> ret);
|
||||||
};
|
};
|
||||||
|
|
||||||
simd_add, (c x, c y) {
|
simd_add, (c x, c y) {
|
||||||
|
|
Loading…
Reference in New Issue