|
1 | 1 | //@compile-flags: -Zmiri-strict-provenance |
2 | | -#![feature(portable_simd, platform_intrinsics, adt_const_params, inline_const)] |
| 2 | +#![feature(portable_simd, platform_intrinsics, adt_const_params, inline_const, core_intrinsics)] |
3 | 3 | #![allow(incomplete_features, internal_features)] |
| 4 | +use std::intrinsics::simd as intrinsics; |
| 5 | +use std::ptr; |
4 | 6 | use std::simd::{prelude::*, StdFloat}; |
5 | 7 |
|
6 | 8 | fn simd_ops_f32() { |
@@ -421,6 +423,40 @@ fn simd_gather_scatter() { |
421 | 423 | let idxs = Simd::from_array([9, 3, 0, 0]); |
422 | 424 | Simd::from_array([-27, 82, -41, 124]).scatter(&mut vec, idxs); |
423 | 425 | assert_eq!(vec, vec![124, 11, 12, 82, 14, 15, 16, 17, 18]); |
| 426 | + |
| 427 | + // We call the intrinsics directly to experiment with dangling pointers and masks. |
| 428 | + let val = 42u8; |
| 429 | + let ptrs: Simd<*const u8, 4> = |
| 430 | + Simd::from_array([ptr::null(), ptr::addr_of!(val), ptr::addr_of!(val), ptr::addr_of!(val)]); |
| 431 | + let default = u8x4::splat(0); |
| 432 | + let mask = i8x4::from_array([0, !0, 0, !0]); |
| 433 | + let vals = unsafe { intrinsics::simd_gather(default, ptrs, mask) }; |
| 434 | + assert_eq!(vals, u8x4::from_array([0, 42, 0, 42]),); |
| 435 | + |
| 436 | + let mut val1 = 0u8; |
| 437 | + let mut val2 = 0u8; |
| 438 | + let ptrs: Simd<*mut u8, 4> = Simd::from_array([ |
| 439 | + ptr::null_mut(), |
| 440 | + ptr::addr_of_mut!(val1), |
| 441 | + ptr::addr_of_mut!(val1), |
| 442 | + ptr::addr_of_mut!(val2), |
| 443 | + ]); |
| 444 | + let vals = u8x4::from_array([1, 2, 3, 4]); |
| 445 | + unsafe { intrinsics::simd_scatter(vals, ptrs, mask) }; |
| 446 | + assert_eq!(val1, 2); |
| 447 | + assert_eq!(val2, 4); |
| 448 | + |
| 449 | + // Also check what happens when `scatter` has multiple overlapping pointers. |
| 450 | + let mut val = 0u8; |
| 451 | + let ptrs: Simd<*mut u8, 4> = Simd::from_array([ |
| 452 | + ptr::addr_of_mut!(val), |
| 453 | + ptr::addr_of_mut!(val), |
| 454 | + ptr::addr_of_mut!(val), |
| 455 | + ptr::addr_of_mut!(val), |
| 456 | + ]); |
| 457 | + let vals = u8x4::from_array([1, 2, 3, 4]); |
| 458 | + unsafe { intrinsics::simd_scatter(vals, ptrs, mask) }; |
| 459 | + assert_eq!(val, 4); |
424 | 460 | } |
425 | 461 |
|
426 | 462 | fn simd_round() { |
@@ -460,14 +496,11 @@ fn simd_round() { |
460 | 496 | } |
461 | 497 |
|
462 | 498 | fn simd_intrinsics() { |
| 499 | + use intrinsics::*; |
463 | 500 | extern "platform-intrinsic" { |
464 | | - fn simd_eq<T, U>(x: T, y: T) -> U; |
465 | | - fn simd_reduce_any<T>(x: T) -> bool; |
466 | | - fn simd_reduce_all<T>(x: T) -> bool; |
467 | | - fn simd_select<M, T>(m: M, yes: T, no: T) -> T; |
468 | 501 | fn simd_shuffle_generic<T, U, const IDX: &'static [u32]>(x: T, y: T) -> U; |
469 | | - fn simd_shuffle<T, IDX, U>(x: T, y: T, idx: IDX) -> U; |
470 | 502 | } |
| 503 | + |
471 | 504 | unsafe { |
472 | 505 | // Make sure simd_eq returns all-1 for `true` |
473 | 506 | let a = i32x4::splat(10); |
|
0 commit comments