this.write_immediate(*val, &dest.into())?;
}
}
+ "simd_gather" => {
+ let &[ref passthru, ref ptrs, ref mask] = check_arg_count(args)?;
+ let (passthru, passthru_len) = this.operand_to_simd(passthru)?;
+ let (ptrs, ptrs_len) = this.operand_to_simd(ptrs)?;
+ let (mask, mask_len) = this.operand_to_simd(mask)?;
+ let (dest, dest_len) = this.place_to_simd(dest)?;
+
+ assert_eq!(dest_len, passthru_len);
+ assert_eq!(dest_len, ptrs_len);
+ assert_eq!(dest_len, mask_len);
+
+ for i in 0..dest_len {
+ let passthru = this.read_immediate(&this.mplace_index(&passthru, i)?.into())?;
+ let ptr = this.read_immediate(&this.mplace_index(&ptrs, i)?.into())?;
+ let mask = this.read_immediate(&this.mplace_index(&mask, i)?.into())?;
+ let dest = this.mplace_index(&dest, i)?;
+
+ let mask = simd_element_to_bool(mask)?;
+ let val = if mask {
+ let place = this.deref_operand(&ptr.into())?;
+ this.read_immediate(&place.into())?
+ } else {
+ passthru
+ };
+ this.write_immediate(*val, &dest.into())?;
+ }
+ }
// Atomic operations
"atomic_load" => this.atomic_load(args, dest, AtomicReadOp::SeqCst)?,
--- /dev/null
+// error-pattern: out-of-bounds
+#![feature(portable_simd)]
+use std::simd::*;
+
+fn main() { unsafe {
+ let vec: &[i16] = &[10, 11, 12, 13, 14, 15, 16, 17, 18];
+ let idxs = Simd::from_array([9, 3, 0, 17]);
+ let _result = Simd::gather_select_unchecked(&vec, Mask::splat(true), idxs, Simd::splat(0));
+} }
assert_eq!(simd_swizzle!(b, a, [First(3), Second(0)]), f32x2::from_array([-4.0, 10.0]));
}
+fn simd_gather_scatter() {
+ let vec: &[i16] = &[10, 11, 12, 13, 14, 15, 16, 17, 18];
+ let idxs = Simd::from_array([9, 3, 0, 17]);
+ let result = Simd::gather_or_default(&vec, idxs); // Note the lane that is out-of-bounds.
+ assert_eq!(result, Simd::from_array([0, 13, 10, 0]));
+}
+
fn simd_intrinsics() {
extern "platform-intrinsic" {
fn simd_eq<T, U>(x: T, y: T) -> U;
simd_ops_i32();
simd_cast();
simd_swizzle();
+ simd_gather_scatter();
simd_intrinsics();
}