Skip to content

Commit aa4f82e

Browse files
committed
implement simd_select
1 parent f672282 commit aa4f82e

File tree

3 files changed

+35
-10
lines changed

3 files changed

+35
-10
lines changed

rust-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
6a705566166debf5eff88c57140df607fa409aaa
1+
f0c4da49983aa699f715caf681e3154b445fb60b

src/shims/intrinsics.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
386386

387387
this.write_scalar(Scalar::from_bool(res), dest)?;
388388
}
389+
"simd_select" => {
390+
let &[ref mask, ref yes, ref no] = check_arg_count(args)?;
391+
let (mask, mask_len) = this.operand_to_simd(mask)?;
392+
let (yes, yes_len) = this.operand_to_simd(yes)?;
393+
let (no, no_len) = this.operand_to_simd(no)?;
394+
let (dest, dest_len) = this.place_to_simd(dest)?;
395+
396+
assert_eq!(dest_len, mask_len);
397+
assert_eq!(dest_len, yes_len);
398+
assert_eq!(dest_len, no_len);
399+
400+
for i in 0..dest_len {
401+
let mask = this.read_immediate(&this.mplace_index(&mask, i)?.into())?;
402+
let yes = this.read_immediate(&this.mplace_index(&yes, i)?.into())?;
403+
let no = this.read_immediate(&this.mplace_index(&no, i)?.into())?;
404+
let dest = this.mplace_index(&dest, i)?;
405+
406+
let mask = simd_element_to_bool(mask)?;
407+
let val = if mask { yes } else { no };
408+
this.write_immediate(*val, &dest.into())?;
409+
}
410+
}
389411

390412
// Atomic operations
391413
"atomic_load" => this.atomic_load(args, dest, AtomicReadOp::SeqCst)?,

tests/run-pass/portable-simd.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,22 @@ fn simd_ops_i32() {
2929

3030
fn simd_intrinsics() {
3131
extern "platform-intrinsic" {
32-
pub(crate) fn simd_eq<T, U>(x: T, y: T) -> U;
33-
pub(crate) fn simd_reduce_any<T>(x: T) -> bool;
32+
fn simd_eq<T, U>(x: T, y: T) -> U;
33+
fn simd_reduce_any<T>(x: T) -> bool;
34+
fn simd_select<M, T>(m: M, yes: T, no: T) -> T;
3435
}
35-
36-
// Make sure simd_eq returns all-1 for `true`
37-
let a = i32x4::splat(10);
38-
let b = i32x4::from_array([1, 2, 10, 4]);
39-
let c: i32x4 = unsafe { simd_eq(a, b) };
40-
assert_eq!(c, i32x4::from_array([0, 0, -1, 0]));
41-
4236
unsafe {
37+
// Make sure simd_eq returns all-1 for `true`
38+
let a = i32x4::splat(10);
39+
let b = i32x4::from_array([1, 2, 10, 4]);
40+
let c: i32x4 = simd_eq(a, b);
41+
assert_eq!(c, i32x4::from_array([0, 0, -1, 0]));
42+
4343
assert!(!simd_reduce_any(i32x4::splat(0)));
4444
assert!(simd_reduce_any(i32x4::splat(-1)));
45+
46+
assert_eq!(simd_select(i8x4::from_array([0, -1, -1, 0]), a, b), i32x4::from_array([1, 10, 10, 4]));
47+
assert_eq!(simd_select(i8x4::from_array([0, -1, -1, 0]), b, a), i32x4::from_array([10, 2, 10, 10]));
4548
}
4649
}
4750

0 commit comments

Comments
 (0)