Skip to content

Commit 15b4e28

Browse files
Add from_bitmask (#136)
* Add from_bitmask * Add mips workaround
1 parent 57e67c9 commit 15b4e28

File tree

4 files changed

+42
-2
lines changed

4 files changed

+42
-2
lines changed

crates/core_simd/src/masks/bitmask.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,15 @@ impl<T: Mask, const LANES: usize> BitMask<T, LANES> {
100100
unsafe { core::mem::transmute_copy(&self.0) }
101101
}
102102

103+
#[inline]
104+
pub fn from_bitmask<U: Mask>(bitmask: U::BitMask) -> Self {
105+
assert_eq!(
106+
core::mem::size_of::<T::BitMask>(),
107+
core::mem::size_of::<U::BitMask>()
108+
);
109+
unsafe { core::mem::transmute_copy(&bitmask) }
110+
}
111+
103112
#[inline]
104113
pub fn any(self) -> bool {
105114
self != Self::splat(false)

crates/core_simd/src/masks/full_masks.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,30 @@ macro_rules! define_mask {
126126
bitmask
127127
}
128128
}
129+
130+
#[inline]
131+
pub fn from_bitmask<U: crate::Mask>(mut bitmask: U::BitMask) -> Self {
132+
unsafe {
133+
// There is a bug where LLVM appears to implement this operation with the wrong
134+
// bit order.
135+
// TODO fix this in a better way
136+
if cfg!(any(target_arch = "mips", target_arch = "mips64")) {
137+
for x in bitmask.as_mut() {
138+
*x = x.reverse_bits();
139+
}
140+
}
141+
142+
// TODO remove the transmute when rustc is more flexible
143+
assert_eq!(core::mem::size_of::<U::IntBitMask>(), core::mem::size_of::<U::BitMask>());
144+
let bitmask: U::IntBitMask = core::mem::transmute_copy(&bitmask);
145+
146+
Self::from_int_unchecked(crate::intrinsics::simd_select_bitmask(
147+
bitmask,
148+
Self::splat(true).to_int(),
149+
Self::splat(false).to_int(),
150+
))
151+
}
152+
}
129153
}
130154

131155
impl<T: Mask, const LANES: usize> core::convert::From<$name<T, LANES>> for crate::$type<LANES>

crates/core_simd/src/masks/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@ macro_rules! define_opaque_mask {
178178
pub fn to_bitmask(self) -> <Self as Mask>::BitMask {
179179
self.0.to_bitmask::<Self>()
180180
}
181+
182+
/// Convert a bitmask to a mask.
183+
pub fn from_bitmask(bitmask: <Self as Mask>::BitMask) -> Self {
184+
Self(<$inner_ty>::from_bitmask::<Self>(bitmask))
185+
}
181186
}
182187

183188
// vector/array conversion

crates/core_simd/tests/masks.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,15 @@ macro_rules! test_mask_api {
6767
}
6868

6969
#[test]
70-
fn to_bitmask() {
70+
fn roundtrip_bitmask_conversion() {
7171
let values = [
7272
true, false, false, true, false, false, true, false,
7373
true, true, false, false, false, false, false, true,
7474
];
7575
let mask = core_simd::$name::<16>::from_array(values);
76-
assert_eq!(mask.to_bitmask(), [0b01001001, 0b10000011]);
76+
let bitmask = mask.to_bitmask();
77+
assert_eq!(bitmask, [0b01001001, 0b10000011]);
78+
assert_eq!(core_simd::$name::<16>::from_bitmask(bitmask), mask);
7779
}
7880
}
7981
}

0 commit comments

Comments
 (0)