|
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