diff options
| author | Caleb Zulawski <caleb.zulawski@gmail.com> | 2021-06-21 17:05:43 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-06-21 14:05:43 -0700 |
| commit | 15b4e280049a2b495635027ebfcb3b6930fbc12a (patch) | |
| tree | cb6d38b90c600e0faf9ff5083b378858d20552b0 | |
| parent | 57e67c905fe9fb3d45a1714d25baa5dfc143299c (diff) | |
| download | rust-15b4e280049a2b495635027ebfcb3b6930fbc12a.tar.gz rust-15b4e280049a2b495635027ebfcb3b6930fbc12a.zip | |
Add from_bitmask (#136)
* Add from_bitmask * Add mips workaround
| -rw-r--r-- | crates/core_simd/src/masks/bitmask.rs | 9 | ||||
| -rw-r--r-- | crates/core_simd/src/masks/full_masks.rs | 24 | ||||
| -rw-r--r-- | crates/core_simd/src/masks/mod.rs | 5 | ||||
| -rw-r--r-- | crates/core_simd/tests/masks.rs | 6 |
4 files changed, 42 insertions, 2 deletions
diff --git a/crates/core_simd/src/masks/bitmask.rs b/crates/core_simd/src/masks/bitmask.rs index 31c7f6e7c28..fab136d2b24 100644 --- a/crates/core_simd/src/masks/bitmask.rs +++ b/crates/core_simd/src/masks/bitmask.rs @@ -101,6 +101,15 @@ impl<T: Mask, const LANES: usize> BitMask<T, LANES> { } #[inline] + pub fn from_bitmask<U: Mask>(bitmask: U::BitMask) -> Self { + assert_eq!( + core::mem::size_of::<T::BitMask>(), + core::mem::size_of::<U::BitMask>() + ); + unsafe { core::mem::transmute_copy(&bitmask) } + } + + #[inline] pub fn any(self) -> bool { self != Self::splat(false) } diff --git a/crates/core_simd/src/masks/full_masks.rs b/crates/core_simd/src/masks/full_masks.rs index c2bfa03dfc6..7d98333ef60 100644 --- a/crates/core_simd/src/masks/full_masks.rs +++ b/crates/core_simd/src/masks/full_masks.rs @@ -126,6 +126,30 @@ macro_rules! define_mask { bitmask } } + + #[inline] + pub fn from_bitmask<U: crate::Mask>(mut bitmask: U::BitMask) -> Self { + unsafe { + // There is a bug where LLVM appears to implement this operation with the wrong + // bit order. + // TODO fix this in a better way + if cfg!(any(target_arch = "mips", target_arch = "mips64")) { + for x in bitmask.as_mut() { + *x = x.reverse_bits(); + } + } + + // TODO remove the transmute when rustc is more flexible + assert_eq!(core::mem::size_of::<U::IntBitMask>(), core::mem::size_of::<U::BitMask>()); + let bitmask: U::IntBitMask = core::mem::transmute_copy(&bitmask); + + Self::from_int_unchecked(crate::intrinsics::simd_select_bitmask( + bitmask, + Self::splat(true).to_int(), + Self::splat(false).to_int(), + )) + } + } } impl<T: Mask, const LANES: usize> core::convert::From<$name<T, LANES>> for crate::$type<LANES> diff --git a/crates/core_simd/src/masks/mod.rs b/crates/core_simd/src/masks/mod.rs index 81a410de200..1d6b2e45224 100644 --- a/crates/core_simd/src/masks/mod.rs +++ b/crates/core_simd/src/masks/mod.rs @@ -178,6 +178,11 @@ macro_rules! define_opaque_mask { pub fn to_bitmask(self) -> <Self as Mask>::BitMask { self.0.to_bitmask::<Self>() } + + /// Convert a bitmask to a mask. + pub fn from_bitmask(bitmask: <Self as Mask>::BitMask) -> Self { + Self(<$inner_ty>::from_bitmask::<Self>(bitmask)) + } } // vector/array conversion diff --git a/crates/core_simd/tests/masks.rs b/crates/core_simd/tests/masks.rs index 5c2e60dd7c8..32dea49729f 100644 --- a/crates/core_simd/tests/masks.rs +++ b/crates/core_simd/tests/masks.rs @@ -67,13 +67,15 @@ macro_rules! test_mask_api { } #[test] - fn to_bitmask() { + fn roundtrip_bitmask_conversion() { let values = [ true, false, false, true, false, false, true, false, true, true, false, false, false, false, false, true, ]; let mask = core_simd::$name::<16>::from_array(values); - assert_eq!(mask.to_bitmask(), [0b01001001, 0b10000011]); + let bitmask = mask.to_bitmask(); + assert_eq!(bitmask, [0b01001001, 0b10000011]); + assert_eq!(core_simd::$name::<16>::from_bitmask(bitmask), mask); } } } |
