Skip to content

Commit 60555b5

Browse files
committed
fix big-endian bitmasks smaller than a byte
1 parent 50fbfa4 commit 60555b5

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

crates/core_simd/src/masks/full_masks.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,26 @@ where
6868

6969
// Used for bitmask bit order workaround
7070
pub(crate) trait ReverseBits {
71-
fn reverse_bits(self) -> Self;
71+
// Reverse the least significant `n` bits of `self`.
72+
// (Remaining bits must be 0.)
73+
fn reverse_bits(self, n: usize) -> Self;
7274
}
7375

7476
macro_rules! impl_reverse_bits {
7577
{ $($int:ty),* } => {
7678
$(
7779
impl ReverseBits for $int {
78-
fn reverse_bits(self) -> Self { <$int>::reverse_bits(self) }
80+
#[inline(always)]
81+
fn reverse_bits(self, n: usize) -> Self {
82+
let rev = <$int>::reverse_bits(self);
83+
let bitsize = core::mem::size_of::<$int>() * 8;
84+
if n < bitsize {
85+
// Shift things back to the right
86+
rev >> (bitsize - n)
87+
} else {
88+
rev
89+
}
90+
}
7991
}
8092
)*
8193
}
@@ -137,7 +149,7 @@ where
137149

138150
// LLVM assumes bit order should match endianness
139151
if cfg!(target_endian = "big") {
140-
bitmask.reverse_bits()
152+
bitmask.reverse_bits(LANES)
141153
} else {
142154
bitmask
143155
}
@@ -150,7 +162,7 @@ where
150162
{
151163
// LLVM assumes bit order should match endianness
152164
let bitmask = if cfg!(target_endian = "big") {
153-
bitmask.reverse_bits()
165+
bitmask.reverse_bits(LANES)
154166
} else {
155167
bitmask
156168
};

crates/core_simd/tests/masks.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,20 @@ macro_rules! test_mask_api {
8484
#[test]
8585
fn roundtrip_bitmask_conversion_short() {
8686
use core_simd::ToBitMask;
87+
8788
let values = [
8889
false, false, false, true,
8990
];
9091
let mask = core_simd::Mask::<$type, 4>::from_array(values);
9192
let bitmask = mask.to_bitmask();
9293
assert_eq!(bitmask, 0b1000);
9394
assert_eq!(core_simd::Mask::<$type, 4>::from_bitmask(bitmask), mask);
95+
96+
let values = [true, false];
97+
let mask = core_simd::Mask::<$type, 2>::from_array(values);
98+
let bitmask = mask.to_bitmask();
99+
assert_eq!(bitmask, 0b01);
100+
assert_eq!(core_simd::Mask::<$type, 2>::from_bitmask(bitmask), mask);
94101
}
95102
}
96103
}

0 commit comments

Comments
 (0)