diff options
| author | Stuart Cook <Zalathar@users.noreply.github.com> | 2025-04-11 13:31:43 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-11 13:31:43 +1000 |
| commit | 45ebc4060b54009ef32fbcb91e26621e8380abd4 (patch) | |
| tree | 407182697816547aea32a3d1602026d43bcf832a /library/core/src | |
| parent | e62d47daceeec445edede74c87d0d0a3acb1a175 (diff) | |
| parent | 59c55339af73b5345ec28d7d830c7bd3feee45b3 (diff) | |
| download | rust-45ebc4060b54009ef32fbcb91e26621e8380abd4.tar.gz rust-45ebc4060b54009ef32fbcb91e26621e8380abd4.zip | |
Rollup merge of #137447 - folkertdev:simd-extract-insert-dyn, r=scottmcm
add `core::intrinsics::simd::{simd_extract_dyn, simd_insert_dyn}`
fixes https://github.com/rust-lang/rust/issues/137372
adds `core::intrinsics::simd::{simd_extract_dyn, simd_insert_dyn}`, which contrary to their non-dyn counterparts allow a non-const index. Many platforms (but notably not x86_64 or aarch64) have dedicated instructions for this operation, which stdarch can emit with this change.
Future work is to also make the `Index` operation on the `Simd` type emit this operation, but the intrinsic can't be used directly. We'll need some MIR shenanigans for that.
r? `@ghost`
Diffstat (limited to 'library/core/src')
| -rw-r--r-- | library/core/src/intrinsics/simd.rs | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index ae6e1a779ed..9ac6ee85535 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -4,7 +4,7 @@ /// Inserts an element into a vector, returning the updated vector. /// -/// `T` must be a vector with element type `U`. +/// `T` must be a vector with element type `U`, and `idx` must be `const`. /// /// # Safety /// @@ -15,15 +15,48 @@ pub const unsafe fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T; /// Extracts an element from a vector. /// -/// `T` must be a vector with element type `U`. +/// `T` must be a vector with element type `U`, and `idx` must be `const`. /// /// # Safety /// -/// `idx` must be in-bounds of the vector. +/// `idx` must be const and in-bounds of the vector. #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn simd_extract<T, U>(x: T, idx: u32) -> U; +/// Inserts an element into a vector, returning the updated vector. +/// +/// `T` must be a vector with element type `U`. +/// +/// If the index is `const`, [`simd_insert`] may emit better assembly. +/// +/// # Safety +/// +/// `idx` must be in-bounds of the vector. +#[rustc_nounwind] +#[cfg_attr(not(bootstrap), rustc_intrinsic)] +pub unsafe fn simd_insert_dyn<T, U>(mut x: T, idx: u32, val: U) -> T { + // SAFETY: `idx` must be in-bounds + unsafe { (&raw mut x).cast::<U>().add(idx as usize).write(val) } + x +} + +/// Extracts an element from a vector. +/// +/// `T` must be a vector with element type `U`. +/// +/// If the index is `const`, [`simd_extract`] may emit better assembly. +/// +/// # Safety +/// +/// `idx` must be in-bounds of the vector. +#[rustc_nounwind] +#[cfg_attr(not(bootstrap), rustc_intrinsic)] +pub unsafe fn simd_extract_dyn<T, U>(x: T, idx: u32) -> U { + // SAFETY: `idx` must be in-bounds + unsafe { (&raw const x).cast::<U>().add(idx as usize).read() } +} + /// Adds two simd vectors elementwise. /// /// `T` must be a vector of integers or floats. |
