Skip to content

Commit fd68a6d

Browse files
committedJul 7, 2023
Auto merge of #113437 - workingjubilee:sync-simd-2023-july-07, r=workingjubilee
Sync portable-simd to 2023 July 07 r? `@ghost`
2 parents 1a449dc + 37fea34 commit fd68a6d

File tree

19 files changed

+339
-134
lines changed

19 files changed

+339
-134
lines changed
 

‎library/portable-simd/.github/workflows/ci.yml

+5-4
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ jobs:
3838
- i586-unknown-linux-gnu
3939
- aarch64-unknown-linux-gnu
4040
- armv7-unknown-linux-gnueabihf
41-
- mips-unknown-linux-gnu
42-
- mips64-unknown-linux-gnuabi64
41+
# non-nightly since https://github.com/rust-lang/rust/pull/113274
42+
# - mips-unknown-linux-gnu
43+
# - mips64-unknown-linux-gnuabi64
4344
- powerpc-unknown-linux-gnu
4445
- powerpc64-unknown-linux-gnu
4546
- riscv64gc-unknown-linux-gnu
@@ -191,8 +192,8 @@ jobs:
191192
# Note: The issue above means neither of these mips targets will use
192193
# MSA (mips simd) but MIPS uses a nonstandard binary representation
193194
# for NaNs which makes it worth testing on despite that.
194-
- mips-unknown-linux-gnu
195-
- mips64-unknown-linux-gnuabi64
195+
# - mips-unknown-linux-gnu
196+
# - mips64-unknown-linux-gnuabi64
196197
- riscv64gc-unknown-linux-gnu
197198
# TODO this test works, but it appears to time out
198199
# - powerpc-unknown-linux-gnu
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,51 @@
11
use crate::simd::SimdElement;
22

3+
mod sealed {
4+
/// Cast vector elements to other types.
5+
///
6+
/// # Safety
7+
/// Implementing this trait asserts that the type is a valid vector element for the `simd_cast`
8+
/// or `simd_as` intrinsics.
9+
pub unsafe trait Sealed {}
10+
}
11+
use sealed::Sealed;
12+
313
/// Supporting trait for `Simd::cast`. Typically doesn't need to be used directly.
4-
///
5-
/// # Safety
6-
/// Implementing this trait asserts that the type is a valid vector element for the `simd_cast` or
7-
/// `simd_as` intrinsics.
8-
pub unsafe trait SimdCast: SimdElement {}
14+
pub trait SimdCast: Sealed + SimdElement {}
915

1016
// Safety: primitive number types can be cast to other primitive number types
11-
unsafe impl SimdCast for i8 {}
17+
unsafe impl Sealed for i8 {}
18+
impl SimdCast for i8 {}
1219
// Safety: primitive number types can be cast to other primitive number types
13-
unsafe impl SimdCast for i16 {}
20+
unsafe impl Sealed for i16 {}
21+
impl SimdCast for i16 {}
1422
// Safety: primitive number types can be cast to other primitive number types
15-
unsafe impl SimdCast for i32 {}
23+
unsafe impl Sealed for i32 {}
24+
impl SimdCast for i32 {}
1625
// Safety: primitive number types can be cast to other primitive number types
17-
unsafe impl SimdCast for i64 {}
26+
unsafe impl Sealed for i64 {}
27+
impl SimdCast for i64 {}
1828
// Safety: primitive number types can be cast to other primitive number types
19-
unsafe impl SimdCast for isize {}
29+
unsafe impl Sealed for isize {}
30+
impl SimdCast for isize {}
2031
// Safety: primitive number types can be cast to other primitive number types
21-
unsafe impl SimdCast for u8 {}
32+
unsafe impl Sealed for u8 {}
33+
impl SimdCast for u8 {}
2234
// Safety: primitive number types can be cast to other primitive number types
23-
unsafe impl SimdCast for u16 {}
35+
unsafe impl Sealed for u16 {}
36+
impl SimdCast for u16 {}
2437
// Safety: primitive number types can be cast to other primitive number types
25-
unsafe impl SimdCast for u32 {}
38+
unsafe impl Sealed for u32 {}
39+
impl SimdCast for u32 {}
2640
// Safety: primitive number types can be cast to other primitive number types
27-
unsafe impl SimdCast for u64 {}
41+
unsafe impl Sealed for u64 {}
42+
impl SimdCast for u64 {}
2843
// Safety: primitive number types can be cast to other primitive number types
29-
unsafe impl SimdCast for usize {}
44+
unsafe impl Sealed for usize {}
45+
impl SimdCast for usize {}
3046
// Safety: primitive number types can be cast to other primitive number types
31-
unsafe impl SimdCast for f32 {}
47+
unsafe impl Sealed for f32 {}
48+
impl SimdCast for f32 {}
3249
// Safety: primitive number types can be cast to other primitive number types
33-
unsafe impl SimdCast for f64 {}
34-
35-
/// Supporting trait for `Simd::cast_ptr`. Typically doesn't need to be used directly.
36-
///
37-
/// # Safety
38-
/// Implementing this trait asserts that the type is a valid vector element for the `simd_cast_ptr`
39-
/// intrinsic.
40-
pub unsafe trait SimdCastPtr<T> {}
41-
42-
// Safety: pointers can be cast to other pointer types
43-
unsafe impl<T, U> SimdCastPtr<T> for *const U
44-
where
45-
U: core::ptr::Pointee,
46-
T: core::ptr::Pointee<Metadata = U::Metadata>,
47-
{
48-
}
49-
// Safety: pointers can be cast to other pointer types
50-
unsafe impl<T, U> SimdCastPtr<T> for *mut U
51-
where
52-
U: core::ptr::Pointee,
53-
T: core::ptr::Pointee<Metadata = U::Metadata>,
54-
{
55-
}
50+
unsafe impl Sealed for f64 {}
51+
impl SimdCast for f64 {}

‎library/portable-simd/crates/core_simd/src/elements/const_ptr.rs

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

44
/// Operations on SIMD vectors of constant pointers.
55
pub trait SimdConstPtr: Copy + Sealed {
@@ -9,6 +9,9 @@ pub trait SimdConstPtr: Copy + Sealed {
99
/// Vector of `isize` with the same number of lanes.
1010
type Isize;
1111

12+
/// Vector of const pointers with the same number of lanes.
13+
type CastPtr<T>;
14+
1215
/// Vector of mutable pointers to the same type.
1316
type MutPtr;
1417

@@ -18,6 +21,11 @@ pub trait SimdConstPtr: Copy + Sealed {
1821
/// Returns `true` for each lane that is null.
1922
fn is_null(self) -> Self::Mask;
2023

24+
/// Casts to a pointer of another type.
25+
///
26+
/// Equivalent to calling [`pointer::cast`] on each lane.
27+
fn cast<T>(self) -> Self::CastPtr<T>;
28+
2129
/// Changes constness without changing the type.
2230
///
2331
/// Equivalent to calling [`pointer::cast_mut`] on each lane.
@@ -78,6 +86,7 @@ where
7886
{
7987
type Usize = Simd<usize, LANES>;
8088
type Isize = Simd<isize, LANES>;
89+
type CastPtr<U> = Simd<*const U, LANES>;
8190
type MutPtr = Simd<*mut T, LANES>;
8291
type Mask = Mask<isize, LANES>;
8392

@@ -86,9 +95,22 @@ where
8695
Simd::splat(core::ptr::null()).simd_eq(self)
8796
}
8897

98+
#[inline]
99+
fn cast<U>(self) -> Self::CastPtr<U> {
100+
// SimdElement currently requires zero-sized metadata, so this should never fail.
101+
// If this ever changes, `simd_cast_ptr` should produce a post-mono error.
102+
use core::{mem::size_of, ptr::Pointee};
103+
assert_eq!(size_of::<<T as Pointee>::Metadata>(), 0);
104+
assert_eq!(size_of::<<U as Pointee>::Metadata>(), 0);
105+
106+
// Safety: pointers can be cast
107+
unsafe { intrinsics::simd_cast_ptr(self) }
108+
}
109+
89110
#[inline]
90111
fn cast_mut(self) -> Self::MutPtr {
91-
self.cast_ptr()
112+
// Safety: pointers can be cast
113+
unsafe { intrinsics::simd_cast_ptr(self) }
92114
}
93115

94116
#[inline]
@@ -106,9 +128,9 @@ where
106128
// In the mean-time, this operation is defined to be "as if" it was
107129
// a wrapping_offset, so we can emulate it as such. This should properly
108130
// restore pointer provenance even under today's compiler.
109-
self.cast_ptr::<*const u8>()
131+
self.cast::<u8>()
110132
.wrapping_offset(addr.cast::<isize>() - self.addr().cast::<isize>())
111-
.cast_ptr()
133+
.cast()
112134
}
113135

114136
#[inline]

‎library/portable-simd/crates/core_simd/src/elements/float.rs

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

@@ -15,6 +15,53 @@ pub trait SimdFloat: Copy + Sealed {
1515
/// Bit representation of this SIMD vector type.
1616
type Bits;
1717

18+
/// A SIMD vector with a different element type.
19+
type Cast<T: SimdElement>;
20+
21+
/// Performs elementwise conversion of this vector's elements to another SIMD-valid type.
22+
///
23+
/// This follows the semantics of Rust's `as` conversion for floats (truncating or saturating
24+
/// at the limits) for each element.
25+
///
26+
/// # Example
27+
/// ```
28+
/// # #![feature(portable_simd)]
29+
/// # #[cfg(feature = "as_crate")] use core_simd::simd;
30+
/// # #[cfg(not(feature = "as_crate"))] use core::simd;
31+
/// # use simd::{SimdFloat, SimdInt, Simd};
32+
/// let floats: Simd<f32, 4> = Simd::from_array([1.9, -4.5, f32::INFINITY, f32::NAN]);
33+
/// let ints = floats.cast::<i32>();
34+
/// assert_eq!(ints, Simd::from_array([1, -4, i32::MAX, 0]));
35+
///
36+
/// // Formally equivalent, but `Simd::cast` can optimize better.
37+
/// assert_eq!(ints, Simd::from_array(floats.to_array().map(|x| x as i32)));
38+
///
39+
/// // The float conversion does not round-trip.
40+
/// let floats_again = ints.cast();
41+
/// assert_ne!(floats, floats_again);
42+
/// assert_eq!(floats_again, Simd::from_array([1.0, -4.0, 2147483647.0, 0.0]));
43+
/// ```
44+
#[must_use]
45+
fn cast<T: SimdCast>(self) -> Self::Cast<T>;
46+
47+
/// Rounds toward zero and converts to the same-width integer type, assuming that
48+
/// the value is finite and fits in that type.
49+
///
50+
/// # Safety
51+
/// The value must:
52+
///
53+
/// * Not be NaN
54+
/// * Not be infinite
55+
/// * Be representable in the return type, after truncating off its fractional part
56+
///
57+
/// If these requirements are infeasible or costly, consider using the safe function [cast],
58+
/// which saturates on conversion.
59+
///
60+
/// [cast]: Simd::cast
61+
unsafe fn to_int_unchecked<I: SimdCast>(self) -> Self::Cast<I>
62+
where
63+
Self::Scalar: core::convert::FloatToInt<I>;
64+
1865
/// Raw transmutation to an unsigned integer vector type with the
1966
/// same size and number of lanes.
2067
#[must_use = "method returns a new vector and does not mutate the original value"]
@@ -206,6 +253,24 @@ macro_rules! impl_trait {
206253
type Mask = Mask<<$mask_ty as SimdElement>::Mask, LANES>;
207254
type Scalar = $ty;
208255
type Bits = Simd<$bits_ty, LANES>;
256+
type Cast<T: SimdElement> = Simd<T, LANES>;
257+
258+
#[inline]
259+
fn cast<T: SimdCast>(self) -> Self::Cast<T>
260+
{
261+
// Safety: supported types are guaranteed by SimdCast
262+
unsafe { intrinsics::simd_as(self) }
263+
}
264+
265+
#[inline]
266+
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
267+
unsafe fn to_int_unchecked<I: SimdCast>(self) -> Self::Cast<I>
268+
where
269+
Self::Scalar: core::convert::FloatToInt<I>,
270+
{
271+
// Safety: supported types are guaranteed by SimdCast, the caller is responsible for the extra invariants
272+
unsafe { intrinsics::simd_cast(self) }
273+
}
209274

210275
#[inline]
211276
fn to_bits(self) -> Simd<$bits_ty, LANES> {

‎library/portable-simd/crates/core_simd/src/elements/int.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::sealed::Sealed;
22
use crate::simd::{
3-
intrinsics, LaneCount, Mask, Simd, SimdElement, SimdPartialOrd, SupportedLaneCount,
3+
intrinsics, LaneCount, Mask, Simd, SimdCast, SimdElement, SimdPartialOrd, SupportedLaneCount,
44
};
55

66
/// Operations on SIMD vectors of signed integers.
@@ -11,6 +11,16 @@ pub trait SimdInt: Copy + Sealed {
1111
/// Scalar type contained by this SIMD vector type.
1212
type Scalar;
1313

14+
/// A SIMD vector with a different element type.
15+
type Cast<T: SimdElement>;
16+
17+
/// Performs elementwise conversion of this vector's elements to another SIMD-valid type.
18+
///
19+
/// This follows the semantics of Rust's `as` conversion for casting integers (wrapping to
20+
/// other integer types, and saturating to float types).
21+
#[must_use]
22+
fn cast<T: SimdCast>(self) -> Self::Cast<T>;
23+
1424
/// Lanewise saturating add.
1525
///
1626
/// # Examples
@@ -198,6 +208,13 @@ macro_rules! impl_trait {
198208
{
199209
type Mask = Mask<<$ty as SimdElement>::Mask, LANES>;
200210
type Scalar = $ty;
211+
type Cast<T: SimdElement> = Simd<T, LANES>;
212+
213+
#[inline]
214+
fn cast<T: SimdCast>(self) -> Self::Cast<T> {
215+
// Safety: supported types are guaranteed by SimdCast
216+
unsafe { intrinsics::simd_as(self) }
217+
}
201218

202219
#[inline]
203220
fn saturating_add(self, second: Self) -> Self {

‎library/portable-simd/crates/core_simd/src/elements/mut_ptr.rs

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

44
/// Operations on SIMD vectors of mutable pointers.
55
pub trait SimdMutPtr: Copy + Sealed {
@@ -9,6 +9,9 @@ pub trait SimdMutPtr: Copy + Sealed {
99
/// Vector of `isize` with the same number of lanes.
1010
type Isize;
1111

12+
/// Vector of const pointers with the same number of lanes.
13+
type CastPtr<T>;
14+
1215
/// Vector of constant pointers to the same type.
1316
type ConstPtr;
1417

@@ -18,6 +21,11 @@ pub trait SimdMutPtr: Copy + Sealed {
1821
/// Returns `true` for each lane that is null.
1922
fn is_null(self) -> Self::Mask;
2023

24+
/// Casts to a pointer of another type.
25+
///
26+
/// Equivalent to calling [`pointer::cast`] on each lane.
27+
fn cast<T>(self) -> Self::CastPtr<T>;
28+
2129
/// Changes constness without changing the type.
2230
///
2331
/// Equivalent to calling [`pointer::cast_const`] on each lane.
@@ -73,6 +81,7 @@ where
7381
{
7482
type Usize = Simd<usize, LANES>;
7583
type Isize = Simd<isize, LANES>;
84+
type CastPtr<U> = Simd<*mut U, LANES>;
7685
type ConstPtr = Simd<*const T, LANES>;
7786
type Mask = Mask<isize, LANES>;
7887

@@ -81,9 +90,22 @@ where
8190
Simd::splat(core::ptr::null_mut()).simd_eq(self)
8291
}
8392

93+
#[inline]
94+
fn cast<U>(self) -> Self::CastPtr<U> {
95+
// SimdElement currently requires zero-sized metadata, so this should never fail.
96+
// If this ever changes, `simd_cast_ptr` should produce a post-mono error.
97+
use core::{mem::size_of, ptr::Pointee};
98+
assert_eq!(size_of::<<T as Pointee>::Metadata>(), 0);
99+
assert_eq!(size_of::<<U as Pointee>::Metadata>(), 0);
100+
101+
// Safety: pointers can be cast
102+
unsafe { intrinsics::simd_cast_ptr(self) }
103+
}
104+
84105
#[inline]
85106
fn cast_const(self) -> Self::ConstPtr {
86-
self.cast_ptr()
107+
// Safety: pointers can be cast
108+
unsafe { intrinsics::simd_cast_ptr(self) }
87109
}
88110

89111
#[inline]
@@ -101,9 +123,9 @@ where
101123
// In the mean-time, this operation is defined to be "as if" it was
102124
// a wrapping_offset, so we can emulate it as such. This should properly
103125
// restore pointer provenance even under today's compiler.
104-
self.cast_ptr::<*mut u8>()
126+
self.cast::<u8>()
105127
.wrapping_offset(addr.cast::<isize>() - self.addr().cast::<isize>())
106-
.cast_ptr()
128+
.cast()
107129
}
108130

109131
#[inline]

‎library/portable-simd/crates/core_simd/src/elements/uint.rs

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

44
/// Operations on SIMD vectors of unsigned integers.
55
pub trait SimdUint: Copy + Sealed {
66
/// Scalar type contained by this SIMD vector type.
77
type Scalar;
88

9+
/// A SIMD vector with a different element type.
10+
type Cast<T: SimdElement>;
11+
12+
/// Performs elementwise conversion of this vector's elements to another SIMD-valid type.
13+
///
14+
/// This follows the semantics of Rust's `as` conversion for casting integers (wrapping to
15+
/// other integer types, and saturating to float types).
16+
#[must_use]
17+
fn cast<T: SimdCast>(self) -> Self::Cast<T>;
18+
919
/// Lanewise saturating add.
1020
///
1121
/// # Examples
@@ -77,6 +87,13 @@ macro_rules! impl_trait {
7787
LaneCount<LANES>: SupportedLaneCount,
7888
{
7989
type Scalar = $ty;
90+
type Cast<T: SimdElement> = Simd<T, LANES>;
91+
92+
#[inline]
93+
fn cast<T: SimdCast>(self) -> Self::Cast<T> {
94+
// Safety: supported types are guaranteed by SimdCast
95+
unsafe { intrinsics::simd_as(self) }
96+
}
8097

8198
#[inline]
8299
fn saturating_add(self, second: Self) -> Self {

‎library/portable-simd/crates/core_simd/src/iter.rs

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ macro_rules! impl_traits {
1010
where
1111
LaneCount<LANES>: SupportedLaneCount,
1212
{
13+
#[inline]
1314
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
1415
iter.fold(Simd::splat(0 as $type), Add::add)
1516
}
@@ -19,6 +20,7 @@ macro_rules! impl_traits {
1920
where
2021
LaneCount<LANES>: SupportedLaneCount,
2122
{
23+
#[inline]
2224
fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
2325
iter.fold(Simd::splat(1 as $type), Mul::mul)
2426
}
@@ -28,6 +30,7 @@ macro_rules! impl_traits {
2830
where
2931
LaneCount<LANES>: SupportedLaneCount,
3032
{
33+
#[inline]
3134
fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
3235
iter.fold(Simd::splat(0 as $type), Add::add)
3336
}
@@ -37,6 +40,7 @@ macro_rules! impl_traits {
3740
where
3841
LaneCount<LANES>: SupportedLaneCount,
3942
{
43+
#[inline]
4044
fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
4145
iter.fold(Simd::splat(1 as $type), Mul::mul)
4246
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
)]
1717
#![cfg_attr(feature = "generic_const_exprs", feature(generic_const_exprs))]
1818
#![cfg_attr(feature = "generic_const_exprs", allow(incomplete_features))]
19-
#![warn(missing_docs)]
19+
#![warn(missing_docs, clippy::missing_inline_in_public_items)] // basically all items, really
2020
#![deny(unsafe_op_in_unsafe_fn, clippy::undocumented_unsafe_blocks)]
2121
#![unstable(feature = "portable_simd", issue = "86656")]
2222
//! Portable SIMD module.

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

+4
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ where
179179
/// Panics if any lane is not 0 or -1.
180180
#[inline]
181181
#[must_use = "method returns a new mask and does not mutate the original value"]
182+
#[track_caller]
182183
pub fn from_int(value: Simd<T, LANES>) -> Self {
183184
assert!(T::valid(value), "all values must be either 0 or -1",);
184185
// Safety: the validity has been checked
@@ -217,6 +218,7 @@ where
217218
/// Panics if `lane` is greater than or equal to the number of lanes in the vector.
218219
#[inline]
219220
#[must_use = "method returns a new bool and does not mutate the original value"]
221+
#[track_caller]
220222
pub fn test(&self, lane: usize) -> bool {
221223
assert!(lane < LANES, "lane index out of range");
222224
// Safety: the lane index has been checked
@@ -240,6 +242,7 @@ where
240242
/// # Panics
241243
/// Panics if `lane` is greater than or equal to the number of lanes in the vector.
242244
#[inline]
245+
#[track_caller]
243246
pub fn set(&mut self, lane: usize, value: bool) {
244247
assert!(lane < LANES, "lane index out of range");
245248
// Safety: the lane index has been checked
@@ -327,6 +330,7 @@ where
327330
T: MaskElement + fmt::Debug,
328331
LaneCount<LANES>: SupportedLaneCount,
329332
{
333+
#[inline]
330334
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
331335
f.debug_list()
332336
.entries((0..LANES).map(|lane| self.test(lane)))

‎library/portable-simd/crates/core_simd/src/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ mod vendor;
2323

2424
#[doc = include_str!("core_simd_docs.md")]
2525
pub mod simd {
26+
pub mod prelude;
27+
2628
pub(crate) use crate::core_simd::intrinsics;
2729

2830
pub use crate::core_simd::alias::*;

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

+7-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ where
1515
I: core::slice::SliceIndex<[T]>,
1616
{
1717
type Output = I::Output;
18+
#[inline]
1819
fn index(&self, index: I) -> &Self::Output {
1920
&self.as_array()[index]
2021
}
@@ -26,6 +27,7 @@ where
2627
LaneCount<LANES>: SupportedLaneCount,
2728
I: core::slice::SliceIndex<[T]>,
2829
{
30+
#[inline]
2931
fn index_mut(&mut self, index: I) -> &mut Self::Output {
3032
&mut self.as_mut_array()[index]
3133
}
@@ -118,10 +120,14 @@ macro_rules! for_base_types {
118120

119121
#[inline]
120122
#[must_use = "operator returns a new vector without mutating the inputs"]
123+
// TODO: only useful for int Div::div, but we hope that this
124+
// will essentially always always get inlined anyway.
125+
#[track_caller]
121126
fn $call(self, rhs: Self) -> Self::Output {
122127
$macro_impl!(self, rhs, $inner, $scalar)
123128
}
124-
})*
129+
}
130+
)*
125131
}
126132
}
127133

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

+4
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ macro_rules! impl_integer {
9494
}
9595

9696
#[inline]
97+
#[track_caller]
9798
fn simd_clamp(self, min: Self, max: Self) -> Self {
9899
assert!(
99100
min.simd_le(max).all(),
@@ -200,6 +201,7 @@ macro_rules! impl_mask {
200201
}
201202

202203
#[inline]
204+
#[track_caller]
203205
fn simd_clamp(self, min: Self, max: Self) -> Self {
204206
assert!(
205207
min.simd_le(max).all(),
@@ -254,6 +256,7 @@ where
254256
}
255257

256258
#[inline]
259+
#[track_caller]
257260
fn simd_clamp(self, min: Self, max: Self) -> Self {
258261
assert!(
259262
min.simd_le(max).all(),
@@ -303,6 +306,7 @@ where
303306
}
304307

305308
#[inline]
309+
#[track_caller]
306310
fn simd_clamp(self, min: Self, max: Self) -> Self {
307311
assert!(
308312
min.simd_le(max).all(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//! The portable SIMD prelude.
2+
//!
3+
//! Includes important traits and types to be imported with a glob:
4+
//! ```ignore
5+
//! use std::simd::prelude::*;
6+
//! ```
7+
8+
#[doc(no_inline)]
9+
pub use super::{
10+
simd_swizzle, Mask, Simd, SimdConstPtr, SimdFloat, SimdInt, SimdMutPtr, SimdOrd, SimdPartialEq,
11+
SimdPartialOrd, SimdUint,
12+
};
13+
14+
#[rustfmt::skip]
15+
#[doc(no_inline)]
16+
pub use super::{f32x1, f32x2, f32x4, f32x8, f32x16, f32x32, f32x64};
17+
18+
#[rustfmt::skip]
19+
#[doc(no_inline)]
20+
pub use super::{f64x1, f64x2, f64x4, f64x8, f64x16, f64x32, f64x64};
21+
22+
#[rustfmt::skip]
23+
#[doc(no_inline)]
24+
pub use super::{i8x1, i8x2, i8x4, i8x8, i8x16, i8x32, i8x64};
25+
26+
#[rustfmt::skip]
27+
#[doc(no_inline)]
28+
pub use super::{i16x1, i16x2, i16x4, i16x8, i16x16, i16x32, i16x64};
29+
30+
#[rustfmt::skip]
31+
#[doc(no_inline)]
32+
pub use super::{i32x1, i32x2, i32x4, i32x8, i32x16, i32x32, i32x64};
33+
34+
#[rustfmt::skip]
35+
#[doc(no_inline)]
36+
pub use super::{i64x1, i64x2, i64x4, i64x8, i64x16, i64x32, i64x64};
37+
38+
#[rustfmt::skip]
39+
#[doc(no_inline)]
40+
pub use super::{isizex1, isizex2, isizex4, isizex8, isizex16, isizex32, isizex64};
41+
42+
#[rustfmt::skip]
43+
#[doc(no_inline)]
44+
pub use super::{u8x1, u8x2, u8x4, u8x8, u8x16, u8x32, u8x64};
45+
46+
#[rustfmt::skip]
47+
#[doc(no_inline)]
48+
pub use super::{u16x1, u16x2, u16x4, u16x8, u16x16, u16x32, u16x64};
49+
50+
#[rustfmt::skip]
51+
#[doc(no_inline)]
52+
pub use super::{u32x1, u32x2, u32x4, u32x8, u32x16, u32x32, u32x64};
53+
54+
#[rustfmt::skip]
55+
#[doc(no_inline)]
56+
pub use super::{u64x1, u64x2, u64x4, u64x8, u64x16, u64x32, u64x64};
57+
58+
#[rustfmt::skip]
59+
#[doc(no_inline)]
60+
pub use super::{usizex1, usizex2, usizex4, usizex8, usizex16, usizex32, usizex64};
61+
62+
#[rustfmt::skip]
63+
#[doc(no_inline)]
64+
pub use super::{mask8x1, mask8x2, mask8x4, mask8x8, mask8x16, mask8x32, mask8x64};
65+
66+
#[rustfmt::skip]
67+
#[doc(no_inline)]
68+
pub use super::{mask16x1, mask16x2, mask16x4, mask16x8, mask16x16, mask16x32, mask16x64};
69+
70+
#[rustfmt::skip]
71+
#[doc(no_inline)]
72+
pub use super::{mask32x1, mask32x2, mask32x4, mask32x8, mask32x16, mask32x32, mask32x64};
73+
74+
#[rustfmt::skip]
75+
#[doc(no_inline)]
76+
pub use super::{mask64x1, mask64x2, mask64x4, mask64x8, mask64x16, mask64x32, mask64x64};
77+
78+
#[rustfmt::skip]
79+
#[doc(no_inline)]
80+
pub use super::{masksizex1, masksizex2, masksizex4, masksizex8, masksizex16, masksizex32, masksizex64};

‎library/portable-simd/crates/core_simd/src/swizzle_dyn.rs

+20-4
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,14 @@ where
1616
#[inline]
1717
pub fn swizzle_dyn(self, idxs: Simd<u8, N>) -> Self {
1818
#![allow(unused_imports, unused_unsafe)]
19-
#[cfg(target_arch = "aarch64")]
19+
#[cfg(all(target_arch = "aarch64", target_endian = "little"))]
2020
use core::arch::aarch64::{uint8x8_t, vqtbl1q_u8, vtbl1_u8};
21-
#[cfg(all(target_arch = "arm", target_feature = "v7", target_feature = "neon"))]
21+
#[cfg(all(
22+
target_arch = "arm",
23+
target_feature = "v7",
24+
target_feature = "neon",
25+
target_endian = "little"
26+
))]
2227
use core::arch::arm::{uint8x8_t, vtbl1_u8};
2328
#[cfg(target_arch = "wasm32")]
2429
use core::arch::wasm32 as wasm;
@@ -29,13 +34,24 @@ where
2934
// SAFETY: Intrinsics covered by cfg
3035
unsafe {
3136
match N {
32-
#[cfg(target_feature = "neon")]
37+
#[cfg(all(
38+
any(
39+
target_arch = "aarch64",
40+
all(target_arch = "arm", target_feature = "v7")
41+
),
42+
target_feature = "neon",
43+
target_endian = "little"
44+
))]
3345
8 => transize(vtbl1_u8, self, idxs),
3446
#[cfg(target_feature = "ssse3")]
3547
16 => transize(x86::_mm_shuffle_epi8, self, idxs),
3648
#[cfg(target_feature = "simd128")]
3749
16 => transize(wasm::i8x16_swizzle, self, idxs),
38-
#[cfg(all(target_arch = "aarch64", target_feature = "neon"))]
50+
#[cfg(all(
51+
target_arch = "aarch64",
52+
target_feature = "neon",
53+
target_endian = "little"
54+
))]
3955
16 => transize(vqtbl1q_u8, self, idxs),
4056
#[cfg(all(target_feature = "avx2", not(target_feature = "avx512vbmi")))]
4157
32 => transize_raw(avx2_pshufb, self, idxs),

‎library/portable-simd/crates/core_simd/src/vector.rs

+19-72
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::simd::{
2-
intrinsics, LaneCount, Mask, MaskElement, SimdCast, SimdCastPtr, SimdConstPtr, SimdMutPtr,
3-
SimdPartialOrd, SupportedLaneCount, Swizzle,
2+
intrinsics, LaneCount, Mask, MaskElement, SimdConstPtr, SimdMutPtr, SimdPartialOrd,
3+
SupportedLaneCount, Swizzle,
44
};
55
use core::convert::{TryFrom, TryInto};
66

@@ -122,6 +122,7 @@ where
122122
/// let v = u32x4::splat(0);
123123
/// assert_eq!(v.lanes(), 4);
124124
/// ```
125+
#[inline]
125126
pub const fn lanes(&self) -> usize {
126127
Self::LANES
127128
}
@@ -136,6 +137,7 @@ where
136137
/// let v = u32x4::splat(8);
137138
/// assert_eq!(v.as_array(), &[8, 8, 8, 8]);
138139
/// ```
140+
#[inline]
139141
pub fn splat(value: T) -> Self {
140142
// This is preferred over `[value; N]`, since it's explicitly a splat:
141143
// https://github.com/rust-lang/rust/issues/97804
@@ -156,6 +158,7 @@ where
156158
/// let v: u64x4 = Simd::from_array([0, 1, 2, 3]);
157159
/// assert_eq!(v.as_array(), &[0, 1, 2, 3]);
158160
/// ```
161+
#[inline]
159162
pub const fn as_array(&self) -> &[T; N] {
160163
// SAFETY: `Simd<T, N>` is just an overaligned `[T; N]` with
161164
// potential padding at the end, so pointer casting to a
@@ -167,6 +170,7 @@ where
167170
}
168171

169172
/// Returns a mutable array reference containing the entire SIMD vector.
173+
#[inline]
170174
pub fn as_mut_array(&mut self) -> &mut [T; N] {
171175
// SAFETY: `Simd<T, N>` is just an overaligned `[T; N]` with
172176
// potential padding at the end, so pointer casting to a
@@ -184,6 +188,7 @@ where
184188
///
185189
/// # Safety
186190
/// Reading `ptr` must be safe, as if by `<*const [T; N]>::read_unaligned`.
191+
#[inline]
187192
const unsafe fn load(ptr: *const [T; N]) -> Self {
188193
// There are potentially simpler ways to write this function, but this should result in
189194
// LLVM `load <N x T>`
@@ -204,6 +209,7 @@ where
204209
///
205210
/// # Safety
206211
/// Writing to `ptr` must be safe, as if by `<*mut [T; N]>::write_unaligned`.
212+
#[inline]
207213
const unsafe fn store(self, ptr: *mut [T; N]) {
208214
// There are potentially simpler ways to write this function, but this should result in
209215
// LLVM `store <N x T>`
@@ -216,6 +222,7 @@ where
216222
}
217223

218224
/// Converts an array to a SIMD vector.
225+
#[inline]
219226
pub const fn from_array(array: [T; N]) -> Self {
220227
// SAFETY: `&array` is safe to read.
221228
//
@@ -228,6 +235,7 @@ where
228235
}
229236

230237
/// Converts a SIMD vector to an array.
238+
#[inline]
231239
pub const fn to_array(self) -> [T; N] {
232240
let mut tmp = core::mem::MaybeUninit::uninit();
233241
// SAFETY: writing to `tmp` is safe and initializes it.
@@ -259,6 +267,8 @@ where
259267
/// assert_eq!(v.as_array(), &[1, 2, 3, 4]);
260268
/// ```
261269
#[must_use]
270+
#[inline]
271+
#[track_caller]
262272
pub const fn from_slice(slice: &[T]) -> Self {
263273
assert!(
264274
slice.len() >= Self::LANES,
@@ -287,6 +297,8 @@ where
287297
/// v.copy_to_slice(&mut dest);
288298
/// assert_eq!(&dest, &[1, 2, 3, 4, 0, 0]);
289299
/// ```
300+
#[inline]
301+
#[track_caller]
290302
pub fn copy_to_slice(self, slice: &mut [T]) {
291303
assert!(
292304
slice.len() >= Self::LANES,
@@ -297,76 +309,6 @@ where
297309
unsafe { self.store(slice.as_mut_ptr().cast()) }
298310
}
299311

300-
/// Performs elementwise conversion of a SIMD vector's elements to another SIMD-valid type.
301-
///
302-
/// This follows the semantics of Rust's `as` conversion for casting integers between
303-
/// signed and unsigned (interpreting integers as 2s complement, so `-1` to `U::MAX` and
304-
/// `1 << (U::BITS -1)` becoming `I::MIN` ), and from floats to integers (truncating,
305-
/// or saturating at the limits) for each element.
306-
///
307-
/// # Examples
308-
/// ```
309-
/// # #![feature(portable_simd)]
310-
/// # use core::simd::Simd;
311-
/// let floats: Simd<f32, 4> = Simd::from_array([1.9, -4.5, f32::INFINITY, f32::NAN]);
312-
/// let ints = floats.cast::<i32>();
313-
/// assert_eq!(ints, Simd::from_array([1, -4, i32::MAX, 0]));
314-
///
315-
/// // Formally equivalent, but `Simd::cast` can optimize better.
316-
/// assert_eq!(ints, Simd::from_array(floats.to_array().map(|x| x as i32)));
317-
///
318-
/// // The float conversion does not round-trip.
319-
/// let floats_again = ints.cast();
320-
/// assert_ne!(floats, floats_again);
321-
/// assert_eq!(floats_again, Simd::from_array([1.0, -4.0, 2147483647.0, 0.0]));
322-
/// ```
323-
#[must_use]
324-
#[inline]
325-
pub fn cast<U: SimdCast>(self) -> Simd<U, N>
326-
where
327-
T: SimdCast,
328-
{
329-
// Safety: supported types are guaranteed by SimdCast
330-
unsafe { intrinsics::simd_as(self) }
331-
}
332-
333-
/// Casts a vector of pointers to another pointer type.
334-
#[must_use]
335-
#[inline]
336-
pub fn cast_ptr<U>(self) -> Simd<U, N>
337-
where
338-
T: SimdCastPtr<U>,
339-
U: SimdElement,
340-
{
341-
// Safety: supported types are guaranteed by SimdCastPtr
342-
unsafe { intrinsics::simd_cast_ptr(self) }
343-
}
344-
345-
/// Rounds toward zero and converts to the same-width integer type, assuming that
346-
/// the value is finite and fits in that type.
347-
///
348-
/// # Safety
349-
/// The value must:
350-
///
351-
/// * Not be NaN
352-
/// * Not be infinite
353-
/// * Be representable in the return type, after truncating off its fractional part
354-
///
355-
/// If these requirements are infeasible or costly, consider using the safe function [cast],
356-
/// which saturates on conversion.
357-
///
358-
/// [cast]: Simd::cast
359-
#[inline]
360-
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
361-
pub unsafe fn to_int_unchecked<I>(self) -> Simd<I, N>
362-
where
363-
T: core::convert::FloatToInt<I> + SimdCast,
364-
I: SimdCast,
365-
{
366-
// Safety: supported types are guaranteed by SimdCast, the caller is responsible for the extra invariants
367-
unsafe { intrinsics::simd_cast(self) }
368-
}
369-
370312
/// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector.
371313
/// If an index is out-of-bounds, the element is instead selected from the `or` vector.
372314
///
@@ -717,6 +659,7 @@ where
717659
LaneCount<N>: SupportedLaneCount,
718660
T: SimdElement,
719661
{
662+
#[inline]
720663
fn clone(&self) -> Self {
721664
*self
722665
}
@@ -861,6 +804,7 @@ where
861804
LaneCount<N>: SupportedLaneCount,
862805
T: SimdElement,
863806
{
807+
#[inline]
864808
fn from(array: [T; N]) -> Self {
865809
Self::from_array(array)
866810
}
@@ -871,6 +815,7 @@ where
871815
LaneCount<N>: SupportedLaneCount,
872816
T: SimdElement,
873817
{
818+
#[inline]
874819
fn from(vector: Simd<T, N>) -> Self {
875820
vector.to_array()
876821
}
@@ -883,6 +828,7 @@ where
883828
{
884829
type Error = core::array::TryFromSliceError;
885830

831+
#[inline]
886832
fn try_from(slice: &[T]) -> Result<Self, core::array::TryFromSliceError> {
887833
Ok(Self::from_array(slice.try_into()?))
888834
}
@@ -895,6 +841,7 @@ where
895841
{
896842
type Error = core::array::TryFromSliceError;
897843

844+
#[inline]
898845
fn try_from(slice: &mut [T]) -> Result<Self, core::array::TryFromSliceError> {
899846
Ok(Self::from_array(slice.try_into()?))
900847
}

‎library/portable-simd/crates/core_simd/tests/cast.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
macro_rules! cast_types {
33
($start:ident, $($target:ident),*) => {
44
mod $start {
5-
use core_simd::simd::Simd;
5+
#[allow(unused)]
6+
use core_simd::simd::{Simd, SimdInt, SimdUint, SimdFloat};
67
type Vector<const N: usize> = Simd<$start, N>;
78
$(
89
mod $target {

‎library/portable-simd/crates/core_simd/tests/round.rs

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ macro_rules! float_rounding_test {
5353

5454
test_helpers::test_lanes! {
5555
fn to_int_unchecked<const LANES: usize>() {
56+
use core_simd::simd::SimdFloat;
5657
// The maximum integer that can be represented by the equivalently sized float has
5758
// all of the mantissa digits set to 1, pushed up to the MSB.
5859
const ALL_MANTISSA_BITS: IntScalar = ((1 << <Scalar>::MANTISSA_DIGITS) - 1);

‎src/tools/miri/tests/pass/portable-simd-ptrs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::simd::*;
66

77
fn main() {
88
// Pointer casts
9-
let _val: Simd<*const u8, 4> = Simd::<*const i32, 4>::splat(ptr::null()).cast_ptr();
9+
let _val: Simd<*const u8, 4> = Simd::<*const i32, 4>::splat(ptr::null()).cast();
1010
let addrs = Simd::<*const i32, 4>::splat(ptr::null()).expose_addr();
1111
let _ptrs = Simd::<*const i32, 4>::from_exposed_addr(addrs);
1212
}

0 commit comments

Comments
 (0)
Please sign in to comment.