implement simd_neg and simd_fabs
This commit is contained in:
parent
0147b88ce5
commit
0d4902f12f
@ -3,6 +3,7 @@
|
||||
#![feature(map_try_insert)]
|
||||
#![feature(never_type)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(let_else)]
|
||||
#![feature(bool_to_option)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![allow(clippy::cast_lossless)]
|
||||
|
@ -316,6 +316,37 @@ fn call_intrinsic(
|
||||
|
||||
// SIMD operations
|
||||
#[rustfmt::skip]
|
||||
| "simd_neg"
|
||||
| "simd_fabs" => {
|
||||
let &[ref op] = check_arg_count(args)?;
|
||||
let (op, op_len) = this.operand_to_simd(op)?;
|
||||
let (dest, dest_len) = this.place_to_simd(dest)?;
|
||||
|
||||
assert_eq!(dest_len, op_len);
|
||||
|
||||
for i in 0..dest_len {
|
||||
let op = this.read_immediate(&this.mplace_index(&op, i)?.into())?;
|
||||
let dest = this.mplace_index(&dest, i)?;
|
||||
let val = match intrinsic_name {
|
||||
"simd_neg" => this.unary_op(mir::UnOp::Neg, &op)?.to_scalar()?,
|
||||
"simd_fabs" => {
|
||||
// Works for f32 and f64.
|
||||
let ty::Float(float_ty) = op.layout.ty.kind() else {
|
||||
bug!("simd_fabs operand is not a float")
|
||||
};
|
||||
let op = op.to_scalar()?;
|
||||
// FIXME: Using host floats.
|
||||
match float_ty {
|
||||
FloatTy::F32 => Scalar::from_f32(op.to_f32()?.abs()),
|
||||
FloatTy::F64 => Scalar::from_f64(op.to_f64()?.abs()),
|
||||
}
|
||||
}
|
||||
_ => bug!(),
|
||||
};
|
||||
this.write_scalar(val, &dest.into())?;
|
||||
}
|
||||
}
|
||||
#[rustfmt::skip]
|
||||
| "simd_add"
|
||||
| "simd_sub"
|
||||
| "simd_mul"
|
||||
@ -374,12 +405,12 @@ fn call_intrinsic(
|
||||
}
|
||||
}
|
||||
"simd_reduce_any" => {
|
||||
let &[ref arg] = check_arg_count(args)?;
|
||||
let (arg, arg_len) = this.operand_to_simd(arg)?;
|
||||
let &[ref op] = check_arg_count(args)?;
|
||||
let (op, op_len) = this.operand_to_simd(op)?;
|
||||
|
||||
let mut res = false; // the neutral element
|
||||
for i in 0..arg_len {
|
||||
let op = this.read_immediate(&this.mplace_index(&arg, i)?.into())?;
|
||||
for i in 0..op_len {
|
||||
let op = this.read_immediate(&this.mplace_index(&op, i)?.into())?;
|
||||
let val = simd_element_to_bool(op)?;
|
||||
res = res | val;
|
||||
}
|
||||
|
@ -3,18 +3,34 @@
|
||||
|
||||
fn simd_ops_f32() {
|
||||
let a = f32x4::splat(10.0);
|
||||
let b = f32x4::from_array([1.0, 2.0, 3.0, 4.0]);
|
||||
assert_eq!(a + b, f32x4::from_array([11.0, 12.0, 13.0, 14.0]));
|
||||
assert_eq!(a - b, f32x4::from_array([9.0, 8.0, 7.0, 6.0]));
|
||||
assert_eq!(a * b, f32x4::from_array([10.0, 20.0, 30.0, 40.0]));
|
||||
assert_eq!(b / a, f32x4::from_array([0.1, 0.2, 0.3, 0.4]));
|
||||
let b = f32x4::from_array([1.0, 2.0, 3.0, -4.0]);
|
||||
assert_eq!(-b, f32x4::from_array([-1.0, -2.0, -3.0, 4.0]));
|
||||
assert_eq!(a + b, f32x4::from_array([11.0, 12.0, 13.0, 6.0]));
|
||||
assert_eq!(a - b, f32x4::from_array([9.0, 8.0, 7.0, 14.0]));
|
||||
assert_eq!(a * b, f32x4::from_array([10.0, 20.0, 30.0, -40.0]));
|
||||
assert_eq!(b / a, f32x4::from_array([0.1, 0.2, 0.3, -0.4]));
|
||||
assert_eq!(a / f32x4::splat(2.0), f32x4::splat(5.0));
|
||||
assert_eq!(a % b, f32x4::from_array([0.0, 0.0, 1.0, 2.0]));
|
||||
assert_eq!(b.abs(), f32x4::from_array([1.0, 2.0, 3.0, 4.0]));
|
||||
}
|
||||
|
||||
fn simd_ops_f64() {
|
||||
let a = f64x4::splat(10.0);
|
||||
let b = f64x4::from_array([1.0, 2.0, 3.0, -4.0]);
|
||||
assert_eq!(-b, f64x4::from_array([-1.0, -2.0, -3.0, 4.0]));
|
||||
assert_eq!(a + b, f64x4::from_array([11.0, 12.0, 13.0, 6.0]));
|
||||
assert_eq!(a - b, f64x4::from_array([9.0, 8.0, 7.0, 14.0]));
|
||||
assert_eq!(a * b, f64x4::from_array([10.0, 20.0, 30.0, -40.0]));
|
||||
assert_eq!(b / a, f64x4::from_array([0.1, 0.2, 0.3, -0.4]));
|
||||
assert_eq!(a / f64x4::splat(2.0), f64x4::splat(5.0));
|
||||
assert_eq!(a % b, f64x4::from_array([0.0, 0.0, 1.0, 2.0]));
|
||||
assert_eq!(b.abs(), f64x4::from_array([1.0, 2.0, 3.0, 4.0]));
|
||||
}
|
||||
|
||||
fn simd_ops_i32() {
|
||||
let a = i32x4::splat(10);
|
||||
let b = i32x4::from_array([1, 2, 3, 4]);
|
||||
assert_eq!(-b, i32x4::from_array([-1, -2, -3, -4]));
|
||||
assert_eq!(a + b, i32x4::from_array([11, 12, 13, 14]));
|
||||
assert_eq!(a - b, i32x4::from_array([9, 8, 7, 6]));
|
||||
assert_eq!(a * b, i32x4::from_array([10, 20, 30, 40]));
|
||||
@ -52,6 +68,7 @@ fn simd_intrinsics() {
|
||||
|
||||
fn main() {
|
||||
simd_ops_f32();
|
||||
simd_ops_f64();
|
||||
simd_ops_i32();
|
||||
simd_intrinsics();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user