diff --git a/README.md b/README.md index e8ac600debe..458226f5a84 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Currently, vectors may have up to 64 elements, but aliases are provided only up Depending on the size of the primitive type, the number of lanes the vector will have varies. For example, 128-bit vectors have four `f32` lanes and two `f64` lanes. The supported element types are as follows: -* **Floating Point:** `f32`, `f64` +* **Floating Point:** `f16`, `f32`, `f64` * **Signed Integers:** `i8`, `i16`, `i32`, `i64`, `isize` (`i128` excluded) * **Unsigned Integers:** `u8`, `u16`, `u32`, `u64`, `usize` (`u128` excluded) * **Pointers:** `*const T` and `*mut T` (zero-sized metadata only) diff --git a/crates/core_simd/src/alias.rs b/crates/core_simd/src/alias.rs index 23f121c4619..6dcfcb660c2 100644 --- a/crates/core_simd/src/alias.rs +++ b/crates/core_simd/src/alias.rs @@ -153,6 +153,16 @@ alias! { usizex64 64 } + f16 = { + f16x1 1 + f16x2 2 + f16x4 4 + f16x8 8 + f16x16 16 + f16x32 32 + f16x64 64 + } + f32 = { f32x1 1 f32x2 2 diff --git a/crates/core_simd/src/cast.rs b/crates/core_simd/src/cast.rs index 1c3592f8075..69dc7ba50d5 100644 --- a/crates/core_simd/src/cast.rs +++ b/crates/core_simd/src/cast.rs @@ -44,6 +44,9 @@ impl SimdCast for u64 {} unsafe impl Sealed for usize {} impl SimdCast for usize {} // Safety: primitive number types can be cast to other primitive number types +unsafe impl Sealed for f16 {} +impl SimdCast for f16 {} +// Safety: primitive number types can be cast to other primitive number types unsafe impl Sealed for f32 {} impl SimdCast for f32 {} // Safety: primitive number types can be cast to other primitive number types diff --git a/crates/core_simd/src/iter.rs b/crates/core_simd/src/iter.rs index fdc458efeda..96b1fbef0de 100644 --- a/crates/core_simd/src/iter.rs +++ b/crates/core_simd/src/iter.rs @@ -40,6 +40,7 @@ macro_rules! impl_traits { } } +impl_traits! { f16 } impl_traits! { f32 } impl_traits! { f64 } impl_traits! { u8 } diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs index 3e5ebe19e4d..339db237004 100644 --- a/crates/core_simd/src/lib.rs +++ b/crates/core_simd/src/lib.rs @@ -10,7 +10,8 @@ staged_api, prelude_import, ptr_metadata, - rustc_attrs + rustc_attrs, + f16 )] #![cfg_attr( all( @@ -35,6 +36,18 @@ all(target_arch = "x86_64", target_feature = "avx512f"), feature(stdarch_x86_avx512) )] +#![cfg_attr( + any(target_arch = "x86", target_arch = "x86_64"), + feature(stdarch_x86_avx512_f16) +)] +#![cfg_attr( + any( + target_arch = "aarch64", + target_arch = "arm64ec", + all(target_arch = "arm", target_feature = "v7"), + ), + feature(stdarch_neon_f16) +)] #![warn(missing_docs, clippy::missing_inline_in_public_items)] // basically all items, really #![deny( unsafe_op_in_unsafe_fn, diff --git a/crates/core_simd/src/ops.rs b/crates/core_simd/src/ops.rs index eb6601f7348..c0a06ed4651 100644 --- a/crates/core_simd/src/ops.rs +++ b/crates/core_simd/src/ops.rs @@ -245,7 +245,7 @@ for_base_ops! { // We don't need any special precautions here: // Floats always accept arithmetic ops, but may become NaN. for_base_ops! { - T = (f32, f64); + T = (f16, f32, f64); type Lhs = Simd; type Rhs = Simd; type Output = Self; diff --git a/crates/core_simd/src/ops/unary.rs b/crates/core_simd/src/ops/unary.rs index e1c06167f97..af7aa8a823d 100644 --- a/crates/core_simd/src/ops/unary.rs +++ b/crates/core_simd/src/ops/unary.rs @@ -19,6 +19,8 @@ macro_rules! neg { } neg! { + impl Neg for Simd + impl Neg for Simd impl Neg for Simd diff --git a/crates/core_simd/src/simd/cmp/eq.rs b/crates/core_simd/src/simd/cmp/eq.rs index d553d6c040c..76836404cbc 100644 --- a/crates/core_simd/src/simd/cmp/eq.rs +++ b/crates/core_simd/src/simd/cmp/eq.rs @@ -42,7 +42,7 @@ macro_rules! impl_number { } } -impl_number! { f32, f64, u8, u16, u32, u64, usize, i8, i16, i32, i64, isize } +impl_number! { f16, f32, f64, u8, u16, u32, u64, usize, i8, i16, i32, i64, isize } macro_rules! impl_mask { { $($integer:ty),* } => { diff --git a/crates/core_simd/src/simd/cmp/ord.rs b/crates/core_simd/src/simd/cmp/ord.rs index 5672fbbf54c..5a4e74c753b 100644 --- a/crates/core_simd/src/simd/cmp/ord.rs +++ b/crates/core_simd/src/simd/cmp/ord.rs @@ -144,7 +144,7 @@ macro_rules! impl_float { } } -impl_float! { f32, f64 } +impl_float! { f16, f32, f64 } macro_rules! impl_mask { { $($integer:ty),* } => { diff --git a/crates/core_simd/src/simd/num/float.rs b/crates/core_simd/src/simd/num/float.rs index efd7c246951..cc307d44347 100644 --- a/crates/core_simd/src/simd/num/float.rs +++ b/crates/core_simd/src/simd/num/float.rs @@ -444,4 +444,4 @@ macro_rules! impl_trait { } } -impl_trait! { f32 { bits: u32, mask: i32 }, f64 { bits: u64, mask: i64 } } +impl_trait! { f16 { bits: u16, mask: i16}, f32 { bits: u32, mask: i32 }, f64 { bits: u64, mask: i64 } } diff --git a/crates/core_simd/src/simd/prelude.rs b/crates/core_simd/src/simd/prelude.rs index e5d7a2aeb73..a54619f995e 100644 --- a/crates/core_simd/src/simd/prelude.rs +++ b/crates/core_simd/src/simd/prelude.rs @@ -14,6 +14,10 @@ pub use super::{ simd_swizzle, }; +#[rustfmt::skip] +#[doc(no_inline)] +pub use super::{f16x1, f16x2, f16x4, f16x8, f16x16, f16x32, f16x64}; + #[rustfmt::skip] #[doc(no_inline)] pub use super::{f32x1, f32x2, f32x4, f32x8, f32x16, f32x32, f32x64}; diff --git a/crates/core_simd/src/to_bytes.rs b/crates/core_simd/src/to_bytes.rs index 1fd285e457d..acf20f7bfc0 100644 --- a/crates/core_simd/src/to_bytes.rs +++ b/crates/core_simd/src/to_bytes.rs @@ -46,6 +46,7 @@ pub trait ToBytes: Sealed { } macro_rules! swap_bytes { + { f16, $x:expr } => { Simd::from_bits($x.to_bits().swap_bytes()) }; { f32, $x:expr } => { Simd::from_bits($x.to_bits().swap_bytes()) }; { f64, $x:expr } => { Simd::from_bits($x.to_bits().swap_bytes()) }; { $ty:ty, $x:expr } => { $x.swap_bytes() } @@ -141,5 +142,6 @@ impl_to_bytes! { isize, 4 } #[cfg(target_pointer_width = "64")] impl_to_bytes! { isize, 8 } +impl_to_bytes! { f16, 2 } impl_to_bytes! { f32, 4 } impl_to_bytes! { f64, 8 } diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs index 2dba5c83e11..52dc742e7ae 100644 --- a/crates/core_simd/src/vector.rs +++ b/crates/core_simd/src/vector.rs @@ -1153,6 +1153,13 @@ unsafe impl SimdElement for isize { type Mask = isize; } +impl Sealed for f16 {} + +// Safety: f16 is a valid SIMD element type, and is supported by this API +unsafe impl SimdElement for f16 { + type Mask = i16; +} + impl Sealed for f32 {} // Safety: f32 is a valid SIMD element type, and is supported by this API diff --git a/crates/core_simd/src/vendor/arm.rs b/crates/core_simd/src/vendor/arm.rs index 3dc54481b6f..b396be089a7 100644 --- a/crates/core_simd/src/vendor/arm.rs +++ b/crates/core_simd/src/vendor/arm.rs @@ -18,6 +18,9 @@ use core::arch::aarch64::*; mod neon { use super::*; + from_transmute! { unsafe f16x4 => float16x4_t } + from_transmute! { unsafe f16x8 => float16x8_t } + from_transmute! { unsafe f32x2 => float32x2_t } from_transmute! { unsafe f32x4 => float32x4_t } diff --git a/crates/core_simd/src/vendor/x86.rs b/crates/core_simd/src/vendor/x86.rs index eae42e6fd0d..ad5caf3eb82 100644 --- a/crates/core_simd/src/vendor/x86.rs +++ b/crates/core_simd/src/vendor/x86.rs @@ -19,6 +19,9 @@ from_transmute! { unsafe u16x32 => __m512i } from_transmute! { unsafe i16x8 => __m128i } from_transmute! { unsafe i16x16 => __m256i } from_transmute! { unsafe i16x32 => __m512i } +from_transmute! { unsafe f16x8 => __m128h } +from_transmute! { unsafe f16x16 => __m256h } +from_transmute! { unsafe f16x32 => __m512h } from_transmute! { unsafe u32x4 => __m128i } from_transmute! { unsafe u32x8 => __m256i } diff --git a/crates/std_float/src/lib.rs b/crates/std_float/src/lib.rs index c3c9b76e50b..397c85f29db 100644 --- a/crates/std_float/src/lib.rs +++ b/crates/std_float/src/lib.rs @@ -2,6 +2,7 @@ feature = "as_crate", feature(core_intrinsics), feature(portable_simd), + feature(f16), allow(internal_features) )] #[cfg(not(feature = "as_crate"))] @@ -140,6 +141,7 @@ pub trait StdFloat: Sealed + Sized { fn fract(self) -> Self; } +impl Sealed for Simd {} impl Sealed for Simd {} impl Sealed for Simd {} @@ -147,6 +149,21 @@ macro_rules! impl_float { { $($fn:ident: $intrinsic:ident,)* } => { + impl StdFloat for Simd + { + #[inline] + fn fract(self) -> Self { + self - self.trunc() + } + + $( + #[inline] + fn $fn(self) -> Self { + unsafe { intrinsics::$intrinsic(self) } + } + )* + } + impl StdFloat for Simd { #[inline]