|
66 | 66 | }
|
67 | 67 | }
|
68 | 68 |
|
| 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 | + |
69 | 86 | impl<T, const LANES: usize> Mask<T, LANES>
|
70 | 87 | where
|
71 | 88 | T: MaskElement,
|
@@ -154,15 +171,33 @@ where
|
154 | 171 | // Safety: U must be the integer with the exact number of bits required to hold the bitmask for
|
155 | 172 | // this mask
|
156 | 173 | #[inline]
|
157 |
| - pub unsafe fn to_bitmask_integer<U>(self) -> U { |
| 174 | + pub(crate) unsafe fn to_bitmask_integer<U: ReverseBits>(self) -> U { |
158 | 175 | // 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 | + } |
160 | 186 | }
|
161 | 187 |
|
162 | 188 | // Safety: U must be the integer with the exact number of bits required to hold the bitmask for
|
163 | 189 | // this mask
|
164 | 190 | #[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 | + |
166 | 201 | // Safety: caller must only pass bitmask types
|
167 | 202 | unsafe {
|
168 | 203 | Self::from_int_unchecked(intrinsics::simd_select_bitmask(
|
|
0 commit comments