Skip to content

Move comparisons to traits #265

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 0 additions & 120 deletions crates/core_simd/src/comparisons.rs

This file was deleted.

73 changes: 73 additions & 0 deletions crates/core_simd/src/eq.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use crate::simd::{intrinsics, LaneCount, Mask, Simd, SimdElement, SupportedLaneCount};

/// Parallel `PartialEq`.
pub trait SimdPartialEq {
/// The mask type returned by each comparison.
type Mask;

/// Test if each lane is equal to the corresponding lane in `other`.
#[must_use = "method returns a new mask and does not mutate the original value"]
fn simd_eq(self, other: Self) -> Self::Mask;

/// Test if each lane is equal to the corresponding lane in `other`.
#[must_use = "method returns a new mask and does not mutate the original value"]
fn simd_ne(self, other: Self) -> Self::Mask;
}

macro_rules! impl_number {
{ $($number:ty),* } => {
$(
impl<const LANES: usize> SimdPartialEq for Simd<$number, LANES>
where
LaneCount<LANES>: SupportedLaneCount,
{
type Mask = Mask<<$number as SimdElement>::Mask, LANES>;

#[inline]
fn simd_eq(self, other: Self) -> Self::Mask {
// Safety: `self` is a vector, and the result of the comparison
// is always a valid mask.
unsafe { Mask::from_int_unchecked(intrinsics::simd_eq(self, other)) }
}

#[inline]
fn simd_ne(self, other: Self) -> Self::Mask {
// Safety: `self` is a vector, and the result of the comparison
// is always a valid mask.
unsafe { Mask::from_int_unchecked(intrinsics::simd_ne(self, other)) }
}
}
)*
}
}

impl_number! { f32, f64, u8, u16, u32, u64, usize, i8, i16, i32, i64, isize }

macro_rules! impl_mask {
{ $($integer:ty),* } => {
$(
impl<const LANES: usize> SimdPartialEq for Mask<$integer, LANES>
where
LaneCount<LANES>: SupportedLaneCount,
{
type Mask = Self;

#[inline]
fn simd_eq(self, other: Self) -> Self::Mask {
// Safety: `self` is a vector, and the result of the comparison
// is always a valid mask.
unsafe { Self::from_int_unchecked(intrinsics::simd_eq(self.to_int(), other.to_int())) }
}

#[inline]
fn simd_ne(self, other: Self) -> Self::Mask {
// Safety: `self` is a vector, and the result of the comparison
// is always a valid mask.
unsafe { Self::from_int_unchecked(intrinsics::simd_ne(self.to_int(), other.to_int())) }
}
}
)*
}
}

impl_mask! { i8, i16, i32, i64, isize }
4 changes: 2 additions & 2 deletions crates/core_simd/src/masks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ mod mask_impl;
mod to_bitmask;
pub use to_bitmask::ToBitMask;

use crate::simd::{intrinsics, LaneCount, Simd, SimdElement, SupportedLaneCount};
use crate::simd::{intrinsics, LaneCount, Simd, SimdElement, SimdPartialEq, SupportedLaneCount};
use core::cmp::Ordering;
use core::{fmt, mem};

Expand Down Expand Up @@ -56,7 +56,7 @@ macro_rules! impl_element {
where
LaneCount<LANES>: SupportedLaneCount,
{
(value.lanes_eq(Simd::splat(0)) | value.lanes_eq(Simd::splat(-1))).all()
(value.simd_eq(Simd::splat(0 as _)) | value.simd_eq(Simd::splat(-1 as _))).all()
}

fn eq(self, other: Self) -> bool { self == other }
Expand Down
5 changes: 4 additions & 1 deletion crates/core_simd/src/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ pub(crate) mod intrinsics;
#[cfg(feature = "generic_const_exprs")]
mod to_bytes;

mod comparisons;
mod eq;
mod fmt;
mod iter;
mod lane_count;
mod masks;
mod math;
mod ops;
mod ord;
mod round;
mod select;
mod vector;
Expand All @@ -25,8 +26,10 @@ mod vendor;
pub mod simd {
pub(crate) use crate::core_simd::intrinsics;

pub use crate::core_simd::eq::*;
pub use crate::core_simd::lane_count::{LaneCount, SupportedLaneCount};
pub use crate::core_simd::masks::*;
pub use crate::core_simd::ord::*;
pub use crate::core_simd::swizzle::*;
pub use crate::core_simd::vector::*;
}
10 changes: 5 additions & 5 deletions crates/core_simd/src/ops.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount};
use crate::simd::{LaneCount, Simd, SimdElement, SimdPartialEq, SupportedLaneCount};
use core::ops::{Add, Mul};
use core::ops::{BitAnd, BitOr, BitXor};
use core::ops::{Div, Rem, Sub};
Expand Down Expand Up @@ -74,18 +74,18 @@ macro_rules! int_divrem_guard {
$simd_call:ident
},
$int:ident ) => {
if $rhs.lanes_eq(Simd::splat(0)).any() {
if $rhs.simd_eq(Simd::splat(0 as _)).any() {
panic!($zero);
} else {
// Prevent otherwise-UB overflow on the MIN / -1 case.
let rhs = if <$int>::MIN != 0 {
// This should, at worst, optimize to a few branchless logical ops
// Ideally, this entire conditional should evaporate
// Fire LLVM and implement those manually if it doesn't get the hint
($lhs.lanes_eq(Simd::splat(<$int>::MIN))
($lhs.simd_eq(Simd::splat(<$int>::MIN))
// type inference can break here, so cut an SInt to size
& $rhs.lanes_eq(Simd::splat(-1i64 as _)))
.select(Simd::splat(1), $rhs)
& $rhs.simd_eq(Simd::splat(-1i64 as _)))
.select(Simd::splat(1 as _), $rhs)
} else {
// Nice base case to make it easy to const-fold away the other branch.
$rhs
Expand Down
Loading