Use intrinsics for Mask::{to,from}_array
This significantly simplifies codegen and should improve mask perf. Co-authored-by: Jacob Lifshay <programmerjake@gmail.com>
This commit is contained in:
parent
41db15373a
commit
a4f5f01b8a
@ -12,9 +12,10 @@
|
||||
)]
|
||||
mod mask_impl;
|
||||
|
||||
use crate::simd::intrinsics;
|
||||
use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount};
|
||||
use core::cmp::Ordering;
|
||||
use core::fmt;
|
||||
use core::{fmt, mem};
|
||||
|
||||
mod sealed {
|
||||
use super::*;
|
||||
@ -105,22 +106,39 @@ where
|
||||
Self(mask_impl::Mask::splat(value))
|
||||
}
|
||||
|
||||
/// Converts an array to a SIMD vector.
|
||||
/// Converts an array of bools to a SIMD mask.
|
||||
pub fn from_array(array: [bool; LANES]) -> Self {
|
||||
let mut vector = Self::splat(false);
|
||||
for (i, v) in array.iter().enumerate() {
|
||||
vector.set(i, *v);
|
||||
// SAFETY: Rust's bool has a layout of 1 byte (u8) with a value of
|
||||
// true: 0b_0000_0001
|
||||
// false: 0b_0000_0000
|
||||
// Thus, an array of bools is also a valid array of bytes: [u8; N]
|
||||
// This would be hypothetically valid as an "in-place" transmute,
|
||||
// but these are "dependently-sized" types, so copy elision it is!
|
||||
unsafe {
|
||||
let bytes: [u8; LANES] = mem::transmute_copy(&array);
|
||||
let bools: Simd<i8, LANES> =
|
||||
intrinsics::simd_ne(Simd::from_array(bytes), Simd::splat(0u8));
|
||||
Mask::from_int_unchecked(intrinsics::simd_cast(bools))
|
||||
}
|
||||
vector
|
||||
}
|
||||
|
||||
/// Converts a SIMD vector to an array.
|
||||
/// Converts a SIMD mask to an array of bools.
|
||||
pub fn to_array(self) -> [bool; LANES] {
|
||||
let mut array = [false; LANES];
|
||||
for (i, v) in array.iter_mut().enumerate() {
|
||||
*v = self.test(i);
|
||||
// This follows mostly the same logic as from_array.
|
||||
// SAFETY: Rust's bool has a layout of 1 byte (u8) with a value of
|
||||
// true: 0b_0000_0001
|
||||
// false: 0b_0000_0000
|
||||
// Thus, an array of bools is also a valid array of bytes: [u8; N]
|
||||
// Since our masks are equal to integers where all bits are set,
|
||||
// we can simply convert them to i8s, and then bitand them by the
|
||||
// bitpattern for Rust's "true" bool.
|
||||
// This would be hypothetically valid as an "in-place" transmute,
|
||||
// but these are "dependently-sized" types, so copy elision it is!
|
||||
unsafe {
|
||||
let mut bytes: Simd<i8, LANES> = intrinsics::simd_cast(self.to_int());
|
||||
bytes &= Simd::splat(1i8);
|
||||
mem::transmute_copy(&bytes)
|
||||
}
|
||||
array
|
||||
}
|
||||
|
||||
/// Converts a vector of integers to a mask, where 0 represents `false` and -1
|
||||
|
Loading…
x
Reference in New Issue
Block a user