Skip to content

Commit 70237a8

Browse files
committed
Auto merge of rust-lang#138687 - calebzulawski:sync-from-portable-simd-2025-03-19, r=workingjubilee
Portable SIMD subtree update
2 parents 2947be7 + 3c705b8 commit 70237a8

21 files changed

+96
-46
lines changed

library/portable-simd/beginners-guide.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,12 @@ Most of the portable SIMD API is designed to allow the user to gloss over the de
8080

8181
Fortunately, most SIMD types have a fairly predictable size. `i32x4` is bit-equivalent to `[i32; 4]` and so can be bitcast to it, e.g. using [`mem::transmute`], though the API usually offers a safe cast you can use instead.
8282

83-
However, this is not the same as alignment. Computer architectures generally prefer aligned accesses, especially when moving data between memory and vector registers, and while some support specialized operations that can bend the rules to help with this, unaligned access is still typically slow, or even undefined behavior. In addition, different architectures can require different alignments when interacting with their native SIMD types. For this reason, any `#[repr(simd)]` type has a non-portable alignment. If it is necessary to directly interact with the alignment of these types, it should be via [`mem::align_of`].
83+
However, this is not the same as alignment. Computer architectures generally prefer aligned accesses, especially when moving data between memory and vector registers, and while some support specialized operations that can bend the rules to help with this, unaligned access is still typically slow, or even undefined behavior. In addition, different architectures can require different alignments when interacting with their native SIMD types. For this reason, any `#[repr(simd)]` type has a non-portable alignment. If it is necessary to directly interact with the alignment of these types, it should be via [`align_of`].
8484

8585
When working with slices, data correctly aligned for SIMD can be acquired using the [`as_simd`] and [`as_simd_mut`] methods of the slice primitive.
8686

8787
[`mem::transmute`]: https://doc.rust-lang.org/core/mem/fn.transmute.html
88-
[`mem::align_of`]: https://doc.rust-lang.org/core/mem/fn.align_of.html
88+
[`align_of`]: https://doc.rust-lang.org/core/mem/fn.align_of.html
8989
[`as_simd`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.as_simd
9090
[`as_simd_mut`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.as_simd_mut
9191

library/portable-simd/crates/core_simd/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "core_simd"
33
version = "0.1.0"
4-
edition = "2021"
4+
edition = "2024"
55
homepage = "https://github.com/rust-lang/portable-simd"
66
repository = "https://github.com/rust-lang/portable-simd"
77
keywords = ["core", "simd", "intrinsics"]

library/portable-simd/crates/core_simd/src/lib.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,11 @@
3535
feature(stdarch_x86_avx512)
3636
)]
3737
#![warn(missing_docs, clippy::missing_inline_in_public_items)] // basically all items, really
38-
#![deny(unsafe_op_in_unsafe_fn, clippy::undocumented_unsafe_blocks)]
38+
#![deny(
39+
unsafe_op_in_unsafe_fn,
40+
unreachable_pub,
41+
clippy::undocumented_unsafe_blocks
42+
)]
3943
#![doc(test(attr(deny(warnings))))]
4044
#![allow(internal_features)]
4145
#![unstable(feature = "portable_simd", issue = "86656")]

library/portable-simd/crates/core_simd/src/masks/bitmask.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use core::marker::PhantomData;
55

66
/// A mask where each lane is represented by a single bit.
77
#[repr(transparent)]
8-
pub struct Mask<T, const N: usize>(
8+
pub(crate) struct Mask<T, const N: usize>(
99
<LaneCount<N> as SupportedLaneCount>::BitMask,
1010
PhantomData<T>,
1111
)
@@ -78,7 +78,7 @@ where
7878
{
7979
#[inline]
8080
#[must_use = "method returns a new mask and does not mutate the original value"]
81-
pub fn splat(value: bool) -> Self {
81+
pub(crate) fn splat(value: bool) -> Self {
8282
let mut mask = <LaneCount<N> as SupportedLaneCount>::BitMask::default();
8383
if value {
8484
mask.as_mut().fill(u8::MAX)
@@ -93,20 +93,20 @@ where
9393

9494
#[inline]
9595
#[must_use = "method returns a new bool and does not mutate the original value"]
96-
pub unsafe fn test_unchecked(&self, lane: usize) -> bool {
96+
pub(crate) unsafe fn test_unchecked(&self, lane: usize) -> bool {
9797
(self.0.as_ref()[lane / 8] >> (lane % 8)) & 0x1 > 0
9898
}
9999

100100
#[inline]
101-
pub unsafe fn set_unchecked(&mut self, lane: usize, value: bool) {
101+
pub(crate) unsafe fn set_unchecked(&mut self, lane: usize, value: bool) {
102102
unsafe {
103103
self.0.as_mut()[lane / 8] ^= ((value ^ self.test_unchecked(lane)) as u8) << (lane % 8)
104104
}
105105
}
106106

107107
#[inline]
108108
#[must_use = "method returns a new vector and does not mutate the original value"]
109-
pub fn to_int(self) -> Simd<T, N> {
109+
pub(crate) fn to_int(self) -> Simd<T, N> {
110110
unsafe {
111111
core::intrinsics::simd::simd_select_bitmask(
112112
self.0,
@@ -118,19 +118,19 @@ where
118118

119119
#[inline]
120120
#[must_use = "method returns a new mask and does not mutate the original value"]
121-
pub unsafe fn from_int_unchecked(value: Simd<T, N>) -> Self {
121+
pub(crate) unsafe fn from_int_unchecked(value: Simd<T, N>) -> Self {
122122
unsafe { Self(core::intrinsics::simd::simd_bitmask(value), PhantomData) }
123123
}
124124

125125
#[inline]
126-
pub fn to_bitmask_integer(self) -> u64 {
126+
pub(crate) fn to_bitmask_integer(self) -> u64 {
127127
let mut bitmask = [0u8; 8];
128128
bitmask[..self.0.as_ref().len()].copy_from_slice(self.0.as_ref());
129129
u64::from_ne_bytes(bitmask)
130130
}
131131

132132
#[inline]
133-
pub fn from_bitmask_integer(bitmask: u64) -> Self {
133+
pub(crate) fn from_bitmask_integer(bitmask: u64) -> Self {
134134
let mut bytes = <LaneCount<N> as SupportedLaneCount>::BitMask::default();
135135
let len = bytes.as_mut().len();
136136
bytes
@@ -141,7 +141,7 @@ where
141141

142142
#[inline]
143143
#[must_use = "method returns a new mask and does not mutate the original value"]
144-
pub fn convert<U>(self) -> Mask<U, N>
144+
pub(crate) fn convert<U>(self) -> Mask<U, N>
145145
where
146146
U: MaskElement,
147147
{
@@ -151,13 +151,13 @@ where
151151

152152
#[inline]
153153
#[must_use = "method returns a new bool and does not mutate the original value"]
154-
pub fn any(self) -> bool {
154+
pub(crate) fn any(self) -> bool {
155155
self != Self::splat(false)
156156
}
157157

158158
#[inline]
159159
#[must_use = "method returns a new bool and does not mutate the original value"]
160-
pub fn all(self) -> bool {
160+
pub(crate) fn all(self) -> bool {
161161
self == Self::splat(true)
162162
}
163163
}

library/portable-simd/crates/core_simd/src/masks/full_masks.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use crate::simd::{LaneCount, MaskElement, Simd, SupportedLaneCount};
44

55
#[repr(transparent)]
6-
pub struct Mask<T, const N: usize>(Simd<T, N>)
6+
pub(crate) struct Mask<T, const N: usize>(Simd<T, N>)
77
where
88
T: MaskElement,
99
LaneCount<N>: SupportedLaneCount;
@@ -80,7 +80,7 @@ macro_rules! impl_reverse_bits {
8080
#[inline(always)]
8181
fn reverse_bits(self, n: usize) -> Self {
8282
let rev = <$int>::reverse_bits(self);
83-
let bitsize = core::mem::size_of::<$int>() * 8;
83+
let bitsize = size_of::<$int>() * 8;
8484
if n < bitsize {
8585
// Shift things back to the right
8686
rev >> (bitsize - n)
@@ -102,36 +102,36 @@ where
102102
{
103103
#[inline]
104104
#[must_use = "method returns a new mask and does not mutate the original value"]
105-
pub fn splat(value: bool) -> Self {
105+
pub(crate) fn splat(value: bool) -> Self {
106106
Self(Simd::splat(if value { T::TRUE } else { T::FALSE }))
107107
}
108108

109109
#[inline]
110110
#[must_use = "method returns a new bool and does not mutate the original value"]
111-
pub unsafe fn test_unchecked(&self, lane: usize) -> bool {
111+
pub(crate) unsafe fn test_unchecked(&self, lane: usize) -> bool {
112112
T::eq(self.0[lane], T::TRUE)
113113
}
114114

115115
#[inline]
116-
pub unsafe fn set_unchecked(&mut self, lane: usize, value: bool) {
116+
pub(crate) unsafe fn set_unchecked(&mut self, lane: usize, value: bool) {
117117
self.0[lane] = if value { T::TRUE } else { T::FALSE }
118118
}
119119

120120
#[inline]
121121
#[must_use = "method returns a new vector and does not mutate the original value"]
122-
pub fn to_int(self) -> Simd<T, N> {
122+
pub(crate) fn to_int(self) -> Simd<T, N> {
123123
self.0
124124
}
125125

126126
#[inline]
127127
#[must_use = "method returns a new mask and does not mutate the original value"]
128-
pub unsafe fn from_int_unchecked(value: Simd<T, N>) -> Self {
128+
pub(crate) unsafe fn from_int_unchecked(value: Simd<T, N>) -> Self {
129129
Self(value)
130130
}
131131

132132
#[inline]
133133
#[must_use = "method returns a new mask and does not mutate the original value"]
134-
pub fn convert<U>(self) -> Mask<U, N>
134+
pub(crate) fn convert<U>(self) -> Mask<U, N>
135135
where
136136
U: MaskElement,
137137
{
@@ -220,14 +220,14 @@ where
220220

221221
#[inline]
222222
#[must_use = "method returns a new bool and does not mutate the original value"]
223-
pub fn any(self) -> bool {
223+
pub(crate) fn any(self) -> bool {
224224
// Safety: use `self` as an integer vector
225225
unsafe { core::intrinsics::simd::simd_reduce_any(self.to_int()) }
226226
}
227227

228228
#[inline]
229229
#[must_use = "method returns a new bool and does not mutate the original value"]
230-
pub fn all(self) -> bool {
230+
pub(crate) fn all(self) -> bool {
231231
// Safety: use `self` as an integer vector
232232
unsafe { core::intrinsics::simd::simd_reduce_all(self.to_int()) }
233233
}

library/portable-simd/crates/core_simd/src/ops.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::simd::{cmp::SimdPartialEq, LaneCount, Simd, SimdElement, SupportedLaneCount};
1+
use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount, cmp::SimdPartialEq};
22
use core::ops::{Add, Mul};
33
use core::ops::{BitAnd, BitOr, BitXor};
44
use core::ops::{Div, Rem, Sub};

library/portable-simd/crates/core_simd/src/simd/cmp/eq.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::simd::{
2-
ptr::{SimdConstPtr, SimdMutPtr},
32
LaneCount, Mask, Simd, SimdElement, SupportedLaneCount,
3+
ptr::{SimdConstPtr, SimdMutPtr},
44
};
55

66
/// Parallel `PartialEq`.

library/portable-simd/crates/core_simd/src/simd/cmp/ord.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::simd::{
2+
LaneCount, Mask, Simd, SupportedLaneCount,
23
cmp::SimdPartialEq,
34
ptr::{SimdConstPtr, SimdMutPtr},
4-
LaneCount, Mask, Simd, SupportedLaneCount,
55
};
66

77
/// Parallel `PartialOrd`.

library/portable-simd/crates/core_simd/src/simd/num/float.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::sealed::Sealed;
22
use crate::simd::{
3-
cmp::{SimdPartialEq, SimdPartialOrd},
43
LaneCount, Mask, Simd, SimdCast, SimdElement, SupportedLaneCount,
4+
cmp::{SimdPartialEq, SimdPartialOrd},
55
};
66

77
/// Operations on SIMD vectors of floats.
@@ -263,7 +263,8 @@ macro_rules! impl_trait {
263263
unsafe { core::intrinsics::simd::simd_as(self) }
264264
}
265265

266-
// https://github.com/llvm/llvm-project/issues/94694
266+
// workaround for https://github.com/llvm/llvm-project/issues/94694 (fixed in LLVM 20)
267+
// tracked in: https://github.com/rust-lang/rust/issues/135982
267268
#[cfg(target_arch = "aarch64")]
268269
#[inline]
269270
fn cast<T: SimdCast>(self) -> Self::Cast<T>
@@ -302,14 +303,14 @@ macro_rules! impl_trait {
302303

303304
#[inline]
304305
fn to_bits(self) -> Simd<$bits_ty, N> {
305-
assert_eq!(core::mem::size_of::<Self>(), core::mem::size_of::<Self::Bits>());
306+
assert_eq!(size_of::<Self>(), size_of::<Self::Bits>());
306307
// Safety: transmuting between vector types is safe
307308
unsafe { core::mem::transmute_copy(&self) }
308309
}
309310

310311
#[inline]
311312
fn from_bits(bits: Simd<$bits_ty, N>) -> Self {
312-
assert_eq!(core::mem::size_of::<Self>(), core::mem::size_of::<Self::Bits>());
313+
assert_eq!(size_of::<Self>(), size_of::<Self::Bits>());
313314
// Safety: transmuting between vector types is safe
314315
unsafe { core::mem::transmute_copy(&bits) }
315316
}

library/portable-simd/crates/core_simd/src/simd/num/int.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::sealed::Sealed;
22
use crate::simd::{
3-
cmp::SimdOrd, cmp::SimdPartialOrd, num::SimdUint, LaneCount, Mask, Simd, SimdCast, SimdElement,
4-
SupportedLaneCount,
3+
LaneCount, Mask, Simd, SimdCast, SimdElement, SupportedLaneCount, cmp::SimdOrd,
4+
cmp::SimdPartialOrd, num::SimdUint,
55
};
66

77
/// Operations on SIMD vectors of signed integers.

library/portable-simd/crates/core_simd/src/simd/num/uint.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::sealed::Sealed;
2-
use crate::simd::{cmp::SimdOrd, LaneCount, Simd, SimdCast, SimdElement, SupportedLaneCount};
2+
use crate::simd::{LaneCount, Simd, SimdCast, SimdElement, SupportedLaneCount, cmp::SimdOrd};
33

44
/// Operations on SIMD vectors of unsigned integers.
55
pub trait SimdUint: Copy + Sealed {

library/portable-simd/crates/core_simd/src/simd/prelude.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
88
#[doc(no_inline)]
99
pub use super::{
10+
Mask, Simd,
1011
cmp::{SimdOrd, SimdPartialEq, SimdPartialOrd},
1112
num::{SimdFloat, SimdInt, SimdUint},
1213
ptr::{SimdConstPtr, SimdMutPtr},
13-
simd_swizzle, Mask, Simd,
14+
simd_swizzle,
1415
};
1516

1617
#[rustfmt::skip]

library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::sealed::Sealed;
2-
use crate::simd::{cmp::SimdPartialEq, num::SimdUint, LaneCount, Mask, Simd, SupportedLaneCount};
2+
use crate::simd::{LaneCount, Mask, Simd, SupportedLaneCount, cmp::SimdPartialEq, num::SimdUint};
33

44
/// Operations on SIMD vectors of constant pointers.
55
pub trait SimdConstPtr: Copy + Sealed {

library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::sealed::Sealed;
2-
use crate::simd::{cmp::SimdPartialEq, num::SimdUint, LaneCount, Mask, Simd, SupportedLaneCount};
2+
use crate::simd::{LaneCount, Mask, Simd, SupportedLaneCount, cmp::SimdPartialEq, num::SimdUint};
33

44
/// Operations on SIMD vectors of mutable pointers.
55
pub trait SimdMutPtr: Copy + Sealed {

library/portable-simd/crates/core_simd/src/swizzle.rs

+44
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,17 @@ where
214214
/// Rotates the vector such that the first `OFFSET` elements of the slice move to the end
215215
/// while the last `self.len() - OFFSET` elements move to the front. After calling `rotate_elements_left`,
216216
/// the element previously at index `OFFSET` will become the first element in the slice.
217+
/// ```
218+
/// # #![feature(portable_simd)]
219+
/// # #[cfg(feature = "as_crate")] use core_simd::simd::Simd;
220+
/// # #[cfg(not(feature = "as_crate"))] use core::simd::Simd;
221+
/// let a = Simd::from_array([0, 1, 2, 3]);
222+
/// let x = a.rotate_elements_left::<3>();
223+
/// assert_eq!(x.to_array(), [3, 0, 1, 2]);
224+
///
225+
/// let y = a.rotate_elements_left::<7>();
226+
/// assert_eq!(y.to_array(), [3, 0, 1, 2]);
227+
/// ```
217228
#[inline]
218229
#[must_use = "method returns a new vector and does not mutate the original inputs"]
219230
pub fn rotate_elements_left<const OFFSET: usize>(self) -> Self {
@@ -238,6 +249,17 @@ where
238249
/// Rotates the vector such that the first `self.len() - OFFSET` elements of the vector move to
239250
/// the end while the last `OFFSET` elements move to the front. After calling `rotate_elements_right`,
240251
/// the element previously at index `self.len() - OFFSET` will become the first element in the slice.
252+
/// ```
253+
/// # #![feature(portable_simd)]
254+
/// # #[cfg(feature = "as_crate")] use core_simd::simd::Simd;
255+
/// # #[cfg(not(feature = "as_crate"))] use core::simd::Simd;
256+
/// let a = Simd::from_array([0, 1, 2, 3]);
257+
/// let x = a.rotate_elements_right::<3>();
258+
/// assert_eq!(x.to_array(), [1, 2, 3, 0]);
259+
///
260+
/// let y = a.rotate_elements_right::<7>();
261+
/// assert_eq!(y.to_array(), [1, 2, 3, 0]);
262+
/// ```
241263
#[inline]
242264
#[must_use = "method returns a new vector and does not mutate the original inputs"]
243265
pub fn rotate_elements_right<const OFFSET: usize>(self) -> Self {
@@ -261,6 +283,17 @@ where
261283

262284
/// Shifts the vector elements to the left by `OFFSET`, filling in with
263285
/// `padding` from the right.
286+
/// ```
287+
/// # #![feature(portable_simd)]
288+
/// # #[cfg(feature = "as_crate")] use core_simd::simd::Simd;
289+
/// # #[cfg(not(feature = "as_crate"))] use core::simd::Simd;
290+
/// let a = Simd::from_array([0, 1, 2, 3]);
291+
/// let x = a.shift_elements_left::<3>(255);
292+
/// assert_eq!(x.to_array(), [3, 255, 255, 255]);
293+
///
294+
/// let y = a.shift_elements_left::<7>(255);
295+
/// assert_eq!(y.to_array(), [255, 255, 255, 255]);
296+
/// ```
264297
#[inline]
265298
#[must_use = "method returns a new vector and does not mutate the original inputs"]
266299
pub fn shift_elements_left<const OFFSET: usize>(self, padding: T) -> Self {
@@ -283,6 +316,17 @@ where
283316

284317
/// Shifts the vector elements to the right by `OFFSET`, filling in with
285318
/// `padding` from the left.
319+
/// ```
320+
/// # #![feature(portable_simd)]
321+
/// # #[cfg(feature = "as_crate")] use core_simd::simd::Simd;
322+
/// # #[cfg(not(feature = "as_crate"))] use core::simd::Simd;
323+
/// let a = Simd::from_array([0, 1, 2, 3]);
324+
/// let x = a.shift_elements_right::<3>(255);
325+
/// assert_eq!(x.to_array(), [255, 255, 255, 0]);
326+
///
327+
/// let y = a.shift_elements_right::<7>(255);
328+
/// assert_eq!(y.to_array(), [255, 255, 255, 255]);
329+
/// ```
286330
#[inline]
287331
#[must_use = "method returns a new vector and does not mutate the original inputs"]
288332
pub fn shift_elements_right<const OFFSET: usize>(self, padding: T) -> Self {

library/portable-simd/crates/core_simd/src/to_bytes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::simd::{
2-
num::{SimdFloat, SimdInt, SimdUint},
32
LaneCount, Simd, SimdElement, SupportedLaneCount,
3+
num::{SimdFloat, SimdInt, SimdUint},
44
};
55

66
mod sealed {

0 commit comments

Comments
 (0)