Skip to content

Commit 9cc3dea

Browse files
committed
Finish refactoring vector types
1 parent 25c7640 commit 9cc3dea

27 files changed

+568
-685
lines changed

crates/core_simd/src/intrinsics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! This module contains the LLVM intrinsics bindings that provide the functionality for this
22
//! crate.
33
//!
4-
//! The LLVM assembly language is documented here: https://llvm.org/docs/LangRef.html
4+
//! The LLVM assembly language is documented here: <https://llvm.org/docs/LangRef.html>
55
66
/// These intrinsics aren't linked directly from LLVM and are mostly undocumented, however they are
77
/// simply lowered to the matching LLVM instructions by the compiler. The associated instruction

crates/core_simd/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ mod intrinsics;
1111
mod ops;
1212
//mod round;
1313

14-
//pub mod masks;
15-
//pub use masks::opaque::*;
14+
mod masks;
15+
pub use masks::*;
1616

1717
mod vectors_u8;
1818
pub use vectors_u8::*;
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
//! Masks that take up full SIMD vector registers.
2+
3+
/// The error type returned when converting an integer to a mask fails.
4+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
5+
pub struct TryFromMaskError(());
6+
7+
impl core::fmt::Display for TryFromMaskError {
8+
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
9+
write!(f, "mask vector must have all bits set or unset in each lane")
10+
}
11+
}
12+
13+
macro_rules! define_mask {
14+
{ $(#[$attr:meta])* struct $name:ident<const $lanes:ident: usize>($type:ty); } => {
15+
$(#[$attr])*
16+
#[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
17+
#[repr(transparent)]
18+
pub struct $name<const $lanes: usize>($type);
19+
20+
delegate_ops_to_inner! { $name }
21+
22+
impl<const $lanes: usize> $name<$lanes> {
23+
/// Construct a mask by setting all lanes to the given value.
24+
pub fn splat(value: bool) -> Self {
25+
Self(<$type>::splat(value.into()))
26+
}
27+
28+
/// Tests the value of the specified lane.
29+
///
30+
/// # Panics
31+
/// Panics if `lane` is greater than or equal to the number of lanes in the vector.
32+
#[inline]
33+
pub fn test(&self, lane: usize) -> bool {
34+
self.0[lane] > 0
35+
}
36+
37+
/// Sets the value of the specified lane.
38+
///
39+
/// # Panics
40+
/// Panics if `lane` is greater than or equal to the number of lanes in the vector.
41+
#[inline]
42+
pub fn set(&mut self, lane: usize, value: bool) {
43+
self.0[lane] = if value {
44+
!0
45+
} else {
46+
0
47+
}
48+
}
49+
}
50+
51+
impl<const $lanes: usize> core::convert::From<bool> for $name<$lanes> {
52+
fn from(value: bool) -> Self {
53+
Self::splat(value)
54+
}
55+
}
56+
57+
impl<const $lanes: usize> core::convert::TryFrom<$type> for $name<$lanes> {
58+
type Error = TryFromMaskError;
59+
fn try_from(value: $type) -> Result<Self, Self::Error> {
60+
if value.as_slice().iter().all(|x| *x == 0 || !*x == 0) {
61+
Ok(Self(value))
62+
} else {
63+
Err(TryFromMaskError(()))
64+
}
65+
}
66+
}
67+
68+
impl<const $lanes: usize> core::convert::From<$name<$lanes>> for $type {
69+
fn from(value: $name<$lanes>) -> Self {
70+
value.0
71+
}
72+
}
73+
74+
impl<const $lanes: usize> core::fmt::Debug for $name<$lanes> {
75+
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
76+
f.debug_list()
77+
.entries((0..LANES).map(|lane| self.test(lane)))
78+
.finish()
79+
}
80+
}
81+
82+
impl<const $lanes: usize> core::fmt::Binary for $name<$lanes> {
83+
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
84+
core::fmt::Binary::fmt(&self.0, f)
85+
}
86+
}
87+
88+
impl<const $lanes: usize> core::fmt::Octal for $name<$lanes> {
89+
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
90+
core::fmt::Octal::fmt(&self.0, f)
91+
}
92+
}
93+
94+
impl<const $lanes: usize> core::fmt::LowerHex for $name<$lanes> {
95+
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
96+
core::fmt::LowerHex::fmt(&self.0, f)
97+
}
98+
}
99+
100+
impl<const $lanes: usize> core::fmt::UpperHex for $name<$lanes> {
101+
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
102+
core::fmt::UpperHex::fmt(&self.0, f)
103+
}
104+
}
105+
}
106+
}
107+
108+
define_mask! {
109+
/// A mask equivalent to [SimdI8](crate::SimdI8), where all bits in the lane must be either set
110+
/// or unset.
111+
struct SimdI8Mask<const LANES: usize>(crate::SimdI8<LANES>);
112+
}
113+
114+
define_mask! {
115+
/// A mask equivalent to [SimdI16](crate::SimdI16), where all bits in the lane must be either set
116+
/// or unset.
117+
struct SimdI16Mask<const LANES: usize>(crate::SimdI16<LANES>);
118+
}
119+
120+
define_mask! {
121+
/// A mask equivalent to [SimdI32](crate::SimdI32), where all bits in the lane must be either set
122+
/// or unset.
123+
struct SimdI32Mask<const LANES: usize>(crate::SimdI32<LANES>);
124+
}
125+
126+
define_mask! {
127+
/// A mask equivalent to [SimdI64](crate::SimdI64), where all bits in the lane must be either set
128+
/// or unset.
129+
struct SimdI64Mask<const LANES: usize>(crate::SimdI64<LANES>);
130+
}
131+
132+
define_mask! {
133+
/// A mask equivalent to [SimdI128](crate::SimdI128), where all bits in the lane must be either set
134+
/// or unset.
135+
struct SimdI128Mask<const LANES: usize>(crate::SimdI64<LANES>);
136+
}
137+
138+
define_mask! {
139+
/// A mask equivalent to [SimdIsize](crate::SimdIsize), where all bits in the lane must be either set
140+
/// or unset.
141+
struct SimdIsizeMask<const LANES: usize>(crate::SimdI64<LANES>);
142+
}
143+
144+
macro_rules! implement_mask_ext {
145+
{ $($vector:ident => $mask:ident,)* } => {
146+
$(
147+
impl<const LANES: usize> crate::masks::MaskExt<$mask<LANES>> for crate::$vector<LANES> {
148+
#[inline]
149+
fn lanes_eq(&self, other: &Self) -> $mask<LANES> {
150+
unsafe { crate::intrinsics::simd_eq(self, other) }
151+
}
152+
153+
#[inline]
154+
fn lanes_ne(&self, other: &Self) -> $mask<LANES> {
155+
unsafe { crate::intrinsics::simd_ne(self, other) }
156+
}
157+
158+
#[inline]
159+
fn lanes_lt(&self, other: &Self) -> $mask<LANES> {
160+
unsafe { crate::intrinsics::simd_lt(self, other) }
161+
}
162+
163+
#[inline]
164+
fn lanes_gt(&self, other: &Self) -> $mask<LANES> {
165+
unsafe { crate::intrinsics::simd_gt(self, other) }
166+
}
167+
168+
#[inline]
169+
fn lanes_le(&self, other: &Self) -> $mask<LANES> {
170+
unsafe { crate::intrinsics::simd_le(self, other) }
171+
}
172+
173+
#[inline]
174+
fn lanes_ge(&self, other: &Self) -> $mask<LANES> {
175+
unsafe { crate::intrinsics::simd_ge(self, other) }
176+
}
177+
}
178+
)*
179+
}
180+
}
181+
182+
implement_mask_ext! {
183+
SimdI8 => SimdI8Mask,
184+
SimdI16 => SimdI16Mask,
185+
SimdI32 => SimdI32Mask,
186+
SimdI64 => SimdI64Mask,
187+
SimdI128 => SimdI128Mask,
188+
SimdIsize => SimdIsizeMask,
189+
190+
SimdU8 => SimdI8Mask,
191+
SimdU16 => SimdI16Mask,
192+
SimdU32 => SimdI32Mask,
193+
SimdU64 => SimdI64Mask,
194+
SimdU128 => SimdI128Mask,
195+
SimdUsize => SimdIsizeMask,
196+
197+
SimdF32 => SimdI32Mask,
198+
SimdF64 => SimdI64Mask,
199+
}

crates/core_simd/src/masks/wide/vectors_m8.rs renamed to crates/core_simd/src/masks/full_masks/vectors_m8.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,6 @@ define_mask_vector! {
1919
/// Vector of 64 `m8` values
2020
struct m8x64([i8 as m8; 64]);
2121
}
22+
23+
#[repr(transparent)]
24+
struct VectorMask8<const LANES: usize>(crate::SimdI8<LANES>);

0 commit comments

Comments
 (0)