Skip to content

Commit

Permalink
Finish refactoring vector types
Browse files Browse the repository at this point in the history
  • Loading branch information
calebzulawski committed Dec 14, 2020
1 parent 6e90824 commit b699d72
Show file tree
Hide file tree
Showing 27 changed files with 568 additions and 685 deletions.
2 changes: 1 addition & 1 deletion crates/core_simd/src/intrinsics.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! This module contains the LLVM intrinsics bindings that provide the functionality for this
//! crate.
//!
//! The LLVM assembly language is documented here: https://llvm.org/docs/LangRef.html
//! The LLVM assembly language is documented here: <https://llvm.org/docs/LangRef.html>
/// These intrinsics aren't linked directly from LLVM and are mostly undocumented, however they are
/// simply lowered to the matching LLVM instructions by the compiler. The associated instruction
Expand Down
4 changes: 2 additions & 2 deletions crates/core_simd/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ mod intrinsics;
mod ops;
//mod round;

//pub mod masks;
//pub use masks::opaque::*;
mod masks;
pub use masks::*;

mod vectors_u8;
pub use vectors_u8::*;
Expand Down
199 changes: 199 additions & 0 deletions crates/core_simd/src/masks/full_masks/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
//! Masks that take up full SIMD vector registers.
/// The error type returned when converting an integer to a mask fails.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct TryFromMaskError(());

impl core::fmt::Display for TryFromMaskError {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "mask vector must have all bits set or unset in each lane")
}
}

macro_rules! define_mask {
{ $(#[$attr:meta])* struct $name:ident<const $lanes:ident: usize>($type:ty); } => {
$(#[$attr])*
#[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[repr(transparent)]
pub struct $name<const $lanes: usize>($type);

delegate_ops_to_inner! { $name }

impl<const $lanes: usize> $name<$lanes> {
/// Construct a mask by setting all lanes to the given value.
pub fn splat(value: bool) -> Self {
Self(<$type>::splat(value.into()))
}

/// Tests the value of the specified lane.
///
/// # Panics
/// Panics if `lane` is greater than or equal to the number of lanes in the vector.
#[inline]
pub fn test(&self, lane: usize) -> bool {
self.0[lane] > 0
}

/// Sets the value of the specified lane.
///
/// # Panics
/// Panics if `lane` is greater than or equal to the number of lanes in the vector.
#[inline]
pub fn set(&mut self, lane: usize, value: bool) {
self.0[lane] = if value {
!0
} else {
0
}
}
}

impl<const $lanes: usize> core::convert::From<bool> for $name<$lanes> {
fn from(value: bool) -> Self {
Self::splat(value)
}
}

impl<const $lanes: usize> core::convert::TryFrom<$type> for $name<$lanes> {
type Error = TryFromMaskError;
fn try_from(value: $type) -> Result<Self, Self::Error> {
if value.as_slice().iter().all(|x| *x == 0 || !*x == 0) {
Ok(Self(value))
} else {
Err(TryFromMaskError(()))
}
}
}

impl<const $lanes: usize> core::convert::From<$name<$lanes>> for $type {
fn from(value: $name<$lanes>) -> Self {
value.0
}
}

impl<const $lanes: usize> core::fmt::Debug for $name<$lanes> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_list()
.entries((0..LANES).map(|lane| self.test(lane)))
.finish()
}
}

impl<const $lanes: usize> core::fmt::Binary for $name<$lanes> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
core::fmt::Binary::fmt(&self.0, f)
}
}

impl<const $lanes: usize> core::fmt::Octal for $name<$lanes> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
core::fmt::Octal::fmt(&self.0, f)
}
}

impl<const $lanes: usize> core::fmt::LowerHex for $name<$lanes> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
core::fmt::LowerHex::fmt(&self.0, f)
}
}

impl<const $lanes: usize> core::fmt::UpperHex for $name<$lanes> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
core::fmt::UpperHex::fmt(&self.0, f)
}
}
}
}

define_mask! {
/// A mask equivalent to [SimdI8](crate::SimdI8), where all bits in the lane must be either set
/// or unset.
struct SimdI8Mask<const LANES: usize>(crate::SimdI8<LANES>);
}

define_mask! {
/// A mask equivalent to [SimdI16](crate::SimdI16), where all bits in the lane must be either set
/// or unset.
struct SimdI16Mask<const LANES: usize>(crate::SimdI16<LANES>);
}

define_mask! {
/// A mask equivalent to [SimdI32](crate::SimdI32), where all bits in the lane must be either set
/// or unset.
struct SimdI32Mask<const LANES: usize>(crate::SimdI32<LANES>);
}

define_mask! {
/// A mask equivalent to [SimdI64](crate::SimdI64), where all bits in the lane must be either set
/// or unset.
struct SimdI64Mask<const LANES: usize>(crate::SimdI64<LANES>);
}

define_mask! {
/// A mask equivalent to [SimdI128](crate::SimdI128), where all bits in the lane must be either set
/// or unset.
struct SimdI128Mask<const LANES: usize>(crate::SimdI64<LANES>);
}

define_mask! {
/// A mask equivalent to [SimdIsize](crate::SimdIsize), where all bits in the lane must be either set
/// or unset.
struct SimdIsizeMask<const LANES: usize>(crate::SimdI64<LANES>);
}

macro_rules! implement_mask_ext {
{ $($vector:ident => $mask:ident,)* } => {
$(
impl<const LANES: usize> crate::masks::MaskExt<$mask<LANES>> for crate::$vector<LANES> {
#[inline]
fn lanes_eq(&self, other: &Self) -> $mask<LANES> {
unsafe { crate::intrinsics::simd_eq(self, other) }
}

#[inline]
fn lanes_ne(&self, other: &Self) -> $mask<LANES> {
unsafe { crate::intrinsics::simd_ne(self, other) }
}

#[inline]
fn lanes_lt(&self, other: &Self) -> $mask<LANES> {
unsafe { crate::intrinsics::simd_lt(self, other) }
}

#[inline]
fn lanes_gt(&self, other: &Self) -> $mask<LANES> {
unsafe { crate::intrinsics::simd_gt(self, other) }
}

#[inline]
fn lanes_le(&self, other: &Self) -> $mask<LANES> {
unsafe { crate::intrinsics::simd_le(self, other) }
}

#[inline]
fn lanes_ge(&self, other: &Self) -> $mask<LANES> {
unsafe { crate::intrinsics::simd_ge(self, other) }
}
}
)*
}
}

implement_mask_ext! {
SimdI8 => SimdI8Mask,
SimdI16 => SimdI16Mask,
SimdI32 => SimdI32Mask,
SimdI64 => SimdI64Mask,
SimdI128 => SimdI128Mask,
SimdIsize => SimdIsizeMask,

SimdU8 => SimdI8Mask,
SimdU16 => SimdI16Mask,
SimdU32 => SimdI32Mask,
SimdU64 => SimdI64Mask,
SimdU128 => SimdI128Mask,
SimdUsize => SimdIsizeMask,

SimdF32 => SimdI32Mask,
SimdF64 => SimdI64Mask,
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@ define_mask_vector! {
/// Vector of 64 `m8` values
struct m8x64([i8 as m8; 64]);
}

#[repr(transparent)]
struct VectorMask8<const LANES: usize>(crate::SimdI8<LANES>);
Loading

0 comments on commit b699d72

Please sign in to comment.