diff --git a/src/lib.rs b/src/lib.rs index 7b96707..ff50bc4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,7 +37,7 @@ #![cfg_attr(all(nightly, feature = "clippy"), plugin(clippy))] //#![cfg_attr(all(nightly, feature="repr_simd" ), feature(cfg_target_feature))] #![cfg_attr(all(nightly, feature = "repr_simd"), feature(repr_simd, simd_ffi))] -#![cfg_attr(all(nightly, feature = "platform_intrinsics"), feature(platform_intrinsics))] +#![cfg_attr(all(nightly, feature = "platform_intrinsics"), feature(portable_simd, core_intrinsics))] //#![cfg_attr(feature="repr_simd", allow(improper_ctypes)] //#![cfg_attr(feature="repr_simd", feature(link_llvm_intrinsics)] #![cfg_attr(all(nightly, test), feature(test))] @@ -72,10 +72,6 @@ pub extern crate num_traits; #[macro_use] pub extern crate approx; -#[cfg(feature = "platform_intrinsics")] -mod simd_llvm; -// ^ Please do not make this module public; we don't want people to use it, because it could change as the SIMD infrastructure evolves. - pub mod ops; pub use crate::ops::*; pub mod vec; @@ -92,5 +88,3 @@ pub mod bezier; pub use crate::bezier::*; pub mod geom; pub use crate::geom::*; -pub mod simd_traits; -pub use crate::simd_traits::*; diff --git a/src/simd_llvm.rs b/src/simd_llvm.rs deleted file mode 100644 index ac98202..0000000 --- a/src/simd_llvm.rs +++ /dev/null @@ -1,96 +0,0 @@ -// !!! NOTE !!! -// -// Downloaded from https://raw.githubusercontent.com/rust-lang/stdarch/master/crates/core_arch/src/simd_llvm.rs -// -// The relevant RFC is https://github.com/rust-lang/rfcs/blob/master/text/1199-simd-infrastructure.md -// - -//! LLVM's simd platform intrinsics -//! -//! TODO: should use `link_llvm_intrinsic` instead: issue #112 - -#[allow(dead_code)] -extern "platform-intrinsic" { - //pub fn simd_select_bitmask - pub fn simd_eq(x: T, y: T) -> U; - pub fn simd_ne(x: T, y: T) -> U; - pub fn simd_lt(x: T, y: T) -> U; - pub fn simd_le(x: T, y: T) -> U; - pub fn simd_gt(x: T, y: T) -> U; - pub fn simd_ge(x: T, y: T) -> U; - - // #[rustc_args_required_const(2)] - // pub fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; - // #[rustc_args_required_const(2)] - // pub fn simd_shuffle4(x: T, y: T, idx: [u32; 4]) -> U; - // #[rustc_args_required_const(2)] - // pub fn simd_shuffle8(x: T, y: T, idx: [u32; 8]) -> U; - // #[rustc_args_required_const(2)] - // pub fn simd_shuffle16(x: T, y: T, idx: [u32; 16]) -> U; - // #[rustc_args_required_const(2)] - // pub fn simd_shuffle32(x: T, y: T, idx: [u32; 32]) -> U; - // #[rustc_args_required_const(2)] - // pub fn simd_shuffle64(x: T, y: T, idx: [u32; 64]) -> U; - // #[rustc_args_required_const(2)] - // pub fn simd_shuffle128(x: T, y: T, idx: [u32; 128]) -> U; - - // #[rustc_const_unstable(feature = "const_simd_insert", issue = "none")] - // pub fn simd_insert(x: T, idx: u32, val: U) -> T; - // #[rustc_const_unstable(feature = "const_simd_extract", issue = "none")] - // pub fn simd_extract(x: T, idx: u32) -> U; - //pub fn simd_select - pub fn simd_bitmask(x: T) -> U; - - pub fn simd_cast(x: T) -> U; - - pub fn simd_add(x: T, y: T) -> T; - pub fn simd_sub(x: T, y: T) -> T; - pub fn simd_mul(x: T, y: T) -> T; - pub fn simd_div(x: T, y: T) -> T; - pub fn simd_shl(x: T, y: T) -> T; - pub fn simd_shr(x: T, y: T) -> T; - pub fn simd_and(x: T, y: T) -> T; - pub fn simd_or(x: T, y: T) -> T; - pub fn simd_xor(x: T, y: T) -> T; - - pub fn simd_saturating_add(x: T, y: T) -> T; - pub fn simd_saturating_sub(x: T, y: T) -> T; - - pub fn simd_gather(values: T, pointers: U, mask: V) -> T; - pub fn simd_scatter(values: T, pointers: U, mask: V); - - pub fn simd_reduce_add_unordered(x: T) -> U; - pub fn simd_reduce_mul_unordered(x: T) -> U; - pub fn simd_reduce_add_ordered(x: T, acc: U) -> U; - pub fn simd_reduce_mul_ordered(x: T, acc: U) -> U; - pub fn simd_reduce_min(x: T) -> U; - pub fn simd_reduce_max(x: T) -> U; - pub fn simd_reduce_min_nanless(x: T) -> U; - pub fn simd_reduce_max_nanless(x: T) -> U; - pub fn simd_reduce_and(x: T) -> U; - pub fn simd_reduce_or(x: T) -> U; - pub fn simd_reduce_xor(x: T) -> U; - pub fn simd_reduce_all(x: T) -> bool; - pub fn simd_reduce_any(x: T) -> bool; - - pub fn simd_select(m: M, a: T, b: T) -> T; - pub fn simd_select_bitmask(m: M, a: T, b: T) -> T; - - pub fn simd_fmin(a: T, b: T) -> T; - pub fn simd_fmax(a: T, b: T) -> T; - - pub fn simd_fsqrt(a: T) -> T; - pub fn simd_fsin(a: T) -> T; - pub fn simd_fcos(a: T) -> T; - pub fn simd_fabs(a: T) -> T; - pub fn simd_floor(a: T) -> T; - pub fn simd_ceil(a: T) -> T; - pub fn simd_fexp(a: T) -> T; - pub fn simd_fexp2(a: T) -> T; - pub fn simd_flog10(a: T) -> T; - pub fn simd_flog2(a: T) -> T; - pub fn simd_flog(a: T) -> T; - //pub fn simd_fpowi - //pub fn simd_fpow - pub fn simd_fma(a: T, b: T, c: T) -> T; -} diff --git a/src/simd_traits.rs b/src/simd_traits.rs deleted file mode 100644 index 17ab13c..0000000 --- a/src/simd_traits.rs +++ /dev/null @@ -1,57 +0,0 @@ -//! SIMD traits; they are useful when the features "repr_simd" and "platform_intrinsics" are enabled. - -use std::num::Wrapping; -use num_traits; - -/// This trait should be implemented by scalar types, vectors of which are supported by SIMD intrinsics. -/// For instance, i16 and f32 can implement this trait, as well as `#[repr(transparent)]` wrappers of these, but not hand-built numeric types. -pub trait SimdElement { - /// The corresponding mask type for this element type: this is usually the unsigned integer type with the same size. - type SimdMaskType: SimdMask; -} - -/// Implemented by unsigned integer types that can represent the result of SIMD comparison elements: semantically, these are booleans, but in their representation, zero is false and any other value is true. -/// Typically, SIMD comparison of two vectors will yield a vector of mask elements, on which you can call `reduce_and()` or `reduce_or()`. -pub trait SimdMask: num_traits::sign::Unsigned + num_traits::bounds::Bounded + num_traits::cast::FromPrimitive { - /// Used for fallback code. - #[inline] - fn from_bool(b: bool) -> Self { - Self::from_u8(b as _).unwrap() - } -} - -macro_rules! impl_simd_mask { - ($T:ty) => { - impl SimdMask for $T {} - } -} - -macro_rules! impl_simd_element { - ($T:ty, $M:ty) => { - impl SimdElement for $T { - type SimdMaskType = $M; - } - } -} - -impl_simd_mask!{u8} -impl_simd_mask!{u16} -impl_simd_mask!{u32} -impl_simd_mask!{u64} - -impl SimdMask for Wrapping where Wrapping: num_traits::sign::Unsigned {} - -impl_simd_element!{i8, u8} -impl_simd_element!{i16, u16} -impl_simd_element!{i32, u32} -impl_simd_element!{i64, u64} -impl_simd_element!{u8, u8} -impl_simd_element!{u16, u16} -impl_simd_element!{u32, u32} -impl_simd_element!{u64, u64} -impl_simd_element!{f32, u32} -impl_simd_element!{f64, u64} - -impl SimdElement for Wrapping { - type SimdMaskType = T::SimdMaskType; // Don't propagate the Wrapping<>, masks are only intended for reduction to booleans; it doesn't make sense to perform arithmetic on them. -} \ No newline at end of file diff --git a/src/vec.rs b/src/vec.rs index 7c5cc7f..d488a90 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -14,13 +14,11 @@ use std::cmp; use std::ops::*; use std::slice::{self, /*SliceIndex*/}; // NOTE: Will want to use SliceIndex once it's stabilized use std::num::Wrapping; +#[cfg(feature = "platform_intrinsics")] +use std::simd::SimdElement; use num_traits::{Zero, One, NumCast, AsPrimitive, Signed, real::Real}; use approx::{AbsDiffEq, RelativeEq, UlpsEq}; use crate::ops::*; -use crate::simd_traits::{SimdElement, SimdMask}; - -#[cfg(feature = "platform_intrinsics")] -use crate::simd_llvm; #[cfg(feature = "bytemuck")] use crate::bytemuck; @@ -87,13 +85,24 @@ macro_rules! vec_impl_cmp { }} } $(#[$attrs])* + #[cfg(feature = "platform_intrinsics")] #[inline] - pub fn $cmp_simd(self, rhs: Self) -> $Vec where T: $Bounds + SimdElement { + pub fn $cmp_simd(self, rhs: Self) -> $Vec + where + T: $Bounds + SimdElement, + ::Mask: num_traits::cast::FromPrimitive { choose!{$c_or_simd { - c => $Vec::new($(T::SimdMaskType::from_bool(self.$get $op rhs.$get)),+), - simd_llvm => unsafe { simd_llvm::$simd_cmp(self, rhs) }, + c => $Vec::new($(::from_u8((self.$get $op rhs.$get) as _).unwrap()),+), + simd_llvm => unsafe { std::intrinsics::simd::$simd_cmp(self, rhs) }, }} } + + $(#[$attrs])* + #[cfg(not(feature = "platform_intrinsics"))] + #[inline] + pub fn $cmp_simd(self, rhs: Self) -> $Vec where T: $Bounds { + self.$cmp(&rhs) + } } } @@ -167,7 +176,7 @@ macro_rules! vec_impl_binop { let rhs = rhs.into(); choose!{$c_or_simd { c => $Vec::new($(self.$get.$op(rhs.$get)),+), - simd_llvm => unsafe { simd_llvm::$simd_op(self, rhs) }, + simd_llvm => unsafe { std::intrinsics::simd::$simd_op(self, rhs) }, }} } } @@ -273,7 +282,7 @@ macro_rules! vec_impl_reduce_bool_ops_for_primitive { pub fn reduce_and(self) -> bool { choose!{$c_or_simd { c => reduce_binop!(&&, $(!self.$get.is_zero()),+), - simd_llvm => unsafe { simd_llvm::simd_reduce_all(self) }, + simd_llvm => unsafe { std::intrinsics::simd::simd_reduce_all(self) }, }} } /// Returns the result of logical OR (`||`) on all elements of this vector. @@ -288,7 +297,7 @@ macro_rules! vec_impl_reduce_bool_ops_for_primitive { pub fn reduce_or(self) -> bool { choose!{$c_or_simd { c => reduce_binop!(||, $(!self.$get.is_zero()),+), - simd_llvm => unsafe { simd_llvm::simd_reduce_any(self) }, + simd_llvm => unsafe { std::intrinsics::simd::simd_reduce_any(self) }, }} } } @@ -668,7 +677,7 @@ macro_rules! vec_impl_vec { pub fn as_(self) -> $Vec where T: AsPrimitive, D: 'static + Copy { choose!{$c_or_simd { c => $Vec::new($(self.$get.as_()),+), - simd_llvm => unsafe { simd_llvm::simd_cast(self) }, + simd_llvm => unsafe { std::intrinsics::simd::simd_cast(self) }, }} } /// Returns a memberwise-converted copy of this vector, using `NumCast`. @@ -712,7 +721,7 @@ macro_rules! vec_impl_vec { let add = add.into(); choose!{$c_or_simd { c => $Vec::new($(self.$get.mul_add(mul.$get, add.$get)),+), - simd_llvm => unsafe { simd_llvm::simd_fma(self, mul, add) }, + simd_llvm => unsafe { std::intrinsics::simd::simd_fma(self, mul, add) }, }} } @@ -803,7 +812,7 @@ macro_rules! vec_impl_vec { pub fn reduce_min(self) -> T where T: Ord { choose!{$c_or_simd { c => reduce_fn!(cmp::min, $(self.$get),+), - simd_llvm => unsafe { simd_llvm::simd_reduce_min(self) }, + simd_llvm => unsafe { std::intrinsics::simd::simd_reduce_min(self) }, }} } /// Returns the element which has the highest value in this vector, using total @@ -817,7 +826,7 @@ macro_rules! vec_impl_vec { pub fn reduce_max(self) -> T where T: Ord { choose!{$c_or_simd { c => reduce_fn!(cmp::max, $(self.$get),+), - simd_llvm => unsafe { simd_llvm::simd_reduce_max(self) }, + simd_llvm => unsafe { std::intrinsics::simd::simd_reduce_max(self) }, }} } @@ -832,7 +841,7 @@ macro_rules! vec_impl_vec { pub fn reduce_partial_min(self) -> T where T: PartialOrd { choose!{$c_or_simd { c => reduce_fn!(partial_min, $(self.$get),+), - simd_llvm => unsafe { simd_llvm::simd_reduce_min(self) }, + simd_llvm => unsafe { std::intrinsics::simd::simd_reduce_min(self) }, }} } /// Returns the element which has the highest value in this vector, using partial @@ -846,7 +855,7 @@ macro_rules! vec_impl_vec { pub fn reduce_partial_max(self) -> T where T: PartialOrd { choose!{$c_or_simd { c => reduce_fn!(partial_max, $(self.$get),+), - simd_llvm => unsafe { simd_llvm::simd_reduce_max(self) }, + simd_llvm => unsafe { std::intrinsics::simd::simd_reduce_max(self) }, }} } @@ -862,7 +871,7 @@ macro_rules! vec_impl_vec { pub fn reduce_bitand(self) -> T where T: BitAnd { choose!{$c_or_simd { c => reduce_binop!(&, $(self.$get),+), - simd_llvm => unsafe { simd_llvm::simd_reduce_and(self) }, + simd_llvm => unsafe { std::intrinsics::simd::simd_reduce_and(self) }, }} } @@ -877,7 +886,7 @@ macro_rules! vec_impl_vec { pub fn reduce_bitor(self) -> T where T: BitOr { choose!{$c_or_simd { c => reduce_binop!(|, $(self.$get),+), - simd_llvm => unsafe { simd_llvm::simd_reduce_or(self) }, + simd_llvm => unsafe { std::intrinsics::simd::simd_reduce_or(self) }, }} } @@ -892,7 +901,7 @@ macro_rules! vec_impl_vec { pub fn reduce_bitxor(self) -> T where T: BitXor { choose!{$c_or_simd { c => reduce_binop!(^, $(self.$get),+), - simd_llvm => unsafe { simd_llvm::simd_reduce_xor(self) }, + simd_llvm => unsafe { std::intrinsics::simd::simd_reduce_xor(self) }, }} } @@ -912,7 +921,7 @@ macro_rules! vec_impl_vec { pub fn product(self) -> T where T: Mul { choose!{$c_or_simd { c => reduce_binop!(*, $(self.$get),+), - simd_llvm => unsafe { simd_llvm::simd_reduce_mul_unordered(self) }, + simd_llvm => unsafe { std::intrinsics::simd::simd_reduce_mul_unordered(self) }, }} } /// Returns the sum of each of this vector's elements. @@ -925,7 +934,7 @@ macro_rules! vec_impl_vec { pub fn sum(self) -> T where T: Add { choose!{$c_or_simd { c => reduce_binop!(+, $(self.$get),+), - simd_llvm => unsafe { simd_llvm::simd_reduce_add_unordered(self) }, + simd_llvm => unsafe { std::intrinsics::simd::simd_reduce_add_unordered(self) }, }} } /// Returns the average of this vector's elements. @@ -980,7 +989,7 @@ macro_rules! vec_impl_vec { pub fn sqrt(self) -> Self where T: Real { choose!{$c_or_simd { c => Self::new($(self.$get.sqrt()),+), - simd_llvm => unsafe { simd_llvm::simd_fsqrt(self) }, + simd_llvm => unsafe { std::intrinsics::simd::simd_fsqrt(self) }, }} } @@ -1022,7 +1031,7 @@ macro_rules! vec_impl_vec { pub fn ceil(self) -> Self where T: Real { choose!{$c_or_simd { c => Self::new($(self.$get.ceil()),+), - simd_llvm => unsafe { simd_llvm::simd_ceil(self) }, + simd_llvm => unsafe { std::intrinsics::simd::simd_ceil(self) }, }} } /// Returns a new vector which elements are rounded down to the nearest lower integer. @@ -1036,7 +1045,7 @@ macro_rules! vec_impl_vec { pub fn floor(self) -> Self where T: Real { choose!{$c_or_simd { c => Self::new($(self.$get.floor()),+), - simd_llvm => unsafe { simd_llvm::simd_floor(self) }, + simd_llvm => unsafe { std::intrinsics::simd::simd_floor(self) }, }} } /// Returns a new vector which elements are rounded to the nearest integer. @@ -1645,7 +1654,7 @@ macro_rules! vec_impl_vec { pub fn reduce_and(self) -> bool { choose!{$c_or_simd { c => reduce_binop!(&&, $(self.$get),+), - simd_llvm => unsafe { simd_llvm::simd_reduce_all(self.into_native_simd_integer_vector()) }, + simd_llvm => unsafe { std::intrinsics::simd::simd_reduce_all(self.into_native_simd_integer_vector()) }, }} } /// Returns the result of logical OR (`||`) on all elements of this vector. @@ -1659,7 +1668,7 @@ macro_rules! vec_impl_vec { pub fn reduce_or(self) -> bool { choose!{$c_or_simd { c => reduce_binop!(||, $(self.$get),+), - simd_llvm => unsafe { simd_llvm::simd_reduce_any(self.into_native_simd_integer_vector()) }, + simd_llvm => unsafe { std::intrinsics::simd::simd_reduce_any(self.into_native_simd_integer_vector()) }, }} } /// Reduces this vector using total inequality.