Skip to content

Commit 744169a

Browse files
committed
Fix bit order on some targets
1 parent 7b697ff commit 744169a

File tree

1 file changed

+38
-3
lines changed

1 file changed

+38
-3
lines changed

crates/core_simd/src/masks/full_masks.rs

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,23 @@ where
6666
}
6767
}
6868

69+
// Used for bitmask bit order workaround
70+
pub(crate) trait ReverseBits {
71+
fn reverse_bits(self) -> Self;
72+
}
73+
74+
macro_rules! impl_reverse_bits {
75+
{ $($int:ty),* } => {
76+
$(
77+
impl ReverseBits for $int {
78+
fn reverse_bits(self) -> Self { <$int>::reverse_bits(self) }
79+
}
80+
)*
81+
}
82+
}
83+
84+
impl_reverse_bits! { u8, u16, u32, u64 }
85+
6986
impl<T, const LANES: usize> Mask<T, LANES>
7087
where
7188
T: MaskElement,
@@ -154,15 +171,33 @@ where
154171
// Safety: U must be the integer with the exact number of bits required to hold the bitmask for
155172
// this mask
156173
#[inline]
157-
pub unsafe fn to_bitmask_integer<U>(self) -> U {
174+
pub(crate) unsafe fn to_bitmask_integer<U: ReverseBits>(self) -> U {
158175
// Safety: caller must only return bitmask types
159-
unsafe { intrinsics::simd_bitmask(self.0) }
176+
let bitmask: U = unsafe { intrinsics::simd_bitmask(self.0) };
177+
178+
// There is a bug where LLVM appears to implement this operation with the wrong
179+
// bit order.
180+
// TODO fix this in a better way
181+
if cfg!(target_endian = "big") {
182+
bitmask.reverse_bits()
183+
} else {
184+
bitmask
185+
}
160186
}
161187

162188
// Safety: U must be the integer with the exact number of bits required to hold the bitmask for
163189
// this mask
164190
#[inline]
165-
pub unsafe fn from_bitmask_integer<U>(bitmask: U) -> Self {
191+
pub(crate) unsafe fn from_bitmask_integer<U: ReverseBits>(bitmask: U) -> Self {
192+
// There is a bug where LLVM appears to implement this operation with the wrong
193+
// bit order.
194+
// TODO fix this in a better way
195+
let bitmask = if cfg!(target_endian = "big") {
196+
bitmask.reverse_bits()
197+
} else {
198+
bitmask
199+
};
200+
166201
// Safety: caller must only pass bitmask types
167202
unsafe {
168203
Self::from_int_unchecked(intrinsics::simd_select_bitmask(

0 commit comments

Comments
 (0)