Change bitmasks to use less opaque type

This commit is contained in:
Caleb Zulawski 2021-07-29 04:55:28 +00:00
parent 9ab050796f
commit cca9102429
4 changed files with 19 additions and 12 deletions

View File

@ -6,9 +6,14 @@ use sealed::Sealed;
/// A type representing a vector lane count. /// A type representing a vector lane count.
pub struct LaneCount<const LANES: usize>; pub struct LaneCount<const LANES: usize>;
impl<const LANES: usize> LaneCount<LANES> {
/// The number of bytes in a bitmask with this many lanes.
pub const BITMASK_LEN: usize = (LANES + 7) / 8;
}
/// Helper trait for vector lane counts. /// Helper trait for vector lane counts.
pub trait SupportedLaneCount: Sealed { pub trait SupportedLaneCount: Sealed {
/// The bitmask representation of a mask. #[doc(hidden)]
type BitMask: Copy + Default + AsRef<[u8]> + AsMut<[u8]>; type BitMask: Copy + Default + AsRef<[u8]> + AsMut<[u8]>;
#[doc(hidden)] #[doc(hidden)]

View File

@ -160,12 +160,12 @@ macro_rules! define_opaque_mask {
} }
/// Convert this mask to a bitmask, with one bit set per lane. /// Convert this mask to a bitmask, with one bit set per lane.
pub fn to_bitmask(self) -> <crate::LaneCount<LANES> as crate::SupportedLaneCount>::BitMask { pub fn to_bitmask(self) -> [u8; crate::LaneCount::<LANES>::BITMASK_LEN] {
self.0.to_bitmask() self.0.to_bitmask()
} }
/// Convert a bitmask to a mask. /// Convert a bitmask to a mask.
pub fn from_bitmask(bitmask: <crate::LaneCount<LANES> as crate::SupportedLaneCount>::BitMask) -> Self { pub fn from_bitmask(bitmask: [u8; crate::LaneCount::<LANES>::BITMASK_LEN]) -> Self {
Self(<$inner_ty>::from_bitmask(bitmask)) Self(<$inner_ty>::from_bitmask(bitmask))
} }
} }

View File

@ -128,13 +128,15 @@ where
} }
#[inline] #[inline]
pub fn to_bitmask(self) -> <LaneCount<LANES> as SupportedLaneCount>::BitMask { pub fn to_bitmask(self) -> [u8; LaneCount::<LANES>::BITMASK_LEN] {
self.0 // Safety: these are the same type and we are laundering the generic
unsafe { core::mem::transmute_copy(&self.0) }
} }
#[inline] #[inline]
pub fn from_bitmask(bitmask: <LaneCount<LANES> as SupportedLaneCount>::BitMask) -> Self { pub fn from_bitmask(bitmask: [u8; LaneCount::<LANES>::BITMASK_LEN]) -> Self {
Self(bitmask) // Safety: these are the same type and we are laundering the generic
Self(unsafe { core::mem::transmute_copy(&bitmask) })
} }
#[inline] #[inline]

View File

@ -103,15 +103,15 @@ macro_rules! define_mask {
} }
#[inline] #[inline]
pub fn to_bitmask(self) -> <crate::LaneCount::<LANES> as crate::SupportedLaneCount>::BitMask { pub fn to_bitmask(self) -> [u8; crate::LaneCount::<LANES>::BITMASK_LEN] {
unsafe { unsafe {
// TODO remove the transmute when rustc can use arrays of u8 as bitmasks // TODO remove the transmute when rustc can use arrays of u8 as bitmasks
assert_eq!( assert_eq!(
core::mem::size_of::<<crate::LaneCount::<LANES> as crate::SupportedLaneCount>::BitMask>(),
core::mem::size_of::<<crate::LaneCount::<LANES> as crate::SupportedLaneCount>::IntBitMask>(), core::mem::size_of::<<crate::LaneCount::<LANES> as crate::SupportedLaneCount>::IntBitMask>(),
crate::LaneCount::<LANES>::BITMASK_LEN,
); );
let bitmask: <crate::LaneCount::<LANES> as crate::SupportedLaneCount>::IntBitMask = crate::intrinsics::simd_bitmask(self.0); let bitmask: <crate::LaneCount::<LANES> as crate::SupportedLaneCount>::IntBitMask = crate::intrinsics::simd_bitmask(self.0);
let mut bitmask: <crate::LaneCount::<LANES> as crate::SupportedLaneCount>::BitMask = core::mem::transmute_copy(&bitmask); let mut bitmask: [u8; crate::LaneCount::<LANES>::BITMASK_LEN] = core::mem::transmute_copy(&bitmask);
// There is a bug where LLVM appears to implement this operation with the wrong // There is a bug where LLVM appears to implement this operation with the wrong
// bit order. // bit order.
@ -127,7 +127,7 @@ macro_rules! define_mask {
} }
#[inline] #[inline]
pub fn from_bitmask(mut bitmask: <crate::LaneCount::<LANES> as crate::SupportedLaneCount>::BitMask) -> Self { pub fn from_bitmask(mut bitmask: [u8; crate::LaneCount::<LANES>::BITMASK_LEN]) -> Self {
unsafe { unsafe {
// There is a bug where LLVM appears to implement this operation with the wrong // There is a bug where LLVM appears to implement this operation with the wrong
// bit order. // bit order.
@ -140,8 +140,8 @@ macro_rules! define_mask {
// TODO remove the transmute when rustc can use arrays of u8 as bitmasks // TODO remove the transmute when rustc can use arrays of u8 as bitmasks
assert_eq!( assert_eq!(
core::mem::size_of::<<crate::LaneCount::<LANES> as crate::SupportedLaneCount>::BitMask>(),
core::mem::size_of::<<crate::LaneCount::<LANES> as crate::SupportedLaneCount>::IntBitMask>(), core::mem::size_of::<<crate::LaneCount::<LANES> as crate::SupportedLaneCount>::IntBitMask>(),
crate::LaneCount::<LANES>::BITMASK_LEN,
); );
let bitmask: <crate::LaneCount::<LANES> as crate::SupportedLaneCount>::IntBitMask = core::mem::transmute_copy(&bitmask); let bitmask: <crate::LaneCount::<LANES> as crate::SupportedLaneCount>::IntBitMask = core::mem::transmute_copy(&bitmask);