rust-lang/portable-simd#267: fix big-endian bitmasks smaller than a byte

This commit is contained in:
Jubilee 2022-03-21 00:05:38 -07:00 committed by GitHub
commit 0711e11593
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 4 deletions

View file

@ -68,14 +68,26 @@ where
// Used for bitmask bit order workaround
pub(crate) trait ReverseBits {
fn reverse_bits(self) -> Self;
// Reverse the least significant `n` bits of `self`.
// (Remaining bits must be 0.)
fn reverse_bits(self, n: usize) -> Self;
}
macro_rules! impl_reverse_bits {
{ $($int:ty),* } => {
$(
impl ReverseBits for $int {
fn reverse_bits(self) -> Self { <$int>::reverse_bits(self) }
#[inline(always)]
fn reverse_bits(self, n: usize) -> Self {
let rev = <$int>::reverse_bits(self);
let bitsize = core::mem::size_of::<$int>() * 8;
if n < bitsize {
// Shift things back to the right
rev >> (bitsize - n)
} else {
rev
}
}
}
)*
}
@ -137,7 +149,7 @@ where
// LLVM assumes bit order should match endianness
if cfg!(target_endian = "big") {
bitmask.reverse_bits()
bitmask.reverse_bits(LANES)
} else {
bitmask
}
@ -150,7 +162,7 @@ where
{
// LLVM assumes bit order should match endianness
let bitmask = if cfg!(target_endian = "big") {
bitmask.reverse_bits()
bitmask.reverse_bits(LANES)
} else {
bitmask
};

View file

@ -80,6 +80,25 @@ macro_rules! test_mask_api {
assert_eq!(bitmask, 0b1000001101001001);
assert_eq!(core_simd::Mask::<$type, 16>::from_bitmask(bitmask), mask);
}
#[test]
fn roundtrip_bitmask_conversion_short() {
use core_simd::ToBitMask;
let values = [
false, false, false, true,
];
let mask = core_simd::Mask::<$type, 4>::from_array(values);
let bitmask = mask.to_bitmask();
assert_eq!(bitmask, 0b1000);
assert_eq!(core_simd::Mask::<$type, 4>::from_bitmask(bitmask), mask);
let values = [true, false];
let mask = core_simd::Mask::<$type, 2>::from_array(values);
let bitmask = mask.to_bitmask();
assert_eq!(bitmask, 0b01);
assert_eq!(core_simd::Mask::<$type, 2>::from_bitmask(bitmask), mask);
}
}
}
}