From cebc2ca7072b8b33a397adf4f3380099ea25fb19 Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Tue, 13 Oct 2020 01:28:03 -0400 Subject: [PATCH 01/13] Add opaque masks --- crates/core_simd/src/fmt.rs | 20 +- crates/core_simd/src/lib.rs | 16 +- crates/core_simd/src/macros.rs | 11 +- crates/core_simd/src/masks/mod.rs | 215 ++++++++++++++++++ .../src/{masks.rs => masks/wide/mod.rs} | 27 ++- .../core_simd/src/masks/wide/vectors_m128.rs | 11 + .../core_simd/src/masks/wide/vectors_m16.rs | 21 ++ .../core_simd/src/masks/wide/vectors_m32.rs | 21 ++ .../core_simd/src/masks/wide/vectors_m64.rs | 16 ++ crates/core_simd/src/masks/wide/vectors_m8.rs | 21 ++ .../core_simd/src/masks/wide/vectors_msize.rs | 16 ++ crates/core_simd/src/ops.rs | 24 +- crates/core_simd/src/vectors_mask128.rs | 11 - crates/core_simd/src/vectors_mask16.rs | 21 -- crates/core_simd/src/vectors_mask32.rs | 21 -- crates/core_simd/src/vectors_mask64.rs | 16 -- crates/core_simd/src/vectors_mask8.rs | 21 -- crates/core_simd/src/vectors_masksize.rs | 16 -- 18 files changed, 379 insertions(+), 146 deletions(-) create mode 100644 crates/core_simd/src/masks/mod.rs rename crates/core_simd/src/{masks.rs => masks/wide/mod.rs} (87%) create mode 100644 crates/core_simd/src/masks/wide/vectors_m128.rs create mode 100644 crates/core_simd/src/masks/wide/vectors_m16.rs create mode 100644 crates/core_simd/src/masks/wide/vectors_m32.rs create mode 100644 crates/core_simd/src/masks/wide/vectors_m64.rs create mode 100644 crates/core_simd/src/masks/wide/vectors_m8.rs create mode 100644 crates/core_simd/src/masks/wide/vectors_msize.rs delete mode 100644 crates/core_simd/src/vectors_mask128.rs delete mode 100644 crates/core_simd/src/vectors_mask16.rs delete mode 100644 crates/core_simd/src/vectors_mask32.rs delete mode 100644 crates/core_simd/src/vectors_mask64.rs delete mode 100644 crates/core_simd/src/vectors_mask8.rs delete mode 100644 crates/core_simd/src/vectors_masksize.rs diff --git a/crates/core_simd/src/fmt.rs b/crates/core_simd/src/fmt.rs index c634e0546bc..07332c1ccc8 100644 --- a/crates/core_simd/src/fmt.rs +++ b/crates/core_simd/src/fmt.rs @@ -74,10 +74,10 @@ macro_rules! impl_fmt_trait { impl_fmt_trait! { integers: - crate::u8x8, crate::u8x16, crate::u8x32, crate::u8x64, - crate::i8x8, crate::i8x16, crate::i8x32, crate::i8x64, - crate::u16x4, crate::u16x8, crate::u16x16, crate::u16x32, - crate::i16x4, crate::i16x8, crate::i16x16, crate::i16x32, + crate::u8x8, crate::u8x16, crate::u8x32, crate::u8x64, + crate::i8x8, crate::i8x16, crate::i8x32, crate::i8x64, + crate::u16x4, crate::u16x8, crate::u16x16, crate::u16x32, + crate::i16x4, crate::i16x8, crate::i16x16, crate::i16x32, crate::u32x2, crate::u32x4, crate::u32x8, crate::u32x16, crate::i32x2, crate::i32x4, crate::i32x8, crate::i32x16, crate::u64x2, crate::u64x4, crate::u64x8, @@ -96,10 +96,10 @@ impl_fmt_trait! { impl_fmt_trait! { masks: - crate::mask8x8, crate::mask8x16, crate::mask8x32, crate::mask8x64, - crate::mask16x4, crate::mask16x8, crate::mask16x16, crate::mask16x32, - crate::mask32x2, crate::mask32x4, crate::mask32x8, crate::mask32x16, - crate::mask64x2, crate::mask64x4, crate::mask64x8, - crate::mask128x2, crate::mask128x4, - crate::masksizex2, crate::masksizex4, crate::masksizex8, + crate::masks::wide::m8x8, crate::masks::wide::m8x16, crate::masks::wide::m8x32, crate::masks::wide::m8x64, + crate::masks::wide::m16x4, crate::masks::wide::m16x8, crate::masks::wide::m16x16, crate::masks::wide::m16x32, + crate::masks::wide::m32x2, crate::masks::wide::m32x4, crate::masks::wide::m32x8, crate::masks::wide::m32x16, + crate::masks::wide::m64x2, crate::masks::wide::m64x4, crate::masks::wide::m64x8, + crate::masks::wide::m128x2, crate::masks::wide::m128x4, + crate::masks::wide::msizex2, crate::masks::wide::msizex4, crate::masks::wide::msizex8, } diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs index cea39e6f3f3..fd4f9dd16fd 100644 --- a/crates/core_simd/src/lib.rs +++ b/crates/core_simd/src/lib.rs @@ -10,8 +10,7 @@ mod fmt; mod intrinsics; mod ops; -mod masks; -pub use masks::*; +pub mod masks; mod vectors_u8; pub use vectors_u8::*; @@ -44,17 +43,4 @@ pub use vectors_f32::*; mod vectors_f64; pub use vectors_f64::*; -mod vectors_mask8; -pub use vectors_mask8::*; -mod vectors_mask16; -pub use vectors_mask16::*; -mod vectors_mask32; -pub use vectors_mask32::*; -mod vectors_mask64; -pub use vectors_mask64::*; -mod vectors_mask128; -pub use vectors_mask128::*; -mod vectors_masksize; -pub use vectors_masksize::*; - mod round; diff --git a/crates/core_simd/src/macros.rs b/crates/core_simd/src/macros.rs index f37d13c3ca3..b8324ffdb92 100644 --- a/crates/core_simd/src/macros.rs +++ b/crates/core_simd/src/macros.rs @@ -314,7 +314,6 @@ macro_rules! define_float_vector { } } - /// Defines an integer vector `$name` containing multiple `$lanes` of integer `$type`. macro_rules! define_integer_vector { { $(#[$attr:meta])* struct $name:ident([$type:ty; $lanes:tt]); } => { @@ -336,6 +335,7 @@ macro_rules! define_mask_vector { impl $name { call_repeat! { $lanes => define_mask_vector [$impl_type] splat $type | } call_counting_args! { $lanes => define_mask_vector => new $type | } + call_counting_args! { $lanes => define_mask_vector => new_from_bool $type | } } base_vector_traits! { $name => [$type; $lanes] } @@ -361,5 +361,14 @@ macro_rules! define_mask_vector { pub const fn new($($var: $type),*) -> Self { Self($($var.0),*) } + }; + { new_from_bool $type:ty | $($var:ident)* } => { + /// Used internally (since we can't use the Into trait in `const fn`s) + #[allow(clippy::too_many_arguments)] + #[allow(unused)] + #[inline] + pub(crate) const fn new_from_bool($($var: bool),*) -> Self { + Self($(<$type>::new($var).0),*) + } } } diff --git a/crates/core_simd/src/masks/mod.rs b/crates/core_simd/src/masks/mod.rs new file mode 100644 index 00000000000..e138a1b4dd8 --- /dev/null +++ b/crates/core_simd/src/masks/mod.rs @@ -0,0 +1,215 @@ +//! Types and traits associated with masking lanes of vectors. + +pub mod wide; + +trait MaskImpl { + type Mask; +} + +impl MaskImpl for [u8; 8] { + type Mask = wide::m8x8; +} + +impl MaskImpl for [u8; 16] { + type Mask = wide::m8x16; +} + +impl MaskImpl for [u8; 32] { + type Mask = wide::m8x32; +} + +impl MaskImpl for [u8; 64] { + type Mask = wide::m8x64; +} + +impl MaskImpl for [u16; 4] { + type Mask = wide::m16x4; +} + +impl MaskImpl for [u16; 8] { + type Mask = wide::m16x8; +} + +impl MaskImpl for [u16; 16] { + type Mask = wide::m16x16; +} + +impl MaskImpl for [u16; 32] { + type Mask = wide::m16x32; +} + +impl MaskImpl for [u32; 2] { + type Mask = wide::m32x2; +} + +impl MaskImpl for [u32; 4] { + type Mask = wide::m32x4; +} + +impl MaskImpl for [u32; 8] { + type Mask = wide::m32x8; +} + +impl MaskImpl for [u32; 16] { + type Mask = wide::m32x16; +} + +impl MaskImpl for [u64; 2] { + type Mask = wide::m64x2; +} + +impl MaskImpl for [u64; 4] { + type Mask = wide::m64x4; +} + +impl MaskImpl for [u64; 8] { + type Mask = wide::m64x8; +} + +impl MaskImpl for [u128; 2] { + type Mask = wide::m128x2; +} + +impl MaskImpl for [u128; 4] { + type Mask = wide::m128x4; +} + +impl MaskImpl for [usize; 2] { + type Mask = wide::msizex2; +} + +impl MaskImpl for [usize; 4] { + type Mask = wide::msizex4; +} + +impl MaskImpl for [usize; 8] { + type Mask = wide::msizex8; +} + +macro_rules! define_opaque_mask { + { + $(#[$attr:meta])* + struct $name:ident([$width:ty; $lanes:tt]); + } => { + $(#[$attr])* + #[allow(non_camel_case_types)] + pub struct $name(<[$width; $lanes] as MaskImpl>::Mask); + + impl $name { + /// Construct a mask by setting all lanes to the given value. + pub fn splat(value: bool) -> Self { + Self(<[$width; $lanes] as MaskImpl>::Mask::splat(value.into())) + } + + call_counting_args! { $lanes => define_opaque_mask => new [$width; $lanes] } + } + }; + { new [$width:ty; $lanes:tt] $($var:ident)* } => { + /// Construct a vector by setting each lane to the given values. + #[allow(clippy::too_many_arguments)] + #[inline] + pub const fn new($($var: bool),*) -> Self { + Self(<[$width; $lanes] as MaskImpl>::Mask::new_from_bool($($var),*)) + } + } +} + +define_opaque_mask! { + /// Mask for 8 8-bit lanes + struct mask8x8([u8; 8]); +} + +define_opaque_mask! { + /// Mask for 16 8-bit lanes + struct mask8x16([u8; 16]); +} + +define_opaque_mask! { + /// Mask for 32 8-bit lanes + struct mask8x32([u8; 32]); +} + +define_opaque_mask! { + /// Mask for 64 8-bit lanes + struct mask8x64([u8; 64]); +} + +define_opaque_mask! { + /// Mask for 4 16-bit lanes + struct mask16x4([u16; 4]); +} + +define_opaque_mask! { + /// Mask for 8 16-bit lanes + struct mask16x8([u16; 8]); +} + +define_opaque_mask! { + /// Mask for 16 16-bit lanes + struct mask16x16([u16; 16]); +} + +define_opaque_mask! { + /// Mask for 32 16-bit lanes + struct mask16x32([u16; 32]); +} + +define_opaque_mask! { + /// Mask for 2 32-bit lanes + struct mask32x2([u32; 2]); +} + +define_opaque_mask! { + /// Mask for 4 32-bit lanes + struct mask32x4([u32; 4]); +} + +define_opaque_mask! { + /// Mask for 8 32-bit lanes + struct mask32x8([u32; 8]); +} + +define_opaque_mask! { + /// Mask for 16 32-bit lanes + struct mask32x16([u32; 16]); +} + +define_opaque_mask! { + /// Mask for 2 64-bit lanes + struct mask64x2([u64; 2]); +} + +define_opaque_mask! { + /// Mask for 4 64-bit lanes + struct mask64x4([u64; 4]); +} + +define_opaque_mask! { + /// Mask for 8 64-bit lanes + struct mask64x8([u64; 8]); +} + +define_opaque_mask! { + /// Mask for 2 128-bit lanes + struct mask128x2([u128; 2]); +} + +define_opaque_mask! { + /// Mask for 4 128-bit lanes + struct mask128x4([u128; 4]); +} + +define_opaque_mask! { + /// Mask for 2 `isize`-wide lanes + struct masksizex2([usize; 2]); +} + +define_opaque_mask! { + /// Mask for 4 `isize`-wide lanes + struct masksizex4([usize; 4]); +} + +define_opaque_mask! { + /// Mask for 8 `isize`-wide lanes + struct masksizex8([usize; 8]); +} diff --git a/crates/core_simd/src/masks.rs b/crates/core_simd/src/masks/wide/mod.rs similarity index 87% rename from crates/core_simd/src/masks.rs rename to crates/core_simd/src/masks/wide/mod.rs index cba76b6a2a3..1462992197d 100644 --- a/crates/core_simd/src/masks.rs +++ b/crates/core_simd/src/masks/wide/mod.rs @@ -1,3 +1,18 @@ +//! Masks that take up full vector registers. + +mod vectors_m8; +pub use vectors_m8::*; +mod vectors_m16; +pub use vectors_m16::*; +mod vectors_m32; +pub use vectors_m32::*; +mod vectors_m64; +pub use vectors_m64::*; +mod vectors_m128; +pub use vectors_m128::*; +mod vectors_msize; +pub use vectors_msize::*; + /// The error type returned when converting an integer to a mask fails. #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct TryFromMaskError(()); @@ -95,30 +110,30 @@ macro_rules! define_mask { define_mask! { /// 8-bit mask - struct mask8(i8); + struct m8(i8); } define_mask! { /// 16-bit mask - struct mask16(i16); + struct m16(i16); } define_mask! { /// 32-bit mask - struct mask32(i32); + struct m32(i32); } define_mask! { /// 64-bit mask - struct mask64(i64); + struct m64(i64); } define_mask! { /// 128-bit mask - struct mask128(i128); + struct m128(i128); } define_mask! { /// `isize`-wide mask - struct masksize(isize); + struct msize(isize); } diff --git a/crates/core_simd/src/masks/wide/vectors_m128.rs b/crates/core_simd/src/masks/wide/vectors_m128.rs new file mode 100644 index 00000000000..fddddac5fc4 --- /dev/null +++ b/crates/core_simd/src/masks/wide/vectors_m128.rs @@ -0,0 +1,11 @@ +use super::m128; + +define_mask_vector! { + /// Vector of two `m128` values + struct m128x2([i128 as m128; 2]); +} + +define_mask_vector! { + /// Vector of four `m128` values + struct m128x4([i128 as m128; 4]); +} diff --git a/crates/core_simd/src/masks/wide/vectors_m16.rs b/crates/core_simd/src/masks/wide/vectors_m16.rs new file mode 100644 index 00000000000..3b05e83f673 --- /dev/null +++ b/crates/core_simd/src/masks/wide/vectors_m16.rs @@ -0,0 +1,21 @@ +use super::m16; + +define_mask_vector! { + /// Vector of four `m16` values + struct m16x4([i16 as m16; 4]); +} + +define_mask_vector! { + /// Vector of eight `m16` values + struct m16x8([i16 as m16; 8]); +} + +define_mask_vector! { + /// Vector of 16 `m16` values + struct m16x16([i16 as m16; 16]); +} + +define_mask_vector! { + /// Vector of 32 `m16` values + struct m16x32([i16 as m16; 32]); +} diff --git a/crates/core_simd/src/masks/wide/vectors_m32.rs b/crates/core_simd/src/masks/wide/vectors_m32.rs new file mode 100644 index 00000000000..de5745fb283 --- /dev/null +++ b/crates/core_simd/src/masks/wide/vectors_m32.rs @@ -0,0 +1,21 @@ +use super::m32; + +define_mask_vector! { + /// Vector of two `m32` values + struct m32x2([i32 as m32; 2]); +} + +define_mask_vector! { + /// Vector of four `m32` values + struct m32x4([i32 as m32; 4]); +} + +define_mask_vector! { + /// Vector of eight `m32` values + struct m32x8([i32 as m32; 8]); +} + +define_mask_vector! { + /// Vector of 16 `m32` values + struct m32x16([i32 as m32; 16]); +} diff --git a/crates/core_simd/src/masks/wide/vectors_m64.rs b/crates/core_simd/src/masks/wide/vectors_m64.rs new file mode 100644 index 00000000000..55c8687fcfc --- /dev/null +++ b/crates/core_simd/src/masks/wide/vectors_m64.rs @@ -0,0 +1,16 @@ +use super::m64; + +define_mask_vector! { + /// Vector of two `m64` values + struct m64x2([i64 as m64; 2]); +} + +define_mask_vector! { + /// Vector of four `m64` values + struct m64x4([i64 as m64; 4]); +} + +define_mask_vector! { + /// Vector of eight `m64` values + struct m64x8([i64 as m64; 8]); +} diff --git a/crates/core_simd/src/masks/wide/vectors_m8.rs b/crates/core_simd/src/masks/wide/vectors_m8.rs new file mode 100644 index 00000000000..149e138739d --- /dev/null +++ b/crates/core_simd/src/masks/wide/vectors_m8.rs @@ -0,0 +1,21 @@ +use super::m8; + +define_mask_vector! { + /// Vector of eight `m8` values + struct m8x8([i8 as m8; 8]); +} + +define_mask_vector! { + /// Vector of 16 `m8` values + struct m8x16([i8 as m8; 16]); +} + +define_mask_vector! { + /// Vector of 32 `m8` values + struct m8x32([i8 as m8; 32]); +} + +define_mask_vector! { + /// Vector of 64 `m8` values + struct m8x64([i8 as m8; 64]); +} diff --git a/crates/core_simd/src/masks/wide/vectors_msize.rs b/crates/core_simd/src/masks/wide/vectors_msize.rs new file mode 100644 index 00000000000..497aba8ddbb --- /dev/null +++ b/crates/core_simd/src/masks/wide/vectors_msize.rs @@ -0,0 +1,16 @@ +use super::msize; + +define_mask_vector! { + /// Vector of two `msize` values + struct msizex2([isize as msize; 2]); +} + +define_mask_vector! { + /// Vector of four `msize` values + struct msizex4([isize as msize; 4]); +} + +define_mask_vector! { + /// Vector of eight `msize` values + struct msizex8([isize as msize; 8]); +} diff --git a/crates/core_simd/src/ops.rs b/crates/core_simd/src/ops.rs index 5a186649821..ac89feca9d6 100644 --- a/crates/core_simd/src/ops.rs +++ b/crates/core_simd/src/ops.rs @@ -96,7 +96,7 @@ macro_rules! impl_ref_ops { } /// Implements op traits for masks -macro_rules! impl_mask_ops { +macro_rules! impl_mask_element_ops { { $($mask:ty),* } => { $( impl_ref_ops! { @@ -161,7 +161,15 @@ macro_rules! impl_mask_ops { )* } } -impl_mask_ops! { crate::mask8, crate::mask16, crate::mask32, crate::mask64, crate::mask128, crate::masksize } + +impl_mask_element_ops! { + crate::masks::wide::m8, + crate::masks::wide::m16, + crate::masks::wide::m32, + crate::masks::wide::m64, + crate::masks::wide::m128, + crate::masks::wide::msize +} /// Automatically implements operators over vectors and scalars for a particular vector. macro_rules! impl_op { @@ -632,10 +640,10 @@ impl_float_ops! { } impl_mask_ops! { - crate::mask8 => crate::mask8x8, crate::mask8x16, crate::mask8x32, crate::mask8x64; - crate::mask16 => crate::mask16x4, crate::mask16x8, crate::mask16x16, crate::mask16x32; - crate::mask32 => crate::mask32x2, crate::mask32x4, crate::mask32x8, crate::mask32x16; - crate::mask64 => crate::mask64x2, crate::mask64x4, crate::mask64x8; - crate::mask128 => crate::mask128x2, crate::mask128x4; - crate::masksize => crate::masksizex2, crate::masksizex4, crate::masksizex8; + crate::masks::wide::m8 => crate::masks::wide::m8x8, crate::masks::wide::m8x16, crate::masks::wide::m8x32, crate::masks::wide::m8x64; + crate::masks::wide::m16 => crate::masks::wide::m16x4, crate::masks::wide::m16x8, crate::masks::wide::m16x16, crate::masks::wide::m16x32; + crate::masks::wide::m32 => crate::masks::wide::m32x2, crate::masks::wide::m32x4, crate::masks::wide::m32x8, crate::masks::wide::m32x16; + crate::masks::wide::m64 => crate::masks::wide::m64x2, crate::masks::wide::m64x4, crate::masks::wide::m64x8; + crate::masks::wide::m128 => crate::masks::wide::m128x2, crate::masks::wide::m128x4; + crate::masks::wide::msize => crate::masks::wide::msizex2, crate::masks::wide::msizex4, crate::masks::wide::msizex8; } diff --git a/crates/core_simd/src/vectors_mask128.rs b/crates/core_simd/src/vectors_mask128.rs deleted file mode 100644 index adf56a3684b..00000000000 --- a/crates/core_simd/src/vectors_mask128.rs +++ /dev/null @@ -1,11 +0,0 @@ -use crate::mask128; - -define_mask_vector! { - /// Vector of two `mask128` values - struct mask128x2([i128 as mask128; 2]); -} - -define_mask_vector! { - /// Vector of four `mask128` values - struct mask128x4([i128 as mask128; 4]); -} diff --git a/crates/core_simd/src/vectors_mask16.rs b/crates/core_simd/src/vectors_mask16.rs deleted file mode 100644 index 406d7255a11..00000000000 --- a/crates/core_simd/src/vectors_mask16.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::mask16; - -define_mask_vector! { - /// Vector of four `mask16` values - struct mask16x4([i16 as mask16; 4]); -} - -define_mask_vector! { - /// Vector of eight `mask16` values - struct mask16x8([i16 as mask16; 8]); -} - -define_mask_vector! { - /// Vector of 16 `mask16` values - struct mask16x16([i16 as mask16; 16]); -} - -define_mask_vector! { - /// Vector of 32 `mask16` values - struct mask16x32([i16 as mask16; 32]); -} diff --git a/crates/core_simd/src/vectors_mask32.rs b/crates/core_simd/src/vectors_mask32.rs deleted file mode 100644 index fad191421f3..00000000000 --- a/crates/core_simd/src/vectors_mask32.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::mask32; - -define_mask_vector! { - /// Vector of two `mask32` values - struct mask32x2([i32 as mask32; 2]); -} - -define_mask_vector! { - /// Vector of four `mask32` values - struct mask32x4([i32 as mask32; 4]); -} - -define_mask_vector! { - /// Vector of eight `mask32` values - struct mask32x8([i32 as mask32; 8]); -} - -define_mask_vector! { - /// Vector of 16 `mask32` values - struct mask32x16([i32 as mask32; 16]); -} diff --git a/crates/core_simd/src/vectors_mask64.rs b/crates/core_simd/src/vectors_mask64.rs deleted file mode 100644 index 554e731ccf2..00000000000 --- a/crates/core_simd/src/vectors_mask64.rs +++ /dev/null @@ -1,16 +0,0 @@ -use crate::mask64; - -define_mask_vector! { - /// Vector of two `mask64` values - struct mask64x2([i64 as mask64; 2]); -} - -define_mask_vector! { - /// Vector of four `mask64` values - struct mask64x4([i64 as mask64; 4]); -} - -define_mask_vector! { - /// Vector of eight `mask64` values - struct mask64x8([i64 as mask64; 8]); -} diff --git a/crates/core_simd/src/vectors_mask8.rs b/crates/core_simd/src/vectors_mask8.rs deleted file mode 100644 index d038b336104..00000000000 --- a/crates/core_simd/src/vectors_mask8.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::mask8; - -define_mask_vector! { - /// Vector of eight `mask8` values - struct mask8x8([i8 as mask8; 8]); -} - -define_mask_vector! { - /// Vector of 16 `mask8` values - struct mask8x16([i8 as mask8; 16]); -} - -define_mask_vector! { - /// Vector of 32 `mask8` values - struct mask8x32([i8 as mask8; 32]); -} - -define_mask_vector! { - /// Vector of 64 `mask8` values - struct mask8x64([i8 as mask8; 64]); -} diff --git a/crates/core_simd/src/vectors_masksize.rs b/crates/core_simd/src/vectors_masksize.rs deleted file mode 100644 index a838aee5198..00000000000 --- a/crates/core_simd/src/vectors_masksize.rs +++ /dev/null @@ -1,16 +0,0 @@ -use crate::masksize; - -define_mask_vector! { - /// Vector of two `masksize` values - struct masksizex2([isize as masksize; 2]); -} - -define_mask_vector! { - /// Vector of four `masksize` values - struct masksizex4([isize as masksize; 4]); -} - -define_mask_vector! { - /// Vector of eight `masksize` values - struct masksizex8([isize as masksize; 8]); -} From 5bc5d7f0d12bc8d6e0175177e14b38e8c7c3d240 Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Wed, 28 Oct 2020 16:27:15 -0400 Subject: [PATCH 02/13] Add comparison ops --- crates/core_simd/src/intrinsics.rs | 7 + crates/core_simd/src/lib.rs | 1 + crates/core_simd/src/macros.rs | 18 ++ crates/core_simd/src/masks/mod.rs | 263 ++++++++++++++++++++--------- crates/core_simd/src/masks/ops.rs | 208 +++++++++++++++++++++++ 5 files changed, 414 insertions(+), 83 deletions(-) create mode 100644 crates/core_simd/src/masks/ops.rs diff --git a/crates/core_simd/src/intrinsics.rs b/crates/core_simd/src/intrinsics.rs index b2edc3747ef..3dfc77136f2 100644 --- a/crates/core_simd/src/intrinsics.rs +++ b/crates/core_simd/src/intrinsics.rs @@ -45,4 +45,11 @@ extern "platform-intrinsic" { // ceil pub(crate) fn simd_ceil(x: T) -> T; + + pub(crate) fn simd_eq(x: T, y: T) -> U; + pub(crate) fn simd_ne(x: T, y: T) -> U; + pub(crate) fn simd_lt(x: T, y: T) -> U; + pub(crate) fn simd_le(x: T, y: T) -> U; + pub(crate) fn simd_gt(x: T, y: T) -> U; + pub(crate) fn simd_ge(x: T, y: T) -> U; } diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs index fd4f9dd16fd..3c581ad659b 100644 --- a/crates/core_simd/src/lib.rs +++ b/crates/core_simd/src/lib.rs @@ -11,6 +11,7 @@ mod intrinsics; mod ops; pub mod masks; +pub use masks::opaque::*; mod vectors_u8; pub use vectors_u8::*; diff --git a/crates/core_simd/src/macros.rs b/crates/core_simd/src/macros.rs index b8324ffdb92..75584f58b78 100644 --- a/crates/core_simd/src/macros.rs +++ b/crates/core_simd/src/macros.rs @@ -336,6 +336,24 @@ macro_rules! define_mask_vector { call_repeat! { $lanes => define_mask_vector [$impl_type] splat $type | } call_counting_args! { $lanes => define_mask_vector => new $type | } call_counting_args! { $lanes => define_mask_vector => new_from_bool $type | } + + /// Tests the value of the specified lane. + /// + /// # Panics + /// Panics if `lane` is greater than or equal to the number of lanes in the vector. + #[inline] + pub fn test(&self, lane: usize) -> bool { + self[lane].test() + } + + /// Sets the value of the specified lane. + /// + /// # Panics + /// Panics if `lane` is greater than or equal to the number of lanes in the vector. + #[inline] + pub fn set(&mut self, lane: usize, value: bool) { + self[lane] = value.into(); + } } base_vector_traits! { $name => [$type; $lanes] } diff --git a/crates/core_simd/src/masks/mod.rs b/crates/core_simd/src/masks/mod.rs index e138a1b4dd8..6688db290e2 100644 --- a/crates/core_simd/src/masks/mod.rs +++ b/crates/core_simd/src/masks/mod.rs @@ -2,7 +2,10 @@ pub mod wide; -trait MaskImpl { +mod ops; +pub use ops::*; + +pub(crate) trait MaskImpl { type Mask; } @@ -93,15 +96,67 @@ macro_rules! define_opaque_mask { } => { $(#[$attr])* #[allow(non_camel_case_types)] - pub struct $name(<[$width; $lanes] as MaskImpl>::Mask); + pub struct $name(<[$width; $lanes] as crate::masks::MaskImpl>::Mask); impl $name { + pub(crate) fn new_from_inner(inner: <[$width; $lanes] as crate::masks::MaskImpl>::Mask) -> Self { + Self(inner) + } + /// Construct a mask by setting all lanes to the given value. pub fn splat(value: bool) -> Self { - Self(<[$width; $lanes] as MaskImpl>::Mask::splat(value.into())) + Self(<[$width; $lanes] as crate::masks::MaskImpl>::Mask::splat(value.into())) } call_counting_args! { $lanes => define_opaque_mask => new [$width; $lanes] } + + /// Tests the value of the specified lane. + /// + /// # Panics + /// Panics if `lane` is greater than or equal to the number of lanes in the vector. + #[inline] + pub fn test(&self, lane: usize) -> bool { + self.0.test(lane) + } + + /// Sets the value of the specified lane. + /// + /// # Panics + /// Panics if `lane` is greater than or equal to the number of lanes in the vector. + #[inline] + pub fn set(&mut self, lane: usize, value: bool) { + self.0.set(lane, value); + } + } + + impl Copy for $name {} + + impl Clone for $name { + #[inline] + fn clone(&self) -> Self { + *self + } + } + + impl Default for $name { + #[inline] + fn default() -> Self { + Self::splat(false) + } + } + + impl PartialEq for $name { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } + } + + impl PartialOrd for $name { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + self.0.partial_cmp(&other.0) + } } }; { new [$width:ty; $lanes:tt] $($var:ident)* } => { @@ -109,107 +164,149 @@ macro_rules! define_opaque_mask { #[allow(clippy::too_many_arguments)] #[inline] pub const fn new($($var: bool),*) -> Self { - Self(<[$width; $lanes] as MaskImpl>::Mask::new_from_bool($($var),*)) + Self(<[$width; $lanes] as crate::masks::MaskImpl>::Mask::new_from_bool($($var),*)) } } } -define_opaque_mask! { - /// Mask for 8 8-bit lanes - struct mask8x8([u8; 8]); -} +pub(crate) mod opaque { + define_opaque_mask! { + /// Mask for 8 8-bit lanes. + /// + /// The layout of this type is unspecified. + struct mask8x8([u8; 8]); + } -define_opaque_mask! { - /// Mask for 16 8-bit lanes - struct mask8x16([u8; 16]); -} + define_opaque_mask! { + /// Mask for 16 8-bit lanes. + /// + /// The layout of this type is unspecified. + struct mask8x16([u8; 16]); + } -define_opaque_mask! { - /// Mask for 32 8-bit lanes - struct mask8x32([u8; 32]); -} + define_opaque_mask! { + /// Mask for 32 8-bit lanes. + /// + /// The layout of this type is unspecified. + struct mask8x32([u8; 32]); + } -define_opaque_mask! { - /// Mask for 64 8-bit lanes - struct mask8x64([u8; 64]); -} + define_opaque_mask! { + /// Mask for 64 8-bit lanes. + /// + /// The layout of this type is unspecified. + struct mask8x64([u8; 64]); + } -define_opaque_mask! { - /// Mask for 4 16-bit lanes - struct mask16x4([u16; 4]); -} + define_opaque_mask! { + /// Mask for 4 16-bit lanes. + /// + /// The layout of this type is unspecified. + struct mask16x4([u16; 4]); + } -define_opaque_mask! { - /// Mask for 8 16-bit lanes - struct mask16x8([u16; 8]); -} + define_opaque_mask! { + /// Mask for 8 16-bit lanes. + /// + /// The layout of this type is unspecified. + struct mask16x8([u16; 8]); + } -define_opaque_mask! { - /// Mask for 16 16-bit lanes - struct mask16x16([u16; 16]); -} + define_opaque_mask! { + /// Mask for 16 16-bit lanes. + /// + /// The layout of this type is unspecified. + struct mask16x16([u16; 16]); + } -define_opaque_mask! { - /// Mask for 32 16-bit lanes - struct mask16x32([u16; 32]); -} + define_opaque_mask! { + /// Mask for 32 16-bit lanes. + /// + /// The layout of this type is unspecified. + struct mask16x32([u16; 32]); + } -define_opaque_mask! { - /// Mask for 2 32-bit lanes - struct mask32x2([u32; 2]); -} + define_opaque_mask! { + /// Mask for 2 32-bit lanes. + /// + /// The layout of this type is unspecified. + struct mask32x2([u32; 2]); + } -define_opaque_mask! { - /// Mask for 4 32-bit lanes - struct mask32x4([u32; 4]); -} + define_opaque_mask! { + /// Mask for 4 32-bit lanes. + /// + /// The layout of this type is unspecified. + struct mask32x4([u32; 4]); + } -define_opaque_mask! { - /// Mask for 8 32-bit lanes - struct mask32x8([u32; 8]); -} + define_opaque_mask! { + /// Mask for 8 32-bit lanes. + /// + /// The layout of this type is unspecified. + struct mask32x8([u32; 8]); + } -define_opaque_mask! { - /// Mask for 16 32-bit lanes - struct mask32x16([u32; 16]); -} + define_opaque_mask! { + /// Mask for 16 32-bit lanes. + /// + /// The layout of this type is unspecified. + struct mask32x16([u32; 16]); + } -define_opaque_mask! { - /// Mask for 2 64-bit lanes - struct mask64x2([u64; 2]); -} + define_opaque_mask! { + /// Mask for 2 64-bit lanes. + /// + /// The layout of this type is unspecified. + struct mask64x2([u64; 2]); + } -define_opaque_mask! { - /// Mask for 4 64-bit lanes - struct mask64x4([u64; 4]); -} + define_opaque_mask! { + /// Mask for 4 64-bit lanes. + /// + /// The layout of this type is unspecified. + struct mask64x4([u64; 4]); + } -define_opaque_mask! { - /// Mask for 8 64-bit lanes - struct mask64x8([u64; 8]); -} + define_opaque_mask! { + /// Mask for 8 64-bit lanes. + /// + /// The layout of this type is unspecified. + struct mask64x8([u64; 8]); + } -define_opaque_mask! { - /// Mask for 2 128-bit lanes - struct mask128x2([u128; 2]); -} + define_opaque_mask! { + /// Mask for 2 128-bit lanes. + /// + /// The layout of this type is unspecified. + struct mask128x2([u128; 2]); + } -define_opaque_mask! { - /// Mask for 4 128-bit lanes - struct mask128x4([u128; 4]); -} + define_opaque_mask! { + /// Mask for 4 128-bit lanes. + /// + /// The layout of this type is unspecified. + struct mask128x4([u128; 4]); + } -define_opaque_mask! { - /// Mask for 2 `isize`-wide lanes - struct masksizex2([usize; 2]); -} + define_opaque_mask! { + /// Mask for 2 `isize`-wide lanes. + /// + /// The layout of this type is unspecified. + struct masksizex2([usize; 2]); + } -define_opaque_mask! { - /// Mask for 4 `isize`-wide lanes - struct masksizex4([usize; 4]); -} + define_opaque_mask! { + /// Mask for 4 `isize`-wide lanes. + /// + /// The layout of this type is unspecified. + struct masksizex4([usize; 4]); + } -define_opaque_mask! { - /// Mask for 8 `isize`-wide lanes - struct masksizex8([usize; 8]); + define_opaque_mask! { + /// Mask for 8 `isize`-wide lanes. + /// + /// The layout of this type is unspecified. + struct masksizex8([usize; 8]); + } } diff --git a/crates/core_simd/src/masks/ops.rs b/crates/core_simd/src/masks/ops.rs new file mode 100644 index 00000000000..85ce955459a --- /dev/null +++ b/crates/core_simd/src/masks/ops.rs @@ -0,0 +1,208 @@ +/// Mask-related operations using a particular mask layout. +pub trait MaskExt { + /// Test if each lane is equal to the corresponding lane in `other`. + fn lanes_eq(self, other: Self) -> Mask; + + /// Test if each lane is not equal to the corresponding lane in `other`. + fn lanes_ne(self, other: Self) -> Mask; + + /// Test if each lane is less than the corresponding lane in `other`. + fn lanes_lt(self, other: Self) -> Mask; + + /// Test if each lane is greater than the corresponding lane in `other`. + fn lanes_gt(self, other: Self) -> Mask; + + /// Test if each lane is less than or equal to the corresponding lane in `other`. + fn lanes_le(self, other: Self) -> Mask; + + /// Test if each lane is greater than or equal to the corresponding lane in `other`. + fn lanes_ge(self, other: Self) -> Mask; +} + +macro_rules! implement_mask_ext { + { $($vector:ty => $($mask:ty),*;)* } => { + $( // vector + $( // mask + impl MaskExt<$mask> for $vector { + #[inline] + fn lanes_eq(self, other: Self) -> $mask { + unsafe { crate::intrinsics::simd_eq(self, other) } + } + + #[inline] + fn lanes_ne(self, other: Self) -> $mask { + unsafe { crate::intrinsics::simd_ne(self, other) } + } + + #[inline] + fn lanes_lt(self, other: Self) -> $mask { + unsafe { crate::intrinsics::simd_lt(self, other) } + } + + #[inline] + fn lanes_gt(self, other: Self) -> $mask { + unsafe { crate::intrinsics::simd_gt(self, other) } + } + + #[inline] + fn lanes_le(self, other: Self) -> $mask { + unsafe { crate::intrinsics::simd_le(self, other) } + } + + #[inline] + fn lanes_ge(self, other: Self) -> $mask { + unsafe { crate::intrinsics::simd_ge(self, other) } + } + } + )* + )* + } +} + +implement_mask_ext! { + crate::u8x8 => crate::masks::wide::m8x8; + crate::u8x16 => crate::masks::wide::m8x16; + crate::u8x32 => crate::masks::wide::m8x32; + crate::u8x64 => crate::masks::wide::m8x64; + crate::u16x4 => crate::masks::wide::m16x4; + crate::u16x8 => crate::masks::wide::m16x8; + crate::u16x16 => crate::masks::wide::m16x16; + crate::u16x32 => crate::masks::wide::m16x32; + crate::u32x2 => crate::masks::wide::m32x2; + crate::u32x4 => crate::masks::wide::m32x4; + crate::u32x8 => crate::masks::wide::m32x8; + crate::u32x16 => crate::masks::wide::m32x16; + crate::u64x2 => crate::masks::wide::m64x2; + crate::u64x4 => crate::masks::wide::m64x4; + crate::u64x8 => crate::masks::wide::m64x8; + crate::u128x2 => crate::masks::wide::m128x2; + crate::u128x4 => crate::masks::wide::m128x4; + crate::usizex2 => crate::masks::wide::msizex2; + crate::usizex4 => crate::masks::wide::msizex4; + crate::usizex8 => crate::masks::wide::msizex8; + + crate::i8x8 => crate::masks::wide::m8x8; + crate::i8x16 => crate::masks::wide::m8x16; + crate::i8x32 => crate::masks::wide::m8x32; + crate::i8x64 => crate::masks::wide::m8x64; + crate::i16x4 => crate::masks::wide::m16x4; + crate::i16x8 => crate::masks::wide::m16x8; + crate::i16x16 => crate::masks::wide::m16x16; + crate::i16x32 => crate::masks::wide::m16x32; + crate::i32x2 => crate::masks::wide::m32x2; + crate::i32x4 => crate::masks::wide::m32x4; + crate::i32x8 => crate::masks::wide::m32x8; + crate::i32x16 => crate::masks::wide::m32x16; + crate::i64x2 => crate::masks::wide::m64x2; + crate::i64x4 => crate::masks::wide::m64x4; + crate::i64x8 => crate::masks::wide::m64x8; + crate::i128x2 => crate::masks::wide::m128x2; + crate::i128x4 => crate::masks::wide::m128x4; + crate::isizex2 => crate::masks::wide::msizex2; + crate::isizex4 => crate::masks::wide::msizex4; + crate::isizex8 => crate::masks::wide::msizex8; + + crate::f32x2 => crate::masks::wide::m32x2; + crate::f32x4 => crate::masks::wide::m32x4; + crate::f32x8 => crate::masks::wide::m32x8; + crate::f32x16 => crate::masks::wide::m32x16; + crate::f64x2 => crate::masks::wide::m64x2; + crate::f64x4 => crate::masks::wide::m64x4; + crate::f64x8 => crate::masks::wide::m64x8; +} + +macro_rules! implement_mask_ops { + { $($vector:ty => $mask:ty,)* } => { + $( // vector + impl $vector { + /// Test if each lane is equal to the corresponding lane in `other`. + #[inline] + pub fn lanes_eq(self, other: Self) -> $mask { + <$mask>::new_from_inner(MaskExt::lanes_eq(self, other)) + } + + /// Test if each lane is not equal to the corresponding lane in `other`. + #[inline] + pub fn lanes_ne(self, other: Self) -> $mask { + <$mask>::new_from_inner(MaskExt::lanes_ne(self, other)) + } + + /// Test if each lane is less than the corresponding lane in `other`. + #[inline] + pub fn lanes_lt(self, other: Self) -> $mask { + <$mask>::new_from_inner(MaskExt::lanes_lt(self, other)) + } + + /// Test if each lane is greater than the corresponding lane in `other`. + #[inline] + pub fn lanes_gt(self, other: Self) -> $mask { + <$mask>::new_from_inner(MaskExt::lanes_gt(self, other)) + } + + /// Test if each lane is less than or equal to the corresponding lane in `other`. + #[inline] + pub fn lanes_le(self, other: Self) -> $mask { + <$mask>::new_from_inner(MaskExt::lanes_le(self, other)) + } + + /// Test if each lane is greater than or equal to the corresponding lane in `other`. + #[inline] + pub fn lanes_ge(self, other: Self) -> $mask { + <$mask>::new_from_inner(MaskExt::lanes_ge(self, other)) + } + } + )* + } +} + +implement_mask_ops! { + crate::u8x8 => crate::mask8x8, + crate::u8x16 => crate::mask8x16, + crate::u8x32 => crate::mask8x32, + crate::u8x64 => crate::mask8x64, + crate::u16x4 => crate::mask16x4, + crate::u16x8 => crate::mask16x8, + crate::u16x16 => crate::mask16x16, + crate::u16x32 => crate::mask16x32, + crate::u32x2 => crate::mask32x2, + crate::u32x4 => crate::mask32x4, + crate::u32x8 => crate::mask32x8, + crate::u32x16 => crate::mask32x16, + crate::u64x2 => crate::mask64x2, + crate::u64x4 => crate::mask64x4, + crate::u64x8 => crate::mask64x8, + crate::u128x2 => crate::mask128x2, + crate::u128x4 => crate::mask128x4, + crate::usizex2 => crate::masksizex2, + crate::usizex4 => crate::masksizex4, + crate::usizex8 => crate::masksizex8, + + crate::i8x8 => crate::mask8x8, + crate::i8x16 => crate::mask8x16, + crate::i8x32 => crate::mask8x32, + crate::i8x64 => crate::mask8x64, + crate::i16x4 => crate::mask16x4, + crate::i16x8 => crate::mask16x8, + crate::i16x16 => crate::mask16x16, + crate::i16x32 => crate::mask16x32, + crate::i32x2 => crate::mask32x2, + crate::i32x4 => crate::mask32x4, + crate::i32x8 => crate::mask32x8, + crate::i32x16 => crate::mask32x16, + crate::i64x2 => crate::mask64x2, + crate::i64x4 => crate::mask64x4, + crate::i64x8 => crate::mask64x8, + crate::i128x2 => crate::mask128x2, + crate::i128x4 => crate::mask128x4, + crate::isizex2 => crate::masksizex2, + crate::isizex4 => crate::masksizex4, + crate::isizex8 => crate::masksizex8, + + crate::f32x2 => crate::mask32x2, + crate::f32x4 => crate::mask32x4, + crate::f32x8 => crate::mask32x8, + crate::f32x16 => crate::mask32x16, + crate::f64x2 => crate::mask64x2, + crate::f64x4 => crate::mask64x4, + crate::f64x8 => crate::mask64x8, +} From 78a8d615b51195c9154f95afdd5f870857ae512b Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Sun, 22 Nov 2020 15:18:31 -0500 Subject: [PATCH 03/13] Implement missing traits on opaque masks, fix tests --- crates/core_simd/src/masks/mod.rs | 130 ++++++++++++++++++ crates/core_simd/tests/helpers/biteq.rs | 19 ++- crates/core_simd/tests/ops_impl/mask128.rs | 6 +- crates/core_simd/tests/ops_impl/mask16.rs | 10 +- crates/core_simd/tests/ops_impl/mask32.rs | 10 +- crates/core_simd/tests/ops_impl/mask64.rs | 8 +- crates/core_simd/tests/ops_impl/mask8.rs | 10 +- .../core_simd/tests/ops_impl/mask_macros.rs | 118 +++++++++------- crates/core_simd/tests/ops_impl/masksize.rs | 8 +- 9 files changed, 233 insertions(+), 86 deletions(-) diff --git a/crates/core_simd/src/masks/mod.rs b/crates/core_simd/src/masks/mod.rs index 6688db290e2..676a5560d2f 100644 --- a/crates/core_simd/src/masks/mod.rs +++ b/crates/core_simd/src/masks/mod.rs @@ -158,6 +158,136 @@ macro_rules! define_opaque_mask { self.0.partial_cmp(&other.0) } } + + impl core::fmt::Debug for $name { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + f.debug_list() + .entries((0..$lanes).map(|i| self.test(i))) + .finish() + } + } + + impl core::ops::BitAnd for $name { + type Output = Self; + #[inline] + fn bitand(self, rhs: Self) -> Self { + Self(self.0 & rhs.0) + } + } + + impl core::ops::BitAnd for $name { + type Output = Self; + #[inline] + fn bitand(self, rhs: bool) -> Self { + self & Self::splat(rhs) + } + } + + impl core::ops::BitAnd<$name> for bool { + type Output = $name; + #[inline] + fn bitand(self, rhs: $name) -> $name { + $name::splat(self) & rhs + } + } + + impl core::ops::BitOr for $name { + type Output = Self; + #[inline] + fn bitor(self, rhs: Self) -> Self { + Self(self.0 | rhs.0) + } + } + + impl core::ops::BitOr for $name { + type Output = Self; + #[inline] + fn bitor(self, rhs: bool) -> Self { + self | Self::splat(rhs) + } + } + + impl core::ops::BitOr<$name> for bool { + type Output = $name; + #[inline] + fn bitor(self, rhs: $name) -> $name { + $name::splat(self) | rhs + } + } + + impl core::ops::BitXor for $name { + type Output = Self; + #[inline] + fn bitxor(self, rhs: Self) -> Self::Output { + Self(self.0 ^ rhs.0) + } + } + + impl core::ops::BitXor for $name { + type Output = Self; + #[inline] + fn bitxor(self, rhs: bool) -> Self::Output { + self ^ Self::splat(rhs) + } + } + + impl core::ops::BitXor<$name> for bool { + type Output = $name; + #[inline] + fn bitxor(self, rhs: $name) -> Self::Output { + $name::splat(self) ^ rhs + } + } + + impl core::ops::Not for $name { + type Output = $name; + #[inline] + fn not(self) -> Self::Output { + Self(!self.0) + } + } + + impl core::ops::BitAndAssign for $name { + #[inline] + fn bitand_assign(&mut self, rhs: Self) { + self.0 &= rhs.0; + } + } + + impl core::ops::BitAndAssign for $name { + #[inline] + fn bitand_assign(&mut self, rhs: bool) { + *self &= Self::splat(rhs); + } + } + + impl core::ops::BitOrAssign for $name { + #[inline] + fn bitor_assign(&mut self, rhs: Self) { + self.0 |= rhs.0; + } + } + + impl core::ops::BitOrAssign for $name { + #[inline] + fn bitor_assign(&mut self, rhs: bool) { + *self |= Self::splat(rhs); + } + } + + impl core::ops::BitXorAssign for $name { + #[inline] + fn bitxor_assign(&mut self, rhs: Self) { + self.0 ^= rhs.0; + } + } + + impl core::ops::BitXorAssign for $name { + #[inline] + fn bitxor_assign(&mut self, rhs: bool) { + *self ^= Self::splat(rhs); + } + } }; { new [$width:ty; $lanes:tt] $($var:ident)* } => { /// Construct a vector by setting each lane to the given values. diff --git a/crates/core_simd/tests/helpers/biteq.rs b/crates/core_simd/tests/helpers/biteq.rs index f932eba907c..00fc31f3d05 100644 --- a/crates/core_simd/tests/helpers/biteq.rs +++ b/crates/core_simd/tests/helpers/biteq.rs @@ -70,7 +70,12 @@ impl_biteq! { integer impl BitEq for u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, - core_simd::mask8, core_simd::mask16, core_simd::mask32, core_simd::mask64, core_simd::mask128, core_simd::masksize, + core_simd::masks::wide::m8, + core_simd::masks::wide::m16, + core_simd::masks::wide::m32, + core_simd::masks::wide::m64, + core_simd::masks::wide::m128, + core_simd::masks::wide::msize, } impl_biteq! { @@ -93,12 +98,12 @@ impl_biteq! { core_simd::isizex2, core_simd::isizex4, core_simd::isizex8, core_simd::f32x2, core_simd::f32x4, core_simd::f32x8, core_simd::f32x16, core_simd::f64x2, core_simd::f64x4, core_simd::f64x8, - core_simd::mask8x8, core_simd::mask8x16, core_simd::mask8x32, core_simd::mask8x64, - core_simd::mask16x4, core_simd::mask16x8, core_simd::mask16x16, core_simd::mask16x32, - core_simd::mask32x2, core_simd::mask32x4, core_simd::mask32x8, core_simd::mask32x16, - core_simd::mask64x2, core_simd::mask64x4, core_simd::mask64x8, - core_simd::mask128x2, core_simd::mask128x4, - core_simd::masksizex2, core_simd::masksizex4, core_simd::masksizex8, + core_simd::masks::wide::m8x8, core_simd::masks::wide::m8x16, core_simd::masks::wide::m8x32, core_simd::masks::wide::m8x64, + core_simd::masks::wide::m16x4, core_simd::masks::wide::m16x8, core_simd::masks::wide::m16x16, core_simd::masks::wide::m16x32, + core_simd::masks::wide::m32x2, core_simd::masks::wide::m32x4, core_simd::masks::wide::m32x8, core_simd::masks::wide::m32x16, + core_simd::masks::wide::m64x2, core_simd::masks::wide::m64x4, core_simd::masks::wide::m64x8, + core_simd::masks::wide::m128x2, core_simd::masks::wide::m128x4, + core_simd::masks::wide::msizex2, core_simd::masks::wide::msizex4, core_simd::masks::wide::msizex8, } pub(crate) struct BitEqWrapper<'a, T>(pub(crate) &'a T); diff --git a/crates/core_simd/tests/ops_impl/mask128.rs b/crates/core_simd/tests/ops_impl/mask128.rs index f0bcdb4d4df..27ba4e2d29f 100644 --- a/crates/core_simd/tests/ops_impl/mask128.rs +++ b/crates/core_simd/tests/ops_impl/mask128.rs @@ -1,4 +1,2 @@ -use super::helpers; - -mask_tests! { mask128x2, mask128 } -mask_tests! { mask128x4, mask128 } +mask_tests! { mask128x2, 2 } +mask_tests! { mask128x4, 4 } diff --git a/crates/core_simd/tests/ops_impl/mask16.rs b/crates/core_simd/tests/ops_impl/mask16.rs index 6f3f8e0ee02..0fe82fa6804 100644 --- a/crates/core_simd/tests/ops_impl/mask16.rs +++ b/crates/core_simd/tests/ops_impl/mask16.rs @@ -1,6 +1,4 @@ -use super::helpers; - -mask_tests! { mask16x4, mask16 } -mask_tests! { mask16x8, mask16 } -mask_tests! { mask16x16, mask16 } -mask_tests! { mask16x32, mask16 } +mask_tests! { mask16x4, 4 } +mask_tests! { mask16x8, 8 } +mask_tests! { mask16x16, 16 } +mask_tests! { mask16x32, 32 } diff --git a/crates/core_simd/tests/ops_impl/mask32.rs b/crates/core_simd/tests/ops_impl/mask32.rs index 5c35885a2f5..66d987a43ce 100644 --- a/crates/core_simd/tests/ops_impl/mask32.rs +++ b/crates/core_simd/tests/ops_impl/mask32.rs @@ -1,6 +1,4 @@ -use super::helpers; - -mask_tests! { mask32x2, mask32 } -mask_tests! { mask32x4, mask32 } -mask_tests! { mask32x8, mask32 } -mask_tests! { mask32x16, mask32 } +mask_tests! { mask32x2, 2 } +mask_tests! { mask32x4, 4 } +mask_tests! { mask32x8, 8 } +mask_tests! { mask32x16, 16 } diff --git a/crates/core_simd/tests/ops_impl/mask64.rs b/crates/core_simd/tests/ops_impl/mask64.rs index 88d3211465c..a1f1f67b238 100644 --- a/crates/core_simd/tests/ops_impl/mask64.rs +++ b/crates/core_simd/tests/ops_impl/mask64.rs @@ -1,5 +1,3 @@ -use super::helpers; - -mask_tests! { mask64x2, mask64 } -mask_tests! { mask64x4, mask64 } -mask_tests! { mask64x8, mask64 } +mask_tests! { mask64x2, 2 } +mask_tests! { mask64x4, 4 } +mask_tests! { mask64x8, 8 } diff --git a/crates/core_simd/tests/ops_impl/mask8.rs b/crates/core_simd/tests/ops_impl/mask8.rs index fa4bcf09f36..218fa9fe895 100644 --- a/crates/core_simd/tests/ops_impl/mask8.rs +++ b/crates/core_simd/tests/ops_impl/mask8.rs @@ -1,6 +1,4 @@ -use super::helpers; - -mask_tests! { mask8x8, mask8 } -mask_tests! { mask8x16, mask8 } -mask_tests! { mask8x32, mask8 } -mask_tests! { mask8x64, mask8 } +mask_tests! { mask8x8, 8 } +mask_tests! { mask8x16, 16 } +mask_tests! { mask8x32, 32 } +mask_tests! { mask8x64, 64 } diff --git a/crates/core_simd/tests/ops_impl/mask_macros.rs b/crates/core_simd/tests/ops_impl/mask_macros.rs index e6aee4c1d30..795f9e27c44 100644 --- a/crates/core_simd/tests/ops_impl/mask_macros.rs +++ b/crates/core_simd/tests/ops_impl/mask_macros.rs @@ -1,9 +1,9 @@ macro_rules! mask_tests { - { $vector:ident, $scalar:ident } => { + { $vector:ident, $lanes:literal } => { #[cfg(test)] mod $vector { - use super::*; - use helpers::lanewise::*; + use core_simd::$vector as Vector; + const LANES: usize = $lanes; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -11,15 +11,44 @@ macro_rules! mask_tests { #[cfg(target_arch = "wasm32")] wasm_bindgen_test_configure!(run_in_browser); - fn from_slice(slice: &[bool]) -> core_simd::$vector { - let mut value = core_simd::$vector::default(); - let value_slice: &mut [_] = value.as_mut(); - for (m, b) in value_slice.iter_mut().zip(slice.iter()) { - *m = (*b).into(); + fn from_slice(slice: &[bool]) -> Vector { + let mut value = Vector::default(); + for (i, b) in slice.iter().take(LANES).enumerate() { + value.set(i, *b); } value } + fn apply_unary_lanewise(x: Vector, f: impl Fn(bool) -> bool) -> Vector { + let mut value = Vector::default(); + for i in 0..LANES { + value.set(i, f(x.test(i))); + } + value + } + + fn apply_binary_lanewise(x: Vector, y: Vector, f: impl Fn(bool, bool) -> bool) -> Vector { + let mut value = Vector::default(); + for i in 0..LANES { + value.set(i, f(x.test(i), y.test(i))); + } + value + } + + fn apply_binary_scalar_lhs_lanewise(x: bool, mut y: Vector, f: impl Fn(bool, bool) -> bool) -> Vector { + for i in 0..LANES { + y.set(i, f(x, y.test(i))); + } + y + } + + fn apply_binary_scalar_rhs_lanewise(mut x: Vector, y: bool, f: impl Fn(bool, bool) -> bool) -> Vector { + for i in 0..LANES { + x.set(i, f(x.test(i), y)); + } + x + } + const A: [bool; 64] = [ false, true, false, true, false, false, true, true, false, true, false, true, false, false, true, true, @@ -41,18 +70,13 @@ macro_rules! mask_tests { false, false, true, true, false, true, false, true, ]; - const SET_SCALAR: core_simd::$scalar = core_simd::$scalar::new(true); - const UNSET_SCALAR: core_simd::$scalar = core_simd::$scalar::new(false); - const SET_VECTOR: core_simd::$vector = core_simd::$vector::splat(SET_SCALAR); - const UNSET_VECTOR: core_simd::$vector = core_simd::$vector::splat(UNSET_SCALAR); - #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn bitand() { let a = from_slice(&A); let b = from_slice(&B); let expected = apply_binary_lanewise(a, b, core::ops::BitAnd::bitand); - assert_biteq!(a & b, expected); + assert_eq!(a & b, expected); } #[test] @@ -62,7 +86,7 @@ macro_rules! mask_tests { let b = from_slice(&B); let expected = apply_binary_lanewise(a, b, core::ops::BitAnd::bitand); a &= b; - assert_biteq!(a, expected); + assert_eq!(a, expected); } #[test] @@ -70,8 +94,8 @@ macro_rules! mask_tests { fn bitand_scalar_rhs() { let a = from_slice(&A); let expected = a; - assert_biteq!(a & SET_SCALAR, expected); - assert_biteq!(a & UNSET_SCALAR, UNSET_VECTOR); + assert_eq!(a & true, expected); + assert_eq!(a & false, Vector::splat(false)); } #[test] @@ -79,8 +103,8 @@ macro_rules! mask_tests { fn bitand_scalar_lhs() { let a = from_slice(&A); let expected = a; - assert_biteq!(SET_SCALAR & a, expected); - assert_biteq!(UNSET_SCALAR & a, UNSET_VECTOR); + assert_eq!(true & a, expected); + assert_eq!(false & a, Vector::splat(false)); } #[test] @@ -88,10 +112,10 @@ macro_rules! mask_tests { fn bitand_assign_scalar() { let mut a = from_slice(&A); let expected = a; - a &= SET_SCALAR; - assert_biteq!(a, expected); - a &= UNSET_SCALAR; - assert_biteq!(a, UNSET_VECTOR); + a &= true; + assert_eq!(a, expected); + a &= false; + assert_eq!(a, Vector::splat(false)); } #[test] @@ -100,7 +124,7 @@ macro_rules! mask_tests { let a = from_slice(&A); let b = from_slice(&B); let expected = apply_binary_lanewise(a, b, core::ops::BitOr::bitor); - assert_biteq!(a | b, expected); + assert_eq!(a | b, expected); } #[test] @@ -110,23 +134,23 @@ macro_rules! mask_tests { let b = from_slice(&B); let expected = apply_binary_lanewise(a, b, core::ops::BitOr::bitor); a |= b; - assert_biteq!(a, expected); + assert_eq!(a, expected); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn bitor_scalar_rhs() { let a = from_slice(&A); - assert_biteq!(a | UNSET_SCALAR, a); - assert_biteq!(a | SET_SCALAR, SET_VECTOR); + assert_eq!(a | false, a); + assert_eq!(a | true, Vector::splat(true)); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn bitor_scalar_lhs() { let a = from_slice(&A); - assert_biteq!(UNSET_SCALAR | a, a); - assert_biteq!(SET_SCALAR | a, SET_VECTOR); + assert_eq!(false | a, a); + assert_eq!(true | a, Vector::splat(true)); } #[test] @@ -134,10 +158,10 @@ macro_rules! mask_tests { fn bitor_assign_scalar() { let mut a = from_slice(&A); let expected = a; - a |= UNSET_SCALAR; - assert_biteq!(a, expected); - a |= SET_SCALAR; - assert_biteq!(a, SET_VECTOR); + a |= false; + assert_eq!(a, expected); + a |= true; + assert_eq!(a, Vector::splat(true)); } #[test] @@ -146,7 +170,7 @@ macro_rules! mask_tests { let a = from_slice(&A); let b = from_slice(&B); let expected = apply_binary_lanewise(a, b, core::ops::BitXor::bitxor); - assert_biteq!(a ^ b, expected); + assert_eq!(a ^ b, expected); } #[test] @@ -156,25 +180,25 @@ macro_rules! mask_tests { let b = from_slice(&B); let expected = apply_binary_lanewise(a, b, core::ops::BitXor::bitxor); a ^= b; - assert_biteq!(a, expected); + assert_eq!(a, expected); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn bitxor_scalar_rhs() { let a = from_slice(&A); - let expected = apply_binary_scalar_rhs_lanewise(a, SET_SCALAR, core::ops::BitXor::bitxor); - assert_biteq!(a ^ UNSET_SCALAR, a); - assert_biteq!(a ^ SET_SCALAR, expected); + let expected = apply_binary_scalar_rhs_lanewise(a, true, core::ops::BitXor::bitxor); + assert_eq!(a ^ false, a); + assert_eq!(a ^ true, expected); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn bitxor_scalar_lhs() { let a = from_slice(&A); - let expected = apply_binary_scalar_lhs_lanewise(SET_SCALAR, a, core::ops::BitXor::bitxor); - assert_biteq!(UNSET_SCALAR ^ a, a); - assert_biteq!(SET_SCALAR ^ a, expected); + let expected = apply_binary_scalar_lhs_lanewise(true, a, core::ops::BitXor::bitxor); + assert_eq!(false ^ a, a); + assert_eq!(true ^ a, expected); } #[test] @@ -182,11 +206,11 @@ macro_rules! mask_tests { fn bitxor_assign_scalar() { let mut a = from_slice(&A); let expected_unset = a; - let expected_set = apply_binary_scalar_rhs_lanewise(a, SET_SCALAR, core::ops::BitXor::bitxor); - a ^= UNSET_SCALAR; - assert_biteq!(a, expected_unset); - a ^= SET_SCALAR; - assert_biteq!(a, expected_set); + let expected_set = apply_binary_scalar_rhs_lanewise(a, true, core::ops::BitXor::bitxor); + a ^= false; + assert_eq!(a, expected_unset); + a ^= true; + assert_eq!(a, expected_set); } #[test] @@ -194,7 +218,7 @@ macro_rules! mask_tests { fn not() { let v = from_slice(&A); let expected = apply_unary_lanewise(v, core::ops::Not::not); - assert_biteq!(!v, expected); + assert_eq!(!v, expected); } } } diff --git a/crates/core_simd/tests/ops_impl/masksize.rs b/crates/core_simd/tests/ops_impl/masksize.rs index 76e333f3c15..e0a44d870ca 100644 --- a/crates/core_simd/tests/ops_impl/masksize.rs +++ b/crates/core_simd/tests/ops_impl/masksize.rs @@ -1,5 +1,3 @@ -use super::helpers; - -mask_tests! { masksizex2, masksize } -mask_tests! { masksizex4, masksize } -mask_tests! { masksizex8, masksize } +mask_tests! { masksizex2, 2 } +mask_tests! { masksizex4, 4 } +mask_tests! { masksizex8, 8 } From 35b9ab9f5cf446712ea74ce8603267f9338c4440 Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Fri, 27 Nov 2020 00:23:49 -0500 Subject: [PATCH 04/13] Simplify some formatting --- crates/core_simd/src/masks/mod.rs | 4 +--- crates/core_simd/src/masks/wide/mod.rs | 8 ++++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/crates/core_simd/src/masks/mod.rs b/crates/core_simd/src/masks/mod.rs index 676a5560d2f..9fb3da00604 100644 --- a/crates/core_simd/src/masks/mod.rs +++ b/crates/core_simd/src/masks/mod.rs @@ -161,9 +161,7 @@ macro_rules! define_opaque_mask { impl core::fmt::Debug for $name { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - f.debug_list() - .entries((0..$lanes).map(|i| self.test(i))) - .finish() + core::fmt::Debug::fmt(&self.0, f) } } diff --git a/crates/core_simd/src/masks/wide/mod.rs b/crates/core_simd/src/masks/wide/mod.rs index 1462992197d..7df8ca7e53d 100644 --- a/crates/core_simd/src/masks/wide/mod.rs +++ b/crates/core_simd/src/masks/wide/mod.rs @@ -84,25 +84,25 @@ macro_rules! define_mask { impl core::fmt::Binary for $name { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - <$type as core::fmt::Binary>::fmt(&self.0, f) + core::fmt::Binary::fmt(&self.0, f) } } impl core::fmt::Octal for $name { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - <$type as core::fmt::Octal>::fmt(&self.0, f) + core::fmt::Octal::fmt(&self.0, f) } } impl core::fmt::LowerHex for $name { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - <$type as core::fmt::LowerHex>::fmt(&self.0, f) + core::fmt::LowerHex::fmt(&self.0, f) } } impl core::fmt::UpperHex for $name { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - <$type as core::fmt::UpperHex>::fmt(&self.0, f) + core::fmt::UpperHex::fmt(&self.0, f) } } } From 27e944231c3ca26add3c1a801fbe1c6de79f51fd Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Sat, 5 Dec 2020 00:03:20 -0500 Subject: [PATCH 05/13] Begin changing vectors to const generics --- crates/core_simd/src/fmt.rs | 38 +--- crates/core_simd/src/lib.rs | 22 ++- crates/core_simd/src/macros.rs | 263 +++++++++----------------- crates/core_simd/src/vectors_f32.rs | 31 +-- crates/core_simd/src/vectors_f64.rs | 24 +-- crates/core_simd/src/vectors_i128.rs | 19 +- crates/core_simd/src/vectors_i16.rs | 25 +-- crates/core_simd/src/vectors_i32.rs | 25 +-- crates/core_simd/src/vectors_i64.rs | 21 +- crates/core_simd/src/vectors_i8.rs | 25 +-- crates/core_simd/src/vectors_isize.rs | 21 +- crates/core_simd/src/vectors_u128.rs | 19 +- crates/core_simd/src/vectors_u16.rs | 25 +-- crates/core_simd/src/vectors_u32.rs | 25 +-- crates/core_simd/src/vectors_u64.rs | 21 +- crates/core_simd/src/vectors_u8.rs | 25 +-- crates/core_simd/src/vectors_usize.rs | 21 +- 17 files changed, 243 insertions(+), 407 deletions(-) diff --git a/crates/core_simd/src/fmt.rs b/crates/core_simd/src/fmt.rs index 07332c1ccc8..16b8f3b95d9 100644 --- a/crates/core_simd/src/fmt.rs +++ b/crates/core_simd/src/fmt.rs @@ -30,10 +30,10 @@ debug_wrapper! { } macro_rules! impl_fmt_trait { - { $($type:ty => $(($trait:ident, $format:ident)),*;)* } => { + { $($type:ident => $(($trait:ident, $format:ident)),*;)* } => { $( // repeat type $( // repeat trait - impl core::fmt::$trait for $type { + impl core::fmt::$trait for crate::$type { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { $format(self.as_ref(), f) } @@ -41,7 +41,7 @@ macro_rules! impl_fmt_trait { )* )* }; - { integers: $($type:ty,)* } => { + { integers: $($type:ident,)* } => { impl_fmt_trait! { $($type => (Debug, format), @@ -54,7 +54,7 @@ macro_rules! impl_fmt_trait { )* } }; - { floats: $($type:ty,)* } => { + { floats: $($type:ident,)* } => { impl_fmt_trait! { $($type => (Debug, format), @@ -63,7 +63,7 @@ macro_rules! impl_fmt_trait { )* } }; - { masks: $($type:ty,)* } => { + { masks: $($type:ident,)* } => { impl_fmt_trait! { $($type => (Debug, format); @@ -74,32 +74,12 @@ macro_rules! impl_fmt_trait { impl_fmt_trait! { integers: - crate::u8x8, crate::u8x16, crate::u8x32, crate::u8x64, - crate::i8x8, crate::i8x16, crate::i8x32, crate::i8x64, - crate::u16x4, crate::u16x8, crate::u16x16, crate::u16x32, - crate::i16x4, crate::i16x8, crate::i16x16, crate::i16x32, - crate::u32x2, crate::u32x4, crate::u32x8, crate::u32x16, - crate::i32x2, crate::i32x4, crate::i32x8, crate::i32x16, - crate::u64x2, crate::u64x4, crate::u64x8, - crate::i64x2, crate::i64x4, crate::i64x8, - crate::u128x2, crate::u128x4, - crate::i128x2, crate::i128x4, - crate::usizex2, crate::usizex4, crate::usizex8, - crate::isizex2, crate::isizex4, crate::isizex8, + SimdU8, SimdU16, SimdU32, SimdU64, SimdU128, + SimdI8, SimdI16, SimdI32, SimdI64, SimdI128, + SimdUsize, SimdIsize, } impl_fmt_trait! { floats: - crate::f32x2, crate::f32x4, crate::f32x8, crate::f32x16, - crate::f64x2, crate::f64x4, crate::f64x8, -} - -impl_fmt_trait! { - masks: - crate::masks::wide::m8x8, crate::masks::wide::m8x16, crate::masks::wide::m8x32, crate::masks::wide::m8x64, - crate::masks::wide::m16x4, crate::masks::wide::m16x8, crate::masks::wide::m16x16, crate::masks::wide::m16x32, - crate::masks::wide::m32x2, crate::masks::wide::m32x4, crate::masks::wide::m32x8, crate::masks::wide::m32x16, - crate::masks::wide::m64x2, crate::masks::wide::m64x4, crate::masks::wide::m64x8, - crate::masks::wide::m128x2, crate::masks::wide::m128x4, - crate::masks::wide::msizex2, crate::masks::wide::msizex4, crate::masks::wide::msizex8, + SimdF32, SimdF64, } diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs index 3c581ad659b..ba5e4db9312 100644 --- a/crates/core_simd/src/lib.rs +++ b/crates/core_simd/src/lib.rs @@ -1,5 +1,5 @@ #![no_std] -#![feature(repr_simd, platform_intrinsics, link_llvm_intrinsics, simd_ffi)] +#![feature(repr_simd, platform_intrinsics, link_llvm_intrinsics, simd_ffi, min_const_generics)] #![warn(missing_docs)] //! Portable SIMD module. @@ -8,10 +8,11 @@ mod macros; mod fmt; mod intrinsics; -mod ops; +//mod ops; +//mod round; -pub mod masks; -pub use masks::opaque::*; +//pub mod masks; +//pub use masks::opaque::*; mod vectors_u8; pub use vectors_u8::*; @@ -44,4 +45,15 @@ pub use vectors_f32::*; mod vectors_f64; pub use vectors_f64::*; -mod round; +//mod vectors_mask8; +//pub use vectors_mask8::*; +//mod vectors_mask16; +//pub use vectors_mask16::*; +//mod vectors_mask32; +//pub use vectors_mask32::*; +//mod vectors_mask64; +//pub use vectors_mask64::*; +//mod vectors_mask128; +//pub use vectors_mask128::*; +//mod vectors_masksize; +//pub use vectors_masksize::*; diff --git a/crates/core_simd/src/macros.rs b/crates/core_simd/src/macros.rs index 75584f58b78..abf165c78b2 100644 --- a/crates/core_simd/src/macros.rs +++ b/crates/core_simd/src/macros.rs @@ -136,73 +136,110 @@ macro_rules! call_counting_args { } /// Implements common traits on the specified vector `$name`, holding multiple `$lanes` of `$type`. -macro_rules! base_vector_traits { - { $name:path => [$type:ty; $lanes:literal] } => { - impl Copy for $name {} +macro_rules! impl_vector { + { $name:ident, $type:ty } => { + impl $name { + /// Construct a vector by setting all lanes to the given value. + pub const fn splat(value: $type) -> Self { + Self([value; LANES]) + } + + pub const fn as_slice(&self) -> &[$type] { + &self.0 + } + + pub fn as_mut_slice(&mut self) -> &mut [$type] { + &mut self.0 + } + + pub const fn as_ptr(&self) -> *const $type { + self.0.as_ptr() + } + + pub fn as_mut_ptr(&mut self) -> *mut $type { + self.0.as_mut_ptr() + } - impl Clone for $name { + pub const fn from_array(array: [$type; LANES]) -> Self { + Self(array) + } + + pub const fn to_array(self) -> [$type; LANES] { + self.0 + } + } + + impl Copy for $name {} + + impl Clone for $name { #[inline] fn clone(&self) -> Self { *self } } - impl Default for $name { + impl Default for $name { #[inline] fn default() -> Self { Self::splat(<$type>::default()) } } - impl PartialEq for $name { + impl PartialEq for $name { #[inline] fn eq(&self, other: &Self) -> bool { - AsRef::<[$type]>::as_ref(self) == AsRef::<[$type]>::as_ref(other) + // TODO use SIMD equality + self.to_array() == other.to_array() } } - impl PartialOrd for $name { + impl PartialOrd for $name { #[inline] fn partial_cmp(&self, other: &Self) -> Option { - AsRef::<[$type]>::as_ref(self).partial_cmp(AsRef::<[$type]>::as_ref(other)) + // TODO use SIMD equalitya + self.to_array().partial_cmp(other.as_ref()) } } // array references - impl AsRef<[$type; $lanes]> for $name { + impl AsRef<[$type; LANES]> for $name { #[inline] - fn as_ref(&self) -> &[$type; $lanes] { - unsafe { &*(self as *const _ as *const _) } + fn as_ref(&self) -> &[$type; LANES] { + &self.0 } } - impl AsMut<[$type; $lanes]> for $name { + impl AsMut<[$type; LANES]> for $name { #[inline] - fn as_mut(&mut self) -> &mut [$type; $lanes] { - unsafe { &mut *(self as *mut _ as *mut _) } + fn as_mut(&mut self) -> &mut [$type; LANES] { + &mut self.0 } } // slice references - impl AsRef<[$type]> for $name { + impl AsRef<[$type]> for $name { #[inline] fn as_ref(&self) -> &[$type] { - AsRef::<[$type; $lanes]>::as_ref(self) + &self.0 } } - impl AsMut<[$type]> for $name { + impl AsMut<[$type]> for $name { #[inline] fn as_mut(&mut self) -> &mut [$type] { - AsMut::<[$type; $lanes]>::as_mut(self) + &mut self.0 } } // vector/array conversion - from_transmute! { unsafe $name => [$type; $lanes] } + impl From<[$type; LANES]> for $name { + fn from(array: [$type; LANES]) -> Self { + Self(array) + } + } // splat - impl From<$type> for $name { + impl From<$type> for $name { #[inline] fn from(value: $type) -> Self { Self::splat(value) @@ -212,181 +249,59 @@ macro_rules! base_vector_traits { } /// Implements additional integer traits (Eq, Ord, Hash) on the specified vector `$name`, holding multiple `$lanes` of `$type`. -macro_rules! integer_vector_traits { - { $name:path => [$type:ty; $lanes:literal] } => { - impl Eq for $name {} +macro_rules! impl_integer_vector { + { $name:path, $type:ty } => { + impl_vector! { $name, $type } - impl Ord for $name { + impl Eq for $name {} + + impl Ord for $name { #[inline] fn cmp(&self, other: &Self) -> core::cmp::Ordering { - AsRef::<[$type]>::as_ref(self).cmp(AsRef::<[$type]>::as_ref(other)) + // TODO use SIMD cmp + self.to_array().cmp(other.as_ref()) } } - impl core::hash::Hash for $name { + impl core::hash::Hash for $name { #[inline] fn hash(&self, state: &mut H) where H: core::hash::Hasher { - AsRef::<[$type]>::as_ref(self).hash(state) + self.as_slice().hash(state) } } } } -/// Defines a vector `$name` containing multiple `$lanes` of `$type`. -macro_rules! define_vector { - { $(#[$attr:meta])* struct $name:ident([$type:ty; $lanes:tt]); } => { - call_repeat! { $lanes => define_vector [$type] def $(#[$attr])* | $name | } - - impl $name { - call_repeat! { $lanes => define_vector [$type] splat $type | } - call_counting_args! { $lanes => define_vector => new $type | } - } - - base_vector_traits! { $name => [$type; $lanes] } - }; - { def $(#[$attr:meta])* | $name:ident | $($itype:ty)* } => { - $(#[$attr])* - #[allow(non_camel_case_types)] - #[repr(simd)] - pub struct $name($($itype),*); - }; - { splat $type:ty | $($itype:ty)* } => { - /// Construct a vector by setting all lanes to the given value. - #[inline] - pub const fn splat(value: $type) -> Self { - Self($(value as $itype),*) - } - }; - { new $type:ty | $($var:ident)* } => { - /// Construct a vector by setting each lane to the given values. - #[allow(clippy::too_many_arguments)] - #[inline] - pub const fn new($($var: $type),*) -> Self { - Self($($var),*) - } - } -} - /// Implements inherent methods for a float vector `$name` containing multiple /// `$lanes` of float `$type`, which uses `$bits_ty` as its binary /// representation. Called from `define_float_vector!`. macro_rules! impl_float_vector { { $name:path => [$type:ty; $lanes:literal]; bits $bits_ty:ty; } => { impl $name { - /// Raw transmutation to an unsigned integer vector type with the - /// same size and number of lanes. - #[inline] - pub fn to_bits(self) -> $bits_ty { - unsafe { core::mem::transmute(self) } - } - - /// Raw transmutation from an unsigned integer vector type with the - /// same size and number of lanes. - #[inline] - pub fn from_bits(bits: $bits_ty) -> Self { - unsafe { core::mem::transmute(bits) } - } - - /// Produces a vector where every lane has the absolute value of the - /// equivalently-indexed lane in `self`. - #[inline] - pub fn abs(self) -> Self { - let no_sign = <$bits_ty>::splat(!0 >> 1); - Self::from_bits(self.to_bits() & no_sign) - } - } - }; -} - -/// Defines a float vector `$name` containing multiple `$lanes` of float -/// `$type`, which uses `$bits_ty` as its binary representation. -macro_rules! define_float_vector { - { $(#[$attr:meta])* struct $name:ident([$type:ty; $lanes:tt]); bits $bits_ty:ty; } => { - define_vector! { - $(#[$attr])* - struct $name([$type; $lanes]); - } - - impl_float_vector! { $name => [$type; $lanes]; bits $bits_ty; } - } -} - -/// Defines an integer vector `$name` containing multiple `$lanes` of integer `$type`. -macro_rules! define_integer_vector { - { $(#[$attr:meta])* struct $name:ident([$type:ty; $lanes:tt]); } => { - define_vector! { - $(#[$attr])* - struct $name([$type; $lanes]); - } - - integer_vector_traits! { $name => [$type; $lanes] } - } -} - -/// Defines a mask vector `$name` containing multiple `$lanes` of `$type`, represented by the -/// underlying type `$impl_type`. -macro_rules! define_mask_vector { - { $(#[$attr:meta])* struct $name:ident([$impl_type:ty as $type:ty; $lanes:tt]); } => { - call_repeat! { $lanes => define_mask_vector [$impl_type] def $(#[$attr])* | $name | } - - impl $name { - call_repeat! { $lanes => define_mask_vector [$impl_type] splat $type | } - call_counting_args! { $lanes => define_mask_vector => new $type | } - call_counting_args! { $lanes => define_mask_vector => new_from_bool $type | } - - /// Tests the value of the specified lane. - /// - /// # Panics - /// Panics if `lane` is greater than or equal to the number of lanes in the vector. - #[inline] - pub fn test(&self, lane: usize) -> bool { - self[lane].test() - } - - /// Sets the value of the specified lane. - /// - /// # Panics - /// Panics if `lane` is greater than or equal to the number of lanes in the vector. - #[inline] - pub fn set(&mut self, lane: usize, value: bool) { - self[lane] = value.into(); - } - } - - base_vector_traits! { $name => [$type; $lanes] } - integer_vector_traits! { $name => [$type; $lanes] } - }; - { def $(#[$attr:meta])* | $name:ident | $($itype:ty)* } => { - $(#[$attr])* - #[allow(non_camel_case_types)] - #[repr(simd)] - pub struct $name($($itype),*); - }; - { splat $type:ty | $($itype:ty)* } => { - /// Construct a vector by setting all lanes to the given value. - #[inline] - pub const fn splat(value: $type) -> Self { - Self($(value.0 as $itype),*) +// /// Raw transmutation to an unsigned integer vector type with the +// /// same size and number of lanes. +// #[inline] +// pub fn to_bits(self) -> $bits_ty { +// unsafe { core::mem::transmute(self) } +// } +// +// /// Raw transmutation from an unsigned integer vector type with the +// /// same size and number of lanes. +// #[inline] +// pub fn from_bits(bits: $bits_ty) -> Self { +// unsafe { core::mem::transmute(bits) } +// } +// +// /// Produces a vector where every lane has the absolute value of the +// /// equivalently-indexed lane in `self`. +// #[inline] +// pub fn abs(self) -> Self { +// let no_sign = <$bits_ty>::splat(!0 >> 1); +// Self::from_bits(self.to_bits() & no_sign) +// } } }; - { new $type:ty | $($var:ident)* } => { - /// Construct a vector by setting each lane to the given values. - #[allow(clippy::too_many_arguments)] - #[inline] - pub const fn new($($var: $type),*) -> Self { - Self($($var.0),*) - } - }; - { new_from_bool $type:ty | $($var:ident)* } => { - /// Used internally (since we can't use the Into trait in `const fn`s) - #[allow(clippy::too_many_arguments)] - #[allow(unused)] - #[inline] - pub(crate) const fn new_from_bool($($var: bool),*) -> Self { - Self($(<$type>::new($var).0),*) - } - } } diff --git a/crates/core_simd/src/vectors_f32.rs b/crates/core_simd/src/vectors_f32.rs index 17b382ee739..fbe89bb853b 100644 --- a/crates/core_simd/src/vectors_f32.rs +++ b/crates/core_simd/src/vectors_f32.rs @@ -1,29 +1,16 @@ -define_float_vector! { - /// Vector of two `f32` values - struct f32x2([f32; 2]); - bits crate::u32x2; -} +#![allow(non_camel_case_types)] -define_float_vector! { - /// Vector of four `f32` values - struct f32x4([f32; 4]); - bits crate::u32x4; -} +/// A SIMD vector of containing `LANES` lanes of `f32`. +#[repr(simd)] +pub struct SimdF32([f32; LANES]); -define_float_vector! { - /// Vector of eight `f32` values - struct f32x8([f32; 8]); - bits crate::u32x8; -} +impl_vector! { SimdF32, f32 } -define_float_vector! { - /// Vector of 16 `f32` values - struct f32x16([f32; 16]); - bits crate::u32x16; -} +pub type f32x2 = SimdF32<2>; +pub type f32x4 = SimdF32<4>; +pub type f32x8 = SimdF32<8>; +pub type f32x16 = SimdF32<16>; from_transmute_x86! { unsafe f32x4 => __m128 } from_transmute_x86! { unsafe f32x8 => __m256 } //from_transmute_x86! { unsafe f32x16 => __m512 } - - diff --git a/crates/core_simd/src/vectors_f64.rs b/crates/core_simd/src/vectors_f64.rs index b41923ca6f1..f588aa4b15d 100644 --- a/crates/core_simd/src/vectors_f64.rs +++ b/crates/core_simd/src/vectors_f64.rs @@ -1,20 +1,14 @@ -define_float_vector! { - /// Vector of two `f64` values - struct f64x2([f64; 2]); - bits crate::u64x2; -} +#![allow(non_camel_case_types)] -define_float_vector! { - /// Vector of four `f64` values - struct f64x4([f64; 4]); - bits crate::u64x4; -} +/// A SIMD vector of containing `LANES` lanes of `f64`. +#[repr(simd)] +pub struct SimdF64([f64; LANES]); -define_float_vector! { - /// Vector of eight `f64` values - struct f64x8([f64; 8]); - bits crate::u64x8; -} +impl_vector! { SimdF64, f64 } + +pub type f64x2 = SimdF64<2>; +pub type f64x4 = SimdF64<4>; +pub type f64x8 = SimdF64<8>; from_transmute_x86! { unsafe f64x2 => __m128d } from_transmute_x86! { unsafe f64x4 => __m256d } diff --git a/crates/core_simd/src/vectors_i128.rs b/crates/core_simd/src/vectors_i128.rs index 5c8354070e8..46c17fa12fa 100644 --- a/crates/core_simd/src/vectors_i128.rs +++ b/crates/core_simd/src/vectors_i128.rs @@ -1,12 +1,13 @@ -define_integer_vector! { - /// Vector of two `i128` values - struct i128x2([i128; 2]); -} - -define_integer_vector! { - /// Vector of four `i128` values - struct i128x4([i128; 4]); -} +#![allow(non_camel_case_types)] + +/// A SIMD vector of containing `LANES` lanes of `i128`. +#[repr(simd)] +pub struct SimdI128([i128; LANES]); + +impl_vector! { SimdI128, i128 } + +pub type i128x2 = SimdI128<2>; +pub type i128x4 = SimdI128<4>; from_transmute_x86! { unsafe i128x2 => __m256i } //from_transmute_x86! { unsafe i128x4 => __m512i } diff --git a/crates/core_simd/src/vectors_i16.rs b/crates/core_simd/src/vectors_i16.rs index 8aabd136b10..d3eefdb745c 100644 --- a/crates/core_simd/src/vectors_i16.rs +++ b/crates/core_simd/src/vectors_i16.rs @@ -1,22 +1,15 @@ -define_integer_vector! { - /// Vector of four `i16` values - struct i16x4([i16; 4]); -} +#![allow(non_camel_case_types)] -define_integer_vector! { - /// Vector of eight `i16` values - struct i16x8([i16; 8]); -} +/// A SIMD vector of containing `LANES` lanes of `i16`. +#[repr(simd)] +pub struct SimdI16([i16; LANES]); -define_integer_vector! { - /// Vector of 16 `i16` values - struct i16x16([i16; 16]); -} +impl_vector! { SimdI16, i16 } -define_integer_vector! { - /// Vector of 32 `i16` values - struct i16x32([i16; 32]); -} +pub type i16x4 = SimdI16<4>; +pub type i16x8 = SimdI16<8>; +pub type i16x16 = SimdI16<16>; +pub type i16x32 = SimdI16<32>; from_transmute_x86! { unsafe i16x8 => __m128i } from_transmute_x86! { unsafe i16x16 => __m256i } diff --git a/crates/core_simd/src/vectors_i32.rs b/crates/core_simd/src/vectors_i32.rs index 9aa9bc8e9dc..63e70393d7f 100644 --- a/crates/core_simd/src/vectors_i32.rs +++ b/crates/core_simd/src/vectors_i32.rs @@ -1,22 +1,15 @@ -define_integer_vector! { - /// Vector of two `i32` values - struct i32x2([i32; 2]); -} +#![allow(non_camel_case_types)] -define_integer_vector! { - /// Vector of four `i32` values - struct i32x4([i32; 4]); -} +/// A SIMD vector of containing `LANES` lanes of `i32`. +#[repr(simd)] +pub struct SimdI32([i32; LANES]); -define_integer_vector! { - /// Vector of eight `i32` values - struct i32x8([i32; 8]); -} +impl_vector! { SimdI32, i32 } -define_integer_vector! { - /// Vector of 16 `i32` values - struct i32x16([i32; 16]); -} +pub type i32x2 = SimdI32<2>; +pub type i32x4 = SimdI32<4>; +pub type i32x8 = SimdI32<8>; +pub type i32x16 = SimdI32<16>; from_transmute_x86! { unsafe i32x4 => __m128i } from_transmute_x86! { unsafe i32x8 => __m256i } diff --git a/crates/core_simd/src/vectors_i64.rs b/crates/core_simd/src/vectors_i64.rs index ba66aba2095..1d5e9b89f9a 100644 --- a/crates/core_simd/src/vectors_i64.rs +++ b/crates/core_simd/src/vectors_i64.rs @@ -1,17 +1,14 @@ -define_integer_vector! { - /// Vector of two `i64` values - struct i64x2([i64; 2]); -} +#![allow(non_camel_case_types)] -define_integer_vector! { - /// Vector of four `i64` values - struct i64x4([i64; 4]); -} +/// A SIMD vector of containing `LANES` lanes of `i64`. +#[repr(simd)] +pub struct SimdI64([i64; LANES]); -define_integer_vector! { - /// Vector of eight `i64` values - struct i64x8([i64; 8]); -} +impl_vector! { SimdI64, i64 } + +pub type i64x2 = SimdI64<2>; +pub type i64x4 = SimdI64<4>; +pub type i64x8 = SimdI64<8>; from_transmute_x86! { unsafe i64x2 => __m128i } from_transmute_x86! { unsafe i64x4 => __m256i } diff --git a/crates/core_simd/src/vectors_i8.rs b/crates/core_simd/src/vectors_i8.rs index 3e52d894cc2..6a38bd42122 100644 --- a/crates/core_simd/src/vectors_i8.rs +++ b/crates/core_simd/src/vectors_i8.rs @@ -1,22 +1,15 @@ -define_integer_vector! { - /// Vector of eight `i8` values - struct i8x8([i8; 8]); -} +#![allow(non_camel_case_types)] -define_integer_vector! { - /// Vector of 16 `i8` values - struct i8x16([i8; 16]); -} +/// A SIMD vector of containing `LANES` lanes of `i8`. +#[repr(simd)] +pub struct SimdI8([i8; LANES]); -define_integer_vector! { - /// Vector of 32 `i8` values - struct i8x32([i8; 32]); -} +impl_vector! { SimdI8, i8 } -define_integer_vector! { - /// Vector of 64 `i8` values - struct i8x64([i8; 64]); -} +pub type i8x8 = SimdI8<8>; +pub type i8x16 = SimdI8<16>; +pub type i8x32 = SimdI8<32>; +pub type i8x64 = SimdI8<64>; from_transmute_x86! { unsafe i8x16 => __m128i } from_transmute_x86! { unsafe i8x32 => __m256i } diff --git a/crates/core_simd/src/vectors_isize.rs b/crates/core_simd/src/vectors_isize.rs index 35dac8bcbd4..805aade88bb 100644 --- a/crates/core_simd/src/vectors_isize.rs +++ b/crates/core_simd/src/vectors_isize.rs @@ -1,17 +1,14 @@ -define_integer_vector! { - /// Vector of two `isize` values - struct isizex2([isize; 2]); -} +#![allow(non_camel_case_types)] -define_integer_vector! { - /// Vector of four `isize` values - struct isizex4([isize; 4]); -} +/// A SIMD vector of containing `LANES` lanes of `isize`. +#[repr(simd)] +pub struct SimdIsize([isize; LANES]); -define_integer_vector! { - /// Vector of eight `isize` values - struct isizex8([isize; 8]); -} +impl_vector! { SimdIsize, isize } + +pub type isizex2 = SimdIsize<2>; +pub type isizex4 = SimdIsize<4>; +pub type isizex8 = SimdIsize<8>; #[cfg(target_pointer_width = "32")] from_transmute_x86! { unsafe isizex4 => __m128i } diff --git a/crates/core_simd/src/vectors_u128.rs b/crates/core_simd/src/vectors_u128.rs index eec7bde1722..06617876ce0 100644 --- a/crates/core_simd/src/vectors_u128.rs +++ b/crates/core_simd/src/vectors_u128.rs @@ -1,12 +1,13 @@ -define_integer_vector! { - /// Vector of two `u128` values - struct u128x2([u128; 2]); -} - -define_integer_vector! { - /// Vector of four `u128` values - struct u128x4([u128; 4]); -} +#![allow(non_camel_case_types)] + +/// A SIMD vector of containing `LANES` lanes of `u128`. +#[repr(simd)] +pub struct SimdU128([u128; LANES]); + +impl_vector! { SimdU128, u128 } + +pub type u128x2 = SimdU128<2>; +pub type u128x4 = SimdU128<4>; from_transmute_x86! { unsafe u128x2 => __m256i } //from_transmute_x86! { unsafe u128x4 => __m512i } diff --git a/crates/core_simd/src/vectors_u16.rs b/crates/core_simd/src/vectors_u16.rs index 809ab10383c..208c0e36aa3 100644 --- a/crates/core_simd/src/vectors_u16.rs +++ b/crates/core_simd/src/vectors_u16.rs @@ -1,22 +1,15 @@ -define_integer_vector! { - /// Vector of four `u16` values - struct u16x4([u16; 4]); -} +#![allow(non_camel_case_types)] -define_integer_vector! { - /// Vector of eight `u16` values - struct u16x8([u16; 8]); -} +/// A SIMD vector of containing `LANES` lanes of `u16`. +#[repr(simd)] +pub struct SimdU16([u16; LANES]); -define_integer_vector! { - /// Vector of 16 `u16` values - struct u16x16([u16; 16]); -} +impl_vector! { SimdU16, u16 } -define_integer_vector! { - /// Vector of 32 `u16` values - struct u16x32([u16; 32]); -} +pub type u16x4 = SimdU16<4>; +pub type u16x8 = SimdU16<8>; +pub type u16x16 = SimdU16<16>; +pub type u16x32 = SimdU16<32>; from_transmute_x86! { unsafe u16x8 => __m128i } from_transmute_x86! { unsafe u16x16 => __m256i } diff --git a/crates/core_simd/src/vectors_u32.rs b/crates/core_simd/src/vectors_u32.rs index b00c63d9058..8a5239e7daf 100644 --- a/crates/core_simd/src/vectors_u32.rs +++ b/crates/core_simd/src/vectors_u32.rs @@ -1,22 +1,15 @@ -define_integer_vector! { - /// Vector of two `u32` values - struct u32x2([u32; 2]); -} +#![allow(non_camel_case_types)] -define_integer_vector! { - /// Vector of four `u32` values - struct u32x4([u32; 4]); -} +/// A SIMD vector of containing `LANES` lanes of `u32`. +#[repr(simd)] +pub struct SimdU32([u32; LANES]); -define_integer_vector! { - /// Vector of eight `u32` values - struct u32x8([u32; 8]); -} +impl_vector! { SimdU32, u32 } -define_integer_vector! { - /// Vector of 16 `u32` values - struct u32x16([u32; 16]); -} +pub type u32x2 = SimdU32<2>; +pub type u32x4 = SimdU32<4>; +pub type u32x8 = SimdU32<8>; +pub type u32x16 = SimdU32<16>; from_transmute_x86! { unsafe u32x4 => __m128i } from_transmute_x86! { unsafe u32x8 => __m256i } diff --git a/crates/core_simd/src/vectors_u64.rs b/crates/core_simd/src/vectors_u64.rs index 0bcf28ebc26..48b8a9ef390 100644 --- a/crates/core_simd/src/vectors_u64.rs +++ b/crates/core_simd/src/vectors_u64.rs @@ -1,17 +1,14 @@ -define_integer_vector! { - /// Vector of two `u64` values - struct u64x2([u64; 2]); -} +#![allow(non_camel_case_types)] -define_integer_vector! { - /// Vector of four `u64` values - struct u64x4([u64; 4]); -} +/// A SIMD vector of containing `LANES` lanes of `u64`. +#[repr(simd)] +pub struct SimdU64([u64; LANES]); -define_integer_vector! { - /// Vector of eight `u64` values - struct u64x8([u64; 8]); -} +impl_vector! { SimdU64, u64 } + +pub type u64x2 = SimdU64<2>; +pub type u64x4 = SimdU64<4>; +pub type u64x8 = SimdU64<8>; from_transmute_x86! { unsafe u64x2 => __m128i } from_transmute_x86! { unsafe u64x4 => __m256i } diff --git a/crates/core_simd/src/vectors_u8.rs b/crates/core_simd/src/vectors_u8.rs index a187bc6f7b4..83a179eff57 100644 --- a/crates/core_simd/src/vectors_u8.rs +++ b/crates/core_simd/src/vectors_u8.rs @@ -1,22 +1,15 @@ -define_integer_vector! { - /// Vector of eight `u8` values - struct u8x8([u8; 8]); -} +#![allow(non_camel_case_types)] -define_integer_vector! { - /// Vector of 16 `u8` values - struct u8x16([u8; 16]); -} +/// A SIMD vector of containing `LANES` lanes of `u8`. +#[repr(simd)] +pub struct SimdU8([u8; LANES]); -define_integer_vector! { - /// Vector of 32 `u8` values - struct u8x32([u8; 32]); -} +impl_vector! { SimdU8, u8 } -define_integer_vector! { - /// Vector of 64 `u8` values - struct u8x64([u8; 64]); -} +pub type u8x8 = SimdU8<8>; +pub type u8x16 = SimdU8<16>; +pub type u8x32 = SimdU8<32>; +pub type u8x64 = SimdU8<64>; from_transmute_x86! { unsafe u8x16 => __m128i } from_transmute_x86! { unsafe u8x32 => __m256i } diff --git a/crates/core_simd/src/vectors_usize.rs b/crates/core_simd/src/vectors_usize.rs index 84a4b8e509b..096b6cea08d 100644 --- a/crates/core_simd/src/vectors_usize.rs +++ b/crates/core_simd/src/vectors_usize.rs @@ -1,17 +1,14 @@ -define_integer_vector! { - /// Vector of two `usize` values - struct usizex2([usize; 2]); -} +#![allow(non_camel_case_types)] -define_integer_vector! { - /// Vector of four `usize` values - struct usizex4([usize; 4]); -} +/// A SIMD vector of containing `LANES` lanes of `usize`. +#[repr(simd)] +pub struct SimdUsize([usize; LANES]); -define_integer_vector! { - /// Vector of eight `usize` values - struct usizex8([usize; 8]); -} +impl_vector! { SimdUsize, usize } + +pub type usizex2 = SimdUsize<2>; +pub type usizex4 = SimdUsize<4>; +pub type usizex8 = SimdUsize<8>; #[cfg(target_pointer_width = "32")] from_transmute_x86! { unsafe usizex4 => __m128i } From 22576bb6e0080fc8eb00d40168b3b608d3756735 Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Sat, 5 Dec 2020 23:49:42 -0500 Subject: [PATCH 06/13] Implement additional functions --- crates/core_simd/src/macros.rs | 52 +++++++++++++-------------- crates/core_simd/src/vectors_f32.rs | 2 +- crates/core_simd/src/vectors_f64.rs | 2 +- crates/core_simd/src/vectors_i128.rs | 2 +- crates/core_simd/src/vectors_i16.rs | 2 +- crates/core_simd/src/vectors_i32.rs | 2 +- crates/core_simd/src/vectors_i64.rs | 2 +- crates/core_simd/src/vectors_i8.rs | 2 +- crates/core_simd/src/vectors_isize.rs | 2 +- crates/core_simd/src/vectors_u128.rs | 2 +- crates/core_simd/src/vectors_u16.rs | 2 +- crates/core_simd/src/vectors_u32.rs | 2 +- crates/core_simd/src/vectors_u64.rs | 2 +- crates/core_simd/src/vectors_u8.rs | 2 +- crates/core_simd/src/vectors_usize.rs | 2 +- 15 files changed, 40 insertions(+), 40 deletions(-) diff --git a/crates/core_simd/src/macros.rs b/crates/core_simd/src/macros.rs index abf165c78b2..c588505daf8 100644 --- a/crates/core_simd/src/macros.rs +++ b/crates/core_simd/src/macros.rs @@ -139,31 +139,27 @@ macro_rules! call_counting_args { macro_rules! impl_vector { { $name:ident, $type:ty } => { impl $name { - /// Construct a vector by setting all lanes to the given value. + /// Construct a SIMD vector by setting all lanes to the given value. pub const fn splat(value: $type) -> Self { Self([value; LANES]) } + /// Returns a slice containing the entire SIMD vector. pub const fn as_slice(&self) -> &[$type] { &self.0 } + /// Returns a mutable slice containing the entire SIMD vector. pub fn as_mut_slice(&mut self) -> &mut [$type] { &mut self.0 } - pub const fn as_ptr(&self) -> *const $type { - self.0.as_ptr() - } - - pub fn as_mut_ptr(&mut self) -> *mut $type { - self.0.as_mut_ptr() - } - + /// Converts an array to a SIMD vector. pub const fn from_array(array: [$type; LANES]) -> Self { Self(array) } + /// Converts a SIMD vector to an array. pub const fn to_array(self) -> [$type; LANES] { self.0 } @@ -250,7 +246,7 @@ macro_rules! impl_vector { /// Implements additional integer traits (Eq, Ord, Hash) on the specified vector `$name`, holding multiple `$lanes` of `$type`. macro_rules! impl_integer_vector { - { $name:path, $type:ty } => { + { $name:ident, $type:ty } => { impl_vector! { $name, $type } impl Eq for $name {} @@ -279,22 +275,26 @@ macro_rules! impl_integer_vector { /// `$lanes` of float `$type`, which uses `$bits_ty` as its binary /// representation. Called from `define_float_vector!`. macro_rules! impl_float_vector { - { $name:path => [$type:ty; $lanes:literal]; bits $bits_ty:ty; } => { - impl $name { -// /// Raw transmutation to an unsigned integer vector type with the -// /// same size and number of lanes. -// #[inline] -// pub fn to_bits(self) -> $bits_ty { -// unsafe { core::mem::transmute(self) } -// } -// -// /// Raw transmutation from an unsigned integer vector type with the -// /// same size and number of lanes. -// #[inline] -// pub fn from_bits(bits: $bits_ty) -> Self { -// unsafe { core::mem::transmute(bits) } -// } -// + { $name:ident, $type:ty, $bits_ty:ident } => { + impl_vector! { $name, $type } + + impl $name { + /// Raw transmutation to an unsigned integer vector type with the + /// same size and number of lanes. + #[inline] + pub fn to_bits(self) -> crate::$bits_ty { + assert_eq!(core::mem::size_of::(), core::mem::size_of::>()); + unsafe { core::mem::transmute_copy(&self) } + } + + /// Raw transmutation from an unsigned integer vector type with the + /// same size and number of lanes. + #[inline] + pub fn from_bits(bits: crate::$bits_ty) -> Self { + assert_eq!(core::mem::size_of::(), core::mem::size_of::>()); + unsafe { core::mem::transmute_copy(&bits) } + } + // /// Produces a vector where every lane has the absolute value of the // /// equivalently-indexed lane in `self`. // #[inline] diff --git a/crates/core_simd/src/vectors_f32.rs b/crates/core_simd/src/vectors_f32.rs index fbe89bb853b..b1e13408cc9 100644 --- a/crates/core_simd/src/vectors_f32.rs +++ b/crates/core_simd/src/vectors_f32.rs @@ -4,7 +4,7 @@ #[repr(simd)] pub struct SimdF32([f32; LANES]); -impl_vector! { SimdF32, f32 } +impl_float_vector! { SimdF32, f32, SimdU32 } pub type f32x2 = SimdF32<2>; pub type f32x4 = SimdF32<4>; diff --git a/crates/core_simd/src/vectors_f64.rs b/crates/core_simd/src/vectors_f64.rs index f588aa4b15d..4297c9d636c 100644 --- a/crates/core_simd/src/vectors_f64.rs +++ b/crates/core_simd/src/vectors_f64.rs @@ -4,7 +4,7 @@ #[repr(simd)] pub struct SimdF64([f64; LANES]); -impl_vector! { SimdF64, f64 } +impl_float_vector! { SimdF64, f64, SimdU64 } pub type f64x2 = SimdF64<2>; pub type f64x4 = SimdF64<4>; diff --git a/crates/core_simd/src/vectors_i128.rs b/crates/core_simd/src/vectors_i128.rs index 46c17fa12fa..a48c823cbd6 100644 --- a/crates/core_simd/src/vectors_i128.rs +++ b/crates/core_simd/src/vectors_i128.rs @@ -4,7 +4,7 @@ #[repr(simd)] pub struct SimdI128([i128; LANES]); -impl_vector! { SimdI128, i128 } +impl_integer_vector! { SimdI128, i128 } pub type i128x2 = SimdI128<2>; pub type i128x4 = SimdI128<4>; diff --git a/crates/core_simd/src/vectors_i16.rs b/crates/core_simd/src/vectors_i16.rs index d3eefdb745c..7bc522287a3 100644 --- a/crates/core_simd/src/vectors_i16.rs +++ b/crates/core_simd/src/vectors_i16.rs @@ -4,7 +4,7 @@ #[repr(simd)] pub struct SimdI16([i16; LANES]); -impl_vector! { SimdI16, i16 } +impl_integer_vector! { SimdI16, i16 } pub type i16x4 = SimdI16<4>; pub type i16x8 = SimdI16<8>; diff --git a/crates/core_simd/src/vectors_i32.rs b/crates/core_simd/src/vectors_i32.rs index 63e70393d7f..05533bb0b6d 100644 --- a/crates/core_simd/src/vectors_i32.rs +++ b/crates/core_simd/src/vectors_i32.rs @@ -4,7 +4,7 @@ #[repr(simd)] pub struct SimdI32([i32; LANES]); -impl_vector! { SimdI32, i32 } +impl_integer_vector! { SimdI32, i32 } pub type i32x2 = SimdI32<2>; pub type i32x4 = SimdI32<4>; diff --git a/crates/core_simd/src/vectors_i64.rs b/crates/core_simd/src/vectors_i64.rs index 1d5e9b89f9a..e669e8a367c 100644 --- a/crates/core_simd/src/vectors_i64.rs +++ b/crates/core_simd/src/vectors_i64.rs @@ -4,7 +4,7 @@ #[repr(simd)] pub struct SimdI64([i64; LANES]); -impl_vector! { SimdI64, i64 } +impl_integer_vector! { SimdI64, i64 } pub type i64x2 = SimdI64<2>; pub type i64x4 = SimdI64<4>; diff --git a/crates/core_simd/src/vectors_i8.rs b/crates/core_simd/src/vectors_i8.rs index 6a38bd42122..55a440cc92f 100644 --- a/crates/core_simd/src/vectors_i8.rs +++ b/crates/core_simd/src/vectors_i8.rs @@ -4,7 +4,7 @@ #[repr(simd)] pub struct SimdI8([i8; LANES]); -impl_vector! { SimdI8, i8 } +impl_integer_vector! { SimdI8, i8 } pub type i8x8 = SimdI8<8>; pub type i8x16 = SimdI8<16>; diff --git a/crates/core_simd/src/vectors_isize.rs b/crates/core_simd/src/vectors_isize.rs index 805aade88bb..6d9b2061532 100644 --- a/crates/core_simd/src/vectors_isize.rs +++ b/crates/core_simd/src/vectors_isize.rs @@ -4,7 +4,7 @@ #[repr(simd)] pub struct SimdIsize([isize; LANES]); -impl_vector! { SimdIsize, isize } +impl_integer_vector! { SimdIsize, isize } pub type isizex2 = SimdIsize<2>; pub type isizex4 = SimdIsize<4>; diff --git a/crates/core_simd/src/vectors_u128.rs b/crates/core_simd/src/vectors_u128.rs index 06617876ce0..54ad6e191f7 100644 --- a/crates/core_simd/src/vectors_u128.rs +++ b/crates/core_simd/src/vectors_u128.rs @@ -4,7 +4,7 @@ #[repr(simd)] pub struct SimdU128([u128; LANES]); -impl_vector! { SimdU128, u128 } +impl_integer_vector! { SimdU128, u128 } pub type u128x2 = SimdU128<2>; pub type u128x4 = SimdU128<4>; diff --git a/crates/core_simd/src/vectors_u16.rs b/crates/core_simd/src/vectors_u16.rs index 208c0e36aa3..7b0e345ef15 100644 --- a/crates/core_simd/src/vectors_u16.rs +++ b/crates/core_simd/src/vectors_u16.rs @@ -4,7 +4,7 @@ #[repr(simd)] pub struct SimdU16([u16; LANES]); -impl_vector! { SimdU16, u16 } +impl_integer_vector! { SimdU16, u16 } pub type u16x4 = SimdU16<4>; pub type u16x8 = SimdU16<8>; diff --git a/crates/core_simd/src/vectors_u32.rs b/crates/core_simd/src/vectors_u32.rs index 8a5239e7daf..f80efbc59eb 100644 --- a/crates/core_simd/src/vectors_u32.rs +++ b/crates/core_simd/src/vectors_u32.rs @@ -4,7 +4,7 @@ #[repr(simd)] pub struct SimdU32([u32; LANES]); -impl_vector! { SimdU32, u32 } +impl_integer_vector! { SimdU32, u32 } pub type u32x2 = SimdU32<2>; pub type u32x4 = SimdU32<4>; diff --git a/crates/core_simd/src/vectors_u64.rs b/crates/core_simd/src/vectors_u64.rs index 48b8a9ef390..848d90faaa7 100644 --- a/crates/core_simd/src/vectors_u64.rs +++ b/crates/core_simd/src/vectors_u64.rs @@ -4,7 +4,7 @@ #[repr(simd)] pub struct SimdU64([u64; LANES]); -impl_vector! { SimdU64, u64 } +impl_integer_vector! { SimdU64, u64 } pub type u64x2 = SimdU64<2>; pub type u64x4 = SimdU64<4>; diff --git a/crates/core_simd/src/vectors_u8.rs b/crates/core_simd/src/vectors_u8.rs index 83a179eff57..b172801aa99 100644 --- a/crates/core_simd/src/vectors_u8.rs +++ b/crates/core_simd/src/vectors_u8.rs @@ -4,7 +4,7 @@ #[repr(simd)] pub struct SimdU8([u8; LANES]); -impl_vector! { SimdU8, u8 } +impl_integer_vector! { SimdU8, u8 } pub type u8x8 = SimdU8<8>; pub type u8x16 = SimdU8<16>; diff --git a/crates/core_simd/src/vectors_usize.rs b/crates/core_simd/src/vectors_usize.rs index 096b6cea08d..b0655ab311b 100644 --- a/crates/core_simd/src/vectors_usize.rs +++ b/crates/core_simd/src/vectors_usize.rs @@ -4,7 +4,7 @@ #[repr(simd)] pub struct SimdUsize([usize; LANES]); -impl_vector! { SimdUsize, usize } +impl_integer_vector! { SimdUsize, usize } pub type usizex2 = SimdUsize<2>; pub type usizex4 = SimdUsize<4>; From 25c7640fb331112d5bf445c0893af89ee3e9ea9d Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Sun, 6 Dec 2020 00:36:33 -0500 Subject: [PATCH 07/13] Reenable ops and fix tests --- crates/core_simd/src/lib.rs | 2 +- crates/core_simd/src/macros.rs | 14 +- crates/core_simd/src/ops.rs | 283 ++++++------------ crates/core_simd/tests/helpers/biteq.rs | 12 - .../core_simd/tests/ops_impl/float_macros.rs | 3 + .../core_simd/tests/ops_impl/mask_macros.rs | 2 + 6 files changed, 112 insertions(+), 204 deletions(-) diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs index ba5e4db9312..d23e5ad21ba 100644 --- a/crates/core_simd/src/lib.rs +++ b/crates/core_simd/src/lib.rs @@ -8,7 +8,7 @@ mod macros; mod fmt; mod intrinsics; -//mod ops; +mod ops; //mod round; //pub mod masks; diff --git a/crates/core_simd/src/macros.rs b/crates/core_simd/src/macros.rs index c588505daf8..99adb669bc5 100644 --- a/crates/core_simd/src/macros.rs +++ b/crates/core_simd/src/macros.rs @@ -295,13 +295,13 @@ macro_rules! impl_float_vector { unsafe { core::mem::transmute_copy(&bits) } } -// /// Produces a vector where every lane has the absolute value of the -// /// equivalently-indexed lane in `self`. -// #[inline] -// pub fn abs(self) -> Self { -// let no_sign = <$bits_ty>::splat(!0 >> 1); -// Self::from_bits(self.to_bits() & no_sign) -// } + /// Produces a vector where every lane has the absolute value of the + /// equivalently-indexed lane in `self`. + #[inline] + pub fn abs(self) -> Self { + let no_sign = crate::$bits_ty::splat(!0 >> 1); + Self::from_bits(self.to_bits() & no_sign) + } } }; } diff --git a/crates/core_simd/src/ops.rs b/crates/core_simd/src/ops.rs index ac89feca9d6..942d071de44 100644 --- a/crates/core_simd/src/ops.rs +++ b/crates/core_simd/src/ops.rs @@ -12,21 +12,21 @@ where macro_rules! impl_ref_ops { // binary op { - impl core::ops::$trait:ident<$rhs:ty> for $type:ty { + impl core::ops::$trait:ident<$rhs:ty> for $type:ty { type Output = $output:ty; $(#[$attrs:meta])* fn $fn:ident($self_tok:ident, $rhs_arg:ident: $rhs_arg_ty:ty) -> Self::Output $body:tt } } => { - impl core::ops::$trait<$rhs> for $type { + impl core::ops::$trait<$rhs> for $type { type Output = $output; $(#[$attrs])* fn $fn($self_tok, $rhs_arg: $rhs_arg_ty) -> Self::Output $body } - impl core::ops::$trait<&'_ $rhs> for $type { + impl core::ops::$trait<&'_ $rhs> for $type { type Output = <$type as core::ops::$trait<$rhs>>::Output; $(#[$attrs])* @@ -35,7 +35,7 @@ macro_rules! impl_ref_ops { } } - impl core::ops::$trait<$rhs> for &'_ $type { + impl core::ops::$trait<$rhs> for &'_ $type { type Output = <$type as core::ops::$trait<$rhs>>::Output; $(#[$attrs])* @@ -44,7 +44,7 @@ macro_rules! impl_ref_ops { } } - impl core::ops::$trait<&'_ $rhs> for &'_ $type { + impl core::ops::$trait<&'_ $rhs> for &'_ $type { type Output = <$type as core::ops::$trait<$rhs>>::Output; $(#[$attrs])* @@ -56,17 +56,17 @@ macro_rules! impl_ref_ops { // binary assignment op { - impl core::ops::$trait:ident<$rhs:ty> for $type:ty { + impl core::ops::$trait:ident<$rhs:ty> for $type:ty { $(#[$attrs:meta])* fn $fn:ident(&mut $self_tok:ident, $rhs_arg:ident: $rhs_arg_ty:ty) $body:tt } } => { - impl core::ops::$trait<$rhs> for $type { + impl core::ops::$trait<$rhs> for $type { $(#[$attrs])* fn $fn(&mut $self_tok, $rhs_arg: $rhs_arg_ty) $body } - impl core::ops::$trait<&'_ $rhs> for $type { + impl core::ops::$trait<&'_ $rhs> for $type { $(#[$attrs])* fn $fn(&mut $self_tok, $rhs_arg: &$rhs_arg_ty) { core::ops::$trait::$fn($self_tok, *$rhs_arg) @@ -76,17 +76,17 @@ macro_rules! impl_ref_ops { // unary op { - impl core::ops::$trait:ident for $type:ty { + impl core::ops::$trait:ident for $type:ty { type Output = $output:ty; fn $fn:ident($self_tok:ident) -> Self::Output $body:tt } } => { - impl core::ops::$trait for $type { + impl core::ops::$trait for $type { type Output = $output; fn $fn($self_tok) -> Self::Output $body } - impl core::ops::$trait for &'_ $type { + impl core::ops::$trait for &'_ $type { type Output = <$type as core::ops::$trait>::Output; fn $fn($self_tok) -> Self::Output { core::ops::$trait::$fn(*$self_tok) @@ -95,152 +95,76 @@ macro_rules! impl_ref_ops { } } -/// Implements op traits for masks -macro_rules! impl_mask_element_ops { - { $($mask:ty),* } => { - $( - impl_ref_ops! { - impl core::ops::BitAnd<$mask> for $mask { - type Output = Self; - fn bitand(self, rhs: Self) -> Self::Output { - Self(self.0 & rhs.0) - } - } - } - - impl_ref_ops! { - impl core::ops::BitAndAssign<$mask> for $mask { - fn bitand_assign(&mut self, rhs: Self) { - *self = *self & rhs; - } - } - } - - impl_ref_ops! { - impl core::ops::BitOr<$mask> for $mask { - type Output = Self; - fn bitor(self, rhs: Self) -> Self::Output { - Self(self.0 | rhs.0) - } - } - } - - impl_ref_ops! { - impl core::ops::BitOrAssign<$mask> for $mask { - fn bitor_assign(&mut self, rhs: Self) { - *self = *self | rhs; - } - } - } - - impl_ref_ops! { - impl core::ops::BitXor<$mask> for $mask { - type Output = Self; - fn bitxor(self, rhs: Self) -> Self::Output { - Self(self.0 ^ rhs.0) - } - } - } - - impl_ref_ops! { - impl core::ops::BitXorAssign<$mask> for $mask { - fn bitxor_assign(&mut self, rhs: Self) { - *self = *self ^ rhs; - } - } - } - - impl_ref_ops! { - impl core::ops::Not for $mask { - type Output = Self; - fn not(self) -> Self::Output { - Self(!self.0) - } - } - } - )* - } -} - -impl_mask_element_ops! { - crate::masks::wide::m8, - crate::masks::wide::m16, - crate::masks::wide::m32, - crate::masks::wide::m64, - crate::masks::wide::m128, - crate::masks::wide::msize -} - /// Automatically implements operators over vectors and scalars for a particular vector. macro_rules! impl_op { - { impl Add for $type:ty, $scalar:ty } => { + { impl Add for $type:ident, $scalar:ty } => { impl_op! { @binary $type, $scalar, Add::add, AddAssign::add_assign, simd_add } }; - { impl Sub for $type:ty, $scalar:ty } => { + { impl Sub for $type:ident, $scalar:ty } => { impl_op! { @binary $type, $scalar, Sub::sub, SubAssign::sub_assign, simd_sub } }; - { impl Mul for $type:ty, $scalar:ty } => { + { impl Mul for $type:ident, $scalar:ty } => { impl_op! { @binary $type, $scalar, Mul::mul, MulAssign::mul_assign, simd_mul } }; - { impl Div for $type:ty, $scalar:ty } => { + { impl Div for $type:ident, $scalar:ty } => { impl_op! { @binary $type, $scalar, Div::div, DivAssign::div_assign, simd_div } }; - { impl Rem for $type:ty, $scalar:ty } => { + { impl Rem for $type:ident, $scalar:ty } => { impl_op! { @binary $type, $scalar, Rem::rem, RemAssign::rem_assign, simd_rem } }; - { impl Shl for $type:ty, $scalar:ty } => { + { impl Shl for $type:ident, $scalar:ty } => { impl_op! { @binary $type, $scalar, Shl::shl, ShlAssign::shl_assign, simd_shl } }; - { impl Shr for $type:ty, $scalar:ty } => { + { impl Shr for $type:ident, $scalar:ty } => { impl_op! { @binary $type, $scalar, Shr::shr, ShrAssign::shr_assign, simd_shr } }; - { impl BitAnd for $type:ty, $scalar:ty } => { + { impl BitAnd for $type:ident, $scalar:ty } => { impl_op! { @binary $type, $scalar, BitAnd::bitand, BitAndAssign::bitand_assign, simd_and } }; - { impl BitOr for $type:ty, $scalar:ty } => { + { impl BitOr for $type:ident, $scalar:ty } => { impl_op! { @binary $type, $scalar, BitOr::bitor, BitOrAssign::bitor_assign, simd_or } }; - { impl BitXor for $type:ty, $scalar:ty } => { + { impl BitXor for $type:ident, $scalar:ty } => { impl_op! { @binary $type, $scalar, BitXor::bitxor, BitXorAssign::bitxor_assign, simd_xor } }; - { impl Not for $type:ty, $scalar:ty } => { + { impl Not for $type:ident, $scalar:ty } => { impl_ref_ops! { - impl core::ops::Not for $type { + impl core::ops::Not for crate::$type { type Output = Self; fn not(self) -> Self::Output { - self ^ <$type>::splat(!<$scalar>::default()) + self ^ Self::splat(!<$scalar>::default()) } } } }; - { impl Neg for $type:ty, $scalar:ty } => { + { impl Neg for $type:ident, $scalar:ty } => { impl_ref_ops! { - impl core::ops::Neg for $type { + impl core::ops::Neg for crate::$type { type Output = Self; fn neg(self) -> Self::Output { - <$type>::splat(0) - self + Self::splat(0) - self } } } }; - { impl Neg for $type:ty, $scalar:ty, @float } => { + { impl Neg for $type:ident, $scalar:ty, @float } => { impl_ref_ops! { - impl core::ops::Neg for $type { + impl core::ops::Neg for crate::$type { type Output = Self; fn neg(self) -> Self::Output { // FIXME: Replace this with fneg intrinsic once available. // https://github.com/rust-lang/stdsimd/issues/32 - Self::from_bits(<$type>::splat(-0.0).to_bits() ^ self.to_bits()) + Self::from_bits(Self::splat(-0.0).to_bits() ^ self.to_bits()) } } } }; - { impl Index for $type:ty, $scalar:ty } => { - impl core::ops::Index for $type + { impl Index for $type:ident, $scalar:ty } => { + impl core::ops::Index for crate::$type where I: core::slice::SliceIndex<[$scalar]>, { @@ -251,7 +175,7 @@ macro_rules! impl_op { } } - impl core::ops::IndexMut for $type + impl core::ops::IndexMut for crate::$type where I: core::slice::SliceIndex<[$scalar]>, { @@ -263,13 +187,13 @@ macro_rules! impl_op { }; // generic binary op with assignment when output is `Self` - { @binary $type:ty, $scalar:ty, $trait:ident :: $trait_fn:ident, $assign_trait:ident :: $assign_trait_fn:ident, $intrinsic:ident } => { + { @binary $type:ident, $scalar:ty, $trait:ident :: $trait_fn:ident, $assign_trait:ident :: $assign_trait_fn:ident, $intrinsic:ident } => { impl_ref_ops! { - impl core::ops::$trait<$type> for $type { - type Output = $type; + impl core::ops::$trait for crate::$type { + type Output = Self; #[inline] - fn $trait_fn(self, rhs: $type) -> Self::Output { + fn $trait_fn(self, rhs: Self) -> Self::Output { unsafe { crate::intrinsics::$intrinsic(self, rhs) } @@ -278,31 +202,31 @@ macro_rules! impl_op { } impl_ref_ops! { - impl core::ops::$trait<$scalar> for $type { - type Output = $type; + impl core::ops::$trait<$scalar> for crate::$type { + type Output = Self; #[inline] fn $trait_fn(self, rhs: $scalar) -> Self::Output { - core::ops::$trait::$trait_fn(self, <$type>::splat(rhs)) + core::ops::$trait::$trait_fn(self, Self::splat(rhs)) } } } impl_ref_ops! { - impl core::ops::$trait<$type> for $scalar { - type Output = $type; + impl core::ops::$trait> for $scalar { + type Output = crate::$type; #[inline] - fn $trait_fn(self, rhs: $type) -> Self::Output { - core::ops::$trait::$trait_fn(<$type>::splat(self), rhs) + fn $trait_fn(self, rhs: crate::$type) -> Self::Output { + core::ops::$trait::$trait_fn(crate::$type::splat(self), rhs) } } } impl_ref_ops! { - impl core::ops::$assign_trait<$type> for $type { + impl core::ops::$assign_trait for crate::$type { #[inline] - fn $assign_trait_fn(&mut self, rhs: $type) { + fn $assign_trait_fn(&mut self, rhs: Self) { unsafe { *self = crate::intrinsics::$intrinsic(*self, rhs); } @@ -311,10 +235,10 @@ macro_rules! impl_op { } impl_ref_ops! { - impl core::ops::$assign_trait<$scalar> for $type { + impl core::ops::$assign_trait<$scalar> for crate::$type { #[inline] fn $assign_trait_fn(&mut self, rhs: $scalar) { - core::ops::$assign_trait::$assign_trait_fn(self, <$type>::splat(rhs)); + core::ops::$assign_trait::$assign_trait_fn(self, Self::splat(rhs)); } } } @@ -323,7 +247,7 @@ macro_rules! impl_op { /// Implements floating-point operators for the provided types. macro_rules! impl_float_ops { - { $($scalar:ty => $($vector:ty),*;)* } => { + { $($scalar:ty => $($vector:ident),*;)* } => { $( // scalar $( // vector impl_op! { impl Add for $vector, $scalar } @@ -340,7 +264,7 @@ macro_rules! impl_float_ops { /// Implements mask operators for the provided types. macro_rules! impl_mask_ops { - { $($scalar:ty => $($vector:ty),*;)* } => { + { $($scalar:ty => $($vector:ident),*;)* } => { $( // scalar $( // vector impl_op! { impl BitAnd for $vector, $scalar } @@ -355,7 +279,7 @@ macro_rules! impl_mask_ops { /// Implements unsigned integer operators for the provided types. macro_rules! impl_unsigned_int_ops { - { $($scalar:ty => $($vector:ty),*;)* } => { + { $($scalar:ty => $($vector:ident),*;)* } => { $( // scalar $( // vector impl_op! { impl Add for $vector, $scalar } @@ -369,11 +293,11 @@ macro_rules! impl_unsigned_int_ops { // Integers panic on divide by 0 impl_ref_ops! { - impl core::ops::Div<$vector> for $vector { + impl core::ops::Div for crate::$vector { type Output = Self; #[inline] - fn div(self, rhs: $vector) -> Self::Output { + fn div(self, rhs: Self) -> Self::Output { // TODO there is probably a better way of doing this if AsRef::<[$scalar]>::as_ref(&rhs) .iter() @@ -387,8 +311,8 @@ macro_rules! impl_unsigned_int_ops { } impl_ref_ops! { - impl core::ops::Div<$scalar> for $vector { - type Output = $vector; + impl core::ops::Div<$scalar> for crate::$vector { + type Output = Self; #[inline] fn div(self, rhs: $scalar) -> Self::Output { @@ -402,18 +326,18 @@ macro_rules! impl_unsigned_int_ops { } impl_ref_ops! { - impl core::ops::Div<$vector> for $scalar { - type Output = $vector; + impl core::ops::Div> for $scalar { + type Output = crate::$vector; #[inline] - fn div(self, rhs: $vector) -> Self::Output { - <$vector>::splat(self) / rhs + fn div(self, rhs: crate::$vector) -> Self::Output { + crate::$vector::splat(self) / rhs } } } impl_ref_ops! { - impl core::ops::DivAssign<$vector> for $vector { + impl core::ops::DivAssign for crate::$vector { #[inline] fn div_assign(&mut self, rhs: Self) { *self = *self / rhs; @@ -422,7 +346,7 @@ macro_rules! impl_unsigned_int_ops { } impl_ref_ops! { - impl core::ops::DivAssign<$scalar> for $vector { + impl core::ops::DivAssign<$scalar> for crate::$vector { #[inline] fn div_assign(&mut self, rhs: $scalar) { *self = *self / rhs; @@ -432,11 +356,11 @@ macro_rules! impl_unsigned_int_ops { // remainder panics on zero divisor impl_ref_ops! { - impl core::ops::Rem<$vector> for $vector { + impl core::ops::Rem for crate::$vector { type Output = Self; #[inline] - fn rem(self, rhs: $vector) -> Self::Output { + fn rem(self, rhs: Self) -> Self::Output { // TODO there is probably a better way of doing this if AsRef::<[$scalar]>::as_ref(&rhs) .iter() @@ -450,8 +374,8 @@ macro_rules! impl_unsigned_int_ops { } impl_ref_ops! { - impl core::ops::Rem<$scalar> for $vector { - type Output = $vector; + impl core::ops::Rem<$scalar> for crate::$vector { + type Output = Self; #[inline] fn rem(self, rhs: $scalar) -> Self::Output { @@ -465,18 +389,18 @@ macro_rules! impl_unsigned_int_ops { } impl_ref_ops! { - impl core::ops::Rem<$vector> for $scalar { - type Output = $vector; + impl core::ops::Rem> for $scalar { + type Output = crate::$vector; #[inline] - fn rem(self, rhs: $vector) -> Self::Output { - <$vector>::splat(self) % rhs + fn rem(self, rhs: crate::$vector) -> Self::Output { + crate::$vector::splat(self) % rhs } } } impl_ref_ops! { - impl core::ops::RemAssign<$vector> for $vector { + impl core::ops::RemAssign for crate::$vector { #[inline] fn rem_assign(&mut self, rhs: Self) { *self = *self % rhs; @@ -485,7 +409,7 @@ macro_rules! impl_unsigned_int_ops { } impl_ref_ops! { - impl core::ops::RemAssign<$scalar> for $vector { + impl core::ops::RemAssign<$scalar> for crate::$vector { #[inline] fn rem_assign(&mut self, rhs: $scalar) { *self = *self % rhs; @@ -495,11 +419,11 @@ macro_rules! impl_unsigned_int_ops { // shifts panic on overflow impl_ref_ops! { - impl core::ops::Shl<$vector> for $vector { + impl core::ops::Shl for crate::$vector { type Output = Self; #[inline] - fn shl(self, rhs: $vector) -> Self::Output { + fn shl(self, rhs: Self) -> Self::Output { // TODO there is probably a better way of doing this if AsRef::<[$scalar]>::as_ref(&rhs) .iter() @@ -514,8 +438,8 @@ macro_rules! impl_unsigned_int_ops { } impl_ref_ops! { - impl core::ops::Shl<$scalar> for $vector { - type Output = $vector; + impl core::ops::Shl<$scalar> for crate::$vector { + type Output = Self; #[inline] fn shl(self, rhs: $scalar) -> Self::Output { @@ -530,7 +454,7 @@ macro_rules! impl_unsigned_int_ops { impl_ref_ops! { - impl core::ops::ShlAssign<$vector> for $vector { + impl core::ops::ShlAssign for crate::$vector { #[inline] fn shl_assign(&mut self, rhs: Self) { *self = *self << rhs; @@ -539,7 +463,7 @@ macro_rules! impl_unsigned_int_ops { } impl_ref_ops! { - impl core::ops::ShlAssign<$scalar> for $vector { + impl core::ops::ShlAssign<$scalar> for crate::$vector { #[inline] fn shl_assign(&mut self, rhs: $scalar) { *self = *self << rhs; @@ -548,13 +472,13 @@ macro_rules! impl_unsigned_int_ops { } impl_ref_ops! { - impl core::ops::Shr<$vector> for $vector { + impl core::ops::Shr for crate::$vector { type Output = Self; #[inline] - fn shr(self, rhs: $vector) -> Self::Output { + fn shr(self, rhs: Self) -> Self::Output { // TODO there is probably a better way of doing this - if AsRef::<[$scalar]>::as_ref(&rhs) + if rhs.as_slice() .iter() .copied() .any(invalid_shift_rhs) @@ -567,8 +491,8 @@ macro_rules! impl_unsigned_int_ops { } impl_ref_ops! { - impl core::ops::Shr<$scalar> for $vector { - type Output = $vector; + impl core::ops::Shr<$scalar> for crate::$vector { + type Output = Self; #[inline] fn shr(self, rhs: $scalar) -> Self::Output { @@ -583,7 +507,7 @@ macro_rules! impl_unsigned_int_ops { impl_ref_ops! { - impl core::ops::ShrAssign<$vector> for $vector { + impl core::ops::ShrAssign for crate::$vector { #[inline] fn shr_assign(&mut self, rhs: Self) { *self = *self >> rhs; @@ -592,7 +516,7 @@ macro_rules! impl_unsigned_int_ops { } impl_ref_ops! { - impl core::ops::ShrAssign<$scalar> for $vector { + impl core::ops::ShrAssign<$scalar> for crate::$vector { #[inline] fn shr_assign(&mut self, rhs: $scalar) { *self = *self >> rhs; @@ -606,7 +530,7 @@ macro_rules! impl_unsigned_int_ops { /// Implements unsigned integer operators for the provided types. macro_rules! impl_signed_int_ops { - { $($scalar:ty => $($vector:ty),*;)* } => { + { $($scalar:ty => $($vector:ident),*;)* } => { impl_unsigned_int_ops! { $($scalar => $($vector),*;)* } $( // scalar $( // vector @@ -617,33 +541,24 @@ macro_rules! impl_signed_int_ops { } impl_unsigned_int_ops! { - u8 => crate::u8x8, crate::u8x16, crate::u8x32, crate::u8x64; - u16 => crate::u16x4, crate::u16x8, crate::u16x16, crate::u16x32; - u32 => crate::u32x2, crate::u32x4, crate::u32x8, crate::u32x16; - u64 => crate::u64x2, crate::u64x4, crate::u64x8; - u128 => crate::u128x2, crate::u128x4; - usize => crate::usizex2, crate::usizex4, crate::usizex8; + u8 => SimdU8; + u16 => SimdU16; + u32 => SimdU32; + u64 => SimdU64; + u128 => SimdU128; + usize => SimdUsize; } impl_signed_int_ops! { - i8 => crate::i8x8, crate::i8x16, crate::i8x32, crate::i8x64; - i16 => crate::i16x4, crate::i16x8, crate::i16x16, crate::i16x32; - i32 => crate::i32x2, crate::i32x4, crate::i32x8, crate::i32x16; - i64 => crate::i64x2, crate::i64x4, crate::i64x8; - i128 => crate::i128x2, crate::i128x4; - isize => crate::isizex2, crate::isizex4, crate::isizex8; + i8 => SimdI8; + i16 => SimdI16; + i32 => SimdI32; + i64 => SimdI64; + i128 => SimdI128; + isize => SimdIsize; } impl_float_ops! { - f32 => crate::f32x2, crate::f32x4, crate::f32x8, crate::f32x16; - f64 => crate::f64x2, crate::f64x4, crate::f64x8; -} - -impl_mask_ops! { - crate::masks::wide::m8 => crate::masks::wide::m8x8, crate::masks::wide::m8x16, crate::masks::wide::m8x32, crate::masks::wide::m8x64; - crate::masks::wide::m16 => crate::masks::wide::m16x4, crate::masks::wide::m16x8, crate::masks::wide::m16x16, crate::masks::wide::m16x32; - crate::masks::wide::m32 => crate::masks::wide::m32x2, crate::masks::wide::m32x4, crate::masks::wide::m32x8, crate::masks::wide::m32x16; - crate::masks::wide::m64 => crate::masks::wide::m64x2, crate::masks::wide::m64x4, crate::masks::wide::m64x8; - crate::masks::wide::m128 => crate::masks::wide::m128x2, crate::masks::wide::m128x4; - crate::masks::wide::msize => crate::masks::wide::msizex2, crate::masks::wide::msizex4, crate::masks::wide::msizex8; + f32 => SimdF32; + f64 => SimdF64; } diff --git a/crates/core_simd/tests/helpers/biteq.rs b/crates/core_simd/tests/helpers/biteq.rs index 00fc31f3d05..9da2bdfce42 100644 --- a/crates/core_simd/tests/helpers/biteq.rs +++ b/crates/core_simd/tests/helpers/biteq.rs @@ -70,12 +70,6 @@ impl_biteq! { integer impl BitEq for u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, - core_simd::masks::wide::m8, - core_simd::masks::wide::m16, - core_simd::masks::wide::m32, - core_simd::masks::wide::m64, - core_simd::masks::wide::m128, - core_simd::masks::wide::msize, } impl_biteq! { @@ -98,12 +92,6 @@ impl_biteq! { core_simd::isizex2, core_simd::isizex4, core_simd::isizex8, core_simd::f32x2, core_simd::f32x4, core_simd::f32x8, core_simd::f32x16, core_simd::f64x2, core_simd::f64x4, core_simd::f64x8, - core_simd::masks::wide::m8x8, core_simd::masks::wide::m8x16, core_simd::masks::wide::m8x32, core_simd::masks::wide::m8x64, - core_simd::masks::wide::m16x4, core_simd::masks::wide::m16x8, core_simd::masks::wide::m16x16, core_simd::masks::wide::m16x32, - core_simd::masks::wide::m32x2, core_simd::masks::wide::m32x4, core_simd::masks::wide::m32x8, core_simd::masks::wide::m32x16, - core_simd::masks::wide::m64x2, core_simd::masks::wide::m64x4, core_simd::masks::wide::m64x8, - core_simd::masks::wide::m128x2, core_simd::masks::wide::m128x4, - core_simd::masks::wide::msizex2, core_simd::masks::wide::msizex4, core_simd::masks::wide::msizex8, } pub(crate) struct BitEqWrapper<'a, T>(pub(crate) &'a T); diff --git a/crates/core_simd/tests/ops_impl/float_macros.rs b/crates/core_simd/tests/ops_impl/float_macros.rs index fe347a5362d..a46367d0cc2 100644 --- a/crates/core_simd/tests/ops_impl/float_macros.rs +++ b/crates/core_simd/tests/ops_impl/float_macros.rs @@ -335,6 +335,8 @@ macro_rules! float_tests { } } + // TODO reenable after converting float ops to platform intrinsics + /* #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn ceil_odd_floats() { @@ -413,6 +415,7 @@ macro_rules! float_tests { assert_biteq!(core_simd::$vector::round_from_int(v), expected); } } + */ } } } diff --git a/crates/core_simd/tests/ops_impl/mask_macros.rs b/crates/core_simd/tests/ops_impl/mask_macros.rs index 795f9e27c44..3aaa036b994 100644 --- a/crates/core_simd/tests/ops_impl/mask_macros.rs +++ b/crates/core_simd/tests/ops_impl/mask_macros.rs @@ -1,5 +1,6 @@ macro_rules! mask_tests { { $vector:ident, $lanes:literal } => { + /* #[cfg(test)] mod $vector { use core_simd::$vector as Vector; @@ -221,5 +222,6 @@ macro_rules! mask_tests { assert_eq!(!v, expected); } } + */ } } From 9cc3deaa9256060868bb952ea5f850a910633f19 Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Sun, 13 Dec 2020 23:58:33 -0500 Subject: [PATCH 08/13] Finish refactoring vector types --- crates/core_simd/src/intrinsics.rs | 2 +- crates/core_simd/src/lib.rs | 4 +- crates/core_simd/src/masks/full_masks/mod.rs | 199 ++++++ .../{wide => full_masks}/vectors_m128.rs | 0 .../masks/{wide => full_masks}/vectors_m16.rs | 0 .../masks/{wide => full_masks}/vectors_m32.rs | 0 .../masks/{wide => full_masks}/vectors_m64.rs | 0 .../masks/{wide => full_masks}/vectors_m8.rs | 3 + .../{wide => full_masks}/vectors_msize.rs | 0 crates/core_simd/src/masks/mod.rs | 588 ++++++++---------- crates/core_simd/src/masks/ops.rs | 208 ------- crates/core_simd/src/masks/wide/mod.rs | 139 ----- crates/core_simd/src/vectors_f32.rs | 9 +- crates/core_simd/src/vectors_f64.rs | 7 +- crates/core_simd/src/vectors_i128.rs | 5 +- crates/core_simd/src/vectors_i16.rs | 9 +- crates/core_simd/src/vectors_i32.rs | 9 +- crates/core_simd/src/vectors_i64.rs | 7 +- crates/core_simd/src/vectors_i8.rs | 9 +- crates/core_simd/src/vectors_isize.rs | 7 +- crates/core_simd/src/vectors_u128.rs | 5 +- crates/core_simd/src/vectors_u16.rs | 9 +- crates/core_simd/src/vectors_u32.rs | 9 +- crates/core_simd/src/vectors_u64.rs | 7 +- crates/core_simd/src/vectors_u8.rs | 9 +- crates/core_simd/src/vectors_usize.rs | 7 +- .../core_simd/tests/ops_impl/mask_macros.rs | 2 - 27 files changed, 568 insertions(+), 685 deletions(-) create mode 100644 crates/core_simd/src/masks/full_masks/mod.rs rename crates/core_simd/src/masks/{wide => full_masks}/vectors_m128.rs (100%) rename crates/core_simd/src/masks/{wide => full_masks}/vectors_m16.rs (100%) rename crates/core_simd/src/masks/{wide => full_masks}/vectors_m32.rs (100%) rename crates/core_simd/src/masks/{wide => full_masks}/vectors_m64.rs (100%) rename crates/core_simd/src/masks/{wide => full_masks}/vectors_m8.rs (82%) rename crates/core_simd/src/masks/{wide => full_masks}/vectors_msize.rs (100%) delete mode 100644 crates/core_simd/src/masks/ops.rs delete mode 100644 crates/core_simd/src/masks/wide/mod.rs diff --git a/crates/core_simd/src/intrinsics.rs b/crates/core_simd/src/intrinsics.rs index 3dfc77136f2..51689cd97be 100644 --- a/crates/core_simd/src/intrinsics.rs +++ b/crates/core_simd/src/intrinsics.rs @@ -1,7 +1,7 @@ //! This module contains the LLVM intrinsics bindings that provide the functionality for this //! crate. //! -//! The LLVM assembly language is documented here: https://llvm.org/docs/LangRef.html +//! The LLVM assembly language is documented here: /// These intrinsics aren't linked directly from LLVM and are mostly undocumented, however they are /// simply lowered to the matching LLVM instructions by the compiler. The associated instruction diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs index d23e5ad21ba..9d4ce683f22 100644 --- a/crates/core_simd/src/lib.rs +++ b/crates/core_simd/src/lib.rs @@ -11,8 +11,8 @@ mod intrinsics; mod ops; //mod round; -//pub mod masks; -//pub use masks::opaque::*; +mod masks; +pub use masks::*; mod vectors_u8; pub use vectors_u8::*; diff --git a/crates/core_simd/src/masks/full_masks/mod.rs b/crates/core_simd/src/masks/full_masks/mod.rs new file mode 100644 index 00000000000..829174669c2 --- /dev/null +++ b/crates/core_simd/src/masks/full_masks/mod.rs @@ -0,0 +1,199 @@ +//! Masks that take up full SIMD vector registers. + +/// The error type returned when converting an integer to a mask fails. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct TryFromMaskError(()); + +impl core::fmt::Display for TryFromMaskError { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "mask vector must have all bits set or unset in each lane") + } +} + +macro_rules! define_mask { + { $(#[$attr:meta])* struct $name:ident($type:ty); } => { + $(#[$attr])* + #[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash)] + #[repr(transparent)] + pub struct $name($type); + + delegate_ops_to_inner! { $name } + + impl $name<$lanes> { + /// Construct a mask by setting all lanes to the given value. + pub fn splat(value: bool) -> Self { + Self(<$type>::splat(value.into())) + } + + /// Tests the value of the specified lane. + /// + /// # Panics + /// Panics if `lane` is greater than or equal to the number of lanes in the vector. + #[inline] + pub fn test(&self, lane: usize) -> bool { + self.0[lane] > 0 + } + + /// Sets the value of the specified lane. + /// + /// # Panics + /// Panics if `lane` is greater than or equal to the number of lanes in the vector. + #[inline] + pub fn set(&mut self, lane: usize, value: bool) { + self.0[lane] = if value { + !0 + } else { + 0 + } + } + } + + impl core::convert::From for $name<$lanes> { + fn from(value: bool) -> Self { + Self::splat(value) + } + } + + impl core::convert::TryFrom<$type> for $name<$lanes> { + type Error = TryFromMaskError; + fn try_from(value: $type) -> Result { + if value.as_slice().iter().all(|x| *x == 0 || !*x == 0) { + Ok(Self(value)) + } else { + Err(TryFromMaskError(())) + } + } + } + + impl core::convert::From<$name<$lanes>> for $type { + fn from(value: $name<$lanes>) -> Self { + value.0 + } + } + + impl core::fmt::Debug for $name<$lanes> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + f.debug_list() + .entries((0..LANES).map(|lane| self.test(lane))) + .finish() + } + } + + impl core::fmt::Binary for $name<$lanes> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + core::fmt::Binary::fmt(&self.0, f) + } + } + + impl core::fmt::Octal for $name<$lanes> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + core::fmt::Octal::fmt(&self.0, f) + } + } + + impl core::fmt::LowerHex for $name<$lanes> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + core::fmt::LowerHex::fmt(&self.0, f) + } + } + + impl core::fmt::UpperHex for $name<$lanes> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + core::fmt::UpperHex::fmt(&self.0, f) + } + } + } +} + +define_mask! { + /// A mask equivalent to [SimdI8](crate::SimdI8), where all bits in the lane must be either set + /// or unset. + struct SimdI8Mask(crate::SimdI8); +} + +define_mask! { + /// A mask equivalent to [SimdI16](crate::SimdI16), where all bits in the lane must be either set + /// or unset. + struct SimdI16Mask(crate::SimdI16); +} + +define_mask! { + /// A mask equivalent to [SimdI32](crate::SimdI32), where all bits in the lane must be either set + /// or unset. + struct SimdI32Mask(crate::SimdI32); +} + +define_mask! { + /// A mask equivalent to [SimdI64](crate::SimdI64), where all bits in the lane must be either set + /// or unset. + struct SimdI64Mask(crate::SimdI64); +} + +define_mask! { + /// A mask equivalent to [SimdI128](crate::SimdI128), where all bits in the lane must be either set + /// or unset. + struct SimdI128Mask(crate::SimdI64); +} + +define_mask! { + /// A mask equivalent to [SimdIsize](crate::SimdIsize), where all bits in the lane must be either set + /// or unset. + struct SimdIsizeMask(crate::SimdI64); +} + +macro_rules! implement_mask_ext { + { $($vector:ident => $mask:ident,)* } => { + $( + impl crate::masks::MaskExt<$mask> for crate::$vector { + #[inline] + fn lanes_eq(&self, other: &Self) -> $mask { + unsafe { crate::intrinsics::simd_eq(self, other) } + } + + #[inline] + fn lanes_ne(&self, other: &Self) -> $mask { + unsafe { crate::intrinsics::simd_ne(self, other) } + } + + #[inline] + fn lanes_lt(&self, other: &Self) -> $mask { + unsafe { crate::intrinsics::simd_lt(self, other) } + } + + #[inline] + fn lanes_gt(&self, other: &Self) -> $mask { + unsafe { crate::intrinsics::simd_gt(self, other) } + } + + #[inline] + fn lanes_le(&self, other: &Self) -> $mask { + unsafe { crate::intrinsics::simd_le(self, other) } + } + + #[inline] + fn lanes_ge(&self, other: &Self) -> $mask { + unsafe { crate::intrinsics::simd_ge(self, other) } + } + } + )* + } +} + +implement_mask_ext! { + SimdI8 => SimdI8Mask, + SimdI16 => SimdI16Mask, + SimdI32 => SimdI32Mask, + SimdI64 => SimdI64Mask, + SimdI128 => SimdI128Mask, + SimdIsize => SimdIsizeMask, + + SimdU8 => SimdI8Mask, + SimdU16 => SimdI16Mask, + SimdU32 => SimdI32Mask, + SimdU64 => SimdI64Mask, + SimdU128 => SimdI128Mask, + SimdUsize => SimdIsizeMask, + + SimdF32 => SimdI32Mask, + SimdF64 => SimdI64Mask, +} diff --git a/crates/core_simd/src/masks/wide/vectors_m128.rs b/crates/core_simd/src/masks/full_masks/vectors_m128.rs similarity index 100% rename from crates/core_simd/src/masks/wide/vectors_m128.rs rename to crates/core_simd/src/masks/full_masks/vectors_m128.rs diff --git a/crates/core_simd/src/masks/wide/vectors_m16.rs b/crates/core_simd/src/masks/full_masks/vectors_m16.rs similarity index 100% rename from crates/core_simd/src/masks/wide/vectors_m16.rs rename to crates/core_simd/src/masks/full_masks/vectors_m16.rs diff --git a/crates/core_simd/src/masks/wide/vectors_m32.rs b/crates/core_simd/src/masks/full_masks/vectors_m32.rs similarity index 100% rename from crates/core_simd/src/masks/wide/vectors_m32.rs rename to crates/core_simd/src/masks/full_masks/vectors_m32.rs diff --git a/crates/core_simd/src/masks/wide/vectors_m64.rs b/crates/core_simd/src/masks/full_masks/vectors_m64.rs similarity index 100% rename from crates/core_simd/src/masks/wide/vectors_m64.rs rename to crates/core_simd/src/masks/full_masks/vectors_m64.rs diff --git a/crates/core_simd/src/masks/wide/vectors_m8.rs b/crates/core_simd/src/masks/full_masks/vectors_m8.rs similarity index 82% rename from crates/core_simd/src/masks/wide/vectors_m8.rs rename to crates/core_simd/src/masks/full_masks/vectors_m8.rs index 149e138739d..85506dd93e1 100644 --- a/crates/core_simd/src/masks/wide/vectors_m8.rs +++ b/crates/core_simd/src/masks/full_masks/vectors_m8.rs @@ -19,3 +19,6 @@ define_mask_vector! { /// Vector of 64 `m8` values struct m8x64([i8 as m8; 64]); } + +#[repr(transparent)] +struct VectorMask8(crate::SimdI8); diff --git a/crates/core_simd/src/masks/wide/vectors_msize.rs b/crates/core_simd/src/masks/full_masks/vectors_msize.rs similarity index 100% rename from crates/core_simd/src/masks/wide/vectors_msize.rs rename to crates/core_simd/src/masks/full_masks/vectors_msize.rs diff --git a/crates/core_simd/src/masks/mod.rs b/crates/core_simd/src/masks/mod.rs index 9fb3da00604..9c90373fb47 100644 --- a/crates/core_simd/src/masks/mod.rs +++ b/crates/core_simd/src/masks/mod.rs @@ -1,171 +1,9 @@ //! Types and traits associated with masking lanes of vectors. +#![allow(non_camel_case_types)] -pub mod wide; - -mod ops; -pub use ops::*; - -pub(crate) trait MaskImpl { - type Mask; -} - -impl MaskImpl for [u8; 8] { - type Mask = wide::m8x8; -} - -impl MaskImpl for [u8; 16] { - type Mask = wide::m8x16; -} - -impl MaskImpl for [u8; 32] { - type Mask = wide::m8x32; -} - -impl MaskImpl for [u8; 64] { - type Mask = wide::m8x64; -} - -impl MaskImpl for [u16; 4] { - type Mask = wide::m16x4; -} - -impl MaskImpl for [u16; 8] { - type Mask = wide::m16x8; -} - -impl MaskImpl for [u16; 16] { - type Mask = wide::m16x16; -} - -impl MaskImpl for [u16; 32] { - type Mask = wide::m16x32; -} - -impl MaskImpl for [u32; 2] { - type Mask = wide::m32x2; -} - -impl MaskImpl for [u32; 4] { - type Mask = wide::m32x4; -} - -impl MaskImpl for [u32; 8] { - type Mask = wide::m32x8; -} - -impl MaskImpl for [u32; 16] { - type Mask = wide::m32x16; -} - -impl MaskImpl for [u64; 2] { - type Mask = wide::m64x2; -} - -impl MaskImpl for [u64; 4] { - type Mask = wide::m64x4; -} - -impl MaskImpl for [u64; 8] { - type Mask = wide::m64x8; -} - -impl MaskImpl for [u128; 2] { - type Mask = wide::m128x2; -} - -impl MaskImpl for [u128; 4] { - type Mask = wide::m128x4; -} - -impl MaskImpl for [usize; 2] { - type Mask = wide::msizex2; -} - -impl MaskImpl for [usize; 4] { - type Mask = wide::msizex4; -} - -impl MaskImpl for [usize; 8] { - type Mask = wide::msizex8; -} - -macro_rules! define_opaque_mask { - { - $(#[$attr:meta])* - struct $name:ident([$width:ty; $lanes:tt]); - } => { - $(#[$attr])* - #[allow(non_camel_case_types)] - pub struct $name(<[$width; $lanes] as crate::masks::MaskImpl>::Mask); - - impl $name { - pub(crate) fn new_from_inner(inner: <[$width; $lanes] as crate::masks::MaskImpl>::Mask) -> Self { - Self(inner) - } - - /// Construct a mask by setting all lanes to the given value. - pub fn splat(value: bool) -> Self { - Self(<[$width; $lanes] as crate::masks::MaskImpl>::Mask::splat(value.into())) - } - - call_counting_args! { $lanes => define_opaque_mask => new [$width; $lanes] } - - /// Tests the value of the specified lane. - /// - /// # Panics - /// Panics if `lane` is greater than or equal to the number of lanes in the vector. - #[inline] - pub fn test(&self, lane: usize) -> bool { - self.0.test(lane) - } - - /// Sets the value of the specified lane. - /// - /// # Panics - /// Panics if `lane` is greater than or equal to the number of lanes in the vector. - #[inline] - pub fn set(&mut self, lane: usize, value: bool) { - self.0.set(lane, value); - } - } - - impl Copy for $name {} - - impl Clone for $name { - #[inline] - fn clone(&self) -> Self { - *self - } - } - - impl Default for $name { - #[inline] - fn default() -> Self { - Self::splat(false) - } - } - - impl PartialEq for $name { - #[inline] - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } - } - - impl PartialOrd for $name { - #[inline] - fn partial_cmp(&self, other: &Self) -> Option { - self.0.partial_cmp(&other.0) - } - } - - impl core::fmt::Debug for $name { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - core::fmt::Debug::fmt(&self.0, f) - } - } - - impl core::ops::BitAnd for $name { +macro_rules! delegate_ops_to_inner { + { $name:ident } => { + impl core::ops::BitAnd for $name { type Output = Self; #[inline] fn bitand(self, rhs: Self) -> Self { @@ -173,7 +11,7 @@ macro_rules! define_opaque_mask { } } - impl core::ops::BitAnd for $name { + impl core::ops::BitAnd for $name { type Output = Self; #[inline] fn bitand(self, rhs: bool) -> Self { @@ -181,15 +19,15 @@ macro_rules! define_opaque_mask { } } - impl core::ops::BitAnd<$name> for bool { - type Output = $name; + impl core::ops::BitAnd<$name> for bool { + type Output = $name; #[inline] - fn bitand(self, rhs: $name) -> $name { - $name::splat(self) & rhs + fn bitand(self, rhs: $name) -> $name { + $name::::splat(self) & rhs } } - impl core::ops::BitOr for $name { + impl core::ops::BitOr for $name { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self { @@ -197,7 +35,7 @@ macro_rules! define_opaque_mask { } } - impl core::ops::BitOr for $name { + impl core::ops::BitOr for $name { type Output = Self; #[inline] fn bitor(self, rhs: bool) -> Self { @@ -205,15 +43,15 @@ macro_rules! define_opaque_mask { } } - impl core::ops::BitOr<$name> for bool { - type Output = $name; + impl core::ops::BitOr<$name> for bool { + type Output = $name; #[inline] - fn bitor(self, rhs: $name) -> $name { - $name::splat(self) | rhs + fn bitor(self, rhs: $name) -> $name { + $name::::splat(self) | rhs } } - impl core::ops::BitXor for $name { + impl core::ops::BitXor for $name { type Output = Self; #[inline] fn bitxor(self, rhs: Self) -> Self::Output { @@ -221,7 +59,7 @@ macro_rules! define_opaque_mask { } } - impl core::ops::BitXor for $name { + impl core::ops::BitXor for $name { type Output = Self; #[inline] fn bitxor(self, rhs: bool) -> Self::Output { @@ -229,212 +67,324 @@ macro_rules! define_opaque_mask { } } - impl core::ops::BitXor<$name> for bool { - type Output = $name; + impl core::ops::BitXor<$name> for bool { + type Output = $name; #[inline] - fn bitxor(self, rhs: $name) -> Self::Output { - $name::splat(self) ^ rhs + fn bitxor(self, rhs: $name) -> Self::Output { + $name::::splat(self) ^ rhs } } - impl core::ops::Not for $name { - type Output = $name; + impl core::ops::Not for $name { + type Output = $name; #[inline] fn not(self) -> Self::Output { Self(!self.0) } } - impl core::ops::BitAndAssign for $name { + impl core::ops::BitAndAssign for $name { #[inline] fn bitand_assign(&mut self, rhs: Self) { self.0 &= rhs.0; } } - impl core::ops::BitAndAssign for $name { + impl core::ops::BitAndAssign for $name { #[inline] fn bitand_assign(&mut self, rhs: bool) { *self &= Self::splat(rhs); } } - impl core::ops::BitOrAssign for $name { + impl core::ops::BitOrAssign for $name { #[inline] fn bitor_assign(&mut self, rhs: Self) { self.0 |= rhs.0; } } - impl core::ops::BitOrAssign for $name { + impl core::ops::BitOrAssign for $name { #[inline] fn bitor_assign(&mut self, rhs: bool) { *self |= Self::splat(rhs); } } - impl core::ops::BitXorAssign for $name { + impl core::ops::BitXorAssign for $name { #[inline] fn bitxor_assign(&mut self, rhs: Self) { self.0 ^= rhs.0; } } - impl core::ops::BitXorAssign for $name { + impl core::ops::BitXorAssign for $name { #[inline] fn bitxor_assign(&mut self, rhs: bool) { *self ^= Self::splat(rhs); } } - }; - { new [$width:ty; $lanes:tt] $($var:ident)* } => { - /// Construct a vector by setting each lane to the given values. - #[allow(clippy::too_many_arguments)] - #[inline] - pub const fn new($($var: bool),*) -> Self { - Self(<[$width; $lanes] as crate::masks::MaskImpl>::Mask::new_from_bool($($var),*)) - } } } -pub(crate) mod opaque { - define_opaque_mask! { - /// Mask for 8 8-bit lanes. - /// - /// The layout of this type is unspecified. - struct mask8x8([u8; 8]); - } +pub mod full_masks; - define_opaque_mask! { - /// Mask for 16 8-bit lanes. - /// - /// The layout of this type is unspecified. - struct mask8x16([u8; 16]); - } +macro_rules! define_opaque_mask { + { + $(#[$attr:meta])* + struct $name:ident($inner_ty:ty); + } => { + $(#[$attr])* + #[allow(non_camel_case_types)] + pub struct $name($inner_ty); - define_opaque_mask! { - /// Mask for 32 8-bit lanes. - /// - /// The layout of this type is unspecified. - struct mask8x32([u8; 32]); - } + delegate_ops_to_inner! { $name } - define_opaque_mask! { - /// Mask for 64 8-bit lanes. - /// - /// The layout of this type is unspecified. - struct mask8x64([u8; 64]); - } + impl $name<$lanes> { + /// Construct a mask by setting all lanes to the given value. + pub fn splat(value: bool) -> Self { + Self(<$inner_ty>::splat(value)) + } - define_opaque_mask! { - /// Mask for 4 16-bit lanes. - /// - /// The layout of this type is unspecified. - struct mask16x4([u16; 4]); - } + /// Tests the value of the specified lane. + /// + /// # Panics + /// Panics if `lane` is greater than or equal to the number of lanes in the vector. + #[inline] + pub fn test(&self, lane: usize) -> bool { + self.0.test(lane) + } - define_opaque_mask! { - /// Mask for 8 16-bit lanes. - /// - /// The layout of this type is unspecified. - struct mask16x8([u16; 8]); - } + /// Sets the value of the specified lane. + /// + /// # Panics + /// Panics if `lane` is greater than or equal to the number of lanes in the vector. + #[inline] + pub fn set(&mut self, lane: usize, value: bool) { + self.0.set(lane, value); + } + } - define_opaque_mask! { - /// Mask for 16 16-bit lanes. - /// - /// The layout of this type is unspecified. - struct mask16x16([u16; 16]); - } + impl Copy for $name<$lanes> {} - define_opaque_mask! { - /// Mask for 32 16-bit lanes. - /// - /// The layout of this type is unspecified. - struct mask16x32([u16; 32]); - } + impl Clone for $name<$lanes> { + #[inline] + fn clone(&self) -> Self { + *self + } + } - define_opaque_mask! { - /// Mask for 2 32-bit lanes. - /// - /// The layout of this type is unspecified. - struct mask32x2([u32; 2]); - } + impl Default for $name<$lanes> { + #[inline] + fn default() -> Self { + Self::splat(false) + } + } - define_opaque_mask! { - /// Mask for 4 32-bit lanes. - /// - /// The layout of this type is unspecified. - struct mask32x4([u32; 4]); - } + impl PartialEq for $name<$lanes> { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } + } - define_opaque_mask! { - /// Mask for 8 32-bit lanes. - /// - /// The layout of this type is unspecified. - struct mask32x8([u32; 8]); - } + impl PartialOrd for $name<$lanes> { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + self.0.partial_cmp(&other.0) + } + } - define_opaque_mask! { - /// Mask for 16 32-bit lanes. - /// - /// The layout of this type is unspecified. - struct mask32x16([u32; 16]); - } + impl core::fmt::Debug for $name<$lanes> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + core::fmt::Debug::fmt(&self.0, f) + } + } + }; +} - define_opaque_mask! { - /// Mask for 2 64-bit lanes. - /// - /// The layout of this type is unspecified. - struct mask64x2([u64; 2]); - } +define_opaque_mask! { + /// Mask for vectors with `LANES` 8-bit elements. + /// + /// The layout of this type is unspecified. + struct Mask8(full_masks::SimdI8Mask); +} - define_opaque_mask! { - /// Mask for 4 64-bit lanes. - /// - /// The layout of this type is unspecified. - struct mask64x4([u64; 4]); - } +define_opaque_mask! { + /// Mask for vectors with `LANES` 16-bit elements. + /// + /// The layout of this type is unspecified. + struct Mask16(full_masks::SimdI16Mask); +} - define_opaque_mask! { - /// Mask for 8 64-bit lanes. - /// - /// The layout of this type is unspecified. - struct mask64x8([u64; 8]); - } +define_opaque_mask! { + /// Mask for vectors with `LANES` 32-bit elements. + /// + /// The layout of this type is unspecified. + struct Mask32(full_masks::SimdI32Mask); +} - define_opaque_mask! { - /// Mask for 2 128-bit lanes. - /// - /// The layout of this type is unspecified. - struct mask128x2([u128; 2]); - } +define_opaque_mask! { + /// Mask for vectors with `LANES` 64-bit elements. + /// + /// The layout of this type is unspecified. + struct Mask64(full_masks::SimdI64Mask); +} - define_opaque_mask! { - /// Mask for 4 128-bit lanes. - /// - /// The layout of this type is unspecified. - struct mask128x4([u128; 4]); - } +define_opaque_mask! { + /// Mask for vectors with `LANES` 128-bit elements. + /// + /// The layout of this type is unspecified. + struct Mask128(full_masks::SimdI128Mask); +} - define_opaque_mask! { - /// Mask for 2 `isize`-wide lanes. - /// - /// The layout of this type is unspecified. - struct masksizex2([usize; 2]); - } +define_opaque_mask! { + /// Mask for vectors with `LANES` pointer-width elements. + /// + /// The layout of this type is unspecified. + struct MaskSize(full_masks::SimdIsizeMask); +} - define_opaque_mask! { - /// Mask for 4 `isize`-wide lanes. - /// - /// The layout of this type is unspecified. - struct masksizex4([usize; 4]); - } +/// Mask-related operations using a particular mask layout. +pub trait MaskExt { + /// Test if each lane is equal to the corresponding lane in `other`. + fn lanes_eq(&self, other: &Self) -> Mask; + + /// Test if each lane is not equal to the corresponding lane in `other`. + fn lanes_ne(&self, other: &Self) -> Mask; + + /// Test if each lane is less than the corresponding lane in `other`. + fn lanes_lt(&self, other: &Self) -> Mask; + + /// Test if each lane is greater than the corresponding lane in `other`. + fn lanes_gt(&self, other: &Self) -> Mask; - define_opaque_mask! { - /// Mask for 8 `isize`-wide lanes. - /// - /// The layout of this type is unspecified. - struct masksizex8([usize; 8]); + /// Test if each lane is less than or equal to the corresponding lane in `other`. + fn lanes_le(&self, other: &Self) -> Mask; + + /// Test if each lane is greater than or equal to the corresponding lane in `other`. + fn lanes_ge(&self, other: &Self) -> Mask; +} + +macro_rules! implement_mask_ops { + { $($vector:ident => $mask:ident,)* } => { + $( + impl crate::$vector { + /// Test if each lane is equal to the corresponding lane in `other`. + #[inline] + pub fn lanes_eq(&self, other: &Self) -> $mask { + $mask(MaskExt::lanes_eq(self, other)) + } + + /// Test if each lane is not equal to the corresponding lane in `other`. + #[inline] + pub fn lanes_ne(&self, other: &Self) -> $mask { + $mask(MaskExt::lanes_ne(self, other)) + } + + /// Test if each lane is less than the corresponding lane in `other`. + #[inline] + pub fn lanes_lt(&self, other: &Self) -> $mask { + $mask(MaskExt::lanes_lt(self, other)) + } + + /// Test if each lane is greater than the corresponding lane in `other`. + #[inline] + pub fn lanes_gt(&self, other: &Self) -> $mask { + $mask(MaskExt::lanes_gt(self, other)) + } + + /// Test if each lane is less than or equal to the corresponding lane in `other`. + #[inline] + pub fn lanes_le(&self, other: &Self) -> $mask { + $mask(MaskExt::lanes_le(self, other)) + } + + /// Test if each lane is greater than or equal to the corresponding lane in `other`. + #[inline] + pub fn lanes_ge(&self, other: &Self) -> $mask { + $mask(MaskExt::lanes_ge(self, other)) + } + } + )* } } + +implement_mask_ops! { + SimdI8 => Mask8, + SimdI16 => Mask16, + SimdI32 => Mask32, + SimdI64 => Mask64, + SimdI128 => Mask128, + SimdIsize => MaskSize, + + SimdU8 => Mask8, + SimdU16 => Mask16, + SimdU32 => Mask32, + SimdU64 => Mask64, + SimdU128 => Mask128, + SimdUsize => MaskSize, + + SimdF32 => Mask32, + SimdF64 => Mask64, +} + +/// Vector of eight 8-bit masks +pub type mask8x8 = Mask8<8>; + +/// Vector of 16 8-bit masks +pub type mask8x16 = Mask8<16>; + +/// Vector of 32 8-bit masks +pub type mask8x32 = Mask8<32>; + +/// Vector of 16 8-bit masks +pub type mask8x64 = Mask8<64>; + +/// Vector of four 16-bit masks +pub type mask16x4 = Mask16<4>; + +/// Vector of eight 16-bit masks +pub type mask16x8 = Mask16<8>; + +/// Vector of 16 16-bit masks +pub type mask16x16 = Mask16<16>; + +/// Vector of 32 16-bit masks +pub type mask16x32 = Mask32<32>; + +/// Vector of two 32-bit masks +pub type mask32x2 = Mask32<2>; + +/// Vector of four 32-bit masks +pub type mask32x4 = Mask32<4>; + +/// Vector of eight 32-bit masks +pub type mask32x8 = Mask32<8>; + +/// Vector of 16 32-bit masks +pub type mask32x16 = Mask32<16>; + +/// Vector of two 64-bit masks +pub type mask64x2 = Mask64<2>; + +/// Vector of four 64-bit masks +pub type mask64x4 = Mask64<4>; + +/// Vector of eight 64-bit masks +pub type mask64x8 = Mask64<8>; + +/// Vector of two 128-bit masks +pub type mask128x2 = Mask128<2>; + +/// Vector of four 128-bit masks +pub type mask128x4 = Mask128<4>; + +/// Vector of two pointer-width masks +pub type masksizex2 = MaskSize<2>; + +/// Vector of four pointer-width masks +pub type masksizex4 = MaskSize<4>; + +/// Vector of eight pointer-width masks +pub type masksizex8 = MaskSize<8>; diff --git a/crates/core_simd/src/masks/ops.rs b/crates/core_simd/src/masks/ops.rs deleted file mode 100644 index 85ce955459a..00000000000 --- a/crates/core_simd/src/masks/ops.rs +++ /dev/null @@ -1,208 +0,0 @@ -/// Mask-related operations using a particular mask layout. -pub trait MaskExt { - /// Test if each lane is equal to the corresponding lane in `other`. - fn lanes_eq(self, other: Self) -> Mask; - - /// Test if each lane is not equal to the corresponding lane in `other`. - fn lanes_ne(self, other: Self) -> Mask; - - /// Test if each lane is less than the corresponding lane in `other`. - fn lanes_lt(self, other: Self) -> Mask; - - /// Test if each lane is greater than the corresponding lane in `other`. - fn lanes_gt(self, other: Self) -> Mask; - - /// Test if each lane is less than or equal to the corresponding lane in `other`. - fn lanes_le(self, other: Self) -> Mask; - - /// Test if each lane is greater than or equal to the corresponding lane in `other`. - fn lanes_ge(self, other: Self) -> Mask; -} - -macro_rules! implement_mask_ext { - { $($vector:ty => $($mask:ty),*;)* } => { - $( // vector - $( // mask - impl MaskExt<$mask> for $vector { - #[inline] - fn lanes_eq(self, other: Self) -> $mask { - unsafe { crate::intrinsics::simd_eq(self, other) } - } - - #[inline] - fn lanes_ne(self, other: Self) -> $mask { - unsafe { crate::intrinsics::simd_ne(self, other) } - } - - #[inline] - fn lanes_lt(self, other: Self) -> $mask { - unsafe { crate::intrinsics::simd_lt(self, other) } - } - - #[inline] - fn lanes_gt(self, other: Self) -> $mask { - unsafe { crate::intrinsics::simd_gt(self, other) } - } - - #[inline] - fn lanes_le(self, other: Self) -> $mask { - unsafe { crate::intrinsics::simd_le(self, other) } - } - - #[inline] - fn lanes_ge(self, other: Self) -> $mask { - unsafe { crate::intrinsics::simd_ge(self, other) } - } - } - )* - )* - } -} - -implement_mask_ext! { - crate::u8x8 => crate::masks::wide::m8x8; - crate::u8x16 => crate::masks::wide::m8x16; - crate::u8x32 => crate::masks::wide::m8x32; - crate::u8x64 => crate::masks::wide::m8x64; - crate::u16x4 => crate::masks::wide::m16x4; - crate::u16x8 => crate::masks::wide::m16x8; - crate::u16x16 => crate::masks::wide::m16x16; - crate::u16x32 => crate::masks::wide::m16x32; - crate::u32x2 => crate::masks::wide::m32x2; - crate::u32x4 => crate::masks::wide::m32x4; - crate::u32x8 => crate::masks::wide::m32x8; - crate::u32x16 => crate::masks::wide::m32x16; - crate::u64x2 => crate::masks::wide::m64x2; - crate::u64x4 => crate::masks::wide::m64x4; - crate::u64x8 => crate::masks::wide::m64x8; - crate::u128x2 => crate::masks::wide::m128x2; - crate::u128x4 => crate::masks::wide::m128x4; - crate::usizex2 => crate::masks::wide::msizex2; - crate::usizex4 => crate::masks::wide::msizex4; - crate::usizex8 => crate::masks::wide::msizex8; - - crate::i8x8 => crate::masks::wide::m8x8; - crate::i8x16 => crate::masks::wide::m8x16; - crate::i8x32 => crate::masks::wide::m8x32; - crate::i8x64 => crate::masks::wide::m8x64; - crate::i16x4 => crate::masks::wide::m16x4; - crate::i16x8 => crate::masks::wide::m16x8; - crate::i16x16 => crate::masks::wide::m16x16; - crate::i16x32 => crate::masks::wide::m16x32; - crate::i32x2 => crate::masks::wide::m32x2; - crate::i32x4 => crate::masks::wide::m32x4; - crate::i32x8 => crate::masks::wide::m32x8; - crate::i32x16 => crate::masks::wide::m32x16; - crate::i64x2 => crate::masks::wide::m64x2; - crate::i64x4 => crate::masks::wide::m64x4; - crate::i64x8 => crate::masks::wide::m64x8; - crate::i128x2 => crate::masks::wide::m128x2; - crate::i128x4 => crate::masks::wide::m128x4; - crate::isizex2 => crate::masks::wide::msizex2; - crate::isizex4 => crate::masks::wide::msizex4; - crate::isizex8 => crate::masks::wide::msizex8; - - crate::f32x2 => crate::masks::wide::m32x2; - crate::f32x4 => crate::masks::wide::m32x4; - crate::f32x8 => crate::masks::wide::m32x8; - crate::f32x16 => crate::masks::wide::m32x16; - crate::f64x2 => crate::masks::wide::m64x2; - crate::f64x4 => crate::masks::wide::m64x4; - crate::f64x8 => crate::masks::wide::m64x8; -} - -macro_rules! implement_mask_ops { - { $($vector:ty => $mask:ty,)* } => { - $( // vector - impl $vector { - /// Test if each lane is equal to the corresponding lane in `other`. - #[inline] - pub fn lanes_eq(self, other: Self) -> $mask { - <$mask>::new_from_inner(MaskExt::lanes_eq(self, other)) - } - - /// Test if each lane is not equal to the corresponding lane in `other`. - #[inline] - pub fn lanes_ne(self, other: Self) -> $mask { - <$mask>::new_from_inner(MaskExt::lanes_ne(self, other)) - } - - /// Test if each lane is less than the corresponding lane in `other`. - #[inline] - pub fn lanes_lt(self, other: Self) -> $mask { - <$mask>::new_from_inner(MaskExt::lanes_lt(self, other)) - } - - /// Test if each lane is greater than the corresponding lane in `other`. - #[inline] - pub fn lanes_gt(self, other: Self) -> $mask { - <$mask>::new_from_inner(MaskExt::lanes_gt(self, other)) - } - - /// Test if each lane is less than or equal to the corresponding lane in `other`. - #[inline] - pub fn lanes_le(self, other: Self) -> $mask { - <$mask>::new_from_inner(MaskExt::lanes_le(self, other)) - } - - /// Test if each lane is greater than or equal to the corresponding lane in `other`. - #[inline] - pub fn lanes_ge(self, other: Self) -> $mask { - <$mask>::new_from_inner(MaskExt::lanes_ge(self, other)) - } - } - )* - } -} - -implement_mask_ops! { - crate::u8x8 => crate::mask8x8, - crate::u8x16 => crate::mask8x16, - crate::u8x32 => crate::mask8x32, - crate::u8x64 => crate::mask8x64, - crate::u16x4 => crate::mask16x4, - crate::u16x8 => crate::mask16x8, - crate::u16x16 => crate::mask16x16, - crate::u16x32 => crate::mask16x32, - crate::u32x2 => crate::mask32x2, - crate::u32x4 => crate::mask32x4, - crate::u32x8 => crate::mask32x8, - crate::u32x16 => crate::mask32x16, - crate::u64x2 => crate::mask64x2, - crate::u64x4 => crate::mask64x4, - crate::u64x8 => crate::mask64x8, - crate::u128x2 => crate::mask128x2, - crate::u128x4 => crate::mask128x4, - crate::usizex2 => crate::masksizex2, - crate::usizex4 => crate::masksizex4, - crate::usizex8 => crate::masksizex8, - - crate::i8x8 => crate::mask8x8, - crate::i8x16 => crate::mask8x16, - crate::i8x32 => crate::mask8x32, - crate::i8x64 => crate::mask8x64, - crate::i16x4 => crate::mask16x4, - crate::i16x8 => crate::mask16x8, - crate::i16x16 => crate::mask16x16, - crate::i16x32 => crate::mask16x32, - crate::i32x2 => crate::mask32x2, - crate::i32x4 => crate::mask32x4, - crate::i32x8 => crate::mask32x8, - crate::i32x16 => crate::mask32x16, - crate::i64x2 => crate::mask64x2, - crate::i64x4 => crate::mask64x4, - crate::i64x8 => crate::mask64x8, - crate::i128x2 => crate::mask128x2, - crate::i128x4 => crate::mask128x4, - crate::isizex2 => crate::masksizex2, - crate::isizex4 => crate::masksizex4, - crate::isizex8 => crate::masksizex8, - - crate::f32x2 => crate::mask32x2, - crate::f32x4 => crate::mask32x4, - crate::f32x8 => crate::mask32x8, - crate::f32x16 => crate::mask32x16, - crate::f64x2 => crate::mask64x2, - crate::f64x4 => crate::mask64x4, - crate::f64x8 => crate::mask64x8, -} diff --git a/crates/core_simd/src/masks/wide/mod.rs b/crates/core_simd/src/masks/wide/mod.rs deleted file mode 100644 index 7df8ca7e53d..00000000000 --- a/crates/core_simd/src/masks/wide/mod.rs +++ /dev/null @@ -1,139 +0,0 @@ -//! Masks that take up full vector registers. - -mod vectors_m8; -pub use vectors_m8::*; -mod vectors_m16; -pub use vectors_m16::*; -mod vectors_m32; -pub use vectors_m32::*; -mod vectors_m64; -pub use vectors_m64::*; -mod vectors_m128; -pub use vectors_m128::*; -mod vectors_msize; -pub use vectors_msize::*; - -/// The error type returned when converting an integer to a mask fails. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct TryFromMaskError(()); - -impl core::fmt::Display for TryFromMaskError { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - write!(f, "mask must have all bits set or unset") - } -} - -macro_rules! define_mask { - { $(#[$attr:meta])* struct $name:ident($type:ty); } => { - $(#[$attr])* - #[allow(non_camel_case_types)] - #[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash)] - #[repr(transparent)] - pub struct $name(pub(crate) $type); - - impl $name { - /// Construct a mask from the given value. - pub const fn new(value: bool) -> Self { - if value { - Self(!0) - } else { - Self(0) - } - } - - /// Test if the mask is set. - pub const fn test(&self) -> bool { - self.0 != 0 - } - } - - impl core::convert::From for $name { - fn from(value: bool) -> Self { - Self::new(value) - } - } - - impl core::convert::From<$name> for bool { - fn from(mask: $name) -> Self { - mask.test() - } - } - - impl core::convert::TryFrom<$type> for $name { - type Error = TryFromMaskError; - fn try_from(value: $type) -> Result { - if value == 0 || !value == 0 { - Ok(Self(value)) - } else { - Err(TryFromMaskError(())) - } - } - } - - impl core::convert::From<$name> for $type { - fn from(value: $name) -> Self { - value.0 - } - } - - impl core::fmt::Debug for $name { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - self.test().fmt(f) - } - } - - impl core::fmt::Binary for $name { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - core::fmt::Binary::fmt(&self.0, f) - } - } - - impl core::fmt::Octal for $name { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - core::fmt::Octal::fmt(&self.0, f) - } - } - - impl core::fmt::LowerHex for $name { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - core::fmt::LowerHex::fmt(&self.0, f) - } - } - - impl core::fmt::UpperHex for $name { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - core::fmt::UpperHex::fmt(&self.0, f) - } - } - } -} - -define_mask! { - /// 8-bit mask - struct m8(i8); -} - -define_mask! { - /// 16-bit mask - struct m16(i16); -} - -define_mask! { - /// 32-bit mask - struct m32(i32); -} - -define_mask! { - /// 64-bit mask - struct m64(i64); -} - -define_mask! { - /// 128-bit mask - struct m128(i128); -} - -define_mask! { - /// `isize`-wide mask - struct msize(isize); -} diff --git a/crates/core_simd/src/vectors_f32.rs b/crates/core_simd/src/vectors_f32.rs index b1e13408cc9..0b5d8c6ec49 100644 --- a/crates/core_simd/src/vectors_f32.rs +++ b/crates/core_simd/src/vectors_f32.rs @@ -1,14 +1,21 @@ #![allow(non_camel_case_types)] -/// A SIMD vector of containing `LANES` lanes of `f32`. +/// A SIMD vector of containing `LANES` `f32` values. #[repr(simd)] pub struct SimdF32([f32; LANES]); impl_float_vector! { SimdF32, f32, SimdU32 } +/// Vector of two `f32` values pub type f32x2 = SimdF32<2>; + +/// Vector of four `f32` values pub type f32x4 = SimdF32<4>; + +/// Vector of eight `f32` values pub type f32x8 = SimdF32<8>; + +/// Vector of 16 `f32` values pub type f32x16 = SimdF32<16>; from_transmute_x86! { unsafe f32x4 => __m128 } diff --git a/crates/core_simd/src/vectors_f64.rs b/crates/core_simd/src/vectors_f64.rs index 4297c9d636c..307f8a4acac 100644 --- a/crates/core_simd/src/vectors_f64.rs +++ b/crates/core_simd/src/vectors_f64.rs @@ -1,13 +1,18 @@ #![allow(non_camel_case_types)] -/// A SIMD vector of containing `LANES` lanes of `f64`. +/// A SIMD vector of containing `LANES` `f64` values. #[repr(simd)] pub struct SimdF64([f64; LANES]); impl_float_vector! { SimdF64, f64, SimdU64 } +/// Vector of two `f64` values pub type f64x2 = SimdF64<2>; + +/// Vector of four `f64` values pub type f64x4 = SimdF64<4>; + +/// Vector of eight `f64` values pub type f64x8 = SimdF64<8>; from_transmute_x86! { unsafe f64x2 => __m128d } diff --git a/crates/core_simd/src/vectors_i128.rs b/crates/core_simd/src/vectors_i128.rs index a48c823cbd6..16e6162be55 100644 --- a/crates/core_simd/src/vectors_i128.rs +++ b/crates/core_simd/src/vectors_i128.rs @@ -1,12 +1,15 @@ #![allow(non_camel_case_types)] -/// A SIMD vector of containing `LANES` lanes of `i128`. +/// A SIMD vector of containing `LANES` `i128` values. #[repr(simd)] pub struct SimdI128([i128; LANES]); impl_integer_vector! { SimdI128, i128 } +/// Vector of two `i128` values pub type i128x2 = SimdI128<2>; + +/// Vector of four `i128` values pub type i128x4 = SimdI128<4>; from_transmute_x86! { unsafe i128x2 => __m256i } diff --git a/crates/core_simd/src/vectors_i16.rs b/crates/core_simd/src/vectors_i16.rs index 7bc522287a3..08cc4af2a5e 100644 --- a/crates/core_simd/src/vectors_i16.rs +++ b/crates/core_simd/src/vectors_i16.rs @@ -1,14 +1,21 @@ #![allow(non_camel_case_types)] -/// A SIMD vector of containing `LANES` lanes of `i16`. +/// A SIMD vector of containing `LANES` `i16` values. #[repr(simd)] pub struct SimdI16([i16; LANES]); impl_integer_vector! { SimdI16, i16 } +/// Vector of four `i16` values pub type i16x4 = SimdI16<4>; + +/// Vector of eight `i16` values pub type i16x8 = SimdI16<8>; + +/// Vector of 16 `i16` values pub type i16x16 = SimdI16<16>; + +/// Vector of 32 `i16` values pub type i16x32 = SimdI16<32>; from_transmute_x86! { unsafe i16x8 => __m128i } diff --git a/crates/core_simd/src/vectors_i32.rs b/crates/core_simd/src/vectors_i32.rs index 05533bb0b6d..116f2abaeee 100644 --- a/crates/core_simd/src/vectors_i32.rs +++ b/crates/core_simd/src/vectors_i32.rs @@ -1,14 +1,21 @@ #![allow(non_camel_case_types)] -/// A SIMD vector of containing `LANES` lanes of `i32`. +/// A SIMD vector of containing `LANES` `i32` values. #[repr(simd)] pub struct SimdI32([i32; LANES]); impl_integer_vector! { SimdI32, i32 } +/// Vector of two `i32` values pub type i32x2 = SimdI32<2>; + +/// Vector of four `i32` values pub type i32x4 = SimdI32<4>; + +/// Vector of eight `i32` values pub type i32x8 = SimdI32<8>; + +/// Vector of 16 `i32` values pub type i32x16 = SimdI32<16>; from_transmute_x86! { unsafe i32x4 => __m128i } diff --git a/crates/core_simd/src/vectors_i64.rs b/crates/core_simd/src/vectors_i64.rs index e669e8a367c..6a1e2094179 100644 --- a/crates/core_simd/src/vectors_i64.rs +++ b/crates/core_simd/src/vectors_i64.rs @@ -1,13 +1,18 @@ #![allow(non_camel_case_types)] -/// A SIMD vector of containing `LANES` lanes of `i64`. +/// A SIMD vector of containing `LANES` `i64` values. #[repr(simd)] pub struct SimdI64([i64; LANES]); impl_integer_vector! { SimdI64, i64 } +/// Vector of two `i64` values pub type i64x2 = SimdI64<2>; + +/// Vector of four `i64` values pub type i64x4 = SimdI64<4>; + +/// Vector of eight `i64` values pub type i64x8 = SimdI64<8>; from_transmute_x86! { unsafe i64x2 => __m128i } diff --git a/crates/core_simd/src/vectors_i8.rs b/crates/core_simd/src/vectors_i8.rs index 55a440cc92f..0ac5ba9efee 100644 --- a/crates/core_simd/src/vectors_i8.rs +++ b/crates/core_simd/src/vectors_i8.rs @@ -1,14 +1,21 @@ #![allow(non_camel_case_types)] -/// A SIMD vector of containing `LANES` lanes of `i8`. +/// A SIMD vector of containing `LANES` `i8` values. #[repr(simd)] pub struct SimdI8([i8; LANES]); impl_integer_vector! { SimdI8, i8 } +/// Vector of eight `i8` values pub type i8x8 = SimdI8<8>; + +/// Vector of 16 `i8` values pub type i8x16 = SimdI8<16>; + +/// Vector of 32 `i8` values pub type i8x32 = SimdI8<32>; + +/// Vector of 64 `i8` values pub type i8x64 = SimdI8<64>; from_transmute_x86! { unsafe i8x16 => __m128i } diff --git a/crates/core_simd/src/vectors_isize.rs b/crates/core_simd/src/vectors_isize.rs index 6d9b2061532..6856f305092 100644 --- a/crates/core_simd/src/vectors_isize.rs +++ b/crates/core_simd/src/vectors_isize.rs @@ -1,13 +1,18 @@ #![allow(non_camel_case_types)] -/// A SIMD vector of containing `LANES` lanes of `isize`. +/// A SIMD vector of containing `LANES` `isize` values. #[repr(simd)] pub struct SimdIsize([isize; LANES]); impl_integer_vector! { SimdIsize, isize } +/// Vector of two `isize` values pub type isizex2 = SimdIsize<2>; + +/// Vector of four `isize` values pub type isizex4 = SimdIsize<4>; + +/// Vector of eight `isize` values pub type isizex8 = SimdIsize<8>; #[cfg(target_pointer_width = "32")] diff --git a/crates/core_simd/src/vectors_u128.rs b/crates/core_simd/src/vectors_u128.rs index 54ad6e191f7..522404f133e 100644 --- a/crates/core_simd/src/vectors_u128.rs +++ b/crates/core_simd/src/vectors_u128.rs @@ -1,12 +1,15 @@ #![allow(non_camel_case_types)] -/// A SIMD vector of containing `LANES` lanes of `u128`. +/// A SIMD vector of containing `LANES` `u128` values. #[repr(simd)] pub struct SimdU128([u128; LANES]); impl_integer_vector! { SimdU128, u128 } +/// Vector of two `u128` values pub type u128x2 = SimdU128<2>; + +/// Vector of four `u128` values pub type u128x4 = SimdU128<4>; from_transmute_x86! { unsafe u128x2 => __m256i } diff --git a/crates/core_simd/src/vectors_u16.rs b/crates/core_simd/src/vectors_u16.rs index 7b0e345ef15..efe7dea58dc 100644 --- a/crates/core_simd/src/vectors_u16.rs +++ b/crates/core_simd/src/vectors_u16.rs @@ -1,14 +1,21 @@ #![allow(non_camel_case_types)] -/// A SIMD vector of containing `LANES` lanes of `u16`. +/// A SIMD vector of containing `LANES` `u16` values. #[repr(simd)] pub struct SimdU16([u16; LANES]); impl_integer_vector! { SimdU16, u16 } +/// Vector of four `u16` values pub type u16x4 = SimdU16<4>; + +/// Vector of eight `u16` values pub type u16x8 = SimdU16<8>; + +/// Vector of 16 `u16` values pub type u16x16 = SimdU16<16>; + +/// Vector of 32 `u16` values pub type u16x32 = SimdU16<32>; from_transmute_x86! { unsafe u16x8 => __m128i } diff --git a/crates/core_simd/src/vectors_u32.rs b/crates/core_simd/src/vectors_u32.rs index f80efbc59eb..a6cef5baeb7 100644 --- a/crates/core_simd/src/vectors_u32.rs +++ b/crates/core_simd/src/vectors_u32.rs @@ -1,14 +1,21 @@ #![allow(non_camel_case_types)] -/// A SIMD vector of containing `LANES` lanes of `u32`. +/// A SIMD vector of containing `LANES` `u32` values. #[repr(simd)] pub struct SimdU32([u32; LANES]); impl_integer_vector! { SimdU32, u32 } +/// Vector of two `u32` values pub type u32x2 = SimdU32<2>; + +/// Vector of four `u32` values pub type u32x4 = SimdU32<4>; + +/// Vector of eight `u32` values pub type u32x8 = SimdU32<8>; + +/// Vector of 16 `u32` values pub type u32x16 = SimdU32<16>; from_transmute_x86! { unsafe u32x4 => __m128i } diff --git a/crates/core_simd/src/vectors_u64.rs b/crates/core_simd/src/vectors_u64.rs index 848d90faaa7..3982e30f570 100644 --- a/crates/core_simd/src/vectors_u64.rs +++ b/crates/core_simd/src/vectors_u64.rs @@ -1,13 +1,18 @@ #![allow(non_camel_case_types)] -/// A SIMD vector of containing `LANES` lanes of `u64`. +/// A SIMD vector of containing `LANES` `u64` values. #[repr(simd)] pub struct SimdU64([u64; LANES]); impl_integer_vector! { SimdU64, u64 } +/// Vector of two `u64` values pub type u64x2 = SimdU64<2>; + +/// Vector of four `u64` values pub type u64x4 = SimdU64<4>; + +/// Vector of eight `u64` values pub type u64x8 = SimdU64<8>; from_transmute_x86! { unsafe u64x2 => __m128i } diff --git a/crates/core_simd/src/vectors_u8.rs b/crates/core_simd/src/vectors_u8.rs index b172801aa99..9cc4eaca47a 100644 --- a/crates/core_simd/src/vectors_u8.rs +++ b/crates/core_simd/src/vectors_u8.rs @@ -1,14 +1,21 @@ #![allow(non_camel_case_types)] -/// A SIMD vector of containing `LANES` lanes of `u8`. +/// A SIMD vector of containing `LANES` `u8` values. #[repr(simd)] pub struct SimdU8([u8; LANES]); impl_integer_vector! { SimdU8, u8 } +/// Vector of eight `u8` values pub type u8x8 = SimdU8<8>; + +/// Vector of 16 `u8` values pub type u8x16 = SimdU8<16>; + +/// Vector of 32 `u8` values pub type u8x32 = SimdU8<32>; + +/// Vector of 64 `u8` values pub type u8x64 = SimdU8<64>; from_transmute_x86! { unsafe u8x16 => __m128i } diff --git a/crates/core_simd/src/vectors_usize.rs b/crates/core_simd/src/vectors_usize.rs index b0655ab311b..c882898f9fb 100644 --- a/crates/core_simd/src/vectors_usize.rs +++ b/crates/core_simd/src/vectors_usize.rs @@ -1,13 +1,18 @@ #![allow(non_camel_case_types)] -/// A SIMD vector of containing `LANES` lanes of `usize`. +/// A SIMD vector of containing `LANES` `usize` values. #[repr(simd)] pub struct SimdUsize([usize; LANES]); impl_integer_vector! { SimdUsize, usize } +/// Vector of two `usize` values pub type usizex2 = SimdUsize<2>; + +/// Vector of four `usize` values pub type usizex4 = SimdUsize<4>; + +/// Vector of eight `usize` values pub type usizex8 = SimdUsize<8>; #[cfg(target_pointer_width = "32")] diff --git a/crates/core_simd/tests/ops_impl/mask_macros.rs b/crates/core_simd/tests/ops_impl/mask_macros.rs index 3aaa036b994..795f9e27c44 100644 --- a/crates/core_simd/tests/ops_impl/mask_macros.rs +++ b/crates/core_simd/tests/ops_impl/mask_macros.rs @@ -1,6 +1,5 @@ macro_rules! mask_tests { { $vector:ident, $lanes:literal } => { - /* #[cfg(test)] mod $vector { use core_simd::$vector as Vector; @@ -222,6 +221,5 @@ macro_rules! mask_tests { assert_eq!(!v, expected); } } - */ } } From 0ddf7acc89d414d12c4fc04c90cf208c78fd8d5e Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Mon, 14 Dec 2020 00:07:36 -0500 Subject: [PATCH 09/13] Reenable rounding ops --- crates/core_simd/src/lib.rs | 2 +- crates/core_simd/src/round.rs | 111 ++++++------------ .../core_simd/tests/ops_impl/float_macros.rs | 3 - 3 files changed, 35 insertions(+), 81 deletions(-) diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs index 9d4ce683f22..312a3237e23 100644 --- a/crates/core_simd/src/lib.rs +++ b/crates/core_simd/src/lib.rs @@ -9,7 +9,7 @@ mod macros; mod fmt; mod intrinsics; mod ops; -//mod round; +mod round; mod masks; pub use masks::*; diff --git a/crates/core_simd/src/round.rs b/crates/core_simd/src/round.rs index 0529bbe0080..d77bc4e8fa7 100644 --- a/crates/core_simd/src/round.rs +++ b/crates/core_simd/src/round.rs @@ -1,88 +1,45 @@ macro_rules! implement { { - impl $type:ident { - int_type = $int_type:ident - } + $type:ident, $int_type:ident } => { - mod $type { - impl crate::$type { - /// Returns the largest integer less than or equal to each lane. - #[must_use = "method returns a new vector and does not mutate the original value"] - #[inline] - pub fn floor(self) -> Self { - unsafe { crate::intrinsics::simd_floor(self) } - } + impl crate::$type { + /// Returns the largest integer less than or equal to each lane. + #[must_use = "method returns a new vector and does not mutate the original value"] + #[inline] + pub fn floor(self) -> Self { + unsafe { crate::intrinsics::simd_floor(self) } + } - /// Returns the smallest integer greater than or equal to each lane. - #[must_use = "method returns a new vector and does not mutate the original value"] - #[inline] - pub fn ceil(self) -> Self { - unsafe { crate::intrinsics::simd_ceil(self) } - } + /// Returns the smallest integer greater than or equal to each lane. + #[must_use = "method returns a new vector and does not mutate the original value"] + #[inline] + pub fn ceil(self) -> Self { + unsafe { crate::intrinsics::simd_ceil(self) } + } - /// Rounds toward zero and converts to the same-width integer type, assuming that - /// the value is finite and fits in that type. - /// - /// # Safety - /// The value must: - /// - /// * Not be NaN - /// * Not be infinite - /// * Be representable in the return type, after truncating off its fractional part - #[inline] - pub unsafe fn to_int_unchecked(self) -> crate::$int_type { - crate::intrinsics::simd_cast(self) - } + /// Rounds toward zero and converts to the same-width integer type, assuming that + /// the value is finite and fits in that type. + /// + /// # Safety + /// The value must: + /// + /// * Not be NaN + /// * Not be infinite + /// * Be representable in the return type, after truncating off its fractional part + #[inline] + pub unsafe fn to_int_unchecked(self) -> crate::$int_type { + crate::intrinsics::simd_cast(self) + } - /// Creates a floating-point vector from an integer vector. Rounds values that are - /// not exactly representable. - #[inline] - pub fn round_from_int(value: crate::$int_type) -> Self { - unsafe { crate::intrinsics::simd_cast(value) } - } + /// Creates a floating-point vector from an integer vector. Rounds values that are + /// not exactly representable. + #[inline] + pub fn round_from_int(value: crate::$int_type) -> Self { + unsafe { crate::intrinsics::simd_cast(value) } } } } } -implement! { - impl f32x2 { - int_type = i32x2 - } -} - -implement! { - impl f32x4 { - int_type = i32x4 - } -} - -implement! { - impl f32x8 { - int_type = i32x8 - } -} - -implement! { - impl f32x16 { - int_type = i32x16 - } -} - -implement! { - impl f64x2 { - int_type = i64x2 - } -} - -implement! { - impl f64x4 { - int_type = i64x4 - } -} - -implement! { - impl f64x8 { - int_type = i64x8 - } -} +implement! { SimdF32, SimdI32 } +implement! { SimdF64, SimdI64 } diff --git a/crates/core_simd/tests/ops_impl/float_macros.rs b/crates/core_simd/tests/ops_impl/float_macros.rs index a46367d0cc2..fe347a5362d 100644 --- a/crates/core_simd/tests/ops_impl/float_macros.rs +++ b/crates/core_simd/tests/ops_impl/float_macros.rs @@ -335,8 +335,6 @@ macro_rules! float_tests { } } - // TODO reenable after converting float ops to platform intrinsics - /* #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn ceil_odd_floats() { @@ -415,7 +413,6 @@ macro_rules! float_tests { assert_biteq!(core_simd::$vector::round_from_int(v), expected); } } - */ } } } From 2720ccc5a78b4cbad1687aff59bb8631d59109c3 Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Mon, 14 Dec 2020 00:27:20 -0500 Subject: [PATCH 10/13] Fix masks --- crates/core_simd/src/masks/full_masks/mod.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/crates/core_simd/src/masks/full_masks/mod.rs b/crates/core_simd/src/masks/full_masks/mod.rs index 829174669c2..eac5178512e 100644 --- a/crates/core_simd/src/masks/full_masks/mod.rs +++ b/crates/core_simd/src/masks/full_masks/mod.rs @@ -22,7 +22,13 @@ macro_rules! define_mask { impl $name<$lanes> { /// Construct a mask by setting all lanes to the given value. pub fn splat(value: bool) -> Self { - Self(<$type>::splat(value.into())) + Self(<$type>::splat( + if value { + -1 + } else { + 0 + } + )) } /// Tests the value of the specified lane. @@ -31,7 +37,7 @@ macro_rules! define_mask { /// Panics if `lane` is greater than or equal to the number of lanes in the vector. #[inline] pub fn test(&self, lane: usize) -> bool { - self.0[lane] > 0 + self.0[lane] == -1 } /// Sets the value of the specified lane. @@ -41,7 +47,7 @@ macro_rules! define_mask { #[inline] pub fn set(&mut self, lane: usize, value: bool) { self.0[lane] = if value { - !0 + -1 } else { 0 } @@ -57,7 +63,7 @@ macro_rules! define_mask { impl core::convert::TryFrom<$type> for $name<$lanes> { type Error = TryFromMaskError; fn try_from(value: $type) -> Result { - if value.as_slice().iter().all(|x| *x == 0 || !*x == 0) { + if value.as_slice().iter().all(|x| *x == 0 || *x == -1) { Ok(Self(value)) } else { Err(TryFromMaskError(())) From 62d98e3a11a289fc89da73f0c0601727de9cd28e Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Mon, 14 Dec 2020 00:34:32 -0500 Subject: [PATCH 11/13] Remove obsolete macros --- crates/core_simd/src/macros.rs | 109 ------------------------------ crates/core_simd/src/masks/mod.rs | 1 + crates/core_simd/src/ops.rs | 15 ---- 3 files changed, 1 insertion(+), 124 deletions(-) diff --git a/crates/core_simd/src/macros.rs b/crates/core_simd/src/macros.rs index 99adb669bc5..c8f8e222da1 100644 --- a/crates/core_simd/src/macros.rs +++ b/crates/core_simd/src/macros.rs @@ -26,115 +26,6 @@ macro_rules! from_transmute_x86 { } } -/// Calls a the macro `$mac` with the provided `$args` followed by `$repeat` repeated the specified -/// number of times. -macro_rules! call_repeat { - { 1 => $mac:path [$($repeat:tt)*] $($args:tt)* } => { - $mac! { - $($args)* - $($repeat)* - } - }; - { 2 => $mac:path [$($repeat:tt)*] $($args:tt)* } => { - $mac! { - $($args)* - $($repeat)* $($repeat)* - } - }; - { 4 => $mac:path [$($repeat:tt)*] $($args:tt)* } => { - $mac! { - $($args)* - $($repeat)* $($repeat)* $($repeat)* $($repeat)* - } - }; - { 8 => $mac:path [$($repeat:tt)*] $($args:tt)* } => { - $mac! { - $($args)* - $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* - } - }; - { 16 => $mac:path [$($repeat:tt)*] $($args:tt)* } => { - $mac! { - $($args)* - $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* - $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* - } - }; - { 32 => $mac:path [$($repeat:tt)*] $($args:tt)* } => { - $mac! { - $($args)* - $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* - $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* - $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* - $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* - } - }; - { 64 => $mac:path [$($repeat:tt)*] $($args:tt)* } => { - $mac! { - $($args)* - $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* - $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* - $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* - $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* - $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* - $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* - $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* - $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* - } - }; -} - -/// Calls the macro `$mac` with the specified `$args` followed by the specified number of unique -/// identifiers. -macro_rules! call_counting_args { - { 1 => $mac:path => $($args:tt)* } => { - $mac! { - $($args)* - value - } - }; - { 2 => $mac:path => $($args:tt)* } => { - $mac! { - $($args)* - v0 v1 - } - }; - { 4 => $mac:path => $($args:tt)* } => { - $mac! { - $($args)* - v0 v1 v2 v3 - } - }; - { 8 => $mac:path => $($args:tt)* } => { - $mac! { - $($args)* - v0 v1 v2 v3 v4 v5 v6 v7 - } - }; - { 16 => $mac:path => $($args:tt)* } => { - $mac! { - $($args)* - v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 - } - }; - { 32 => $mac:path => $($args:tt)* } => { - $mac! { - $($args)* - v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 - v16 v17 v18 v19 v20 v21 v22 v23 v24 v25 v26 v27 v28 v29 v30 v31 - } - }; - { 64 => $mac:path => $($args:tt)* } => { - $mac! { - $($args)* - v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 - v16 v17 v18 v19 v20 v21 v22 v23 v24 v25 v26 v27 v28 v29 v30 v31 - v32 v33 v34 v35 v36 v37 v38 v39 v40 v41 v42 v43 v44 v45 v46 v47 - v48 v49 v50 v51 v52 v53 v54 v55 v56 v57 v58 v59 v60 v61 v62 v63 - } - }; -} - /// Implements common traits on the specified vector `$name`, holding multiple `$lanes` of `$type`. macro_rules! impl_vector { { $name:ident, $type:ty } => { diff --git a/crates/core_simd/src/masks/mod.rs b/crates/core_simd/src/masks/mod.rs index 9c90373fb47..a075040affe 100644 --- a/crates/core_simd/src/masks/mod.rs +++ b/crates/core_simd/src/masks/mod.rs @@ -1,6 +1,7 @@ //! Types and traits associated with masking lanes of vectors. #![allow(non_camel_case_types)] +/// Implements bitwise ops on mask types by delegating the operators to the inner type. macro_rules! delegate_ops_to_inner { { $name:ident } => { impl core::ops::BitAnd for $name { diff --git a/crates/core_simd/src/ops.rs b/crates/core_simd/src/ops.rs index 942d071de44..a21e9ab5bf1 100644 --- a/crates/core_simd/src/ops.rs +++ b/crates/core_simd/src/ops.rs @@ -262,21 +262,6 @@ macro_rules! impl_float_ops { }; } -/// Implements mask operators for the provided types. -macro_rules! impl_mask_ops { - { $($scalar:ty => $($vector:ident),*;)* } => { - $( // scalar - $( // vector - impl_op! { impl BitAnd for $vector, $scalar } - impl_op! { impl BitOr for $vector, $scalar } - impl_op! { impl BitXor for $vector, $scalar } - impl_op! { impl Not for $vector, $scalar } - impl_op! { impl Index for $vector, $scalar } - )* - )* - }; -} - /// Implements unsigned integer operators for the provided types. macro_rules! impl_unsigned_int_ops { { $($scalar:ty => $($vector:ident),*;)* } => { From 9b8cb18c9f9efe95460a1d748894bc9b6a46a0f3 Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Mon, 14 Dec 2020 00:40:59 -0500 Subject: [PATCH 12/13] Remove obsolete files --- crates/core_simd/src/lib.rs | 13 ---------- .../src/masks/full_masks/vectors_m128.rs | 11 --------- .../src/masks/full_masks/vectors_m16.rs | 21 ---------------- .../src/masks/full_masks/vectors_m32.rs | 21 ---------------- .../src/masks/full_masks/vectors_m64.rs | 16 ------------- .../src/masks/full_masks/vectors_m8.rs | 24 ------------------- .../src/masks/full_masks/vectors_msize.rs | 16 ------------- 7 files changed, 122 deletions(-) delete mode 100644 crates/core_simd/src/masks/full_masks/vectors_m128.rs delete mode 100644 crates/core_simd/src/masks/full_masks/vectors_m16.rs delete mode 100644 crates/core_simd/src/masks/full_masks/vectors_m32.rs delete mode 100644 crates/core_simd/src/masks/full_masks/vectors_m64.rs delete mode 100644 crates/core_simd/src/masks/full_masks/vectors_m8.rs delete mode 100644 crates/core_simd/src/masks/full_masks/vectors_msize.rs diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs index 312a3237e23..3a3346975c1 100644 --- a/crates/core_simd/src/lib.rs +++ b/crates/core_simd/src/lib.rs @@ -44,16 +44,3 @@ mod vectors_f32; pub use vectors_f32::*; mod vectors_f64; pub use vectors_f64::*; - -//mod vectors_mask8; -//pub use vectors_mask8::*; -//mod vectors_mask16; -//pub use vectors_mask16::*; -//mod vectors_mask32; -//pub use vectors_mask32::*; -//mod vectors_mask64; -//pub use vectors_mask64::*; -//mod vectors_mask128; -//pub use vectors_mask128::*; -//mod vectors_masksize; -//pub use vectors_masksize::*; diff --git a/crates/core_simd/src/masks/full_masks/vectors_m128.rs b/crates/core_simd/src/masks/full_masks/vectors_m128.rs deleted file mode 100644 index fddddac5fc4..00000000000 --- a/crates/core_simd/src/masks/full_masks/vectors_m128.rs +++ /dev/null @@ -1,11 +0,0 @@ -use super::m128; - -define_mask_vector! { - /// Vector of two `m128` values - struct m128x2([i128 as m128; 2]); -} - -define_mask_vector! { - /// Vector of four `m128` values - struct m128x4([i128 as m128; 4]); -} diff --git a/crates/core_simd/src/masks/full_masks/vectors_m16.rs b/crates/core_simd/src/masks/full_masks/vectors_m16.rs deleted file mode 100644 index 3b05e83f673..00000000000 --- a/crates/core_simd/src/masks/full_masks/vectors_m16.rs +++ /dev/null @@ -1,21 +0,0 @@ -use super::m16; - -define_mask_vector! { - /// Vector of four `m16` values - struct m16x4([i16 as m16; 4]); -} - -define_mask_vector! { - /// Vector of eight `m16` values - struct m16x8([i16 as m16; 8]); -} - -define_mask_vector! { - /// Vector of 16 `m16` values - struct m16x16([i16 as m16; 16]); -} - -define_mask_vector! { - /// Vector of 32 `m16` values - struct m16x32([i16 as m16; 32]); -} diff --git a/crates/core_simd/src/masks/full_masks/vectors_m32.rs b/crates/core_simd/src/masks/full_masks/vectors_m32.rs deleted file mode 100644 index de5745fb283..00000000000 --- a/crates/core_simd/src/masks/full_masks/vectors_m32.rs +++ /dev/null @@ -1,21 +0,0 @@ -use super::m32; - -define_mask_vector! { - /// Vector of two `m32` values - struct m32x2([i32 as m32; 2]); -} - -define_mask_vector! { - /// Vector of four `m32` values - struct m32x4([i32 as m32; 4]); -} - -define_mask_vector! { - /// Vector of eight `m32` values - struct m32x8([i32 as m32; 8]); -} - -define_mask_vector! { - /// Vector of 16 `m32` values - struct m32x16([i32 as m32; 16]); -} diff --git a/crates/core_simd/src/masks/full_masks/vectors_m64.rs b/crates/core_simd/src/masks/full_masks/vectors_m64.rs deleted file mode 100644 index 55c8687fcfc..00000000000 --- a/crates/core_simd/src/masks/full_masks/vectors_m64.rs +++ /dev/null @@ -1,16 +0,0 @@ -use super::m64; - -define_mask_vector! { - /// Vector of two `m64` values - struct m64x2([i64 as m64; 2]); -} - -define_mask_vector! { - /// Vector of four `m64` values - struct m64x4([i64 as m64; 4]); -} - -define_mask_vector! { - /// Vector of eight `m64` values - struct m64x8([i64 as m64; 8]); -} diff --git a/crates/core_simd/src/masks/full_masks/vectors_m8.rs b/crates/core_simd/src/masks/full_masks/vectors_m8.rs deleted file mode 100644 index 85506dd93e1..00000000000 --- a/crates/core_simd/src/masks/full_masks/vectors_m8.rs +++ /dev/null @@ -1,24 +0,0 @@ -use super::m8; - -define_mask_vector! { - /// Vector of eight `m8` values - struct m8x8([i8 as m8; 8]); -} - -define_mask_vector! { - /// Vector of 16 `m8` values - struct m8x16([i8 as m8; 16]); -} - -define_mask_vector! { - /// Vector of 32 `m8` values - struct m8x32([i8 as m8; 32]); -} - -define_mask_vector! { - /// Vector of 64 `m8` values - struct m8x64([i8 as m8; 64]); -} - -#[repr(transparent)] -struct VectorMask8(crate::SimdI8); diff --git a/crates/core_simd/src/masks/full_masks/vectors_msize.rs b/crates/core_simd/src/masks/full_masks/vectors_msize.rs deleted file mode 100644 index 497aba8ddbb..00000000000 --- a/crates/core_simd/src/masks/full_masks/vectors_msize.rs +++ /dev/null @@ -1,16 +0,0 @@ -use super::msize; - -define_mask_vector! { - /// Vector of two `msize` values - struct msizex2([isize as msize; 2]); -} - -define_mask_vector! { - /// Vector of four `msize` values - struct msizex4([isize as msize; 4]); -} - -define_mask_vector! { - /// Vector of eight `msize` values - struct msizex8([isize as msize; 8]); -} From 59947717c5644a110caea924114b8f64fcb8234c Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Thu, 17 Dec 2020 01:19:39 -0500 Subject: [PATCH 13/13] Add workaround for rust-lang/rust#80108 --- crates/core_simd/src/macros.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/crates/core_simd/src/macros.rs b/crates/core_simd/src/macros.rs index c8f8e222da1..7e4d8514249 100644 --- a/crates/core_simd/src/macros.rs +++ b/crates/core_simd/src/macros.rs @@ -52,7 +52,23 @@ macro_rules! impl_vector { /// Converts a SIMD vector to an array. pub const fn to_array(self) -> [$type; LANES] { - self.0 + // workaround for rust-lang/rust#80108 + // TODO fix this + #[cfg(target_arch = "wasm32")] + { + let mut arr = [self.0[0]; LANES]; + let mut i = 0; + while i < LANES { + arr[i] = self.0[i]; + i += 1; + } + arr + } + + #[cfg(not(target_arch = "wasm32"))] + { + self.0 + } } }