implement simd_select

This commit is contained in:
Ralf Jung 2022-03-01 18:40:40 -05:00
parent f672282bf2
commit aa4f82ea48
3 changed files with 35 additions and 10 deletions

View file

@ -1 +1 @@
6a705566166debf5eff88c57140df607fa409aaa
f0c4da49983aa699f715caf681e3154b445fb60b

View file

@ -386,6 +386,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
this.write_scalar(Scalar::from_bool(res), dest)?;
}
"simd_select" => {
let &[ref mask, ref yes, ref no] = check_arg_count(args)?;
let (mask, mask_len) = this.operand_to_simd(mask)?;
let (yes, yes_len) = this.operand_to_simd(yes)?;
let (no, no_len) = this.operand_to_simd(no)?;
let (dest, dest_len) = this.place_to_simd(dest)?;
assert_eq!(dest_len, mask_len);
assert_eq!(dest_len, yes_len);
assert_eq!(dest_len, no_len);
for i in 0..dest_len {
let mask = this.read_immediate(&this.mplace_index(&mask, i)?.into())?;
let yes = this.read_immediate(&this.mplace_index(&yes, i)?.into())?;
let no = this.read_immediate(&this.mplace_index(&no, i)?.into())?;
let dest = this.mplace_index(&dest, i)?;
let mask = simd_element_to_bool(mask)?;
let val = if mask { yes } else { no };
this.write_immediate(*val, &dest.into())?;
}
}
// Atomic operations
"atomic_load" => this.atomic_load(args, dest, AtomicReadOp::SeqCst)?,

View file

@ -29,19 +29,22 @@ fn simd_ops_i32() {
fn simd_intrinsics() {
extern "platform-intrinsic" {
pub(crate) fn simd_eq<T, U>(x: T, y: T) -> U;
pub(crate) fn simd_reduce_any<T>(x: T) -> bool;
fn simd_eq<T, U>(x: T, y: T) -> U;
fn simd_reduce_any<T>(x: T) -> bool;
fn simd_select<M, T>(m: M, yes: T, no: T) -> T;
}
// Make sure simd_eq returns all-1 for `true`
let a = i32x4::splat(10);
let b = i32x4::from_array([1, 2, 10, 4]);
let c: i32x4 = unsafe { simd_eq(a, b) };
assert_eq!(c, i32x4::from_array([0, 0, -1, 0]));
unsafe {
// Make sure simd_eq returns all-1 for `true`
let a = i32x4::splat(10);
let b = i32x4::from_array([1, 2, 10, 4]);
let c: i32x4 = simd_eq(a, b);
assert_eq!(c, i32x4::from_array([0, 0, -1, 0]));
assert!(!simd_reduce_any(i32x4::splat(0)));
assert!(simd_reduce_any(i32x4::splat(-1)));
assert_eq!(simd_select(i8x4::from_array([0, -1, -1, 0]), a, b), i32x4::from_array([1, 10, 10, 4]));
assert_eq!(simd_select(i8x4::from_array([0, -1, -1, 0]), b, a), i32x4::from_array([10, 2, 10, 10]));
}
}