Skip to content

Commit 1ec010d

Browse files
#265: Move comparisons to traits
A simpler variant of #206. * Comparisons are moved to `SimdPartialEq`, `SimdPartialOrd`, and `SimdOrd`. The function names are prefixed with `simd_` to disambiguate from the regular `PartialEq` etc functions. With the functions on traits instead of `Simd` directly, shadowing the function names doesn't work very well. * Floating point `Ord`-like functions are put into a `SimdFloat` trait. The intention is that eventually (some time after this PR) all floating point functions will be moved from `Simd` to `SimdFloat`, and the same goes for future `SimdInt`/`SimdUint` traits.
2 parents c2fbead + 60486e0 commit 1ec010d

File tree

11 files changed

+412
-230
lines changed

11 files changed

+412
-230
lines changed

crates/core_simd/src/comparisons.rs

Lines changed: 0 additions & 120 deletions
This file was deleted.

crates/core_simd/src/eq.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
use crate::simd::{intrinsics, LaneCount, Mask, Simd, SimdElement, SupportedLaneCount};
2+
3+
/// Parallel `PartialEq`.
4+
pub trait SimdPartialEq {
5+
/// The mask type returned by each comparison.
6+
type Mask;
7+
8+
/// Test if each lane is equal to the corresponding lane in `other`.
9+
#[must_use = "method returns a new mask and does not mutate the original value"]
10+
fn simd_eq(self, other: Self) -> Self::Mask;
11+
12+
/// Test if each lane is equal to the corresponding lane in `other`.
13+
#[must_use = "method returns a new mask and does not mutate the original value"]
14+
fn simd_ne(self, other: Self) -> Self::Mask;
15+
}
16+
17+
macro_rules! impl_number {
18+
{ $($number:ty),* } => {
19+
$(
20+
impl<const LANES: usize> SimdPartialEq for Simd<$number, LANES>
21+
where
22+
LaneCount<LANES>: SupportedLaneCount,
23+
{
24+
type Mask = Mask<<$number as SimdElement>::Mask, LANES>;
25+
26+
#[inline]
27+
fn simd_eq(self, other: Self) -> Self::Mask {
28+
// Safety: `self` is a vector, and the result of the comparison
29+
// is always a valid mask.
30+
unsafe { Mask::from_int_unchecked(intrinsics::simd_eq(self, other)) }
31+
}
32+
33+
#[inline]
34+
fn simd_ne(self, other: Self) -> Self::Mask {
35+
// Safety: `self` is a vector, and the result of the comparison
36+
// is always a valid mask.
37+
unsafe { Mask::from_int_unchecked(intrinsics::simd_ne(self, other)) }
38+
}
39+
}
40+
)*
41+
}
42+
}
43+
44+
impl_number! { f32, f64, u8, u16, u32, u64, usize, i8, i16, i32, i64, isize }
45+
46+
macro_rules! impl_mask {
47+
{ $($integer:ty),* } => {
48+
$(
49+
impl<const LANES: usize> SimdPartialEq for Mask<$integer, LANES>
50+
where
51+
LaneCount<LANES>: SupportedLaneCount,
52+
{
53+
type Mask = Self;
54+
55+
#[inline]
56+
fn simd_eq(self, other: Self) -> Self::Mask {
57+
// Safety: `self` is a vector, and the result of the comparison
58+
// is always a valid mask.
59+
unsafe { Self::from_int_unchecked(intrinsics::simd_eq(self.to_int(), other.to_int())) }
60+
}
61+
62+
#[inline]
63+
fn simd_ne(self, other: Self) -> Self::Mask {
64+
// Safety: `self` is a vector, and the result of the comparison
65+
// is always a valid mask.
66+
unsafe { Self::from_int_unchecked(intrinsics::simd_ne(self.to_int(), other.to_int())) }
67+
}
68+
}
69+
)*
70+
}
71+
}
72+
73+
impl_mask! { i8, i16, i32, i64, isize }

crates/core_simd/src/masks.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ mod mask_impl;
1515
mod to_bitmask;
1616
pub use to_bitmask::ToBitMask;
1717

18-
use crate::simd::{intrinsics, LaneCount, Simd, SimdElement, SupportedLaneCount};
18+
use crate::simd::{intrinsics, LaneCount, Simd, SimdElement, SimdPartialEq, SupportedLaneCount};
1919
use core::cmp::Ordering;
2020
use core::{fmt, mem};
2121

@@ -56,7 +56,7 @@ macro_rules! impl_element {
5656
where
5757
LaneCount<LANES>: SupportedLaneCount,
5858
{
59-
(value.lanes_eq(Simd::splat(0)) | value.lanes_eq(Simd::splat(-1))).all()
59+
(value.simd_eq(Simd::splat(0 as _)) | value.simd_eq(Simd::splat(-1 as _))).all()
6060
}
6161

6262
fn eq(self, other: Self) -> bool { self == other }

crates/core_simd/src/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ pub(crate) mod intrinsics;
99
#[cfg(feature = "generic_const_exprs")]
1010
mod to_bytes;
1111

12-
mod comparisons;
12+
mod eq;
1313
mod fmt;
1414
mod iter;
1515
mod lane_count;
1616
mod masks;
1717
mod math;
1818
mod ops;
19+
mod ord;
1920
mod round;
2021
mod select;
2122
mod vector;
@@ -25,8 +26,10 @@ mod vendor;
2526
pub mod simd {
2627
pub(crate) use crate::core_simd::intrinsics;
2728

29+
pub use crate::core_simd::eq::*;
2830
pub use crate::core_simd::lane_count::{LaneCount, SupportedLaneCount};
2931
pub use crate::core_simd::masks::*;
32+
pub use crate::core_simd::ord::*;
3033
pub use crate::core_simd::swizzle::*;
3134
pub use crate::core_simd::vector::*;
3235
}

crates/core_simd/src/ops.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount};
1+
use crate::simd::{LaneCount, Simd, SimdElement, SimdPartialEq, SupportedLaneCount};
22
use core::ops::{Add, Mul};
33
use core::ops::{BitAnd, BitOr, BitXor};
44
use core::ops::{Div, Rem, Sub};
@@ -74,18 +74,18 @@ macro_rules! int_divrem_guard {
7474
$simd_call:ident
7575
},
7676
$int:ident ) => {
77-
if $rhs.lanes_eq(Simd::splat(0)).any() {
77+
if $rhs.simd_eq(Simd::splat(0 as _)).any() {
7878
panic!($zero);
7979
} else {
8080
// Prevent otherwise-UB overflow on the MIN / -1 case.
8181
let rhs = if <$int>::MIN != 0 {
8282
// This should, at worst, optimize to a few branchless logical ops
8383
// Ideally, this entire conditional should evaporate
8484
// Fire LLVM and implement those manually if it doesn't get the hint
85-
($lhs.lanes_eq(Simd::splat(<$int>::MIN))
85+
($lhs.simd_eq(Simd::splat(<$int>::MIN))
8686
// type inference can break here, so cut an SInt to size
87-
& $rhs.lanes_eq(Simd::splat(-1i64 as _)))
88-
.select(Simd::splat(1), $rhs)
87+
& $rhs.simd_eq(Simd::splat(-1i64 as _)))
88+
.select(Simd::splat(1 as _), $rhs)
8989
} else {
9090
// Nice base case to make it easy to const-fold away the other branch.
9191
$rhs

0 commit comments

Comments
 (0)