]> git.lizzy.rs Git - rust.git/commitdiff
implement gather
authorRalf Jung <post@ralfj.de>
Thu, 10 Mar 2022 00:18:07 +0000 (19:18 -0500)
committerRalf Jung <post@ralfj.de>
Thu, 10 Mar 2022 00:29:05 +0000 (19:29 -0500)
src/shims/intrinsics.rs
tests/compile-fail/intrinsics/simd-gather.rs [new file with mode: 0644]
tests/run-pass/portable-simd.rs

index 43c61091b9e4d47ae5bf8169baf79bbfcf2bf801..54e7118b25936e529830a8d422defbf580684476 100644 (file)
@@ -653,6 +653,33 @@ enum Op {
                     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)?,
diff --git a/tests/compile-fail/intrinsics/simd-gather.rs b/tests/compile-fail/intrinsics/simd-gather.rs
new file mode 100644 (file)
index 0000000..2fb5da0
--- /dev/null
@@ -0,0 +1,9 @@
+// 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));
+} }
index 67e4e52a7849e88fdf2c599886a3d7482744fcb8..ad9dafea4bada1308383ace92bd32765eea38297 100644 (file)
@@ -249,6 +249,13 @@ fn simd_swizzle() {
     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;
@@ -288,5 +295,6 @@ fn main() {
     simd_ops_i32();
     simd_cast();
     simd_swizzle();
+    simd_gather_scatter();
     simd_intrinsics();
 }