So many test updates x_x

This commit is contained in:
Scott McMurray 2025-07-12 02:33:42 -07:00
parent 0864097cd3
commit 08b816ff18
52 changed files with 797 additions and 1029 deletions

160
tests/auxiliary/minisimd.rs Normal file
View file

@ -0,0 +1,160 @@
//! Auxiliary crate for tests that need SIMD types.
//!
//! Historically the tests just made their own, but projections into simd types
//! was banned by <https://github.com/rust-lang/compiler-team/issues/838>, which
//! breaks `derive(Clone)`, so this exists to give easily-usable types that can
//! be used without copy-pasting the definitions of the helpers everywhere.
//!
//! This makes no attempt to guard against ICEs. Using it with proper types
//! and such is your responsibility in the tests you write.
#![allow(unused)]
#![allow(non_camel_case_types)]
// 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
// `.0` projection that doesn't.
#[repr(simd)]
#[derive(Copy, Eq)]
pub struct Simd<T, const N: usize>(pub [T; N]);
impl<T: Copy, const N: usize> Clone for Simd<T, N> {
fn clone(&self) -> 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] {
let p: *const Self = self;
unsafe { &*p.cast::<[T; N]>() }
}
pub fn into_array(self) -> [T; N]
where
T: Copy,
{
*self.as_array()
}
}
pub type u8x2 = Simd<u8, 2>;
pub type u8x4 = Simd<u8, 4>;
pub type u8x8 = Simd<u8, 8>;
pub type u8x16 = Simd<u8, 16>;
pub type u8x32 = Simd<u8, 32>;
pub type u8x64 = Simd<u8, 64>;
pub type u16x2 = Simd<u16, 2>;
pub type u16x4 = Simd<u16, 4>;
pub type u16x8 = Simd<u16, 8>;
pub type u16x16 = Simd<u16, 16>;
pub type u16x32 = Simd<u16, 32>;
pub type u32x2 = Simd<u32, 2>;
pub type u32x4 = Simd<u32, 4>;
pub type u32x8 = Simd<u32, 8>;
pub type u32x16 = Simd<u32, 16>;
pub type u64x2 = Simd<u64, 2>;
pub type u64x4 = Simd<u64, 4>;
pub type u64x8 = Simd<u64, 8>;
pub type u128x2 = Simd<u128, 2>;
pub type u128x4 = Simd<u128, 4>;
pub type i8x2 = Simd<i8, 2>;
pub type i8x4 = Simd<i8, 4>;
pub type i8x8 = Simd<i8, 8>;
pub type i8x16 = Simd<i8, 16>;
pub type i8x32 = Simd<i8, 32>;
pub type i8x64 = Simd<i8, 64>;
pub type i16x2 = Simd<i16, 2>;
pub type i16x4 = Simd<i16, 4>;
pub type i16x8 = Simd<i16, 8>;
pub type i16x16 = Simd<i16, 16>;
pub type i16x32 = Simd<i16, 32>;
pub type i32x2 = Simd<i32, 2>;
pub type i32x4 = Simd<i32, 4>;
pub type i32x8 = Simd<i32, 8>;
pub type i32x16 = Simd<i32, 16>;
pub type i64x2 = Simd<i64, 2>;
pub type i64x4 = Simd<i64, 4>;
pub type i64x8 = Simd<i64, 8>;
pub type i128x2 = Simd<i128, 2>;
pub type i128x4 = Simd<i128, 4>;
pub type f32x2 = Simd<f32, 2>;
pub type f32x4 = Simd<f32, 4>;
pub type f32x8 = Simd<f32, 8>;
pub type f32x16 = Simd<f32, 16>;
pub type f64x2 = Simd<f64, 2>;
pub type f64x4 = Simd<f64, 4>;
pub type f64x8 = Simd<f64, 8>;
// 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
// `.0` projection that doesn't.
#[repr(simd, packed)]
#[derive(Copy)]
pub struct PackedSimd<T, const N: usize>(pub [T; N]);
impl<T: Copy, const N: usize> Clone for PackedSimd<T, N> {
fn clone(&self) -> 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)
}
}
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] {
let p: *const Self = self;
unsafe { &*p.cast::<[T; N]>() }
}
pub fn into_array(self) -> [T; N]
where
T: Copy,
{
*self.as_array()
}
}

View file

@ -16,18 +16,9 @@
#![feature(mips_target_feature)]
#![allow(non_camel_case_types)]
// Setting up structs that can be used as const vectors
#[repr(simd)]
#[derive(Clone)]
pub struct i8x2([i8; 2]);
#[repr(simd)]
#[derive(Clone)]
pub struct f32x2([f32; 2]);
#[repr(simd, packed)]
#[derive(Copy, Clone)]
pub struct Simd<T, const N: usize>([T; N]);
#[path = "../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::{PackedSimd as Simd, f32x2, i8x2};
// The following functions are required for the tests to ensure
// that they are called with a const vector
@ -45,7 +36,7 @@ extern "unadjusted" {
// Ensure the packed variant of the simd struct does not become a const vector
// if the size is not a power of 2
// CHECK: %"Simd<i32, 3>" = type { [3 x i32] }
// CHECK: %"minisimd::PackedSimd<i32, 3>" = type { [3 x i32] }
#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))]
#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))]
@ -54,27 +45,34 @@ extern "unadjusted" {
pub fn do_call() {
unsafe {
// CHECK: call void @test_i8x2(<2 x i8> <i8 32, i8 64>
test_i8x2(const { i8x2([32, 64]) });
test_i8x2(const { i8x2::from_array([32, 64]) });
// CHECK: call void @test_i8x2_two_args(<2 x i8> <i8 32, i8 64>, <2 x i8> <i8 8, i8 16>
test_i8x2_two_args(const { i8x2([32, 64]) }, const { i8x2([8, 16]) });
test_i8x2_two_args(
const { i8x2::from_array([32, 64]) },
const { i8x2::from_array([8, 16]) },
);
// CHECK: call void @test_i8x2_mixed_args(<2 x i8> <i8 32, i8 64>, i32 43, <2 x i8> <i8 8, i8 16>
test_i8x2_mixed_args(const { i8x2([32, 64]) }, 43, const { i8x2([8, 16]) });
test_i8x2_mixed_args(
const { i8x2::from_array([32, 64]) },
43,
const { i8x2::from_array([8, 16]) },
);
// CHECK: call void @test_i8x2_arr(<2 x i8> <i8 32, i8 64>
test_i8x2_arr(const { i8x2([32, 64]) });
test_i8x2_arr(const { i8x2::from_array([32, 64]) });
// CHECK: call void @test_f32x2(<2 x float> <float 0x3FD47AE140000000, float 0x3FE47AE140000000>
test_f32x2(const { f32x2([0.32, 0.64]) });
test_f32x2(const { f32x2::from_array([0.32, 0.64]) });
// CHECK: void @test_f32x2_arr(<2 x float> <float 0x3FD47AE140000000, float 0x3FE47AE140000000>
test_f32x2_arr(const { f32x2([0.32, 0.64]) });
test_f32x2_arr(const { f32x2::from_array([0.32, 0.64]) });
// CHECK: call void @test_simd(<4 x i32> <i32 2, i32 4, i32 6, i32 8>
test_simd(const { Simd::<i32, 4>([2, 4, 6, 8]) });
// CHECK: call void @test_simd_unaligned(%"Simd<i32, 3>" %1
// CHECK: call void @test_simd_unaligned(%"minisimd::PackedSimd<i32, 3>" %1
test_simd_unaligned(const { Simd::<i32, 3>([2, 4, 6]) });
}
}

View file

@ -4,24 +4,12 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_fabs;
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x2(pub [f32; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x4(pub [f32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x8(pub [f32; 8]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x16(pub [f32; 16]);
// CHECK-LABEL: @fabs_32x2
#[no_mangle]
pub unsafe fn fabs_32x2(a: f32x2) -> f32x2 {
@ -50,18 +38,6 @@ pub unsafe fn fabs_32x16(a: f32x16) -> f32x16 {
simd_fabs(a)
}
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x2(pub [f64; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x4(pub [f64; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x8(pub [f64; 8]);
// CHECK-LABEL: @fabs_64x4
#[no_mangle]
pub unsafe fn fabs_64x4(a: f64x4) -> f64x4 {

View file

@ -4,24 +4,12 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_ceil;
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x2(pub [f32; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x4(pub [f32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x8(pub [f32; 8]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x16(pub [f32; 16]);
// CHECK-LABEL: @ceil_32x2
#[no_mangle]
pub unsafe fn ceil_32x2(a: f32x2) -> f32x2 {
@ -50,18 +38,6 @@ pub unsafe fn ceil_32x16(a: f32x16) -> f32x16 {
simd_ceil(a)
}
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x2(pub [f64; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x4(pub [f64; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x8(pub [f64; 8]);
// CHECK-LABEL: @ceil_64x4
#[no_mangle]
pub unsafe fn ceil_64x4(a: f64x4) -> f64x4 {

View file

@ -4,24 +4,12 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_fcos;
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x2(pub [f32; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x4(pub [f32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x8(pub [f32; 8]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x16(pub [f32; 16]);
// CHECK-LABEL: @fcos_32x2
#[no_mangle]
pub unsafe fn fcos_32x2(a: f32x2) -> f32x2 {
@ -50,18 +38,6 @@ pub unsafe fn fcos_32x16(a: f32x16) -> f32x16 {
simd_fcos(a)
}
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x2(pub [f64; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x4(pub [f64; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x8(pub [f64; 8]);
// CHECK-LABEL: @fcos_64x4
#[no_mangle]
pub unsafe fn fcos_64x4(a: f64x4) -> f64x4 {

View file

@ -4,24 +4,12 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_fexp;
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x2(pub [f32; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x4(pub [f32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x8(pub [f32; 8]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x16(pub [f32; 16]);
// CHECK-LABEL: @exp_32x2
#[no_mangle]
pub unsafe fn exp_32x2(a: f32x2) -> f32x2 {
@ -50,18 +38,6 @@ pub unsafe fn exp_32x16(a: f32x16) -> f32x16 {
simd_fexp(a)
}
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x2(pub [f64; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x4(pub [f64; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x8(pub [f64; 8]);
// CHECK-LABEL: @exp_64x4
#[no_mangle]
pub unsafe fn exp_64x4(a: f64x4) -> f64x4 {

View file

@ -4,24 +4,12 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_fexp2;
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x2(pub [f32; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x4(pub [f32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x8(pub [f32; 8]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x16(pub [f32; 16]);
// CHECK-LABEL: @exp2_32x2
#[no_mangle]
pub unsafe fn exp2_32x2(a: f32x2) -> f32x2 {
@ -50,18 +38,6 @@ pub unsafe fn exp2_32x16(a: f32x16) -> f32x16 {
simd_fexp2(a)
}
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x2(pub [f64; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x4(pub [f64; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x8(pub [f64; 8]);
// CHECK-LABEL: @exp2_64x4
#[no_mangle]
pub unsafe fn exp2_64x4(a: f64x4) -> f64x4 {

View file

@ -4,24 +4,12 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_floor;
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x2(pub [f32; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x4(pub [f32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x8(pub [f32; 8]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x16(pub [f32; 16]);
// CHECK-LABEL: @floor_32x2
#[no_mangle]
pub unsafe fn floor_32x2(a: f32x2) -> f32x2 {
@ -50,18 +38,6 @@ pub unsafe fn floor_32x16(a: f32x16) -> f32x16 {
simd_floor(a)
}
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x2(pub [f64; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x4(pub [f64; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x8(pub [f64; 8]);
// CHECK-LABEL: @floor_64x4
#[no_mangle]
pub unsafe fn floor_64x4(a: f64x4) -> f64x4 {

View file

@ -4,24 +4,12 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_fma;
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x2(pub [f32; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x4(pub [f32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x8(pub [f32; 8]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x16(pub [f32; 16]);
// CHECK-LABEL: @fma_32x2
#[no_mangle]
pub unsafe fn fma_32x2(a: f32x2, b: f32x2, c: f32x2) -> f32x2 {
@ -50,18 +38,6 @@ pub unsafe fn fma_32x16(a: f32x16, b: f32x16, c: f32x16) -> f32x16 {
simd_fma(a, b, c)
}
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x2(pub [f64; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x4(pub [f64; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x8(pub [f64; 8]);
// CHECK-LABEL: @fma_64x4
#[no_mangle]
pub unsafe fn fma_64x4(a: f64x4, b: f64x4, c: f64x4) -> f64x4 {

View file

@ -4,24 +4,12 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_fsqrt;
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x2(pub [f32; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x4(pub [f32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x8(pub [f32; 8]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x16(pub [f32; 16]);
// CHECK-LABEL: @fsqrt_32x2
#[no_mangle]
pub unsafe fn fsqrt_32x2(a: f32x2) -> f32x2 {
@ -50,18 +38,6 @@ pub unsafe fn fsqrt_32x16(a: f32x16) -> f32x16 {
simd_fsqrt(a)
}
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x2(pub [f64; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x4(pub [f64; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x8(pub [f64; 8]);
// CHECK-LABEL: @fsqrt_64x4
#[no_mangle]
pub unsafe fn fsqrt_64x4(a: f64x4) -> f64x4 {

View file

@ -4,24 +4,12 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_flog;
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x2(pub [f32; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x4(pub [f32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x8(pub [f32; 8]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x16(pub [f32; 16]);
// CHECK-LABEL: @log_32x2
#[no_mangle]
pub unsafe fn log_32x2(a: f32x2) -> f32x2 {
@ -50,18 +38,6 @@ pub unsafe fn log_32x16(a: f32x16) -> f32x16 {
simd_flog(a)
}
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x2(pub [f64; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x4(pub [f64; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x8(pub [f64; 8]);
// CHECK-LABEL: @log_64x4
#[no_mangle]
pub unsafe fn log_64x4(a: f64x4) -> f64x4 {

View file

@ -4,24 +4,12 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_flog10;
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x2(pub [f32; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x4(pub [f32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x8(pub [f32; 8]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x16(pub [f32; 16]);
// CHECK-LABEL: @log10_32x2
#[no_mangle]
pub unsafe fn log10_32x2(a: f32x2) -> f32x2 {
@ -50,18 +38,6 @@ pub unsafe fn log10_32x16(a: f32x16) -> f32x16 {
simd_flog10(a)
}
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x2(pub [f64; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x4(pub [f64; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x8(pub [f64; 8]);
// CHECK-LABEL: @log10_64x4
#[no_mangle]
pub unsafe fn log10_64x4(a: f64x4) -> f64x4 {

View file

@ -4,24 +4,12 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_flog2;
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x2(pub [f32; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x4(pub [f32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x8(pub [f32; 8]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x16(pub [f32; 16]);
// CHECK-LABEL: @log2_32x2
#[no_mangle]
pub unsafe fn log2_32x2(a: f32x2) -> f32x2 {
@ -50,18 +38,6 @@ pub unsafe fn log2_32x16(a: f32x16) -> f32x16 {
simd_flog2(a)
}
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x2(pub [f64; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x4(pub [f64; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x8(pub [f64; 8]);
// CHECK-LABEL: @log2_64x4
#[no_mangle]
pub unsafe fn log2_64x4(a: f64x4) -> f64x4 {

View file

@ -4,11 +4,11 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
use std::intrinsics::simd::{simd_fmax, simd_fmin};
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x4(pub [f32; 4]);
use std::intrinsics::simd::{simd_fmax, simd_fmin};
// CHECK-LABEL: @fmin
#[no_mangle]

View file

@ -4,24 +4,12 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_fsin;
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x2(pub [f32; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x4(pub [f32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x8(pub [f32; 8]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x16(pub [f32; 16]);
// CHECK-LABEL: @fsin_32x2
#[no_mangle]
pub unsafe fn fsin_32x2(a: f32x2) -> f32x2 {
@ -50,18 +38,6 @@ pub unsafe fn fsin_32x16(a: f32x16) -> f32x16 {
simd_fsin(a)
}
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x2(pub [f64; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x4(pub [f64; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x8(pub [f64; 8]);
// CHECK-LABEL: @fsin_64x4
#[no_mangle]
pub unsafe fn fsin_64x4(a: f64x4) -> f64x4 {

View file

@ -5,67 +5,12 @@
#![allow(non_camel_case_types)]
#![deny(unused)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::{simd_saturating_add, simd_saturating_sub};
#[rustfmt::skip]
mod types {
// signed integer types
#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x2([i8; 2]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x4([i8; 4]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x8([i8; 8]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x16([i8; 16]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x32([i8; 32]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x64([i8; 64]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x2([i16; 2]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x4([i16; 4]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x8([i16; 8]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x16([i16; 16]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x32([i16; 32]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x2([i32; 2]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x4([i32; 4]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x8([i32; 8]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x16([i32; 16]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct i64x2([i64; 2]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct i64x4([i64; 4]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct i64x8([i64; 8]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct i128x2([i128; 2]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct i128x4([i128; 4]);
// unsigned integer types
#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x2([u8; 2]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x4([u8; 4]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x8([u8; 8]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x16([u8; 16]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x32([u8; 32]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x64([u8; 64]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x2([u16; 2]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x4([u16; 4]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x8([u16; 8]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x16([u16; 16]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x32([u16; 32]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x2([u32; 2]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x4([u32; 4]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x8([u32; 8]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x16([u32; 16]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct u64x2([u64; 2]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct u64x4([u64; 4]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct u64x8([u64; 8]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct u128x2([u128; 2]);
#[repr(simd)] #[derive(Copy, Clone)] pub struct u128x4([u128; 4]);
}
use types::*;
// NOTE(eddyb) `%{{x|0}}` is used because on some targets (e.g. WASM)
// SIMD vectors are passed directly, resulting in `%x` being a vector,
// while on others they're passed indirectly, resulting in `%x` being

View file

@ -5,20 +5,12 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_bitmask;
#[repr(simd)]
#[derive(Copy, Clone)]
pub struct u32x2([u32; 2]);
#[repr(simd)]
#[derive(Copy, Clone)]
pub struct i32x2([i32; 2]);
#[repr(simd)]
#[derive(Copy, Clone)]
pub struct i8x16([i8; 16]);
// NOTE(eddyb) `%{{x|1}}` is used because on some targets (e.g. WASM)
// SIMD vectors are passed directly, resulting in `%x` being a vector,
// while on others they're passed indirectly, resulting in `%x` being

View file

@ -6,15 +6,14 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_gather;
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Vec2<T>(pub [T; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Vec4<T>(pub [T; 4]);
pub type Vec2<T> = Simd<T, 2>;
pub type Vec4<T> = Simd<T, 4>;
// CHECK-LABEL: @gather_f32x2
#[no_mangle]

View file

@ -4,15 +4,14 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_masked_load;
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Vec2<T>(pub [T; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Vec4<T>(pub [T; 4]);
pub type Vec2<T> = Simd<T, 2>;
pub type Vec4<T> = Simd<T, 4>;
// CHECK-LABEL: @load_f32x2
#[no_mangle]

View file

@ -4,15 +4,14 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_masked_store;
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Vec2<T>(pub [T; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Vec4<T>(pub [T; 4]);
pub type Vec2<T> = Simd<T, 2>;
pub type Vec4<T> = Simd<T, 4>;
// CHECK-LABEL: @store_f32x2
#[no_mangle]

View file

@ -6,15 +6,14 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_scatter;
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Vec2<T>(pub [T; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Vec4<T>(pub [T; 4]);
pub type Vec2<T> = Simd<T, 2>;
pub type Vec4<T> = Simd<T, 4>;
// CHECK-LABEL: @scatter_f32x2
#[no_mangle]

View file

@ -4,27 +4,13 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::{simd_select, simd_select_bitmask};
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x4(pub [f32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x8([f32; 8]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct b8x4(pub [i8; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct i32x4([i32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct u32x4([u32; 4]);
pub type b8x4 = i8x4;
// CHECK-LABEL: @select_m8
#[no_mangle]

View file

@ -4,15 +4,14 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::{simd_reduce_all, simd_reduce_any};
#[repr(simd)]
#[derive(Copy, Clone)]
pub struct mask32x2([i32; 2]);
#[repr(simd)]
#[derive(Copy, Clone)]
pub struct mask8x16([i8; 16]);
pub type mask32x2 = Simd<i32, 2>;
pub type mask8x16 = Simd<i8, 16>;
// NOTE(eddyb) `%{{x|1}}` is used because on some targets (e.g. WASM)
// SIMD vectors are passed directly, resulting in `%x` being a vector,

View file

@ -8,13 +8,12 @@
#![allow(non_camel_case_types)]
#![feature(repr_simd, core_intrinsics)]
#[repr(simd)]
#[derive(Copy, Clone)]
pub struct S<const N: usize>([f32; N]);
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
#[repr(simd)]
#[derive(Copy, Clone)]
pub struct T([f32; 4]);
pub type S<const N: usize> = Simd<f32, N>;
pub type T = Simd<f32, 4>;
// CHECK-LABEL: @array_align(
#[no_mangle]
@ -34,7 +33,7 @@ pub fn vector_align() -> usize {
#[no_mangle]
pub fn build_array_s(x: [f32; 4]) -> S<4> {
// CHECK: call void @llvm.memcpy.{{.+}}({{.*}} align [[VECTOR_ALIGN]] {{.*}} align [[ARRAY_ALIGN]] {{.*}}, [[USIZE]] 16, i1 false)
S::<4>(x)
Simd(x)
}
// CHECK-LABEL: @build_array_transmute_s
@ -48,7 +47,7 @@ pub fn build_array_transmute_s(x: [f32; 4]) -> S<4> {
#[no_mangle]
pub fn build_array_t(x: [f32; 4]) -> T {
// CHECK: call void @llvm.memcpy.{{.+}}({{.*}} align [[VECTOR_ALIGN]] {{.*}} align [[ARRAY_ALIGN]] {{.*}}, [[USIZE]] 16, i1 false)
T(x)
Simd(x)
}
// CHECK-LABEL: @build_array_transmute_t

View file

@ -5,15 +5,11 @@
#![no_std]
#![crate_type = "lib"]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use core::intrinsics::simd::{simd_add, simd_extract};
#[repr(simd)]
#[derive(Clone, Copy)]
pub struct Simd<T, const N: usize>([T; N]);
#[repr(simd, packed)]
#[derive(Clone, Copy)]
pub struct PackedSimd<T, const N: usize>([T; N]);
use minisimd::*;
#[repr(transparent)]
pub struct Transparent<T>(T);

View file

@ -9,18 +9,14 @@
use core::intrinsics::simd as intrinsics;
use core::{mem, ptr};
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::{PackedSimd, Simd as FullSimd};
// Test codegen for not only "packed" but also "fully aligned" SIMD types, and conversion between
// them. A repr(packed,simd) type with 3 elements can't exceed its element alignment, whereas the
// same type as repr(simd) will instead have padding.
#[repr(simd, packed)]
#[derive(Copy, Clone)]
pub struct PackedSimd<T, const N: usize>([T; N]);
#[repr(simd)]
#[derive(Copy, Clone)]
pub struct FullSimd<T, const N: usize>([T; N]);
// non-powers-of-two have padding and need to be expanded to full vectors
fn load<T, const N: usize>(v: PackedSimd<T, N>) -> FullSimd<T, N> {
unsafe {

View file

@ -5,16 +5,14 @@
#![crate_type = "lib"]
#![feature(repr_simd, core_intrinsics)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use std::intrinsics::simd::simd_arith_offset;
/// A vector of *const T.
#[derive(Debug, Copy, Clone)]
#[repr(simd)]
pub struct SimdConstPtr<T, const LANES: usize>([*const T; LANES]);
use minisimd::*;
#[derive(Debug, Copy, Clone)]
#[repr(simd)]
pub struct Simd<T, const LANES: usize>([T; LANES]);
/// A vector of *const T.
pub type SimdConstPtr<T, const LANES: usize> = Simd<*const T, LANES>;
// CHECK-LABEL: smoke
#[no_mangle]

View file

@ -2,24 +2,18 @@
#![allow(non_camel_case_types)]
#![feature(repr_simd, core_intrinsics)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_add;
use std::ops;
#[repr(simd)]
#[derive(Copy, Clone)]
struct f32x4([f32; 4]);
type A<const N: usize> = Simd<f32, N>;
#[repr(simd)]
#[derive(Copy, Clone)]
struct A<const N: usize>([f32; N]);
type B<T> = Simd<T, 4>;
#[repr(simd)]
#[derive(Copy, Clone)]
struct B<T>([T; 4]);
#[repr(simd)]
#[derive(Copy, Clone)]
struct C<T, const N: usize>([T; N]);
type C<T, const N: usize> = Simd<T, N>;
fn add<T: ops::Add<Output = T>>(lhs: T, rhs: T) -> T {
lhs + rhs
@ -33,48 +27,24 @@ impl ops::Add for f32x4 {
}
}
impl ops::Add for A<4> {
type Output = Self;
fn add(self, rhs: Self) -> Self {
unsafe { simd_add(self, rhs) }
}
}
impl ops::Add for B<f32> {
type Output = Self;
fn add(self, rhs: Self) -> Self {
unsafe { simd_add(self, rhs) }
}
}
impl ops::Add for C<f32, 4> {
type Output = Self;
fn add(self, rhs: Self) -> Self {
unsafe { simd_add(self, rhs) }
}
}
pub fn main() {
let x = [1.0f32, 2.0f32, 3.0f32, 4.0f32];
let y = [2.0f32, 4.0f32, 6.0f32, 8.0f32];
// lame-o
let a = f32x4([1.0f32, 2.0f32, 3.0f32, 4.0f32]);
let f32x4([a0, a1, a2, a3]) = add(a, a);
let a = f32x4::from_array([1.0f32, 2.0f32, 3.0f32, 4.0f32]);
let [a0, a1, a2, a3] = add(a, a).into_array();
assert_eq!(a0, 2.0f32);
assert_eq!(a1, 4.0f32);
assert_eq!(a2, 6.0f32);
assert_eq!(a3, 8.0f32);
let a = A(x);
assert_eq!(add(a, a).0, y);
let a = A::from_array(x);
assert_eq!(add(a, a).into_array(), y);
let b = B(x);
assert_eq!(add(b, b).0, y);
let b = B::from_array(x);
assert_eq!(add(b, b).into_array(), y);
let c = C(x);
assert_eq!(add(c, c).0, y);
let c = C::from_array(x);
assert_eq!(add(c, c).into_array(), y);
}

View file

@ -11,9 +11,9 @@
#![feature(repr_simd, intrinsics, core_intrinsics)]
#![allow(non_camel_case_types)]
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct f32x4(pub [f32; 4]);
#[path = "../../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::*;
@ -27,19 +27,19 @@ macro_rules! assert_approx_eq {
($a:expr, $b:expr) => {{
let a = $a;
let b = $b;
assert_approx_eq_f32!(a.0[0], b.0[0]);
assert_approx_eq_f32!(a.0[1], b.0[1]);
assert_approx_eq_f32!(a.0[2], b.0[2]);
assert_approx_eq_f32!(a.0[3], b.0[3]);
assert_approx_eq_f32!(a[0], b[0]);
assert_approx_eq_f32!(a[1], b[1]);
assert_approx_eq_f32!(a[2], b[2]);
assert_approx_eq_f32!(a[3], b[3]);
}};
}
fn main() {
let x = f32x4([1.0, 1.0, 1.0, 1.0]);
let y = f32x4([-1.0, -1.0, -1.0, -1.0]);
let z = f32x4([0.0, 0.0, 0.0, 0.0]);
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]);
let h = f32x4([0.5, 0.5, 0.5, 0.5]);
let h = f32x4::from_array([0.5, 0.5, 0.5, 0.5]);
unsafe {
let r = simd_fabs(y);

View file

@ -6,15 +6,15 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct f32x4(pub [f32; 4]);
#[path = "../../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::*;
fn main() {
let x = f32x4([1.0, 2.0, 3.0, 4.0]);
let y = f32x4([2.0, 1.0, 4.0, 3.0]);
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]);
#[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
let nan = f32::NAN;
@ -23,13 +23,13 @@ fn main() {
#[cfg(any(target_arch = "mips", target_arch = "mips64"))]
let nan = f32::from_bits(f32::NAN.to_bits() - 1);
let n = f32x4([nan, nan, nan, nan]);
let n = f32x4::from_array([nan, nan, nan, nan]);
unsafe {
let min0 = simd_fmin(x, y);
let min1 = simd_fmin(y, x);
assert_eq!(min0, min1);
let e = f32x4([1.0, 1.0, 3.0, 3.0]);
let e = f32x4::from_array([1.0, 1.0, 3.0, 3.0]);
assert_eq!(min0, e);
let minn = simd_fmin(x, n);
assert_eq!(minn, x);
@ -39,7 +39,7 @@ fn main() {
let max0 = simd_fmax(x, y);
let max1 = simd_fmax(y, x);
assert_eq!(max0, max1);
let e = f32x4([2.0, 2.0, 4.0, 4.0]);
let e = f32x4::from_array([2.0, 2.0, 4.0, 4.0]);
assert_eq!(max0, e);
let maxn = simd_fmax(x, n);
assert_eq!(maxn, x);

View file

@ -2,80 +2,77 @@
#![allow(non_camel_case_types)]
#![feature(repr_simd, core_intrinsics)]
#[repr(simd)]
#[derive(Copy, Clone)]
struct i32x4(pub [i32; 4]);
#[path = "../../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
#[repr(simd)]
#[derive(Copy, Clone)]
struct U32<const N: usize>([u32; N]);
#[repr(simd)]
#[derive(Copy, Clone)]
struct f32x4(pub [f32; 4]);
type U32<const N: usize> = Simd<u32, N>;
macro_rules! all_eq {
($a: expr, $b: expr) => {{
($a: expr, $b: expr $(,)?) => {{
let a = $a;
let b = $b;
assert!(a.0 == b.0);
assert!(a == b);
}};
}
use std::intrinsics::simd::*;
fn main() {
let x1 = i32x4([1, 2, 3, 4]);
let y1 = U32::<4>([1, 2, 3, 4]);
let z1 = f32x4([1.0, 2.0, 3.0, 4.0]);
let x2 = i32x4([2, 3, 4, 5]);
let y2 = U32::<4>([2, 3, 4, 5]);
let z2 = f32x4([2.0, 3.0, 4.0, 5.0]);
let x3 = i32x4([0, i32::MAX, i32::MIN, -1_i32]);
let y3 = U32::<4>([0, i32::MAX as _, i32::MIN as _, -1_i32 as _]);
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]);
let x2 = i32x4::from_array([2, 3, 4, 5]);
let y2 = U32::<4>::from_array([2, 3, 4, 5]);
let z2 = f32x4::from_array([2.0, 3.0, 4.0, 5.0]);
let x3 = i32x4::from_array([0, i32::MAX, i32::MIN, -1_i32]);
let y3 = U32::<4>::from_array([0, i32::MAX as _, i32::MIN as _, -1_i32 as _]);
unsafe {
all_eq!(simd_add(x1, x2), i32x4([3, 5, 7, 9]));
all_eq!(simd_add(x2, x1), i32x4([3, 5, 7, 9]));
all_eq!(simd_add(y1, y2), U32::<4>([3, 5, 7, 9]));
all_eq!(simd_add(y2, y1), U32::<4>([3, 5, 7, 9]));
all_eq!(simd_add(z1, z2), f32x4([3.0, 5.0, 7.0, 9.0]));
all_eq!(simd_add(z2, z1), f32x4([3.0, 5.0, 7.0, 9.0]));
all_eq!(simd_add(x1, x2), i32x4::from_array([3, 5, 7, 9]));
all_eq!(simd_add(x2, x1), i32x4::from_array([3, 5, 7, 9]));
all_eq!(simd_add(y1, y2), U32::<4>::from_array([3, 5, 7, 9]));
all_eq!(simd_add(y2, y1), U32::<4>::from_array([3, 5, 7, 9]));
all_eq!(simd_add(z1, z2), f32x4::from_array([3.0, 5.0, 7.0, 9.0]));
all_eq!(simd_add(z2, z1), f32x4::from_array([3.0, 5.0, 7.0, 9.0]));
all_eq!(simd_mul(x1, x2), i32x4([2, 6, 12, 20]));
all_eq!(simd_mul(x2, x1), i32x4([2, 6, 12, 20]));
all_eq!(simd_mul(y1, y2), U32::<4>([2, 6, 12, 20]));
all_eq!(simd_mul(y2, y1), U32::<4>([2, 6, 12, 20]));
all_eq!(simd_mul(z1, z2), f32x4([2.0, 6.0, 12.0, 20.0]));
all_eq!(simd_mul(z2, z1), f32x4([2.0, 6.0, 12.0, 20.0]));
all_eq!(simd_mul(x1, x2), i32x4::from_array([2, 6, 12, 20]));
all_eq!(simd_mul(x2, x1), i32x4::from_array([2, 6, 12, 20]));
all_eq!(simd_mul(y1, y2), U32::<4>::from_array([2, 6, 12, 20]));
all_eq!(simd_mul(y2, y1), U32::<4>::from_array([2, 6, 12, 20]));
all_eq!(simd_mul(z1, z2), f32x4::from_array([2.0, 6.0, 12.0, 20.0]));
all_eq!(simd_mul(z2, z1), f32x4::from_array([2.0, 6.0, 12.0, 20.0]));
all_eq!(simd_sub(x2, x1), i32x4([1, 1, 1, 1]));
all_eq!(simd_sub(x1, x2), i32x4([-1, -1, -1, -1]));
all_eq!(simd_sub(y2, y1), U32::<4>([1, 1, 1, 1]));
all_eq!(simd_sub(y1, y2), U32::<4>([!0, !0, !0, !0]));
all_eq!(simd_sub(z2, z1), f32x4([1.0, 1.0, 1.0, 1.0]));
all_eq!(simd_sub(z1, z2), f32x4([-1.0, -1.0, -1.0, -1.0]));
all_eq!(simd_sub(x2, x1), i32x4::from_array([1, 1, 1, 1]));
all_eq!(simd_sub(x1, x2), i32x4::from_array([-1, -1, -1, -1]));
all_eq!(simd_sub(y2, y1), U32::<4>::from_array([1, 1, 1, 1]));
all_eq!(simd_sub(y1, y2), U32::<4>::from_array([!0, !0, !0, !0]));
all_eq!(simd_sub(z2, z1), f32x4::from_array([1.0, 1.0, 1.0, 1.0]));
all_eq!(simd_sub(z1, z2), f32x4::from_array([-1.0, -1.0, -1.0, -1.0]));
all_eq!(simd_div(x1, x1), i32x4([1, 1, 1, 1]));
all_eq!(simd_div(i32x4([2, 4, 6, 8]), i32x4([2, 2, 2, 2])), x1);
all_eq!(simd_div(y1, y1), U32::<4>([1, 1, 1, 1]));
all_eq!(simd_div(U32::<4>([2, 4, 6, 8]), U32::<4>([2, 2, 2, 2])), y1);
all_eq!(simd_div(z1, z1), f32x4([1.0, 1.0, 1.0, 1.0]));
all_eq!(simd_div(z1, z2), f32x4([1.0 / 2.0, 2.0 / 3.0, 3.0 / 4.0, 4.0 / 5.0]));
all_eq!(simd_div(z2, z1), f32x4([2.0 / 1.0, 3.0 / 2.0, 4.0 / 3.0, 5.0 / 4.0]));
all_eq!(simd_div(x1, x1), i32x4::from_array([1, 1, 1, 1]));
all_eq!(simd_div(i32x4::from_array([2, 4, 6, 8]), i32x4::from_array([2, 2, 2, 2])), x1);
all_eq!(simd_div(y1, y1), U32::<4>::from_array([1, 1, 1, 1]));
all_eq!(
simd_div(U32::<4>::from_array([2, 4, 6, 8]), U32::<4>::from_array([2, 2, 2, 2])),
y1,
);
all_eq!(simd_div(z1, z1), f32x4::from_array([1.0, 1.0, 1.0, 1.0]));
all_eq!(simd_div(z1, z2), f32x4::from_array([1.0 / 2.0, 2.0 / 3.0, 3.0 / 4.0, 4.0 / 5.0]));
all_eq!(simd_div(z2, z1), f32x4::from_array([2.0 / 1.0, 3.0 / 2.0, 4.0 / 3.0, 5.0 / 4.0]));
all_eq!(simd_rem(x1, x1), i32x4([0, 0, 0, 0]));
all_eq!(simd_rem(x2, x1), i32x4([0, 1, 1, 1]));
all_eq!(simd_rem(y1, y1), U32::<4>([0, 0, 0, 0]));
all_eq!(simd_rem(y2, y1), U32::<4>([0, 1, 1, 1]));
all_eq!(simd_rem(z1, z1), f32x4([0.0, 0.0, 0.0, 0.0]));
all_eq!(simd_rem(x1, x1), i32x4::from_array([0, 0, 0, 0]));
all_eq!(simd_rem(x2, x1), i32x4::from_array([0, 1, 1, 1]));
all_eq!(simd_rem(y1, y1), U32::<4>::from_array([0, 0, 0, 0]));
all_eq!(simd_rem(y2, y1), U32::<4>::from_array([0, 1, 1, 1]));
all_eq!(simd_rem(z1, z1), f32x4::from_array([0.0, 0.0, 0.0, 0.0]));
all_eq!(simd_rem(z1, z2), z1);
all_eq!(simd_rem(z2, z1), f32x4([0.0, 1.0, 1.0, 1.0]));
all_eq!(simd_rem(z2, z1), f32x4::from_array([0.0, 1.0, 1.0, 1.0]));
all_eq!(simd_shl(x1, x2), i32x4([1 << 2, 2 << 3, 3 << 4, 4 << 5]));
all_eq!(simd_shl(x2, x1), i32x4([2 << 1, 3 << 2, 4 << 3, 5 << 4]));
all_eq!(simd_shl(y1, y2), U32::<4>([1 << 2, 2 << 3, 3 << 4, 4 << 5]));
all_eq!(simd_shl(y2, y1), U32::<4>([2 << 1, 3 << 2, 4 << 3, 5 << 4]));
all_eq!(simd_shl(x1, x2), i32x4::from_array([1 << 2, 2 << 3, 3 << 4, 4 << 5]));
all_eq!(simd_shl(x2, x1), i32x4::from_array([2 << 1, 3 << 2, 4 << 3, 5 << 4]));
all_eq!(simd_shl(y1, y2), U32::<4>::from_array([1 << 2, 2 << 3, 3 << 4, 4 << 5]));
all_eq!(simd_shl(y2, y1), U32::<4>::from_array([2 << 1, 3 << 2, 4 << 3, 5 << 4]));
// test right-shift by assuming left-shift is correct
all_eq!(simd_shr(simd_shl(x1, x2), x2), x1);
@ -85,7 +82,7 @@ fn main() {
all_eq!(
simd_funnel_shl(x1, x2, x1),
i32x4([
i32x4::from_array([
(1 << 1) | (2 >> 31),
(2 << 2) | (3 >> 30),
(3 << 3) | (4 >> 29),
@ -94,7 +91,7 @@ fn main() {
);
all_eq!(
simd_funnel_shl(x2, x1, x1),
i32x4([
i32x4::from_array([
(2 << 1) | (1 >> 31),
(3 << 2) | (2 >> 30),
(4 << 3) | (3 >> 29),
@ -103,7 +100,7 @@ fn main() {
);
all_eq!(
simd_funnel_shl(y1, y2, y1),
U32::<4>([
U32::<4>::from_array([
(1 << 1) | (2 >> 31),
(2 << 2) | (3 >> 30),
(3 << 3) | (4 >> 29),
@ -112,7 +109,7 @@ fn main() {
);
all_eq!(
simd_funnel_shl(y2, y1, y1),
U32::<4>([
U32::<4>::from_array([
(2 << 1) | (1 >> 31),
(3 << 2) | (2 >> 30),
(4 << 3) | (3 >> 29),
@ -122,7 +119,7 @@ fn main() {
all_eq!(
simd_funnel_shr(x1, x2, x1),
i32x4([
i32x4::from_array([
(1 << 31) | (2 >> 1),
(2 << 30) | (3 >> 2),
(3 << 29) | (4 >> 3),
@ -131,7 +128,7 @@ fn main() {
);
all_eq!(
simd_funnel_shr(x2, x1, x1),
i32x4([
i32x4::from_array([
(2 << 31) | (1 >> 1),
(3 << 30) | (2 >> 2),
(4 << 29) | (3 >> 3),
@ -140,7 +137,7 @@ fn main() {
);
all_eq!(
simd_funnel_shr(y1, y2, y1),
U32::<4>([
U32::<4>::from_array([
(1 << 31) | (2 >> 1),
(2 << 30) | (3 >> 2),
(3 << 29) | (4 >> 3),
@ -149,7 +146,7 @@ fn main() {
);
all_eq!(
simd_funnel_shr(y2, y1, y1),
U32::<4>([
U32::<4>::from_array([
(2 << 31) | (1 >> 1),
(3 << 30) | (2 >> 2),
(4 << 29) | (3 >> 3),
@ -159,52 +156,69 @@ fn main() {
// ensure we get logical vs. arithmetic shifts correct
let (a, b, c, d) = (-12, -123, -1234, -12345);
all_eq!(simd_shr(i32x4([a, b, c, d]), x1), i32x4([a >> 1, b >> 2, c >> 3, d >> 4]));
all_eq!(
simd_shr(U32::<4>([a as u32, b as u32, c as u32, d as u32]), y1),
U32::<4>([(a as u32) >> 1, (b as u32) >> 2, (c as u32) >> 3, (d as u32) >> 4])
simd_shr(i32x4::from_array([a, b, c, d]), x1),
i32x4::from_array([a >> 1, b >> 2, c >> 3, d >> 4]),
);
all_eq!(
simd_shr(U32::<4>::from_array([a as u32, b as u32, c as u32, d as u32]), y1),
U32::<4>::from_array([
(a as u32) >> 1,
(b as u32) >> 2,
(c as u32) >> 3,
(d as u32) >> 4,
]),
);
all_eq!(simd_and(x1, x2), i32x4([0, 2, 0, 4]));
all_eq!(simd_and(x2, x1), i32x4([0, 2, 0, 4]));
all_eq!(simd_and(y1, y2), U32::<4>([0, 2, 0, 4]));
all_eq!(simd_and(y2, y1), U32::<4>([0, 2, 0, 4]));
all_eq!(simd_and(x1, x2), i32x4::from_array([0, 2, 0, 4]));
all_eq!(simd_and(x2, x1), i32x4::from_array([0, 2, 0, 4]));
all_eq!(simd_and(y1, y2), U32::<4>::from_array([0, 2, 0, 4]));
all_eq!(simd_and(y2, y1), U32::<4>::from_array([0, 2, 0, 4]));
all_eq!(simd_or(x1, x2), i32x4([3, 3, 7, 5]));
all_eq!(simd_or(x2, x1), i32x4([3, 3, 7, 5]));
all_eq!(simd_or(y1, y2), U32::<4>([3, 3, 7, 5]));
all_eq!(simd_or(y2, y1), U32::<4>([3, 3, 7, 5]));
all_eq!(simd_or(x1, x2), i32x4::from_array([3, 3, 7, 5]));
all_eq!(simd_or(x2, x1), i32x4::from_array([3, 3, 7, 5]));
all_eq!(simd_or(y1, y2), U32::<4>::from_array([3, 3, 7, 5]));
all_eq!(simd_or(y2, y1), U32::<4>::from_array([3, 3, 7, 5]));
all_eq!(simd_xor(x1, x2), i32x4([3, 1, 7, 1]));
all_eq!(simd_xor(x2, x1), i32x4([3, 1, 7, 1]));
all_eq!(simd_xor(y1, y2), U32::<4>([3, 1, 7, 1]));
all_eq!(simd_xor(y2, y1), U32::<4>([3, 1, 7, 1]));
all_eq!(simd_xor(x1, x2), i32x4::from_array([3, 1, 7, 1]));
all_eq!(simd_xor(x2, x1), i32x4::from_array([3, 1, 7, 1]));
all_eq!(simd_xor(y1, y2), U32::<4>::from_array([3, 1, 7, 1]));
all_eq!(simd_xor(y2, y1), U32::<4>::from_array([3, 1, 7, 1]));
all_eq!(simd_neg(x1), i32x4([-1, -2, -3, -4]));
all_eq!(simd_neg(x2), i32x4([-2, -3, -4, -5]));
all_eq!(simd_neg(z1), f32x4([-1.0, -2.0, -3.0, -4.0]));
all_eq!(simd_neg(z2), f32x4([-2.0, -3.0, -4.0, -5.0]));
all_eq!(simd_neg(x1), i32x4::from_array([-1, -2, -3, -4]));
all_eq!(simd_neg(x2), i32x4::from_array([-2, -3, -4, -5]));
all_eq!(simd_neg(z1), f32x4::from_array([-1.0, -2.0, -3.0, -4.0]));
all_eq!(simd_neg(z2), f32x4::from_array([-2.0, -3.0, -4.0, -5.0]));
all_eq!(simd_bswap(x1), i32x4([0x01000000, 0x02000000, 0x03000000, 0x04000000]));
all_eq!(simd_bswap(y1), U32::<4>([0x01000000, 0x02000000, 0x03000000, 0x04000000]));
all_eq!(
simd_bswap(x1),
i32x4::from_array([0x01000000, 0x02000000, 0x03000000, 0x04000000]),
);
all_eq!(
simd_bswap(y1),
U32::<4>::from_array([0x01000000, 0x02000000, 0x03000000, 0x04000000]),
);
all_eq!(
simd_bitreverse(x1),
i32x4([0x80000000u32 as i32, 0x40000000, 0xc0000000u32 as i32, 0x20000000])
i32x4::from_array([0x80000000u32 as i32, 0x40000000, 0xc0000000u32 as i32, 0x20000000])
);
all_eq!(
simd_bitreverse(y1),
U32::<4>::from_array([0x80000000, 0x40000000, 0xc0000000, 0x20000000]),
);
all_eq!(simd_bitreverse(y1), U32::<4>([0x80000000, 0x40000000, 0xc0000000, 0x20000000]));
all_eq!(simd_ctlz(x1), i32x4([31, 30, 30, 29]));
all_eq!(simd_ctlz(y1), U32::<4>([31, 30, 30, 29]));
all_eq!(simd_ctlz(x1), i32x4::from_array([31, 30, 30, 29]));
all_eq!(simd_ctlz(y1), U32::<4>::from_array([31, 30, 30, 29]));
all_eq!(simd_ctpop(x1), i32x4([1, 1, 2, 1]));
all_eq!(simd_ctpop(y1), U32::<4>([1, 1, 2, 1]));
all_eq!(simd_ctpop(x2), i32x4([1, 2, 1, 2]));
all_eq!(simd_ctpop(y2), U32::<4>([1, 2, 1, 2]));
all_eq!(simd_ctpop(x3), i32x4([0, 31, 1, 32]));
all_eq!(simd_ctpop(y3), U32::<4>([0, 31, 1, 32]));
all_eq!(simd_ctpop(x1), i32x4::from_array([1, 1, 2, 1]));
all_eq!(simd_ctpop(y1), U32::<4>::from_array([1, 1, 2, 1]));
all_eq!(simd_ctpop(x2), i32x4::from_array([1, 2, 1, 2]));
all_eq!(simd_ctpop(y2), U32::<4>::from_array([1, 2, 1, 2]));
all_eq!(simd_ctpop(x3), i32x4::from_array([0, 31, 1, 32]));
all_eq!(simd_ctpop(y3), U32::<4>::from_array([0, 31, 1, 32]));
all_eq!(simd_cttz(x1), i32x4([0, 1, 0, 2]));
all_eq!(simd_cttz(y1), U32::<4>([0, 1, 0, 2]));
all_eq!(simd_cttz(x1), i32x4::from_array([0, 1, 0, 2]));
all_eq!(simd_cttz(y1), U32::<4>::from_array([0, 1, 0, 2]));
}
}

View file

@ -4,26 +4,24 @@
#![allow(non_camel_case_types)]
#![feature(repr_simd, core_intrinsics)]
#[path = "../../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::{simd_saturating_add, simd_saturating_sub};
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct u32x4(pub [u32; 4]);
#[repr(simd)]
#[derive(Copy, Clone)]
struct I32<const N: usize>([i32; N]);
type I32<const N: usize> = Simd<i32, N>;
fn main() {
// unsigned
{
const M: u32 = u32::MAX;
let a = u32x4([1, 2, 3, 4]);
let b = u32x4([2, 4, 6, 8]);
let m = u32x4([M, M, M, M]);
let m1 = u32x4([M - 1, M - 1, M - 1, M - 1]);
let z = u32x4([0, 0, 0, 0]);
let a = u32x4::from_array([1, 2, 3, 4]);
let b = u32x4::from_array([2, 4, 6, 8]);
let m = u32x4::from_array([M, M, M, M]);
let m1 = u32x4::from_array([M - 1, M - 1, M - 1, M - 1]);
let z = u32x4::from_array([0, 0, 0, 0]);
unsafe {
assert_eq!(simd_saturating_add(z, z), z);
@ -48,41 +46,41 @@ fn main() {
const MIN: i32 = i32::MIN;
const MAX: i32 = i32::MAX;
let a = I32::<4>([1, 2, 3, 4]);
let b = I32::<4>([2, 4, 6, 8]);
let c = I32::<4>([-1, -2, -3, -4]);
let d = I32::<4>([-2, -4, -6, -8]);
let a = I32::<4>::from_array([1, 2, 3, 4]);
let b = I32::<4>::from_array([2, 4, 6, 8]);
let c = I32::<4>::from_array([-1, -2, -3, -4]);
let d = I32::<4>::from_array([-2, -4, -6, -8]);
let max = I32::<4>([MAX, MAX, MAX, MAX]);
let max1 = I32::<4>([MAX - 1, MAX - 1, MAX - 1, MAX - 1]);
let min = I32::<4>([MIN, MIN, MIN, MIN]);
let min1 = I32::<4>([MIN + 1, MIN + 1, MIN + 1, MIN + 1]);
let max = I32::<4>::from_array([MAX, MAX, MAX, MAX]);
let max1 = I32::<4>::from_array([MAX - 1, MAX - 1, MAX - 1, MAX - 1]);
let min = I32::<4>::from_array([MIN, MIN, MIN, MIN]);
let min1 = I32::<4>::from_array([MIN + 1, MIN + 1, MIN + 1, MIN + 1]);
let z = I32::<4>([0, 0, 0, 0]);
let z = I32::<4>::from_array([0, 0, 0, 0]);
unsafe {
assert_eq!(simd_saturating_add(z, z).0, z.0);
assert_eq!(simd_saturating_add(z, a).0, a.0);
assert_eq!(simd_saturating_add(b, z).0, b.0);
assert_eq!(simd_saturating_add(a, a).0, b.0);
assert_eq!(simd_saturating_add(a, max).0, max.0);
assert_eq!(simd_saturating_add(max, b).0, max.0);
assert_eq!(simd_saturating_add(max1, a).0, max.0);
assert_eq!(simd_saturating_add(min1, z).0, min1.0);
assert_eq!(simd_saturating_add(min, z).0, min.0);
assert_eq!(simd_saturating_add(min1, c).0, min.0);
assert_eq!(simd_saturating_add(min, c).0, min.0);
assert_eq!(simd_saturating_add(min1, d).0, min.0);
assert_eq!(simd_saturating_add(min, d).0, min.0);
assert_eq!(simd_saturating_add(z, z), z);
assert_eq!(simd_saturating_add(z, a), a);
assert_eq!(simd_saturating_add(b, z), b);
assert_eq!(simd_saturating_add(a, a), b);
assert_eq!(simd_saturating_add(a, max), max);
assert_eq!(simd_saturating_add(max, b), max);
assert_eq!(simd_saturating_add(max1, a), max);
assert_eq!(simd_saturating_add(min1, z), min1);
assert_eq!(simd_saturating_add(min, z), min);
assert_eq!(simd_saturating_add(min1, c), min);
assert_eq!(simd_saturating_add(min, c), min);
assert_eq!(simd_saturating_add(min1, d), min);
assert_eq!(simd_saturating_add(min, d), min);
assert_eq!(simd_saturating_sub(b, z).0, b.0);
assert_eq!(simd_saturating_sub(b, a).0, a.0);
assert_eq!(simd_saturating_sub(a, a).0, z.0);
assert_eq!(simd_saturating_sub(a, b).0, c.0);
assert_eq!(simd_saturating_sub(z, max).0, min1.0);
assert_eq!(simd_saturating_sub(min1, z).0, min1.0);
assert_eq!(simd_saturating_sub(min1, a).0, min.0);
assert_eq!(simd_saturating_sub(min1, b).0, min.0);
assert_eq!(simd_saturating_sub(b, z), b);
assert_eq!(simd_saturating_sub(b, a), a);
assert_eq!(simd_saturating_sub(a, a), z);
assert_eq!(simd_saturating_sub(a, b), c);
assert_eq!(simd_saturating_sub(z, max), min1);
assert_eq!(simd_saturating_sub(min1, z), min1);
assert_eq!(simd_saturating_sub(min1, a), min);
assert_eq!(simd_saturating_sub(min1, b), min);
}
}
}

View file

@ -2,45 +2,47 @@
#![feature(repr_simd, core_intrinsics)]
#[path = "../../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_as;
#[derive(Copy, Clone)]
#[repr(simd)]
struct V<T>([T; 2]);
type V<T> = Simd<T, 2>;
fn main() {
unsafe {
let u = V::<u32>([u32::MIN, u32::MAX]);
let u: V::<u32> = Simd([u32::MIN, u32::MAX]);
let i: V<i16> = simd_as(u);
assert_eq!(i.0[0], u.0[0] as i16);
assert_eq!(i.0[1], u.0[1] as i16);
assert_eq!(i[0], u[0] as i16);
assert_eq!(i[1], u[1] as i16);
}
unsafe {
let f = V::<f32>([f32::MIN, f32::MAX]);
let f: V::<f32> = Simd([f32::MIN, f32::MAX]);
let i: V<i16> = simd_as(f);
assert_eq!(i.0[0], f.0[0] as i16);
assert_eq!(i.0[1], f.0[1] as i16);
assert_eq!(i[0], f[0] as i16);
assert_eq!(i[1], f[1] as i16);
}
unsafe {
let f = V::<f32>([f32::MIN, f32::MAX]);
let f: V::<f32> = Simd([f32::MIN, f32::MAX]);
let u: V<u8> = simd_as(f);
assert_eq!(u.0[0], f.0[0] as u8);
assert_eq!(u.0[1], f.0[1] as u8);
assert_eq!(u[0], f[0] as u8);
assert_eq!(u[1], f[1] as u8);
}
unsafe {
let f = V::<f64>([f64::MIN, f64::MAX]);
let f: V::<f64> = Simd([f64::MIN, f64::MAX]);
let i: V<isize> = simd_as(f);
assert_eq!(i.0[0], f.0[0] as isize);
assert_eq!(i.0[1], f.0[1] as isize);
assert_eq!(i[0], f[0] as isize);
assert_eq!(i[1], f[1] as isize);
}
unsafe {
let f = V::<f64>([f64::MIN, f64::MAX]);
let f: V::<f64> = Simd([f64::MIN, f64::MAX]);
let u: V<usize> = simd_as(f);
assert_eq!(u.0[0], f.0[0] as usize);
assert_eq!(u.0[1], f.0[1] as usize);
assert_eq!(u[0], f[0] as usize);
assert_eq!(u[1], f[1] as usize);
}
}

View file

@ -2,19 +2,15 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_bswap;
#[repr(simd)]
#[derive(Copy, Clone)]
struct i8x4([i8; 4]);
#[repr(simd)]
#[derive(Copy, Clone)]
struct u8x4([u8; 4]);
fn main() {
unsafe {
assert_eq!(simd_bswap(i8x4([0, 1, 2, 3])).0, [0, 1, 2, 3]);
assert_eq!(simd_bswap(u8x4([0, 1, 2, 3])).0, [0, 1, 2, 3]);
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]);
}
}

View file

@ -2,55 +2,57 @@
#![feature(repr_simd, core_intrinsics)]
#[path = "../../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_cast;
use std::cmp::{max, min};
#[derive(Copy, Clone)]
#[repr(simd)]
struct V<T>([T; 2]);
type V<T> = Simd<T, 2>;
fn main() {
unsafe {
let u = V::<u32>([i16::MIN as u32, i16::MAX as u32]);
let u: V::<u32> = Simd([i16::MIN as u32, i16::MAX as u32]);
let i: V<i16> = simd_cast(u);
assert_eq!(i.0[0], u.0[0] as i16);
assert_eq!(i.0[1], u.0[1] as i16);
assert_eq!(i[0], u[0] as i16);
assert_eq!(i[1], u[1] as i16);
}
unsafe {
let f = V::<f32>([i16::MIN as f32, i16::MAX as f32]);
let f: V::<f32> = Simd([i16::MIN as f32, i16::MAX as f32]);
let i: V<i16> = simd_cast(f);
assert_eq!(i.0[0], f.0[0] as i16);
assert_eq!(i.0[1], f.0[1] as i16);
assert_eq!(i[0], f[0] as i16);
assert_eq!(i[1], f[1] as i16);
}
unsafe {
let f = V::<f32>([u8::MIN as f32, u8::MAX as f32]);
let f: V::<f32> = Simd([u8::MIN as f32, u8::MAX as f32]);
let u: V<u8> = simd_cast(f);
assert_eq!(u.0[0], f.0[0] as u8);
assert_eq!(u.0[1], f.0[1] as u8);
assert_eq!(u[0], f[0] as u8);
assert_eq!(u[1], f[1] as u8);
}
unsafe {
// We would like to do isize::MIN..=isize::MAX, but those values are not representable in
// an f64, so we clamp to the range of an i32 to prevent running into UB.
let f = V::<f64>([
let f: V::<f64> = Simd([
max(isize::MIN, i32::MIN as isize) as f64,
min(isize::MAX, i32::MAX as isize) as f64,
]);
let i: V<isize> = simd_cast(f);
assert_eq!(i.0[0], f.0[0] as isize);
assert_eq!(i.0[1], f.0[1] as isize);
assert_eq!(i[0], f[0] as isize);
assert_eq!(i[1], f[1] as isize);
}
unsafe {
let f = V::<f64>([
let f: V::<f64> = Simd([
max(usize::MIN, u32::MIN as usize) as f64,
min(usize::MAX, u32::MAX as usize) as f64,
]);
let u: V<usize> = simd_cast(f);
assert_eq!(u.0[0], f.0[0] as usize);
assert_eq!(u.0[1], f.0[1] as usize);
assert_eq!(u[0], f[0] as usize);
assert_eq!(u[1], f[1] as usize);
}
}

View file

@ -1,18 +1,24 @@
//@ run-pass
#![feature(repr_simd, core_intrinsics)]
#[path = "../../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_cast;
#[derive(Copy, Clone)]
#[repr(simd)]
struct V<T>([T; 4]);
type V<T> = Simd<T, 4>;
fn main() {
let u = V::<usize>([0, 1, 2, 3]);
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.0.iter().zip(uu32.0.iter().zip(ui64.0.iter())) {
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);
}

View file

@ -3,17 +3,11 @@
#![feature(repr_simd, core_intrinsics, macro_metavar_expr_concat)]
#![allow(non_camel_case_types)]
use std::intrinsics::simd::{simd_eq, simd_ge, simd_gt, simd_le, simd_lt, simd_ne};
#[path = "../../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
#[repr(simd)]
#[derive(Copy, Clone)]
struct i32x4([i32; 4]);
#[repr(simd)]
#[derive(Copy, Clone)]
struct u32x4(pub [u32; 4]);
#[repr(simd)]
#[derive(Copy, Clone)]
struct f32x4(pub [f32; 4]);
use std::intrinsics::simd::{simd_eq, simd_ge, simd_gt, simd_le, simd_lt, simd_ne};
macro_rules! cmp {
($method: ident($lhs: expr, $rhs: expr)) => {{
@ -21,10 +15,11 @@ macro_rules! cmp {
let rhs = $rhs;
let e: u32x4 = ${concat(simd_, $method)}($lhs, $rhs);
// assume the scalar version is correct/the behaviour we want.
assert!((e.0[0] != 0) == lhs.0[0].$method(&rhs.0[0]));
assert!((e.0[1] != 0) == lhs.0[1].$method(&rhs.0[1]));
assert!((e.0[2] != 0) == lhs.0[2].$method(&rhs.0[2]));
assert!((e.0[3] != 0) == lhs.0[3].$method(&rhs.0[3]));
let (lhs, rhs, e) = (lhs.as_array(), rhs.as_array(), e.as_array());
assert!((e[0] != 0) == lhs[0].$method(&rhs[0]));
assert!((e[1] != 0) == lhs[1].$method(&rhs[1]));
assert!((e[2] != 0) == lhs[2].$method(&rhs[2]));
assert!((e[3] != 0) == lhs[3].$method(&rhs[3]));
}};
}
macro_rules! tests {
@ -53,17 +48,17 @@ macro_rules! tests {
fn main() {
// 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([10, -11, 12, 13]);
let i2 = i32x4([5, -5, 20, -100]);
let i3 = i32x4([10, -11, 20, -100]);
let i1 = i32x4::from_array([10, -11, 12, 13]);
let i2 = i32x4::from_array([5, -5, 20, -100]);
let i3 = i32x4::from_array([10, -11, 20, -100]);
let u1 = u32x4([10, !11 + 1, 12, 13]);
let u2 = u32x4([5, !5 + 1, 20, !100 + 1]);
let u3 = u32x4([10, !11 + 1, 20, !100 + 1]);
let u1 = u32x4::from_array([10, !11 + 1, 12, 13]);
let u2 = u32x4::from_array([5, !5 + 1, 20, !100 + 1]);
let u3 = u32x4::from_array([10, !11 + 1, 20, !100 + 1]);
let f1 = f32x4([10.0, -11.0, 12.0, 13.0]);
let f2 = f32x4([5.0, -5.0, 20.0, -100.0]);
let f3 = f32x4([10.0, -11.0, 20.0, -100.0]);
let f1 = f32x4::from_array([10.0, -11.0, 12.0, 13.0]);
let f2 = f32x4::from_array([5.0, -5.0, 20.0, -100.0]);
let f3 = f32x4::from_array([10.0, -11.0, 20.0, -100.0]);
unsafe {
tests! {
@ -84,7 +79,7 @@ fn main() {
// NAN comparisons are special:
// -11 (*) 13
// -5 -100 (*)
let f4 = f32x4([f32::NAN, f1.0[1], f32::NAN, f2.0[3]]);
let f4 = f32x4::from_array([f32::NAN, f1[1], f32::NAN, f2[3]]);
unsafe {
tests! {

View file

@ -2,23 +2,14 @@
#![feature(repr_simd, intrinsics, core_intrinsics)]
#[path = "../../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::{
simd_extract, simd_extract_dyn, simd_insert, simd_insert_dyn, simd_shuffle,
};
#[repr(simd)]
#[derive(Copy, Clone, Debug, PartialEq)]
#[allow(non_camel_case_types)]
struct i32x2([i32; 2]);
#[repr(simd)]
#[derive(Copy, Clone, Debug, PartialEq)]
#[allow(non_camel_case_types)]
struct i32x4([i32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, Debug, PartialEq)]
#[allow(non_camel_case_types)]
struct i32x8([i32; 8]);
#[repr(simd)]
struct SimdShuffleIdx<const LEN: usize>([u32; LEN]);
@ -34,26 +25,26 @@ macro_rules! all_eq {
}
fn main() {
let x2 = i32x2([20, 21]);
let x4 = i32x4([40, 41, 42, 43]);
let x8 = i32x8([80, 81, 82, 83, 84, 85, 86, 87]);
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(x2, 0, 100), i32x2([100, 21]));
all_eq!(simd_insert(x2, 1, 100), i32x2([20, 100]));
all_eq!(simd_insert(x2, 0, 100), i32x2::from_array([100, 21]));
all_eq!(simd_insert(x2, 1, 100), i32x2::from_array([20, 100]));
all_eq!(simd_insert(x4, 0, 100), i32x4([100, 41, 42, 43]));
all_eq!(simd_insert(x4, 1, 100), i32x4([40, 100, 42, 43]));
all_eq!(simd_insert(x4, 2, 100), i32x4([40, 41, 100, 43]));
all_eq!(simd_insert(x4, 3, 100), i32x4([40, 41, 42, 100]));
all_eq!(simd_insert(x4, 0, 100), i32x4::from_array([100, 41, 42, 43]));
all_eq!(simd_insert(x4, 1, 100), i32x4::from_array([40, 100, 42, 43]));
all_eq!(simd_insert(x4, 2, 100), i32x4::from_array([40, 41, 100, 43]));
all_eq!(simd_insert(x4, 3, 100), i32x4::from_array([40, 41, 42, 100]));
all_eq!(simd_insert(x8, 0, 100), i32x8([100, 81, 82, 83, 84, 85, 86, 87]));
all_eq!(simd_insert(x8, 1, 100), i32x8([80, 100, 82, 83, 84, 85, 86, 87]));
all_eq!(simd_insert(x8, 2, 100), i32x8([80, 81, 100, 83, 84, 85, 86, 87]));
all_eq!(simd_insert(x8, 3, 100), i32x8([80, 81, 82, 100, 84, 85, 86, 87]));
all_eq!(simd_insert(x8, 4, 100), i32x8([80, 81, 82, 83, 100, 85, 86, 87]));
all_eq!(simd_insert(x8, 5, 100), i32x8([80, 81, 82, 83, 84, 100, 86, 87]));
all_eq!(simd_insert(x8, 6, 100), i32x8([80, 81, 82, 83, 84, 85, 100, 87]));
all_eq!(simd_insert(x8, 7, 100), i32x8([80, 81, 82, 83, 84, 85, 86, 100]));
all_eq!(simd_insert(x8, 0, 100), i32x8::from_array([100, 81, 82, 83, 84, 85, 86, 87]));
all_eq!(simd_insert(x8, 1, 100), i32x8::from_array([80, 100, 82, 83, 84, 85, 86, 87]));
all_eq!(simd_insert(x8, 2, 100), i32x8::from_array([80, 81, 100, 83, 84, 85, 86, 87]));
all_eq!(simd_insert(x8, 3, 100), i32x8::from_array([80, 81, 82, 100, 84, 85, 86, 87]));
all_eq!(simd_insert(x8, 4, 100), i32x8::from_array([80, 81, 82, 83, 100, 85, 86, 87]));
all_eq!(simd_insert(x8, 5, 100), i32x8::from_array([80, 81, 82, 83, 84, 100, 86, 87]));
all_eq!(simd_insert(x8, 6, 100), i32x8::from_array([80, 81, 82, 83, 84, 85, 100, 87]));
all_eq!(simd_insert(x8, 7, 100), i32x8::from_array([80, 81, 82, 83, 84, 85, 86, 100]));
all_eq!(simd_extract(x2, 0), 20);
all_eq!(simd_extract(x2, 1), 21);
@ -73,22 +64,22 @@ fn main() {
all_eq!(simd_extract(x8, 7), 87);
}
unsafe {
all_eq!(simd_insert_dyn(x2, 0, 100), i32x2([100, 21]));
all_eq!(simd_insert_dyn(x2, 1, 100), i32x2([20, 100]));
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([100, 41, 42, 43]));
all_eq!(simd_insert_dyn(x4, 1, 100), i32x4([40, 100, 42, 43]));
all_eq!(simd_insert_dyn(x4, 2, 100), i32x4([40, 41, 100, 43]));
all_eq!(simd_insert_dyn(x4, 3, 100), i32x4([40, 41, 42, 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([100, 81, 82, 83, 84, 85, 86, 87]));
all_eq!(simd_insert_dyn(x8, 1, 100), i32x8([80, 100, 82, 83, 84, 85, 86, 87]));
all_eq!(simd_insert_dyn(x8, 2, 100), i32x8([80, 81, 100, 83, 84, 85, 86, 87]));
all_eq!(simd_insert_dyn(x8, 3, 100), i32x8([80, 81, 82, 100, 84, 85, 86, 87]));
all_eq!(simd_insert_dyn(x8, 4, 100), i32x8([80, 81, 82, 83, 100, 85, 86, 87]));
all_eq!(simd_insert_dyn(x8, 5, 100), i32x8([80, 81, 82, 83, 84, 100, 86, 87]));
all_eq!(simd_insert_dyn(x8, 6, 100), i32x8([80, 81, 82, 83, 84, 85, 100, 87]));
all_eq!(simd_insert_dyn(x8, 7, 100), i32x8([80, 81, 82, 83, 84, 85, 86, 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);
@ -108,38 +99,47 @@ fn main() {
all_eq!(simd_extract_dyn(x8, 7), 87);
}
let y2 = i32x2([120, 121]);
let y4 = i32x4([140, 141, 142, 143]);
let y8 = i32x8([180, 181, 182, 183, 184, 185, 186, 187]);
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, const { SimdShuffleIdx([3u32, 0]) }), i32x2([121, 20]));
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([121, 20, 21, 120])
i32x4::from_array([121, 20, 21, 120])
);
all_eq!(
simd_shuffle(x2, y2, const { SimdShuffleIdx([3u32, 0, 1, 2, 1, 2, 3, 0]) }),
i32x8([121, 20, 21, 120, 21, 120, 121, 20])
i32x8::from_array([121, 20, 21, 120, 21, 120, 121, 20])
);
all_eq!(simd_shuffle(x4, y4, const { SimdShuffleIdx([7u32, 2]) }), i32x2([143, 42]));
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([143, 42, 141, 40])
i32x4::from_array([143, 42, 141, 40])
);
all_eq!(
simd_shuffle(x4, y4, const { SimdShuffleIdx([7u32, 2, 5, 0, 3, 6, 4, 1]) }),
i32x8([143, 42, 141, 40, 43, 142, 140, 41])
i32x8::from_array([143, 42, 141, 40, 43, 142, 140, 41])
);
all_eq!(simd_shuffle(x8, y8, const { SimdShuffleIdx([11u32, 5]) }), i32x2([183, 85]));
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([183, 85, 187, 80])
i32x4::from_array([183, 85, 187, 80])
);
all_eq!(
simd_shuffle(x8, y8, const { SimdShuffleIdx([11u32, 5, 15, 0, 3, 8, 12, 1]) }),
i32x8([183, 85, 187, 80, 83, 180, 184, 81])
i32x8::from_array([183, 85, 187, 80, 83, 180, 184, 81])
);
}
}

View file

@ -6,24 +6,26 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::{simd_gather, simd_scatter};
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct x4<T>(pub [T; 4]);
type x4<T> = Simd<T, 4>;
fn main() {
let mut x = [0_f32, 1., 2., 3., 4., 5., 6., 7.];
let default = x4([-3_f32, -3., -3., -3.]);
let s_strided = x4([0_f32, 2., -3., 6.]);
let mask = x4([-1_i32, -1, 0, -1]);
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([pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6)]);
x4::from_array(std::array::from_fn(|i| pointer.add(i * 2)));
let r_strided = simd_gather(default, pointers, mask);
@ -34,7 +36,7 @@ fn main() {
unsafe {
let pointer = x.as_mut_ptr();
let pointers =
x4([pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6)]);
x4::from_array(std::array::from_fn(|i| pointer.add(i * 2)));
let r_strided = simd_gather(default, pointers, mask);
@ -45,9 +47,9 @@ fn main() {
unsafe {
let pointer = x.as_mut_ptr();
let pointers =
x4([pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6)]);
x4::from_array(std::array::from_fn(|i| pointer.add(i * 2)));
let values = x4([42_f32, 43_f32, 44_f32, 45_f32]);
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.]);
@ -65,14 +67,14 @@ fn main() {
&x[7] as *const f32,
];
let default = x4([y[0], y[0], y[0], y[0]]);
let s_strided = x4([y[0], y[2], y[0], y[6]]);
let default = x4::from_array([y[0], y[0], y[0], y[0]]);
let s_strided = x4::from_array([y[0], y[2], y[0], y[6]]);
// reading from *const
unsafe {
let pointer = y.as_ptr();
let pointers =
x4([pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6)]);
x4::from_array(std::array::from_fn(|i| pointer.add(i * 2)));
let r_strided = simd_gather(default, pointers, mask);
@ -83,7 +85,7 @@ fn main() {
unsafe {
let pointer = y.as_mut_ptr();
let pointers =
x4([pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6)]);
x4::from_array(std::array::from_fn(|i| pointer.add(i * 2)));
let r_strided = simd_gather(default, pointers, mask);
@ -94,9 +96,9 @@ fn main() {
unsafe {
let pointer = y.as_mut_ptr();
let pointers =
x4([pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6)]);
x4::from_array(std::array::from_fn(|i| pointer.add(i * 2)));
let values = x4([y[7], y[6], y[5], y[1]]);
let values = x4::from_array([y[7], y[6], y[5], y[1]]);
simd_scatter(values, pointers, mask);
let s = [

View file

@ -6,38 +6,24 @@
// Test that the simd_select intrinsics produces correct results.
#![feature(repr_simd, core_intrinsics)]
#[path = "../../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::{simd_select, simd_select_bitmask};
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct i32x4(pub [i32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct u32x4(pub [u32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct u32x8([u32; 8]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct f32x4(pub [f32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct b8x4(pub [i8; 4]);
type b8x4 = i8x4;
fn main() {
let m0 = b8x4([!0, !0, !0, !0]);
let m1 = b8x4([0, 0, 0, 0]);
let m2 = b8x4([!0, !0, 0, 0]);
let m3 = b8x4([0, 0, !0, !0]);
let m4 = b8x4([!0, 0, !0, 0]);
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]);
let m3 = b8x4::from_array([0, 0, !0, !0]);
let m4 = b8x4::from_array([!0, 0, !0, 0]);
unsafe {
let a = i32x4([1, -2, 3, 4]);
let b = i32x4([5, 6, -7, 8]);
let a = i32x4::from_array([1, -2, 3, 4]);
let b = i32x4::from_array([5, 6, -7, 8]);
let r: i32x4 = simd_select(m0, a, b);
let e = a;
@ -48,21 +34,21 @@ fn main() {
assert_eq!(r, e);
let r: i32x4 = simd_select(m2, a, b);
let e = i32x4([1, -2, -7, 8]);
let e = i32x4::from_array([1, -2, -7, 8]);
assert_eq!(r, e);
let r: i32x4 = simd_select(m3, a, b);
let e = i32x4([5, 6, 3, 4]);
let e = i32x4::from_array([5, 6, 3, 4]);
assert_eq!(r, e);
let r: i32x4 = simd_select(m4, a, b);
let e = i32x4([1, 6, 3, 8]);
let e = i32x4::from_array([1, 6, 3, 8]);
assert_eq!(r, e);
}
unsafe {
let a = u32x4([1, 2, 3, 4]);
let b = u32x4([5, 6, 7, 8]);
let a = u32x4::from_array([1, 2, 3, 4]);
let b = u32x4::from_array([5, 6, 7, 8]);
let r: u32x4 = simd_select(m0, a, b);
let e = a;
@ -73,21 +59,21 @@ fn main() {
assert_eq!(r, e);
let r: u32x4 = simd_select(m2, a, b);
let e = u32x4([1, 2, 7, 8]);
let e = u32x4::from_array([1, 2, 7, 8]);
assert_eq!(r, e);
let r: u32x4 = simd_select(m3, a, b);
let e = u32x4([5, 6, 3, 4]);
let e = u32x4::from_array([5, 6, 3, 4]);
assert_eq!(r, e);
let r: u32x4 = simd_select(m4, a, b);
let e = u32x4([1, 6, 3, 8]);
let e = u32x4::from_array([1, 6, 3, 8]);
assert_eq!(r, e);
}
unsafe {
let a = f32x4([1., 2., 3., 4.]);
let b = f32x4([5., 6., 7., 8.]);
let a = f32x4::from_array([1., 2., 3., 4.]);
let b = f32x4::from_array([5., 6., 7., 8.]);
let r: f32x4 = simd_select(m0, a, b);
let e = a;
@ -98,23 +84,23 @@ fn main() {
assert_eq!(r, e);
let r: f32x4 = simd_select(m2, a, b);
let e = f32x4([1., 2., 7., 8.]);
let e = f32x4::from_array([1., 2., 7., 8.]);
assert_eq!(r, e);
let r: f32x4 = simd_select(m3, a, b);
let e = f32x4([5., 6., 3., 4.]);
let e = f32x4::from_array([5., 6., 3., 4.]);
assert_eq!(r, e);
let r: f32x4 = simd_select(m4, a, b);
let e = f32x4([1., 6., 3., 8.]);
let e = f32x4::from_array([1., 6., 3., 8.]);
assert_eq!(r, e);
}
unsafe {
let t = !0 as i8;
let f = 0 as i8;
let a = b8x4([t, f, t, f]);
let b = b8x4([f, f, f, t]);
let a = b8x4::from_array([t, f, t, f]);
let b = b8x4::from_array([f, f, f, t]);
let r: b8x4 = simd_select(m0, a, b);
let e = a;
@ -125,21 +111,21 @@ fn main() {
assert_eq!(r, e);
let r: b8x4 = simd_select(m2, a, b);
let e = b8x4([t, f, f, t]);
let e = b8x4::from_array([t, f, f, t]);
assert_eq!(r, e);
let r: b8x4 = simd_select(m3, a, b);
let e = b8x4([f, f, t, f]);
let e = b8x4::from_array([f, f, t, f]);
assert_eq!(r, e);
let r: b8x4 = simd_select(m4, a, b);
let e = b8x4([t, f, t, t]);
let e = b8x4::from_array([t, f, t, t]);
assert_eq!(r, e);
}
unsafe {
let a = u32x8([0, 1, 2, 3, 4, 5, 6, 7]);
let b = u32x8([8, 9, 10, 11, 12, 13, 14, 15]);
let a = u32x8::from_array([0, 1, 2, 3, 4, 5, 6, 7]);
let b = u32x8::from_array([8, 9, 10, 11, 12, 13, 14, 15]);
let r: u32x8 = simd_select_bitmask(0u8, a, b);
let e = b;
@ -150,21 +136,21 @@ fn main() {
assert_eq!(r, e);
let r: u32x8 = simd_select_bitmask(0b01010101u8, a, b);
let e = u32x8([0, 9, 2, 11, 4, 13, 6, 15]);
let e = u32x8::from_array([0, 9, 2, 11, 4, 13, 6, 15]);
assert_eq!(r, e);
let r: u32x8 = simd_select_bitmask(0b10101010u8, a, b);
let e = u32x8([8, 1, 10, 3, 12, 5, 14, 7]);
let e = u32x8::from_array([8, 1, 10, 3, 12, 5, 14, 7]);
assert_eq!(r, e);
let r: u32x8 = simd_select_bitmask(0b11110000u8, a, b);
let e = u32x8([8, 9, 10, 11, 4, 5, 6, 7]);
let e = u32x8::from_array([8, 9, 10, 11, 4, 5, 6, 7]);
assert_eq!(r, e);
}
unsafe {
let a = u32x4([0, 1, 2, 3]);
let b = u32x4([4, 5, 6, 7]);
let a = u32x4::from_array([0, 1, 2, 3]);
let b = u32x4::from_array([4, 5, 6, 7]);
let r: u32x4 = simd_select_bitmask(0u8, a, b);
let e = b;
@ -175,15 +161,15 @@ fn main() {
assert_eq!(r, e);
let r: u32x4 = simd_select_bitmask(0b0101u8, a, b);
let e = u32x4([0, 5, 2, 7]);
let e = u32x4::from_array([0, 5, 2, 7]);
assert_eq!(r, e);
let r: u32x4 = simd_select_bitmask(0b1010u8, a, b);
let e = u32x4([4, 1, 6, 3]);
let e = u32x4::from_array([4, 1, 6, 3]);
assert_eq!(r, e);
let r: u32x4 = simd_select_bitmask(0b1100u8, a, b);
let e = u32x4([4, 5, 2, 3]);
let e = u32x4::from_array([4, 5, 2, 3]);
assert_eq!(r, e);
}
}

View file

@ -5,11 +5,13 @@
//@ compile-flags: -Zmir-opt-level=4
#![feature(core_intrinsics, repr_simd)]
#[path = "../../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_shuffle;
#[repr(simd)]
#[derive(Debug, PartialEq)]
struct Simd2([u8; 2]);
type Simd2 = u8x2;
#[repr(simd)]
struct SimdShuffleIdx<const LEN: usize>([u32; LEN]);
@ -17,7 +19,11 @@ struct SimdShuffleIdx<const LEN: usize>([u32; LEN]);
fn main() {
unsafe {
const IDX: SimdShuffleIdx<2> = SimdShuffleIdx([0, 1]);
let p_res: Simd2 = simd_shuffle(Simd2([10, 11]), Simd2([12, 13]), IDX);
let p_res: Simd2 = simd_shuffle(
Simd2::from_array([10, 11]),
Simd2::from_array([12, 13]),
IDX,
);
let a_res: Simd2 = inline_me();
assert_10_11(p_res);
@ -27,16 +33,16 @@ fn main() {
#[inline(never)]
fn assert_10_11(x: Simd2) {
assert_eq!(x, Simd2([10, 11]));
assert_eq!(x.into_array(), [10, 11]);
}
#[inline(never)]
fn assert_10_13(x: Simd2) {
assert_eq!(x, Simd2([10, 13]));
assert_eq!(x.into_array(), [10, 13]);
}
#[inline(always)]
unsafe fn inline_me() -> Simd2 {
const IDX: SimdShuffleIdx<2> = SimdShuffleIdx([0, 3]);
simd_shuffle(Simd2([10, 11]), Simd2([12, 13]), IDX)
simd_shuffle(Simd2::from_array([10, 11]), Simd2::from_array([12, 13]), IDX)
}

View file

@ -2,18 +2,20 @@
#![feature(repr_simd, core_intrinsics)]
#[path = "../../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::{simd_cast_ptr, simd_expose_provenance, simd_with_exposed_provenance};
#[derive(Copy, Clone)]
#[repr(simd)]
struct V<T>([T; 2]);
type V<T> = Simd<T, 2>;
fn main() {
unsafe {
let mut foo = 4i8;
let ptr = &mut foo as *mut i8;
let ptrs = V::<*mut i8>([ptr, core::ptr::null_mut()]);
let ptrs: V::<*mut i8> = Simd([ptr, core::ptr::null_mut()]);
// change constness and type
let const_ptrs: V<*const u8> = simd_cast_ptr(ptrs);
@ -22,8 +24,8 @@ fn main() {
let with_exposed_provenance: V<*mut i8> = simd_with_exposed_provenance(exposed_addr);
assert!(const_ptrs.0 == [ptr as *const u8, core::ptr::null()]);
assert!(exposed_addr.0 == [ptr as usize, 0]);
assert!(with_exposed_provenance.0 == ptrs.0);
assert!(const_ptrs.into_array() == [ptr as *const u8, core::ptr::null()]);
assert!(exposed_addr.into_array() == [ptr as usize, 0]);
assert!(with_exposed_provenance.into_array() == ptrs.into_array());
}
}

View file

@ -2,16 +2,16 @@
#![feature(repr_simd, core_intrinsics)]
#[repr(simd)]
#[derive(Copy, Clone, Debug)]
pub struct Char3(pub [i8; 3]);
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
#[repr(simd)]
#[derive(Copy, Clone, Debug)]
pub struct Short3(pub [i16; 3]);
pub type Char3 = Simd<i8, 3>;
pub type Short3 = Simd<i16, 3>;
fn main() {
let cast: Short3 = unsafe { std::intrinsics::simd::simd_cast(Char3([10, -3, -9])) };
let cast: Short3 = unsafe { std::intrinsics::simd::simd_cast(Char3::from_array([10, -3, -9])) };
println!("{:?}", cast);
}

View file

@ -6,35 +6,27 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::{simd_gather, simd_scatter};
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct cptrx4<T>([*const T; 4]);
type cptrx4<T> = Simd<*const T, 4>;
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct mptrx4<T>([*mut T; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct f32x4([f32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct i32x4([i32; 4]);
type mptrx4<T> = Simd<*mut T, 4>;
fn main() {
let mut x = [0_f32, 1., 2., 3., 4., 5., 6., 7.];
let default = f32x4([-3_f32, -3., -3., -3.]);
let s_strided = f32x4([0_f32, 2., -3., 6.]);
let mask = i32x4([-1_i32, -1, 0, -1]);
let default = f32x4::from_array([-3_f32, -3., -3., -3.]);
let s_strided = f32x4::from_array([0_f32, 2., -3., 6.]);
let mask = i32x4::from_array([-1_i32, -1, 0, -1]);
// reading from *const
unsafe {
let pointer = &x as *const f32;
let pointers = cptrx4([
let pointers = cptrx4::from_array([
pointer.offset(0) as *const f32,
pointer.offset(2),
pointer.offset(4),
@ -49,14 +41,14 @@ fn main() {
// writing to *mut
unsafe {
let pointer = &mut x as *mut f32;
let pointers = mptrx4([
let pointers = mptrx4::from_array([
pointer.offset(0) as *mut f32,
pointer.offset(2),
pointer.offset(4),
pointer.offset(6),
]);
let values = f32x4([42_f32, 43_f32, 44_f32, 45_f32]);
let values = f32x4::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.]);

View file

@ -6,36 +6,38 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_gather;
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct x4<T>(pub [T; 4]);
type x4<T> = Simd<T, 4>;
fn main() {
let x: [usize; 4] = [10, 11, 12, 13];
let default = x4([0_usize, 1, 2, 3]);
let default = x4::from_array([0_usize, 1, 2, 3]);
let all_set = u8::MAX as i8; // aka -1
let mask = x4([all_set, all_set, all_set, all_set]);
let expected = x4([10_usize, 11, 12, 13]);
let mask = x4::from_array([all_set, all_set, all_set, all_set]);
let expected = x4::from_array([10_usize, 11, 12, 13]);
unsafe {
let pointer = x.as_ptr();
let pointers =
x4([pointer.offset(0), pointer.offset(1), pointer.offset(2), pointer.offset(3)]);
x4::from_array(std::array::from_fn(|i| pointer.add(i)));
let result = simd_gather(default, pointers, mask);
assert_eq!(result, expected);
}
// and again for isize
let x: [isize; 4] = [10, 11, 12, 13];
let default = x4([0_isize, 1, 2, 3]);
let expected = x4([10_isize, 11, 12, 13]);
let default = x4::from_array([0_isize, 1, 2, 3]);
let expected = x4::from_array([10_isize, 11, 12, 13]);
unsafe {
let pointer = x.as_ptr();
let pointers =
x4([pointer.offset(0), pointer.offset(1), pointer.offset(2), pointer.offset(3)]);
x4::from_array(std::array::from_fn(|i| pointer.add(i)));
let result = simd_gather(default, pointers, mask);
assert_eq!(result, expected);
}

View file

@ -1,11 +1,11 @@
//@ run-pass
#![feature(repr_simd, core_intrinsics)]
use std::intrinsics::simd::{simd_masked_load, simd_masked_store};
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
#[derive(Copy, Clone)]
#[repr(simd)]
struct Simd<T, const N: usize>([T; N]);
use std::intrinsics::simd::{simd_masked_load, simd_masked_store};
fn main() {
unsafe {
@ -15,7 +15,7 @@ fn main() {
let b: Simd<u8, 4> =
simd_masked_load(Simd::<i8, 4>([-1, 0, -1, -1]), b_src.as_ptr(), b_default);
assert_eq!(&b.0, &[4, 9, 6, 7]);
assert_eq!(b.as_array(), &[4, 9, 6, 7]);
let mut output = [u8::MAX; 5];

View file

@ -11,6 +11,10 @@
)]
#![allow(incomplete_features)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
#[cfg(old)]
use std::intrinsics::simd::simd_shuffle;
@ -18,10 +22,6 @@ use std::intrinsics::simd::simd_shuffle;
#[rustc_intrinsic]
unsafe fn simd_shuffle_const_generic<T, U, const I: &'static [u32]>(a: T, b: T) -> U;
#[derive(Copy, Clone)]
#[repr(simd)]
struct Simd<T, const N: usize>([T; N]);
trait Shuffle<const N: usize> {
const I: Simd<u32, N>;
const J: &'static [u32] = &Self::I.0;
@ -57,9 +57,9 @@ fn main() {
let b = Simd::<u8, 4>([4, 5, 6, 7]);
unsafe {
let x: Simd<u8, 4> = I1.shuffle(a, b);
assert_eq!(x.0, [0, 2, 4, 6]);
assert_eq!(x.into_array(), [0, 2, 4, 6]);
let y: Simd<u8, 2> = I2.shuffle(a, b);
assert_eq!(y.0, [1, 5]);
assert_eq!(y.into_array(), [1, 5]);
}
}

View file

@ -3,15 +3,16 @@
#![feature(repr_simd, core_intrinsics)]
#![allow(non_camel_case_types)]
use std::intrinsics::simd::simd_add;
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
#[repr(simd, packed)]
struct Simd<T, const N: usize>([T; N]);
use std::intrinsics::simd::simd_add;
fn check_size_align<T, const N: usize>() {
use std::mem;
assert_eq!(mem::size_of::<Simd<T, N>>(), mem::size_of::<[T; N]>());
assert_eq!(mem::size_of::<Simd<T, N>>() % mem::align_of::<Simd<T, N>>(), 0);
assert_eq!(mem::size_of::<PackedSimd<T, N>>(), mem::size_of::<[T; N]>());
assert_eq!(mem::size_of::<PackedSimd<T, N>>() % mem::align_of::<PackedSimd<T, N>>(), 0);
}
fn check_ty<T>() {
@ -35,14 +36,21 @@ fn main() {
unsafe {
// powers-of-two have no padding and have the same layout as #[repr(simd)]
let x: Simd<f64, 4> =
simd_add(Simd::<f64, 4>([0., 1., 2., 3.]), Simd::<f64, 4>([2., 2., 2., 2.]));
assert_eq!(std::mem::transmute::<_, [f64; 4]>(x), [2., 3., 4., 5.]);
let x: PackedSimd<f64, 4> =
simd_add(
PackedSimd::<f64, 4>([0., 1., 2., 3.]),
PackedSimd::<f64, 4>([2., 2., 2., 2.]),
);
assert_eq!(x.into_array(), [2., 3., 4., 5.]);
// non-powers-of-two should have padding (which is removed by #[repr(packed)]),
// but the intrinsic handles it
let x: Simd<f64, 3> = simd_add(Simd::<f64, 3>([0., 1., 2.]), Simd::<f64, 3>([2., 2., 2.]));
let arr: [f64; 3] = x.0;
let x: PackedSimd<f64, 3> =
simd_add(
PackedSimd::<f64, 3>([0., 1., 2.]),
PackedSimd::<f64, 3>([2., 2., 2.]),
);
let arr: [f64; 3] = x.into_array();
assert_eq!(arr, [2., 3., 4.]);
}
}

View file

@ -10,10 +10,16 @@ use std::marker::ConstParamTy;
use std::intrinsics::simd::simd_shuffle;
// not using `minisimd` because of the `ConstParamTy`
#[derive(Copy, Clone, ConstParamTy, PartialEq, Eq)]
#[repr(simd)]
struct Simd<T, const N: usize>([T; N]);
fn into_array<T, const N: usize>(v: Simd<T, N>) -> [T; N] {
const { assert!(size_of::<Simd<T, N>>() == size_of::<[T; N]>()) }
unsafe { std::intrinsics::transmute_unchecked(v) }
}
unsafe fn __shuffle_vector16<const IDX: Simd<u32, 16>, T, U>(x: T, y: T) -> U {
simd_shuffle(x, y, IDX)
}
@ -25,10 +31,10 @@ fn main() {
let b = Simd::<u8, 4>([4, 5, 6, 7]);
unsafe {
let x: Simd<u8, 4> = simd_shuffle(a, b, I1);
assert_eq!(x.0, [0, 2, 4, 6]);
assert_eq!(into_array(x), [0, 2, 4, 6]);
let y: Simd<u8, 2> = simd_shuffle(a, b, I2);
assert_eq!(y.0, [1, 5]);
assert_eq!(into_array(y), [1, 5]);
}
// Test that an indirection (via an unnamed constant)

View file

@ -4,21 +4,23 @@
//@ ignore-endian-big
#![feature(repr_simd, core_intrinsics)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::{simd_bitmask, simd_select_bitmask};
fn main() {
// Non-power-of-2 multi-byte mask.
#[repr(simd, packed)]
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, PartialEq)]
struct i32x10([i32; 10]);
type i32x10 = PackedSimd<i32, 10>;
impl i32x10 {
fn splat(x: i32) -> Self {
Self([x; 10])
}
}
unsafe {
let mask = i32x10([!0, !0, 0, !0, 0, 0, !0, 0, !0, 0]);
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 };
let mask_bytes =
if cfg!(target_endian = "little") { [0b01001011, 0b01] } else { [0b11, 0b01001010] };
@ -43,17 +45,20 @@ fn main() {
}
// Test for a mask where the next multiple of 8 is not a power of two.
#[repr(simd, packed)]
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, PartialEq)]
struct i32x20([i32; 20]);
type i32x20 = PackedSimd<i32, 20>;
impl i32x20 {
fn splat(x: i32) -> Self {
Self([x; 20])
}
}
unsafe {
let mask = i32x20([!0, !0, 0, !0, 0, 0, !0, 0, !0, 0, 0, 0, 0, !0, !0, !0, !0, !0, !0, !0]);
let mask = i32x20::from_array([
!0, !0, 0, !0, 0,
0, !0, 0, !0, 0,
0, 0, 0, !0, !0,
!0, !0, !0, !0, !0,
]);
let mask_bits = if cfg!(target_endian = "little") {
0b11111110000101001011
} else {

View file

@ -1,11 +1,11 @@
//@run-pass
#![feature(repr_simd, core_intrinsics)]
use std::intrinsics::simd::{simd_bitmask, simd_select_bitmask};
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
#[derive(Copy, Clone)]
#[repr(simd)]
struct Simd<T, const N: usize>([T; N]);
use std::intrinsics::simd::{simd_bitmask, simd_select_bitmask};
fn main() {
unsafe {
@ -41,11 +41,11 @@ fn main() {
let mask = if cfg!(target_endian = "little") { 0b0101u8 } else { 0b1010u8 };
let r = simd_select_bitmask(mask, a, b);
assert_eq!(r.0, e);
assert_eq!(r.into_array(), e);
let mask = if cfg!(target_endian = "little") { [0b0101u8] } else { [0b1010u8] };
let r = simd_select_bitmask(mask, a, b);
assert_eq!(r.0, e);
assert_eq!(r.into_array(), e);
let a = Simd::<i32, 16>([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
let b = Simd::<i32, 16>([16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]);
@ -57,7 +57,7 @@ fn main() {
0b0011000000001010u16
};
let r = simd_select_bitmask(mask, a, b);
assert_eq!(r.0, e);
assert_eq!(r.into_array(), e);
let mask = if cfg!(target_endian = "little") {
[0b00001100u8, 0b01010000u8]
@ -65,6 +65,6 @@ fn main() {
[0b00110000u8, 0b00001010u8]
};
let r = simd_select_bitmask(mask, a, b);
assert_eq!(r.0, e);
assert_eq!(r.into_array(), e);
}
}

View file

@ -8,6 +8,11 @@
#![feature(repr_simd, target_feature, cfg_target_feature)]
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
#[allow(unused)]
use minisimd::*;
use std::process::{Command, ExitStatus};
use std::env;
@ -50,19 +55,13 @@ fn is_sigill(status: ExitStatus) -> bool {
#[allow(nonstandard_style)]
mod test {
// An SSE type
#[repr(simd)]
#[derive(PartialEq, Debug, Clone, Copy)]
struct __m128i([u64; 2]);
type __m128i = super::u64x2;
// An AVX type
#[repr(simd)]
#[derive(PartialEq, Debug, Clone, Copy)]
struct __m256i([u64; 4]);
type __m256i = super::u64x4;
// An AVX-512 type
#[repr(simd)]
#[derive(PartialEq, Debug, Clone, Copy)]
struct __m512i([u64; 8]);
type __m512i = super::u64x8;
pub fn main(level: &str) {
unsafe {
@ -88,9 +87,9 @@ mod test {
)*) => ($(
$(#[$attr])*
unsafe fn $main(level: &str) {
let m128 = __m128i([1, 2]);
let m256 = __m256i([3, 4, 5, 6]);
let m512 = __m512i([7, 8, 9, 10, 11, 12, 13, 14]);
let m128 = __m128i::from_array([1, 2]);
let m256 = __m256i::from_array([3, 4, 5, 6]);
let m512 = __m512i::from_array([7, 8, 9, 10, 11, 12, 13, 14]);
assert_eq!(id_sse_128(m128), m128);
assert_eq!(id_sse_256(m256), m256);
assert_eq!(id_sse_512(m512), m512);
@ -125,55 +124,55 @@ mod test {
#[target_feature(enable = "sse2")]
unsafe fn id_sse_128(a: __m128i) -> __m128i {
assert_eq!(a, __m128i([1, 2]));
assert_eq!(a, __m128i::from_array([1, 2]));
a.clone()
}
#[target_feature(enable = "sse2")]
unsafe fn id_sse_256(a: __m256i) -> __m256i {
assert_eq!(a, __m256i([3, 4, 5, 6]));
assert_eq!(a, __m256i::from_array([3, 4, 5, 6]));
a.clone()
}
#[target_feature(enable = "sse2")]
unsafe fn id_sse_512(a: __m512i) -> __m512i {
assert_eq!(a, __m512i([7, 8, 9, 10, 11, 12, 13, 14]));
assert_eq!(a, __m512i::from_array([7, 8, 9, 10, 11, 12, 13, 14]));
a.clone()
}
#[target_feature(enable = "avx")]
unsafe fn id_avx_128(a: __m128i) -> __m128i {
assert_eq!(a, __m128i([1, 2]));
assert_eq!(a, __m128i::from_array([1, 2]));
a.clone()
}
#[target_feature(enable = "avx")]
unsafe fn id_avx_256(a: __m256i) -> __m256i {
assert_eq!(a, __m256i([3, 4, 5, 6]));
assert_eq!(a, __m256i::from_array([3, 4, 5, 6]));
a.clone()
}
#[target_feature(enable = "avx")]
unsafe fn id_avx_512(a: __m512i) -> __m512i {
assert_eq!(a, __m512i([7, 8, 9, 10, 11, 12, 13, 14]));
assert_eq!(a, __m512i::from_array([7, 8, 9, 10, 11, 12, 13, 14]));
a.clone()
}
#[target_feature(enable = "avx512bw")]
unsafe fn id_avx512_128(a: __m128i) -> __m128i {
assert_eq!(a, __m128i([1, 2]));
assert_eq!(a, __m128i::from_array([1, 2]));
a.clone()
}
#[target_feature(enable = "avx512bw")]
unsafe fn id_avx512_256(a: __m256i) -> __m256i {
assert_eq!(a, __m256i([3, 4, 5, 6]));
assert_eq!(a, __m256i::from_array([3, 4, 5, 6]));
a.clone()
}
#[target_feature(enable = "avx512bw")]
unsafe fn id_avx512_512(a: __m512i) -> __m512i {
assert_eq!(a, __m512i([7, 8, 9, 10, 11, 12, 13, 14]));
assert_eq!(a, __m512i::from_array([7, 8, 9, 10, 11, 12, 13, 14]));
a.clone()
}
}