about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCaleb Zulawski <caleb.zulawski@gmail.com>2022-02-06 03:25:27 +0000
committerJubilee Young <workingjubilee@gmail.com>2022-02-24 18:03:40 -0800
commit11c3eefa3594055192612d0d6f844e764dcbda15 (patch)
tree4147eaaccf8c9f9b4814856deaf1b6fb6f1c8e78
parent842ac87747c4a6f8002ada6bab04d97320d206fc (diff)
downloadrust-11c3eefa3594055192612d0d6f844e764dcbda15.tar.gz
rust-11c3eefa3594055192612d0d6f844e764dcbda15.zip
Manually implement for supported lanes
-rw-r--r--crates/core_simd/src/masks/bitmask.rs5
-rw-r--r--crates/core_simd/src/masks/full_masks.rs6
-rw-r--r--crates/core_simd/src/masks/to_bitmask.rs84
-rw-r--r--crates/core_simd/tests/masks.rs2
4 files changed, 38 insertions, 59 deletions
diff --git a/crates/core_simd/src/masks/bitmask.rs b/crates/core_simd/src/masks/bitmask.rs
index f20f83ecb38..e27b2689606 100644
--- a/crates/core_simd/src/masks/bitmask.rs
+++ b/crates/core_simd/src/masks/bitmask.rs
@@ -116,12 +116,13 @@ where
     }
 
     #[inline]
-    pub unsafe fn to_bitmask_intrinsic<U>(self) -> U {
+    pub unsafe fn to_bitmask_integer<U>(self) -> U {
         unsafe { core::mem::transmute_copy(&self.0) }
     }
 
+    // Safety: U must be the integer with the exact number of bits required to hold the bitmask for
     #[inline]
-    pub unsafe fn from_bitmask_intrinsic<U>(bitmask: U) -> Self {
+    pub unsafe fn from_bitmask_integer<U>(bitmask: U) -> Self {
         unsafe { Self(core::mem::transmute_copy(&bitmask), PhantomData) }
     }
 
diff --git a/crates/core_simd/src/masks/full_masks.rs b/crates/core_simd/src/masks/full_masks.rs
index b20b0a4b708..90af486a887 100644
--- a/crates/core_simd/src/masks/full_masks.rs
+++ b/crates/core_simd/src/masks/full_masks.rs
@@ -110,13 +110,15 @@ where
     }
 
     #[inline]
-    pub unsafe fn to_bitmask_intrinsic<U>(self) -> U {
+    pub unsafe fn to_bitmask_integer<U>(self) -> U {
         // Safety: caller must only return bitmask types
         unsafe { intrinsics::simd_bitmask(self.0) }
     }
 
+    // Safety: U must be the integer with the exact number of bits required to hold the bitmask for
+    // this mask
     #[inline]
-    pub unsafe fn from_bitmask_intrinsic<U>(bitmask: U) -> Self {
+    pub unsafe fn from_bitmask_integer<U>(bitmask: U) -> Self {
         // Safety: caller must only pass bitmask types
         unsafe {
             Self::from_int_unchecked(intrinsics::simd_select_bitmask(
diff --git a/crates/core_simd/src/masks/to_bitmask.rs b/crates/core_simd/src/masks/to_bitmask.rs
index 3a9f89f19eb..86143f2331f 100644
--- a/crates/core_simd/src/masks/to_bitmask.rs
+++ b/crates/core_simd/src/masks/to_bitmask.rs
@@ -1,78 +1,54 @@
 use super::{mask_impl, Mask, MaskElement};
 
-/// Converts masks to and from bitmasks.
+/// Converts masks to and from integer bitmasks.
 ///
-/// In a bitmask, each bit represents if the corresponding lane in the mask is set.
-pub trait ToBitMask<BitMask> {
+/// Each bit of the bitmask corresponds to a mask lane, starting with the LSB.
+pub trait ToBitMask {
+    /// The integer bitmask type.
+    type BitMask;
+
     /// Converts a mask to a bitmask.
-    fn to_bitmask(self) -> BitMask;
+    fn to_bitmask(self) -> Self::BitMask;
 
     /// Converts a bitmask to a mask.
-    fn from_bitmask(bitmask: BitMask) -> Self;
+    fn from_bitmask(bitmask: Self::BitMask) -> Self;
 }
 
-macro_rules! impl_integer_intrinsic {
-    { $(unsafe impl ToBitMask<$int:ty> for Mask<_, $lanes:literal>)* } => {
-        $(
-        impl<T: MaskElement> ToBitMask<$int> for Mask<T, $lanes> {
-            fn to_bitmask(self) -> $int {
-                unsafe { self.0.to_bitmask_intrinsic() }
-            }
+/// Converts masks to and from byte array bitmasks.
+///
+/// Each bit of the bitmask corresponds to a mask lane, starting with the LSB of the first byte.
+pub trait ToBitMaskArray {
+    /// The length of the bitmask array.
+    const BYTES: usize;
 
-            fn from_bitmask(bitmask: $int) -> Self {
-                unsafe { Self(mask_impl::Mask::from_bitmask_intrinsic(bitmask)) }
-            }
-        }
-        )*
-    }
-}
+    /// Converts a mask to a bitmask.
+    fn to_bitmask_array(self) -> [u8; Self::BYTES];
 
-impl_integer_intrinsic! {
-    unsafe impl ToBitMask<u8> for Mask<_, 8>
-    unsafe impl ToBitMask<u16> for Mask<_, 16>
-    unsafe impl ToBitMask<u32> for Mask<_, 32>
-    unsafe impl ToBitMask<u64> for Mask<_, 64>
+    /// Converts a bitmask to a mask.
+    fn from_bitmask_array(bitmask: [u8; Self::BYTES]) -> Self;
 }
 
-macro_rules! impl_integer_via {
-    { $(impl ToBitMask<$int:ty, via $via:ty> for Mask<_, $lanes:literal>)* } => {
+macro_rules! impl_integer_intrinsic {
+    { $(unsafe impl ToBitMask<BitMask=$int:ty> for Mask<_, $lanes:literal>)* } => {
         $(
-        impl<T: MaskElement> ToBitMask<$int> for Mask<T, $lanes> {
+        impl<T: MaskElement> ToBitMask for Mask<T, $lanes> {
+            type BitMask = $int;
+
             fn to_bitmask(self) -> $int {
-                let bitmask: $via = self.to_bitmask();
-                bitmask as _
+                unsafe { self.0.to_bitmask_integer() }
             }
 
             fn from_bitmask(bitmask: $int) -> Self {
-                Self::from_bitmask(bitmask as $via)
+                unsafe { Self(mask_impl::Mask::from_bitmask_integer(bitmask)) }
             }
         }
         )*
     }
 }
 
-impl_integer_via! {
-    impl ToBitMask<u16, via u8> for Mask<_, 8>
-    impl ToBitMask<u32, via u8> for Mask<_, 8>
-    impl ToBitMask<u64, via u8> for Mask<_, 8>
-
-    impl ToBitMask<u32, via u16> for Mask<_, 16>
-    impl ToBitMask<u64, via u16> for Mask<_, 16>
-
-    impl ToBitMask<u64, via u32> for Mask<_, 32>
-}
-
-#[cfg(target_pointer_width = "32")]
-impl_integer_via! {
-    impl ToBitMask<usize, via u8> for Mask<_, 8>
-    impl ToBitMask<usize, via u16> for Mask<_, 16>
-    impl ToBitMask<usize, via u32> for Mask<_, 32>
-}
-
-#[cfg(target_pointer_width = "64")]
-impl_integer_via! {
-    impl ToBitMask<usize, via u8> for Mask<_, 8>
-    impl ToBitMask<usize, via u16> for Mask<_, 16>
-    impl ToBitMask<usize, via u32> for Mask<_, 32>
-    impl ToBitMask<usize, via u64> for Mask<_, 64>
+impl_integer_intrinsic! {
+    unsafe impl ToBitMask<BitMask=u8> for Mask<_, 8>
+    unsafe impl ToBitMask<BitMask=u16> for Mask<_, 16>
+    unsafe impl ToBitMask<BitMask=u32> for Mask<_, 32>
+    unsafe impl ToBitMask<BitMask=u64> for Mask<_, 64>
 }
diff --git a/crates/core_simd/tests/masks.rs b/crates/core_simd/tests/masks.rs
index 965c0fa2635..3aec36ca7b7 100644
--- a/crates/core_simd/tests/masks.rs
+++ b/crates/core_simd/tests/masks.rs
@@ -76,7 +76,7 @@ macro_rules! test_mask_api {
                     true, true, false, false, false, false, false, true,
                 ];
                 let mask = core_simd::Mask::<$type, 16>::from_array(values);
-                let bitmask: u16 = mask.to_bitmask();
+                let bitmask = mask.to_bitmask();
                 assert_eq!(bitmask, 0b1000001101001001);
                 assert_eq!(core_simd::Mask::<$type, 16>::from_bitmask(bitmask), mask);
             }