Skip to content

Commit 576e2bb

Browse files
committed
implement gather
1 parent 3eba7fc commit 576e2bb

File tree

3 files changed

+44
-0
lines changed

3 files changed

+44
-0
lines changed

src/shims/intrinsics.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,33 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
653653
this.write_immediate(*val, &dest.into())?;
654654
}
655655
}
656+
"simd_gather" => {
657+
let &[ref passthru, ref ptrs, ref mask] = check_arg_count(args)?;
658+
let (passthru, passthru_len) = this.operand_to_simd(passthru)?;
659+
let (ptrs, ptrs_len) = this.operand_to_simd(ptrs)?;
660+
let (mask, mask_len) = this.operand_to_simd(mask)?;
661+
let (dest, dest_len) = this.place_to_simd(dest)?;
662+
663+
assert_eq!(dest_len, passthru_len);
664+
assert_eq!(dest_len, ptrs_len);
665+
assert_eq!(dest_len, mask_len);
666+
667+
for i in 0..dest_len {
668+
let passthru = this.read_immediate(&this.mplace_index(&passthru, i)?.into())?;
669+
let ptr = this.read_immediate(&this.mplace_index(&ptrs, i)?.into())?;
670+
let mask = this.read_immediate(&this.mplace_index(&mask, i)?.into())?;
671+
let dest = this.mplace_index(&dest, i)?;
672+
673+
let mask = simd_element_to_bool(mask)?;
674+
let val = if mask {
675+
let place = this.deref_operand(&ptr.into())?;
676+
this.read_immediate(&place.into())?
677+
} else {
678+
passthru
679+
};
680+
this.write_immediate(*val, &dest.into())?;
681+
}
682+
}
656683

657684
// Atomic operations
658685
"atomic_load" => this.atomic_load(args, dest, AtomicReadOp::SeqCst)?,
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// error-pattern: out-of-bounds
2+
#![feature(portable_simd)]
3+
use std::simd::*;
4+
5+
fn main() { unsafe {
6+
let vec: &[i16] = &[10, 11, 12, 13, 14, 15, 16, 17, 18];
7+
let idxs = Simd::from_array([9, 3, 0, 17]);
8+
let _result = Simd::gather_select_unchecked(&vec, Mask::splat(true), idxs, Simd::splat(0));
9+
} }

tests/run-pass/portable-simd.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,13 @@ fn simd_swizzle() {
249249
assert_eq!(simd_swizzle!(b, a, [First(3), Second(0)]), f32x2::from_array([-4.0, 10.0]));
250250
}
251251

252+
fn simd_gather_scatter() {
253+
let vec: &[i16] = &[10, 11, 12, 13, 14, 15, 16, 17, 18];
254+
let idxs = Simd::from_array([9, 3, 0, 17]);
255+
let result = Simd::gather_or_default(&vec, idxs); // Note the lane that is out-of-bounds.
256+
assert_eq!(result, Simd::from_array([0, 13, 10, 0]));
257+
}
258+
252259
fn simd_intrinsics() {
253260
extern "platform-intrinsic" {
254261
fn simd_eq<T, U>(x: T, y: T) -> U;
@@ -288,5 +295,6 @@ fn main() {
288295
simd_ops_i32();
289296
simd_cast();
290297
simd_swizzle();
298+
simd_gather_scatter();
291299
simd_intrinsics();
292300
}

0 commit comments

Comments
 (0)