From 84304fc00a2b582b1797a52dfaa954ff36b4ff91 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 22 Dec 2023 12:03:54 +0100 Subject: [PATCH] simd_scatter/gather: test OOB cases and the order of writes --- src/tools/miri/tests/pass/portable-simd.rs | 45 +++++++++++++++++++--- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/src/tools/miri/tests/pass/portable-simd.rs b/src/tools/miri/tests/pass/portable-simd.rs index f370e658272f..3d24943293c9 100644 --- a/src/tools/miri/tests/pass/portable-simd.rs +++ b/src/tools/miri/tests/pass/portable-simd.rs @@ -1,6 +1,8 @@ //@compile-flags: -Zmiri-strict-provenance -#![feature(portable_simd, platform_intrinsics, adt_const_params, inline_const)] +#![feature(portable_simd, platform_intrinsics, adt_const_params, inline_const, core_intrinsics)] #![allow(incomplete_features, internal_features)] +use std::intrinsics::simd as intrinsics; +use std::ptr; use std::simd::{prelude::*, StdFloat}; fn simd_ops_f32() { @@ -421,6 +423,40 @@ fn simd_gather_scatter() { 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]); + + // We call the intrinsics directly to experiment with dangling pointers and masks. + let val = 42u8; + let ptrs: Simd<*const u8, 4> = + Simd::from_array([ptr::null(), ptr::addr_of!(val), ptr::addr_of!(val), ptr::addr_of!(val)]); + let default = u8x4::splat(0); + let mask = i8x4::from_array([0, !0, 0, !0]); + let vals = unsafe { intrinsics::simd_gather(default, ptrs, mask) }; + assert_eq!(vals, u8x4::from_array([0, 42, 0, 42]),); + + let mut val1 = 0u8; + let mut val2 = 0u8; + let ptrs: Simd<*mut u8, 4> = Simd::from_array([ + ptr::null_mut(), + ptr::addr_of_mut!(val1), + ptr::addr_of_mut!(val1), + ptr::addr_of_mut!(val2), + ]); + let vals = u8x4::from_array([1, 2, 3, 4]); + unsafe { intrinsics::simd_scatter(vals, ptrs, mask) }; + assert_eq!(val1, 2); + assert_eq!(val2, 4); + + // Also check what happens when `scatter` has multiple overlapping pointers. + let mut val = 0u8; + let ptrs: Simd<*mut u8, 4> = Simd::from_array([ + ptr::addr_of_mut!(val), + ptr::addr_of_mut!(val), + ptr::addr_of_mut!(val), + ptr::addr_of_mut!(val), + ]); + let vals = u8x4::from_array([1, 2, 3, 4]); + unsafe { intrinsics::simd_scatter(vals, ptrs, mask) }; + assert_eq!(val, 4); } fn simd_round() { @@ -460,14 +496,11 @@ fn simd_round() { } fn simd_intrinsics() { + use intrinsics::*; extern "platform-intrinsic" { - fn simd_eq(x: T, y: T) -> U; - fn simd_reduce_any(x: T) -> bool; - fn simd_reduce_all(x: T) -> bool; - fn simd_select(m: M, yes: T, no: T) -> T; fn simd_shuffle_generic(x: T, y: T) -> U; - fn simd_shuffle(x: T, y: T, idx: IDX) -> U; } + unsafe { // Make sure simd_eq returns all-1 for `true` let a = i32x4::splat(10);