]> git.lizzy.rs Git - rust.git/commitdiff
implement simd_scatter
authorRalf Jung <post@ralfj.de>
Thu, 10 Mar 2022 00:26:40 +0000 (19:26 -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
tests/compile-fail/intrinsics/simd-scatter.rs [new file with mode: 0644]
tests/run-pass/portable-simd.rs

index 54e7118b25936e529830a8d422defbf580684476..b4416bfa985989b84c2bcc034a7d71c3b47d2db0 100644 (file)
@@ -570,8 +570,7 @@ enum Op {
                     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 };
+                    let val = if simd_element_to_bool(mask)? { yes } else { no };
                     this.write_immediate(*val, &dest.into())?;
                 }
             }
@@ -670,8 +669,7 @@ enum Op {
                     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 val = if simd_element_to_bool(mask)? {
                         let place = this.deref_operand(&ptr.into())?;
                         this.read_immediate(&place.into())?
                     } else {
@@ -680,6 +678,26 @@ enum Op {
                     this.write_immediate(*val, &dest.into())?;
                 }
             }
+            "simd_scatter" => {
+                let &[ref value, ref ptrs, ref mask] = check_arg_count(args)?;
+                let (value, value_len) = this.operand_to_simd(value)?;
+                let (ptrs, ptrs_len) = this.operand_to_simd(ptrs)?;
+                let (mask, mask_len) = this.operand_to_simd(mask)?;
+
+                assert_eq!(ptrs_len, value_len);
+                assert_eq!(ptrs_len, mask_len);
+
+                for i in 0..ptrs_len {
+                    let value = this.read_immediate(&this.mplace_index(&value, i)?.into())?;
+                    let ptr = this.read_immediate(&this.mplace_index(&ptrs, i)?.into())?;
+                    let mask = this.read_immediate(&this.mplace_index(&mask, i)?.into())?;
+
+                    if simd_element_to_bool(mask)? {
+                        let place = this.deref_operand(&ptr.into())?;
+                        this.write_immediate(*value, &place.into())?;
+                    }
+                }
+            }
 
             // Atomic operations
             "atomic_load" => this.atomic_load(args, dest, AtomicReadOp::SeqCst)?,
index 2fb5da01f10670fd54eb978a30b3856e662c0cb8..ae6f048226ddb5131327c3e3c64d502a60c553f0 100644 (file)
@@ -1,9 +1,9 @@
-// error-pattern: out-of-bounds
+// error-pattern: pointer to 1 byte starting at offset 9 is 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 vec: &[i8] = &[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));
 } }
diff --git a/tests/compile-fail/intrinsics/simd-scatter.rs b/tests/compile-fail/intrinsics/simd-scatter.rs
new file mode 100644 (file)
index 0000000..f46e4f0
--- /dev/null
@@ -0,0 +1,9 @@
+// error-pattern: pointer to 1 byte starting at offset 9 is out-of-bounds
+#![feature(portable_simd)]
+use std::simd::*;
+
+fn main() { unsafe {
+    let mut vec: Vec<i8> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
+    let idxs = Simd::from_array([9, 3, 0, 17]);
+    Simd::from_array([-27, 82, -41, 124]).scatter_select_unchecked(&mut vec, Mask::splat(true), idxs);
+} }
index ad9dafea4bada1308383ace92bd32765eea38297..c046af0bcf52af76bb746787498f2470a0067cfd 100644 (file)
@@ -250,10 +250,14 @@ fn simd_swizzle() {
 }
 
 fn simd_gather_scatter() {
-    let vec: &[i16] = &[10, 11, 12, 13, 14, 15, 16, 17, 18];
+    let mut vec: Vec<i16> = vec![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]));
+
+    let idxs = Simd::from_array([9, 3, 0, 0]);
+    Simd::from_array([-27, 82, -41, 124]).scatter(&mut vec, idxs);
+    assert_eq!(vec, vec![124, 11, 12, 82, 14, 15, 16, 17, 18]);
 }
 
 fn simd_intrinsics() {