//@ run-pass //@ revisions: opt noopt //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O #![feature(repr_simd, intrinsics)] #![allow(incomplete_features)] #![feature(adt_const_params)] use std::marker::ConstParamTy; extern "rust-intrinsic" { fn simd_shuffle(a: T, b: T, i: I) -> U; } #[derive(Copy, Clone, ConstParamTy, PartialEq, Eq)] #[repr(simd)] struct Simd([T; N]); unsafe fn __shuffle_vector16(x: T, y: T) -> U { simd_shuffle(x, y, IDX) } unsafe fn __shuffle_vector16_v2, T, U>(x: T, y: T) -> U { simd_shuffle(x, y, IDX) } fn main() { const I1: [u32; 4] = [0, 2, 4, 6]; const I2: [u32; 2] = [1, 5]; let a = Simd::([0, 1, 2, 3]); let b = Simd::([4, 5, 6, 7]); unsafe { let x: Simd = simd_shuffle(a, b, I1); assert_eq!(x.0, [0, 2, 4, 6]); let y: Simd = simd_shuffle(a, b, I2); assert_eq!(y.0, [1, 5]); } // Test that we can also use a SIMD vector instead of a normal array for the shuffle. const I1_SIMD: Simd = Simd([0, 2, 4, 6]); const I2_SIMD: Simd = Simd([1, 5]); unsafe { let x: Simd = simd_shuffle(a, b, I1_SIMD); assert_eq!(x.0, [0, 2, 4, 6]); let y: Simd = simd_shuffle(a, b, I2_SIMD); assert_eq!(y.0, [1, 5]); } // Test that an indirection (via an unnamed constant) // through a const generic parameter also works. // See https://github.com/rust-lang/rust/issues/113500 for details. let a = Simd::([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); let b = Simd::([16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]); unsafe { __shuffle_vector16::< { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] }, Simd, Simd, >(a, b); } unsafe { __shuffle_vector16_v2::< { Simd([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]) }, Simd, Simd, >(a, b); } }