mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Enable const-testing for the ported SIMD intrinsics
This commit is contained in:
+90
-24
@@ -10,6 +10,10 @@
|
||||
|
||||
#![allow(unused)]
|
||||
#![allow(non_camel_case_types)]
|
||||
// FIXME: `cfg(minisimd_const)` is used to toggle use of const trait impls, which require a few
|
||||
// nightly features. Remove this when `const_trait_impls`, `const_cmp` and `const_index` are
|
||||
// stablilized.
|
||||
#![allow(unexpected_cfgs)]
|
||||
|
||||
// The field is currently left `pub` for convenience in porting tests, many of
|
||||
// which attempt to just construct it directly. That still works; it's just the
|
||||
@@ -24,39 +28,32 @@ fn clone(&self) -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq, const N: usize> PartialEq for Simd<T, N> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.as_array() == other.as_array()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: core::fmt::Debug, const N: usize> core::fmt::Debug for Simd<T, N> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
|
||||
<[T; N] as core::fmt::Debug>::fmt(self.as_array(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> core::ops::Index<usize> for Simd<T, N> {
|
||||
type Output = T;
|
||||
fn index(&self, i: usize) -> &T {
|
||||
&self.as_array()[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> Simd<T, N> {
|
||||
pub const fn from_array(a: [T; N]) -> Self {
|
||||
Simd(a)
|
||||
}
|
||||
pub fn as_array(&self) -> &[T; N] {
|
||||
pub const fn as_array(&self) -> &[T; N] {
|
||||
let p: *const Self = self;
|
||||
unsafe { &*p.cast::<[T; N]>() }
|
||||
}
|
||||
pub fn into_array(self) -> [T; N]
|
||||
pub const fn into_array(self) -> [T; N]
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
*self.as_array()
|
||||
}
|
||||
pub const fn splat(a: T) -> Self
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
Self([a; N])
|
||||
}
|
||||
}
|
||||
|
||||
pub type u8x2 = Simd<u8, 2>;
|
||||
@@ -109,6 +106,14 @@ impl<T, const N: usize> Simd<T, N> {
|
||||
pub type i128x2 = Simd<i128, 2>;
|
||||
pub type i128x4 = Simd<i128, 4>;
|
||||
|
||||
pub type usizex2 = Simd<usize, 2>;
|
||||
pub type usizex4 = Simd<usize, 4>;
|
||||
pub type usizex8 = Simd<usize, 8>;
|
||||
|
||||
pub type isizex2 = Simd<isize, 2>;
|
||||
pub type isizex4 = Simd<isize, 4>;
|
||||
pub type isizex8 = Simd<isize, 8>;
|
||||
|
||||
pub type f32x2 = Simd<f32, 2>;
|
||||
pub type f32x4 = Simd<f32, 4>;
|
||||
pub type f32x8 = Simd<f32, 8>;
|
||||
@@ -122,7 +127,7 @@ impl<T, const N: usize> Simd<T, N> {
|
||||
// which attempt to just construct it directly. That still works; it's just the
|
||||
// `.0` projection that doesn't.
|
||||
#[repr(simd, packed)]
|
||||
#[derive(Copy)]
|
||||
#[derive(Copy, Eq)]
|
||||
pub struct PackedSimd<T, const N: usize>(pub [T; N]);
|
||||
|
||||
impl<T: Copy, const N: usize> Clone for PackedSimd<T, N> {
|
||||
@@ -131,12 +136,6 @@ fn clone(&self) -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq, const N: usize> PartialEq for PackedSimd<T, N> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.as_array() == other.as_array()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: core::fmt::Debug, const N: usize> core::fmt::Debug for PackedSimd<T, N> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
|
||||
<[T; N] as core::fmt::Debug>::fmt(self.as_array(), f)
|
||||
@@ -147,14 +146,81 @@ impl<T, const N: usize> PackedSimd<T, N> {
|
||||
pub const fn from_array(a: [T; N]) -> Self {
|
||||
PackedSimd(a)
|
||||
}
|
||||
pub fn as_array(&self) -> &[T; N] {
|
||||
pub const fn as_array(&self) -> &[T; N] {
|
||||
let p: *const Self = self;
|
||||
unsafe { &*p.cast::<[T; N]>() }
|
||||
}
|
||||
pub fn into_array(self) -> [T; N]
|
||||
pub const fn into_array(self) -> [T; N]
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
*self.as_array()
|
||||
}
|
||||
pub const fn splat(a: T) -> Self
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
Self([a; N])
|
||||
}
|
||||
}
|
||||
|
||||
// As `const_trait_impl` is a language feature with specialized syntax, we have to use them in a way
|
||||
// such that it doesn't get parsed as Rust code unless `cfg(minisimd_const)` is on. The easiest way
|
||||
// for that is a macro
|
||||
|
||||
macro_rules! impl_traits {
|
||||
($($const_:ident)?) => {
|
||||
impl<T: $([$const_])? PartialEq, const N: usize> $($const_)? PartialEq for Simd<T, N> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.as_array() == other.as_array()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> $($const_)? core::ops::Index<usize> for Simd<T, N> {
|
||||
type Output = T;
|
||||
fn index(&self, i: usize) -> &T {
|
||||
&self.as_array()[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: $([$const_])? PartialEq, const N: usize> $($const_)? PartialEq for PackedSimd<T, N>
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.as_array() == other.as_array()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(minisimd_const)]
|
||||
impl_traits!(const);
|
||||
|
||||
#[cfg(not(minisimd_const))]
|
||||
impl_traits!();
|
||||
|
||||
/// Version of `assert_eq` that ignores fancy runtime printing in const context.
|
||||
/// FIXME: Remove once <https://github.com/rust-lang/rust/issues/119826> is fixed.
|
||||
#[cfg(minisimd_const)]
|
||||
#[macro_export]
|
||||
macro_rules! assert_eq {
|
||||
($left:expr, $right:expr $(,)?) => {
|
||||
assert_eq!(
|
||||
$left,
|
||||
$right,
|
||||
concat!("`", stringify!($left), "` == `", stringify!($right), "`")
|
||||
);
|
||||
};
|
||||
($left:expr, $right:expr$(, $($arg:tt)+)?) => {
|
||||
{
|
||||
let left = $left;
|
||||
let right = $right;
|
||||
// type inference works better with the concrete type on the
|
||||
// left, but humans work better with the expected on the
|
||||
// right
|
||||
assert!(right == left, $($($arg)*),*);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(minisimd_const)]
|
||||
use assert_eq;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//@ run-pass
|
||||
//@ ignore-emscripten
|
||||
//@ ignore-android
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
// FIXME: this test fails on arm-android because the NDK version 14 is too old.
|
||||
// It needs at least version 18. We disable it on all android build bots because
|
||||
@@ -8,7 +9,7 @@
|
||||
|
||||
// Test that the simd floating-point math intrinsics produce correct results.
|
||||
|
||||
#![feature(repr_simd, intrinsics, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
@@ -20,7 +21,10 @@
|
||||
macro_rules! assert_approx_eq_f32 {
|
||||
($a:expr, $b:expr) => {{
|
||||
let (a, b) = (&$a, &$b);
|
||||
assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b);
|
||||
assert!(
|
||||
(*a - *b).abs() < 1.0e-6,
|
||||
concat!(stringify!($a), " is not approximately equal to ", stringify!($b))
|
||||
);
|
||||
}};
|
||||
}
|
||||
macro_rules! assert_approx_eq {
|
||||
@@ -34,7 +38,7 @@ macro_rules! assert_approx_eq {
|
||||
}};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const fn simple_math() {
|
||||
let x = f32x4::from_array([1.0, 1.0, 1.0, 1.0]);
|
||||
let y = f32x4::from_array([-1.0, -1.0, -1.0, -1.0]);
|
||||
let z = f32x4::from_array([0.0, 0.0, 0.0, 0.0]);
|
||||
@@ -43,37 +47,7 @@ fn main() {
|
||||
|
||||
unsafe {
|
||||
let r = simd_fabs(y);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_fcos(z);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_fexp(z);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_fexp2(z);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_fma(x, h, h);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_relaxed_fma(x, h, h);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_fsqrt(x);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_flog(x);
|
||||
assert_approx_eq!(z, r);
|
||||
|
||||
let r = simd_flog2(x);
|
||||
assert_approx_eq!(z, r);
|
||||
|
||||
let r = simd_flog10(x);
|
||||
assert_approx_eq!(z, r);
|
||||
|
||||
let r = simd_fsin(z);
|
||||
assert_approx_eq!(z, r);
|
||||
assert_eq!(x, r);
|
||||
|
||||
// rounding functions
|
||||
let r = simd_floor(h);
|
||||
@@ -90,5 +64,48 @@ fn main() {
|
||||
|
||||
let r = simd_trunc(h);
|
||||
assert_eq!(z, r);
|
||||
|
||||
let r = simd_fma(x, h, h);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_relaxed_fma(x, h, h);
|
||||
assert_approx_eq!(x, r);
|
||||
}
|
||||
}
|
||||
|
||||
fn special_math() {
|
||||
let x = f32x4::from_array([1.0, 1.0, 1.0, 1.0]);
|
||||
let z = f32x4::from_array([0.0, 0.0, 0.0, 0.0]);
|
||||
|
||||
unsafe {
|
||||
let r = simd_fcos(z);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_fexp(z);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_fexp2(z);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_fsqrt(x);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_flog(x);
|
||||
assert_approx_eq!(z, r);
|
||||
|
||||
let r = simd_flog2(x);
|
||||
assert_approx_eq!(z, r);
|
||||
|
||||
let r = simd_flog10(x);
|
||||
assert_approx_eq!(z, r);
|
||||
|
||||
let r = simd_fsin(z);
|
||||
assert_approx_eq!(z, r);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { simple_math() };
|
||||
simple_math();
|
||||
special_math();
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
//@ run-pass
|
||||
//@ ignore-emscripten
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
// Test that the simd_f{min,max} intrinsics produce the correct results.
|
||||
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
@@ -12,7 +13,7 @@
|
||||
|
||||
use std::intrinsics::simd::*;
|
||||
|
||||
fn main() {
|
||||
const fn minmax() {
|
||||
let x = f32x4::from_array([1.0, 2.0, 3.0, 4.0]);
|
||||
let y = f32x4::from_array([2.0, 1.0, 4.0, 3.0]);
|
||||
|
||||
@@ -47,3 +48,8 @@ fn main() {
|
||||
assert_eq!(maxn, y);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { minmax() };
|
||||
minmax();
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
//@ run-pass
|
||||
//@ ignore-backends: gcc
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
@@ -20,7 +21,7 @@ macro_rules! all_eq {
|
||||
|
||||
use std::intrinsics::simd::*;
|
||||
|
||||
fn main() {
|
||||
const fn arithmetic() {
|
||||
let x1 = i32x4::from_array([1, 2, 3, 4]);
|
||||
let y1 = U32::<4>::from_array([1, 2, 3, 4]);
|
||||
let z1 = f32x4::from_array([1.0, 2.0, 3.0, 4.0]);
|
||||
@@ -224,3 +225,8 @@ fn main() {
|
||||
all_eq!(simd_cttz(y1), U32::<4>::from_array([0, 1, 0, 2]));
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { arithmetic() };
|
||||
arithmetic();
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
//@ run-pass
|
||||
//@ ignore-emscripten
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
@@ -12,7 +13,7 @@
|
||||
|
||||
type I32<const N: usize> = Simd<i32, N>;
|
||||
|
||||
fn main() {
|
||||
const fn saturating() {
|
||||
// unsigned
|
||||
{
|
||||
const M: u32 = u32::MAX;
|
||||
@@ -84,3 +85,8 @@ fn main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { saturating() };
|
||||
saturating();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
//@ run-pass
|
||||
//@ ignore-backends: gcc
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
@@ -11,7 +12,7 @@
|
||||
|
||||
type V<T> = Simd<T, 2>;
|
||||
|
||||
fn main() {
|
||||
const fn as_simd() {
|
||||
unsafe {
|
||||
let u: V::<u32> = Simd([u32::MIN, u32::MAX]);
|
||||
let i: V<i16> = simd_as(u);
|
||||
@@ -47,3 +48,8 @@ fn main() {
|
||||
assert_eq!(u[1], f[1] as usize);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { as_simd() };
|
||||
as_simd();
|
||||
}
|
||||
|
||||
@@ -1,41 +1,31 @@
|
||||
//@ run-pass
|
||||
#![allow(non_camel_case_types)]
|
||||
//@ ignore-emscripten
|
||||
//@ ignore-endian-big behavior of simd_bitmask is endian-specific
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
// Test that the simd_bitmask intrinsic produces correct results.
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
use minisimd::*;
|
||||
|
||||
use std::intrinsics::simd::simd_bitmask;
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
struct u32x4(pub [u32; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
struct u8x4(pub [u8; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
struct Tx4<T>(pub [T; 4]);
|
||||
|
||||
fn main() {
|
||||
let z = u32x4([0, 0, 0, 0]);
|
||||
const fn bitmask() {
|
||||
let z = u32x4::from_array([0, 0, 0, 0]);
|
||||
let ez = 0_u8;
|
||||
|
||||
let o = u32x4([!0, !0, !0, !0]);
|
||||
let o = u32x4::from_array([!0, !0, !0, !0]);
|
||||
let eo = 0b_1111_u8;
|
||||
|
||||
let m0 = u32x4([!0, 0, !0, 0]);
|
||||
let m0 = u32x4::from_array([!0, 0, !0, 0]);
|
||||
let e0 = 0b_0000_0101_u8;
|
||||
|
||||
// Check that the MSB is extracted:
|
||||
let m = u8x4([0b_1000_0000, 0b_0100_0001, 0b_1100_0001, 0b_1111_1111]);
|
||||
let e = 0b_1101;
|
||||
|
||||
// Check usize / isize
|
||||
let msize: Tx4<usize> = Tx4([usize::MAX, 0, usize::MAX, usize::MAX]);
|
||||
let msize = usizex4::from_array([usize::MAX, 0, usize::MAX, usize::MAX]);
|
||||
|
||||
unsafe {
|
||||
let r: u8 = simd_bitmask(z);
|
||||
@@ -47,10 +37,12 @@ fn main() {
|
||||
let r: u8 = simd_bitmask(m0);
|
||||
assert_eq!(r, e0);
|
||||
|
||||
let r: u8 = simd_bitmask(m);
|
||||
assert_eq!(r, e);
|
||||
|
||||
let r: u8 = simd_bitmask(msize);
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { bitmask() };
|
||||
bitmask();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//@ run-pass
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![allow(non_camel_case_types)]
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
@@ -8,9 +8,14 @@
|
||||
|
||||
use std::intrinsics::simd::simd_bswap;
|
||||
|
||||
fn main() {
|
||||
const fn bswap() {
|
||||
unsafe {
|
||||
assert_eq!(simd_bswap(i8x4::from_array([0, 1, 2, 3])).into_array(), [0, 1, 2, 3]);
|
||||
assert_eq!(simd_bswap(u8x4::from_array([0, 1, 2, 3])).into_array(), [0, 1, 2, 3]);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { bswap() };
|
||||
bswap();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//@ run-pass
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
@@ -12,7 +13,7 @@
|
||||
|
||||
type V<T> = Simd<T, 2>;
|
||||
|
||||
fn main() {
|
||||
const fn cast() {
|
||||
unsafe {
|
||||
let u: V::<u32> = Simd([i16::MIN as u32, i16::MAX as u32]);
|
||||
let i: V<i16> = simd_cast(u);
|
||||
@@ -56,3 +57,8 @@ fn main() {
|
||||
assert_eq!(u[1], f[1] as usize);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { cast() };
|
||||
cast();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//@ run-pass
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
@@ -9,17 +10,16 @@
|
||||
|
||||
type V<T> = Simd<T, 4>;
|
||||
|
||||
fn main() {
|
||||
const fn cast_ptr_width() {
|
||||
let u: V::<usize> = Simd([0, 1, 2, 3]);
|
||||
let uu32: V<u32> = unsafe { simd_cast(u) };
|
||||
let ui64: V<i64> = unsafe { simd_cast(u) };
|
||||
|
||||
for (u, (uu32, ui64)) in u
|
||||
.as_array()
|
||||
.iter()
|
||||
.zip(uu32.as_array().iter().zip(ui64.as_array().iter()))
|
||||
{
|
||||
assert_eq!(*u as u32, *uu32);
|
||||
assert_eq!(*u as i64, *ui64);
|
||||
}
|
||||
assert_eq!(uu32, V::<u32>::from_array([0, 1, 2, 3]));
|
||||
assert_eq!(ui64, V::<i64>::from_array([0, 1, 2, 3]));
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { cast_ptr_width() };
|
||||
cast_ptr_width();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
//@ run-pass
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
#![feature(repr_simd, core_intrinsics, macro_metavar_expr_concat)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![feature(
|
||||
repr_simd,
|
||||
core_intrinsics,
|
||||
const_trait_impl,
|
||||
const_cmp,
|
||||
const_index,
|
||||
macro_metavar_expr_concat
|
||||
)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
@@ -25,27 +32,26 @@ macro_rules! cmp {
|
||||
macro_rules! tests {
|
||||
($($lhs: ident, $rhs: ident;)*) => {{
|
||||
$(
|
||||
(|| {
|
||||
cmp!(eq($lhs, $rhs));
|
||||
cmp!(ne($lhs, $rhs));
|
||||
cmp!(eq($lhs, $rhs));
|
||||
cmp!(ne($lhs, $rhs));
|
||||
|
||||
// test both directions
|
||||
cmp!(lt($lhs, $rhs));
|
||||
cmp!(lt($rhs, $lhs));
|
||||
// test both directions
|
||||
cmp!(lt($lhs, $rhs));
|
||||
cmp!(lt($rhs, $lhs));
|
||||
|
||||
cmp!(le($lhs, $rhs));
|
||||
cmp!(le($rhs, $lhs));
|
||||
cmp!(le($lhs, $rhs));
|
||||
cmp!(le($rhs, $lhs));
|
||||
|
||||
cmp!(gt($lhs, $rhs));
|
||||
cmp!(gt($rhs, $lhs));
|
||||
cmp!(gt($lhs, $rhs));
|
||||
cmp!(gt($rhs, $lhs));
|
||||
|
||||
cmp!(ge($lhs, $rhs));
|
||||
cmp!(ge($rhs, $lhs));
|
||||
})();
|
||||
)*
|
||||
cmp!(ge($lhs, $rhs));
|
||||
cmp!(ge($rhs, $lhs));
|
||||
)*
|
||||
}}
|
||||
}
|
||||
fn main() {
|
||||
|
||||
const fn compare() {
|
||||
// 13 vs. -100 tests that we get signed vs. unsigned comparisons
|
||||
// correct (i32: 13 > -100, u32: 13 < -100). let i1 = i32x4(10, -11, 12, 13);
|
||||
let i1 = i32x4::from_array([10, -11, 12, 13]);
|
||||
@@ -89,3 +95,8 @@ fn main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { compare() };
|
||||
compare();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//@ run-pass
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
#![feature(repr_simd, intrinsics, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
@@ -20,11 +21,59 @@ macro_rules! all_eq {
|
||||
// type inference works better with the concrete type on the
|
||||
// left, but humans work better with the expected on the
|
||||
// right.
|
||||
assert!(b == a, "{:?} != {:?}", a, b);
|
||||
assert!(b == a, concat!(stringify!($a), "!=", stringify!($b)));
|
||||
}};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
fn extract_insert_dyn() {
|
||||
let x2 = i32x2::from_array([20, 21]);
|
||||
let x4 = i32x4::from_array([40, 41, 42, 43]);
|
||||
let x8 = i32x8::from_array([80, 81, 82, 83, 84, 85, 86, 87]);
|
||||
|
||||
unsafe {
|
||||
all_eq!(simd_insert_dyn(x2, 0, 100), i32x2::from_array([100, 21]));
|
||||
all_eq!(simd_insert_dyn(x2, 1, 100), i32x2::from_array([20, 100]));
|
||||
|
||||
all_eq!(simd_insert_dyn(x4, 0, 100), i32x4::from_array([100, 41, 42, 43]));
|
||||
all_eq!(simd_insert_dyn(x4, 1, 100), i32x4::from_array([40, 100, 42, 43]));
|
||||
all_eq!(simd_insert_dyn(x4, 2, 100), i32x4::from_array([40, 41, 100, 43]));
|
||||
all_eq!(simd_insert_dyn(x4, 3, 100), i32x4::from_array([40, 41, 42, 100]));
|
||||
|
||||
all_eq!(simd_insert_dyn(x8, 0, 100), i32x8::from_array([100, 81, 82, 83, 84, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 1, 100), i32x8::from_array([80, 100, 82, 83, 84, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 2, 100), i32x8::from_array([80, 81, 100, 83, 84, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 3, 100), i32x8::from_array([80, 81, 82, 100, 84, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 4, 100), i32x8::from_array([80, 81, 82, 83, 100, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 5, 100), i32x8::from_array([80, 81, 82, 83, 84, 100, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 6, 100), i32x8::from_array([80, 81, 82, 83, 84, 85, 100, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 7, 100), i32x8::from_array([80, 81, 82, 83, 84, 85, 86, 100]));
|
||||
|
||||
all_eq!(simd_extract_dyn(x2, 0), 20);
|
||||
all_eq!(simd_extract_dyn(x2, 1), 21);
|
||||
|
||||
all_eq!(simd_extract_dyn(x4, 0), 40);
|
||||
all_eq!(simd_extract_dyn(x4, 1), 41);
|
||||
all_eq!(simd_extract_dyn(x4, 2), 42);
|
||||
all_eq!(simd_extract_dyn(x4, 3), 43);
|
||||
|
||||
all_eq!(simd_extract_dyn(x8, 0), 80);
|
||||
all_eq!(simd_extract_dyn(x8, 1), 81);
|
||||
all_eq!(simd_extract_dyn(x8, 2), 82);
|
||||
all_eq!(simd_extract_dyn(x8, 3), 83);
|
||||
all_eq!(simd_extract_dyn(x8, 4), 84);
|
||||
all_eq!(simd_extract_dyn(x8, 5), 85);
|
||||
all_eq!(simd_extract_dyn(x8, 6), 86);
|
||||
all_eq!(simd_extract_dyn(x8, 7), 87);
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! simd_shuffle {
|
||||
($a:expr, $b:expr, $swizzle:expr) => {
|
||||
simd_shuffle($a, $b, const { SimdShuffleIdx($swizzle) })
|
||||
};
|
||||
}
|
||||
|
||||
const fn swizzle() {
|
||||
let x2 = i32x2::from_array([20, 21]);
|
||||
let x4 = i32x4::from_array([40, 41, 42, 43]);
|
||||
let x8 = i32x8::from_array([80, 81, 82, 83, 84, 85, 86, 87]);
|
||||
@@ -63,83 +112,36 @@ fn main() {
|
||||
all_eq!(simd_extract(x8, 6), 86);
|
||||
all_eq!(simd_extract(x8, 7), 87);
|
||||
}
|
||||
unsafe {
|
||||
all_eq!(simd_insert_dyn(x2, 0, 100), i32x2::from_array([100, 21]));
|
||||
all_eq!(simd_insert_dyn(x2, 1, 100), i32x2::from_array([20, 100]));
|
||||
|
||||
all_eq!(simd_insert_dyn(x4, 0, 100), i32x4::from_array([100, 41, 42, 43]));
|
||||
all_eq!(simd_insert_dyn(x4, 1, 100), i32x4::from_array([40, 100, 42, 43]));
|
||||
all_eq!(simd_insert_dyn(x4, 2, 100), i32x4::from_array([40, 41, 100, 43]));
|
||||
all_eq!(simd_insert_dyn(x4, 3, 100), i32x4::from_array([40, 41, 42, 100]));
|
||||
|
||||
all_eq!(simd_insert_dyn(x8, 0, 100), i32x8::from_array([100, 81, 82, 83, 84, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 1, 100), i32x8::from_array([80, 100, 82, 83, 84, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 2, 100), i32x8::from_array([80, 81, 100, 83, 84, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 3, 100), i32x8::from_array([80, 81, 82, 100, 84, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 4, 100), i32x8::from_array([80, 81, 82, 83, 100, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 5, 100), i32x8::from_array([80, 81, 82, 83, 84, 100, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 6, 100), i32x8::from_array([80, 81, 82, 83, 84, 85, 100, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 7, 100), i32x8::from_array([80, 81, 82, 83, 84, 85, 86, 100]));
|
||||
|
||||
all_eq!(simd_extract_dyn(x2, 0), 20);
|
||||
all_eq!(simd_extract_dyn(x2, 1), 21);
|
||||
|
||||
all_eq!(simd_extract_dyn(x4, 0), 40);
|
||||
all_eq!(simd_extract_dyn(x4, 1), 41);
|
||||
all_eq!(simd_extract_dyn(x4, 2), 42);
|
||||
all_eq!(simd_extract_dyn(x4, 3), 43);
|
||||
|
||||
all_eq!(simd_extract_dyn(x8, 0), 80);
|
||||
all_eq!(simd_extract_dyn(x8, 1), 81);
|
||||
all_eq!(simd_extract_dyn(x8, 2), 82);
|
||||
all_eq!(simd_extract_dyn(x8, 3), 83);
|
||||
all_eq!(simd_extract_dyn(x8, 4), 84);
|
||||
all_eq!(simd_extract_dyn(x8, 5), 85);
|
||||
all_eq!(simd_extract_dyn(x8, 6), 86);
|
||||
all_eq!(simd_extract_dyn(x8, 7), 87);
|
||||
}
|
||||
|
||||
let y2 = i32x2::from_array([120, 121]);
|
||||
let y4 = i32x4::from_array([140, 141, 142, 143]);
|
||||
let y8 = i32x8::from_array([180, 181, 182, 183, 184, 185, 186, 187]);
|
||||
unsafe {
|
||||
all_eq!(simd_shuffle!(x2, y2, [3u32, 0]), i32x2::from_array([121, 20]));
|
||||
all_eq!(simd_shuffle!(x2, y2, [3u32, 0, 1, 2]), i32x4::from_array([121, 20, 21, 120]));
|
||||
all_eq!(
|
||||
simd_shuffle(x2, y2, const { SimdShuffleIdx([3u32, 0]) }),
|
||||
i32x2::from_array([121, 20])
|
||||
);
|
||||
all_eq!(
|
||||
simd_shuffle(x2, y2, const { SimdShuffleIdx([3u32, 0, 1, 2]) }),
|
||||
i32x4::from_array([121, 20, 21, 120])
|
||||
);
|
||||
all_eq!(
|
||||
simd_shuffle(x2, y2, const { SimdShuffleIdx([3u32, 0, 1, 2, 1, 2, 3, 0]) }),
|
||||
simd_shuffle!(x2, y2, [3u32, 0, 1, 2, 1, 2, 3, 0]),
|
||||
i32x8::from_array([121, 20, 21, 120, 21, 120, 121, 20])
|
||||
);
|
||||
|
||||
all_eq!(simd_shuffle!(x4, y4, [7u32, 2]), i32x2::from_array([143, 42]));
|
||||
all_eq!(simd_shuffle!(x4, y4, [7u32, 2, 5, 0]), i32x4::from_array([143, 42, 141, 40]));
|
||||
all_eq!(
|
||||
simd_shuffle(x4, y4, const { SimdShuffleIdx([7u32, 2]) }),
|
||||
i32x2::from_array([143, 42])
|
||||
);
|
||||
all_eq!(
|
||||
simd_shuffle(x4, y4, const { SimdShuffleIdx([7u32, 2, 5, 0]) }),
|
||||
i32x4::from_array([143, 42, 141, 40])
|
||||
);
|
||||
all_eq!(
|
||||
simd_shuffle(x4, y4, const { SimdShuffleIdx([7u32, 2, 5, 0, 3, 6, 4, 1]) }),
|
||||
simd_shuffle!(x4, y4, [7u32, 2, 5, 0, 3, 6, 4, 1]),
|
||||
i32x8::from_array([143, 42, 141, 40, 43, 142, 140, 41])
|
||||
);
|
||||
|
||||
all_eq!(simd_shuffle!(x8, y8, [11u32, 5]), i32x2::from_array([183, 85]));
|
||||
all_eq!(simd_shuffle!(x8, y8, [11u32, 5, 15, 0]), i32x4::from_array([183, 85, 187, 80]));
|
||||
all_eq!(
|
||||
simd_shuffle(x8, y8, const { SimdShuffleIdx([11u32, 5]) }),
|
||||
i32x2::from_array([183, 85])
|
||||
);
|
||||
all_eq!(
|
||||
simd_shuffle(x8, y8, const { SimdShuffleIdx([11u32, 5, 15, 0]) }),
|
||||
i32x4::from_array([183, 85, 187, 80])
|
||||
);
|
||||
all_eq!(
|
||||
simd_shuffle(x8, y8, const { SimdShuffleIdx([11u32, 5, 15, 0, 3, 8, 12, 1]) }),
|
||||
simd_shuffle!(x8, y8, [11u32, 5, 15, 0, 3, 8, 12, 1]),
|
||||
i32x8::from_array([183, 85, 187, 80, 83, 180, 184, 81])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
extract_insert_dyn();
|
||||
const { swizzle() };
|
||||
swizzle();
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
//@ run-pass
|
||||
//@ ignore-emscripten
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
// Test that the simd_{gather,scatter} intrinsics produce the correct results.
|
||||
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
@@ -14,48 +15,11 @@
|
||||
|
||||
type x4<T> = Simd<T, 4>;
|
||||
|
||||
fn main() {
|
||||
let mut x = [0_f32, 1., 2., 3., 4., 5., 6., 7.];
|
||||
|
||||
let default = x4::from_array([-3_f32, -3., -3., -3.]);
|
||||
let s_strided = x4::from_array([0_f32, 2., -3., 6.]);
|
||||
fn gather_scatter_of_ptrs() {
|
||||
// test modifying array of *const f32
|
||||
let x = [0_f32, 1., 2., 3., 4., 5., 6., 7.];
|
||||
let mask = x4::from_array([-1_i32, -1, 0, -1]);
|
||||
|
||||
// reading from *const
|
||||
unsafe {
|
||||
let pointer = x.as_ptr();
|
||||
let pointers =
|
||||
x4::from_array(std::array::from_fn(|i| pointer.add(i * 2)));
|
||||
|
||||
let r_strided = simd_gather(default, pointers, mask);
|
||||
|
||||
assert_eq!(r_strided, s_strided);
|
||||
}
|
||||
|
||||
// reading from *mut
|
||||
unsafe {
|
||||
let pointer = x.as_mut_ptr();
|
||||
let pointers =
|
||||
x4::from_array(std::array::from_fn(|i| pointer.add(i * 2)));
|
||||
|
||||
let r_strided = simd_gather(default, pointers, mask);
|
||||
|
||||
assert_eq!(r_strided, s_strided);
|
||||
}
|
||||
|
||||
// writing to *mut
|
||||
unsafe {
|
||||
let pointer = x.as_mut_ptr();
|
||||
let pointers =
|
||||
x4::from_array(std::array::from_fn(|i| pointer.add(i * 2)));
|
||||
|
||||
let values = x4::from_array([42_f32, 43_f32, 44_f32, 45_f32]);
|
||||
simd_scatter(values, pointers, mask);
|
||||
|
||||
assert_eq!(x, [42., 1., 43., 3., 4., 5., 45., 7.]);
|
||||
}
|
||||
|
||||
// test modifying array of *const f32
|
||||
let mut y = [
|
||||
&x[0] as *const f32,
|
||||
&x[1] as *const f32,
|
||||
@@ -73,8 +37,7 @@ fn main() {
|
||||
// reading from *const
|
||||
unsafe {
|
||||
let pointer = y.as_ptr();
|
||||
let pointers =
|
||||
x4::from_array(std::array::from_fn(|i| pointer.add(i * 2)));
|
||||
let pointers = x4::from_array([pointer, pointer.add(2), pointer.add(4), pointer.add(6)]);
|
||||
|
||||
let r_strided = simd_gather(default, pointers, mask);
|
||||
|
||||
@@ -84,8 +47,7 @@ fn main() {
|
||||
// reading from *mut
|
||||
unsafe {
|
||||
let pointer = y.as_mut_ptr();
|
||||
let pointers =
|
||||
x4::from_array(std::array::from_fn(|i| pointer.add(i * 2)));
|
||||
let pointers = x4::from_array([pointer, pointer.add(2), pointer.add(4), pointer.add(6)]);
|
||||
|
||||
let r_strided = simd_gather(default, pointers, mask);
|
||||
|
||||
@@ -95,8 +57,7 @@ fn main() {
|
||||
// writing to *mut
|
||||
unsafe {
|
||||
let pointer = y.as_mut_ptr();
|
||||
let pointers =
|
||||
x4::from_array(std::array::from_fn(|i| pointer.add(i * 2)));
|
||||
let pointers = x4::from_array([pointer, pointer.add(2), pointer.add(4), pointer.add(6)]);
|
||||
|
||||
let values = x4::from_array([y[7], y[6], y[5], y[1]]);
|
||||
simd_scatter(values, pointers, mask);
|
||||
@@ -114,3 +75,48 @@ fn main() {
|
||||
assert_eq!(y, s);
|
||||
}
|
||||
}
|
||||
|
||||
const fn gather_scatter() {
|
||||
let mut x = [0_f32, 1., 2., 3., 4., 5., 6., 7.];
|
||||
|
||||
let default = x4::from_array([-3_f32, -3., -3., -3.]);
|
||||
let s_strided = x4::from_array([0_f32, 2., -3., 6.]);
|
||||
let mask = x4::from_array([-1_i32, -1, 0, -1]);
|
||||
|
||||
// reading from *const
|
||||
unsafe {
|
||||
let pointer = x.as_ptr();
|
||||
let pointers = x4::from_array([pointer, pointer.add(2), pointer.add(4), pointer.add(6)]);
|
||||
|
||||
let r_strided = simd_gather(default, pointers, mask);
|
||||
|
||||
assert_eq!(r_strided, s_strided);
|
||||
}
|
||||
|
||||
// reading from *mut
|
||||
unsafe {
|
||||
let pointer = x.as_mut_ptr();
|
||||
let pointers = x4::from_array([pointer, pointer.add(2), pointer.add(4), pointer.add(6)]);
|
||||
|
||||
let r_strided = simd_gather(default, pointers, mask);
|
||||
|
||||
assert_eq!(r_strided, s_strided);
|
||||
}
|
||||
|
||||
// writing to *mut
|
||||
unsafe {
|
||||
let pointer = x.as_mut_ptr();
|
||||
let pointers = x4::from_array([pointer, pointer.add(2), pointer.add(4), pointer.add(6)]);
|
||||
|
||||
let values = x4::from_array([42_f32, 43_f32, 44_f32, 45_f32]);
|
||||
simd_scatter(values, pointers, mask);
|
||||
|
||||
assert_eq!(x, [42., 1., 43., 3., 4., 5., 45., 7.]);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { gather_scatter() };
|
||||
gather_scatter();
|
||||
gather_scatter_of_ptrs();
|
||||
}
|
||||
|
||||
@@ -1,35 +1,46 @@
|
||||
//@ run-pass
|
||||
#![allow(non_camel_case_types)]
|
||||
//@ ignore-emscripten
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
// Test that the simd_reduce_{op} intrinsics produce the correct results.
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
use minisimd::*;
|
||||
|
||||
use std::intrinsics::simd::*;
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct i32x4(pub [i32; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct u32x4(pub [u32; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct f32x4(pub [f32; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct b8x4(pub [i8; 4]);
|
||||
|
||||
fn main() {
|
||||
fn unordered() {
|
||||
unsafe {
|
||||
let x = i32x4([1, -2, 3, 4]);
|
||||
let x = i32x4::from_array([1, -2, 3, 4]);
|
||||
let r: i32 = simd_reduce_add_unordered(x);
|
||||
assert_eq!(r, 6_i32);
|
||||
let r: i32 = simd_reduce_mul_unordered(x);
|
||||
assert_eq!(r, -24_i32);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let x = u32x4::from_array([1, 2, 3, 4]);
|
||||
let r: u32 = simd_reduce_add_unordered(x);
|
||||
assert_eq!(r, 10_u32);
|
||||
let r: u32 = simd_reduce_mul_unordered(x);
|
||||
assert_eq!(r, 24_u32);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let x = f32x4::from_array([1., -2., 3., 4.]);
|
||||
let r: f32 = simd_reduce_add_unordered(x);
|
||||
assert_eq!(r, 6_f32);
|
||||
let r: f32 = simd_reduce_mul_unordered(x);
|
||||
assert_eq!(r, -24_f32);
|
||||
}
|
||||
}
|
||||
|
||||
const fn ordered() {
|
||||
unsafe {
|
||||
let x = i32x4::from_array([1, -2, 3, 4]);
|
||||
let r: i32 = simd_reduce_add_ordered(x, -1);
|
||||
assert_eq!(r, 5_i32);
|
||||
let r: i32 = simd_reduce_mul_ordered(x, -1);
|
||||
@@ -40,7 +51,7 @@ fn main() {
|
||||
let r: i32 = simd_reduce_max(x);
|
||||
assert_eq!(r, 4_i32);
|
||||
|
||||
let x = i32x4([-1, -1, -1, -1]);
|
||||
let x = i32x4::from_array([-1, -1, -1, -1]);
|
||||
let r: i32 = simd_reduce_and(x);
|
||||
assert_eq!(r, -1_i32);
|
||||
let r: i32 = simd_reduce_or(x);
|
||||
@@ -48,7 +59,7 @@ fn main() {
|
||||
let r: i32 = simd_reduce_xor(x);
|
||||
assert_eq!(r, 0_i32);
|
||||
|
||||
let x = i32x4([-1, -1, 0, -1]);
|
||||
let x = i32x4::from_array([-1, -1, 0, -1]);
|
||||
let r: i32 = simd_reduce_and(x);
|
||||
assert_eq!(r, 0_i32);
|
||||
let r: i32 = simd_reduce_or(x);
|
||||
@@ -58,11 +69,7 @@ fn main() {
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let x = u32x4([1, 2, 3, 4]);
|
||||
let r: u32 = simd_reduce_add_unordered(x);
|
||||
assert_eq!(r, 10_u32);
|
||||
let r: u32 = simd_reduce_mul_unordered(x);
|
||||
assert_eq!(r, 24_u32);
|
||||
let x = u32x4::from_array([1, 2, 3, 4]);
|
||||
let r: u32 = simd_reduce_add_ordered(x, 1);
|
||||
assert_eq!(r, 11_u32);
|
||||
let r: u32 = simd_reduce_mul_ordered(x, 2);
|
||||
@@ -74,7 +81,7 @@ fn main() {
|
||||
assert_eq!(r, 4_u32);
|
||||
|
||||
let t = u32::MAX;
|
||||
let x = u32x4([t, t, t, t]);
|
||||
let x = u32x4::from_array([t, t, t, t]);
|
||||
let r: u32 = simd_reduce_and(x);
|
||||
assert_eq!(r, t);
|
||||
let r: u32 = simd_reduce_or(x);
|
||||
@@ -82,7 +89,7 @@ fn main() {
|
||||
let r: u32 = simd_reduce_xor(x);
|
||||
assert_eq!(r, 0_u32);
|
||||
|
||||
let x = u32x4([t, t, 0, t]);
|
||||
let x = u32x4::from_array([t, t, 0, t]);
|
||||
let r: u32 = simd_reduce_and(x);
|
||||
assert_eq!(r, 0_u32);
|
||||
let r: u32 = simd_reduce_or(x);
|
||||
@@ -92,11 +99,7 @@ fn main() {
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let x = f32x4([1., -2., 3., 4.]);
|
||||
let r: f32 = simd_reduce_add_unordered(x);
|
||||
assert_eq!(r, 6_f32);
|
||||
let r: f32 = simd_reduce_mul_unordered(x);
|
||||
assert_eq!(r, -24_f32);
|
||||
let x = f32x4::from_array([1., -2., 3., 4.]);
|
||||
let r: f32 = simd_reduce_add_ordered(x, 0.);
|
||||
assert_eq!(r, 6_f32);
|
||||
let r: f32 = simd_reduce_mul_ordered(x, 1.);
|
||||
@@ -113,22 +116,28 @@ fn main() {
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let x = b8x4([!0, !0, !0, !0]);
|
||||
let x = i8x4::from_array([!0, !0, !0, !0]);
|
||||
let r: bool = simd_reduce_all(x);
|
||||
assert_eq!(r, true);
|
||||
let r: bool = simd_reduce_any(x);
|
||||
assert_eq!(r, true);
|
||||
|
||||
let x = b8x4([!0, !0, 0, !0]);
|
||||
let x = i8x4::from_array([!0, !0, 0, !0]);
|
||||
let r: bool = simd_reduce_all(x);
|
||||
assert_eq!(r, false);
|
||||
let r: bool = simd_reduce_any(x);
|
||||
assert_eq!(r, true);
|
||||
|
||||
let x = b8x4([0, 0, 0, 0]);
|
||||
let x = i8x4::from_array([0, 0, 0, 0]);
|
||||
let r: bool = simd_reduce_all(x);
|
||||
assert_eq!(r, false);
|
||||
let r: bool = simd_reduce_any(x);
|
||||
assert_eq!(r, false);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unordered();
|
||||
const { ordered() };
|
||||
ordered();
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
//@ ignore-emscripten
|
||||
//@ ignore-endian-big behavior of simd_select_bitmask is endian-specific
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
// Test that the simd_select intrinsics produces correct results.
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
@@ -14,7 +15,7 @@
|
||||
|
||||
type b8x4 = i8x4;
|
||||
|
||||
fn main() {
|
||||
const fn select() {
|
||||
let m0 = b8x4::from_array([!0, !0, !0, !0]);
|
||||
let m1 = b8x4::from_array([0, 0, 0, 0]);
|
||||
let m2 = b8x4::from_array([!0, !0, 0, 0]);
|
||||
@@ -173,3 +174,8 @@ fn main() {
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { select() };
|
||||
select();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//@ ignore-backends: gcc
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
//@ run-pass
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
@@ -8,7 +9,7 @@
|
||||
|
||||
use std::intrinsics::simd::{SimdAlign, simd_masked_load, simd_masked_store};
|
||||
|
||||
fn main() {
|
||||
const fn masked_load_store() {
|
||||
unsafe {
|
||||
let a = Simd::<u8, 4>([0, 1, 2, 3]);
|
||||
let b_src = [4u8, 5, 6, 7];
|
||||
@@ -37,3 +38,8 @@ fn main() {
|
||||
assert_eq!(&output, &[0, 1, 9, 6, u8::MAX]);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { masked_load_store() };
|
||||
masked_load_store();
|
||||
}
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
// This should be merged into `simd-bitmask` once that's fixed.
|
||||
//@ ignore-endian-big
|
||||
//@ ignore-backends: gcc
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
@@ -12,15 +13,10 @@
|
||||
|
||||
use std::intrinsics::simd::{simd_bitmask, simd_select_bitmask};
|
||||
|
||||
fn main() {
|
||||
const fn bitmask() {
|
||||
// Non-power-of-2 multi-byte mask.
|
||||
#[allow(non_camel_case_types)]
|
||||
type i32x10 = PackedSimd<i32, 10>;
|
||||
impl i32x10 {
|
||||
fn splat(x: i32) -> Self {
|
||||
Self([x; 10])
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
let mask = i32x10::from_array([!0, !0, 0, !0, 0, 0, !0, 0, !0, 0]);
|
||||
let mask_bits = if cfg!(target_endian = "little") { 0b0101001011 } else { 0b1101001010 };
|
||||
@@ -49,11 +45,6 @@ fn splat(x: i32) -> Self {
|
||||
// Test for a mask where the next multiple of 8 is not a power of two.
|
||||
#[allow(non_camel_case_types)]
|
||||
type i32x20 = PackedSimd<i32, 20>;
|
||||
impl i32x20 {
|
||||
fn splat(x: i32) -> Self {
|
||||
Self([x; 20])
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
let mask = i32x20::from_array([
|
||||
!0, !0, 0, !0, 0,
|
||||
@@ -91,3 +82,8 @@ fn splat(x: i32) -> Self {
|
||||
assert_eq!(selected2, mask);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { bitmask() };
|
||||
bitmask();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//@run-pass
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
@@ -7,7 +8,7 @@
|
||||
|
||||
use std::intrinsics::simd::{simd_bitmask, simd_select_bitmask};
|
||||
|
||||
fn main() {
|
||||
const fn bitmask() {
|
||||
unsafe {
|
||||
let v = Simd::<i8, 4>([-1, 0, -1, 0]);
|
||||
let i: u8 = simd_bitmask(v);
|
||||
@@ -68,3 +69,8 @@ fn main() {
|
||||
assert_eq!(r.into_array(), e);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { bitmask() };
|
||||
bitmask();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user