diff --git a/src/shims/intrinsics.rs b/src/shims/intrinsics.rs index 54e7118b259..b4416bfa985 100644 --- a/src/shims/intrinsics.rs +++ b/src/shims/intrinsics.rs @@ -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)?, diff --git a/tests/compile-fail/intrinsics/simd-gather.rs b/tests/compile-fail/intrinsics/simd-gather.rs index 2fb5da01f10..ae6f048226d 100644 --- a/tests/compile-fail/intrinsics/simd-gather.rs +++ b/tests/compile-fail/intrinsics/simd-gather.rs @@ -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 index 00000000000..f46e4f0d4f6 --- /dev/null +++ b/tests/compile-fail/intrinsics/simd-scatter.rs @@ -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 = 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); +} } diff --git a/tests/run-pass/portable-simd.rs b/tests/run-pass/portable-simd.rs index ad9dafea4ba..c046af0bcf5 100644 --- a/tests/run-pass/portable-simd.rs +++ b/tests/run-pass/portable-simd.rs @@ -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 = 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() {