Skip to content

Commit

Permalink
Auto merge of #91484 - workingjubilee:simd-remove-autosplats, r=Mark-…
Browse files Browse the repository at this point in the history
…Simulacrum

Sync portable-simd to remove autosplats

This PR syncs portable-simd in up to rust-lang/portable-simd@a838552 in order to address the type inference breakages documented on nightly in #90904 by removing the vector + scalar binary operations (called "autosplats", "broadcasting", or "rank promotion", depending on who you ask) that allow `{scalar} + &'_ {scalar}` to fail in some cases, because it becomes possible the programmer may have meant `{scalar} + &'_ {vector}`.

A few quality-of-life improvements make their way in as well:
- Lane counts can now go to 64, as LLVM seems to have fixed their miscompilation for those.
- `{i,u}8x64` to `__m512i` is now available.
- a bunch of `#[must_use]` notes appear throughout the module.
- Some implementations, mostly instances of `impl core::ops::{Op}<Simd> for Simd` that aren't `{vector} + {vector}` (e.g. `{vector} + &'_ {vector}`), leverage some generics and `where` bounds now to make them easier to understand by reducing a dozen implementations into one (and make it possible for people to open the docs on less burly devices).
- And some internal-only improvements.

None of these changes should affect a beta backport, only actual users of `core::simd` (and most aren't even visible in the programmatic sense), though I can extract an even more minimal changeset for beta if necessary. It seemed simpler to just keep moving forward.
  • Loading branch information
bors committed Dec 8, 2021
2 parents 477fd70 + eef4371 commit 11fb21f
Show file tree
Hide file tree
Showing 23 changed files with 540 additions and 525 deletions.
2 changes: 1 addition & 1 deletion library/core/tests/simd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ fn testing() {
let x = f32x4::from_array([1.0, 1.0, 1.0, 1.0]);
let y = -x;

let h = x * 0.5;
let h = x * f32x4::splat(0.5);

let r = y.abs();
assert_eq!(x, r);
Expand Down
2 changes: 1 addition & 1 deletion library/portable-simd/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ SIMD can be quite complex, and even a "simple" issue can be huge. If an issue is

## CI

We currently have 2 CI matrices through Travis CI and GitHub Actions that will automatically build and test your change in order to verify that `std::simd`'s portable API is, in fact, portable. If your change builds locally, but does not build on either, this is likely due to a platform-specific concern that your code has not addressed. Please consult the build logs and address the error, or ask for help if you need it.
We currently use GitHub Actions which will automatically build and test your change in order to verify that `std::simd`'s portable API is, in fact, portable. If your change builds locally, but does not build in CI, this is likely due to a platform-specific concern that your code has not addressed. Please consult the build logs and address the error, or ask for help if you need it.

## Beyond stdsimd

Expand Down
2 changes: 1 addition & 1 deletion library/portable-simd/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# The Rust standard library's portable SIMD API
[![Build Status](https://travis-ci.com/rust-lang/portable-simd.svg?branch=master)](https://travis-ci.com/rust-lang/portable-simd)
![Build Status](https://github.com/rust-lang/portable-simd/actions/workflows/ci.yml/badge.svg?branch=master)

Code repository for the [Portable SIMD Project Group](https://github.com/rust-lang/project-portable-simd).
Please refer to [CONTRIBUTING.md](./CONTRIBUTING.md) for our contributing guidelines.
Expand Down
10 changes: 5 additions & 5 deletions library/portable-simd/crates/core_simd/examples/nbody.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ mod nbody {
let sun = &mut sun[0];
for body in rest {
let m_ratio = body.mass / SOLAR_MASS;
sun.v -= body.v * m_ratio;
sun.v -= body.v * Simd::splat(m_ratio);
}
}

Expand Down Expand Up @@ -143,14 +143,14 @@ mod nbody {
let mut i = 0;
for j in 0..N_BODIES {
for k in j + 1..N_BODIES {
let f = r[i] * mag[i];
bodies[j].v -= f * bodies[k].mass;
bodies[k].v += f * bodies[j].mass;
let f = r[i] * Simd::splat(mag[i]);
bodies[j].v -= f * Simd::splat(bodies[k].mass);
bodies[k].v += f * Simd::splat(bodies[j].mass);
i += 1
}
}
for body in bodies {
body.x += dt * body.v
body.x += Simd::splat(dt) * body.v
}
}

Expand Down
6 changes: 6 additions & 0 deletions library/portable-simd/crates/core_simd/src/comparisons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ where
{
/// Test if each lane is equal to the corresponding lane in `other`.
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
pub fn lanes_eq(self, other: Self) -> Mask<T::Mask, LANES> {
unsafe { Mask::from_int_unchecked(intrinsics::simd_eq(self, other)) }
}

/// Test if each lane is not equal to the corresponding lane in `other`.
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
pub fn lanes_ne(self, other: Self) -> Mask<T::Mask, LANES> {
unsafe { Mask::from_int_unchecked(intrinsics::simd_ne(self, other)) }
}
Expand All @@ -26,24 +28,28 @@ where
{
/// Test if each lane is less than the corresponding lane in `other`.
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
pub fn lanes_lt(self, other: Self) -> Mask<T::Mask, LANES> {
unsafe { Mask::from_int_unchecked(intrinsics::simd_lt(self, other)) }
}

/// Test if each lane is greater than the corresponding lane in `other`.
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
pub fn lanes_gt(self, other: Self) -> Mask<T::Mask, LANES> {
unsafe { Mask::from_int_unchecked(intrinsics::simd_gt(self, other)) }
}

/// Test if each lane is less than or equal to the corresponding lane in `other`.
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
pub fn lanes_le(self, other: Self) -> Mask<T::Mask, LANES> {
unsafe { Mask::from_int_unchecked(intrinsics::simd_le(self, other)) }
}

/// Test if each lane is greater than or equal to the corresponding lane in `other`.
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
pub fn lanes_ge(self, other: Self) -> Mask<T::Mask, LANES> {
unsafe { Mask::from_int_unchecked(intrinsics::simd_ge(self, other)) }
}
Expand Down
12 changes: 3 additions & 9 deletions library/portable-simd/crates/core_simd/src/lane_count.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,28 @@ impl<const LANES: usize> LaneCount<LANES> {
pub trait SupportedLaneCount: Sealed {
#[doc(hidden)]
type BitMask: Copy + Default + AsRef<[u8]> + AsMut<[u8]>;

#[doc(hidden)]
type IntBitMask;
}

impl<const LANES: usize> Sealed for LaneCount<LANES> {}

impl SupportedLaneCount for LaneCount<1> {
type BitMask = [u8; 1];
type IntBitMask = u8;
}
impl SupportedLaneCount for LaneCount<2> {
type BitMask = [u8; 1];
type IntBitMask = u8;
}
impl SupportedLaneCount for LaneCount<4> {
type BitMask = [u8; 1];
type IntBitMask = u8;
}
impl SupportedLaneCount for LaneCount<8> {
type BitMask = [u8; 1];
type IntBitMask = u8;
}
impl SupportedLaneCount for LaneCount<16> {
type BitMask = [u8; 2];
type IntBitMask = u16;
}
impl SupportedLaneCount for LaneCount<32> {
type BitMask = [u8; 4];
type IntBitMask = u32;
}
impl SupportedLaneCount for LaneCount<64> {
type BitMask = [u8; 8];
}
24 changes: 24 additions & 0 deletions library/portable-simd/crates/core_simd/src/masks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ where
/// # Safety
/// All lanes must be either 0 or -1.
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
pub unsafe fn from_int_unchecked(value: Simd<T, LANES>) -> Self {
unsafe { Self(mask_impl::Mask::from_int_unchecked(value)) }
}
Expand All @@ -139,6 +140,7 @@ where
/// # Panics
/// Panics if any lane is not 0 or -1.
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
pub fn from_int(value: Simd<T, LANES>) -> Self {
assert!(T::valid(value), "all values must be either 0 or -1",);
unsafe { Self::from_int_unchecked(value) }
Expand All @@ -147,6 +149,7 @@ where
/// Converts the mask to a vector of integers, where 0 represents `false` and -1
/// represents `true`.
#[inline]
#[must_use = "method returns a new vector and does not mutate the original value"]
pub fn to_int(self) -> Simd<T, LANES> {
self.0.to_int()
}
Expand All @@ -156,6 +159,7 @@ where
/// # Safety
/// `lane` must be less than `LANES`.
#[inline]
#[must_use = "method returns a new bool and does not mutate the original value"]
pub unsafe fn test_unchecked(&self, lane: usize) -> bool {
unsafe { self.0.test_unchecked(lane) }
}
Expand All @@ -165,6 +169,7 @@ where
/// # Panics
/// Panics if `lane` is greater than or equal to the number of lanes in the vector.
#[inline]
#[must_use = "method returns a new bool and does not mutate the original value"]
pub fn test(&self, lane: usize) -> bool {
assert!(lane < LANES, "lane index out of range");
unsafe { self.test_unchecked(lane) }
Expand Down Expand Up @@ -195,24 +200,30 @@ where

/// Convert this mask to a bitmask, with one bit set per lane.
#[cfg(feature = "generic_const_exprs")]
#[inline]
#[must_use = "method returns a new array and does not mutate the original value"]
pub fn to_bitmask(self) -> [u8; LaneCount::<LANES>::BITMASK_LEN] {
self.0.to_bitmask()
}

/// Convert a bitmask to a mask.
#[cfg(feature = "generic_const_exprs")]
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
pub fn from_bitmask(bitmask: [u8; LaneCount::<LANES>::BITMASK_LEN]) -> Self {
Self(mask_impl::Mask::from_bitmask(bitmask))
}

/// Returns true if any lane is set, or false otherwise.
#[inline]
#[must_use = "method returns a new bool and does not mutate the original value"]
pub fn any(self) -> bool {
self.0.any()
}

/// Returns true if all lanes are set, or false otherwise.
#[inline]
#[must_use = "method returns a new bool and does not mutate the original value"]
pub fn all(self) -> bool {
self.0.all()
}
Expand Down Expand Up @@ -245,6 +256,7 @@ where
LaneCount<LANES>: SupportedLaneCount,
{
#[inline]
#[must_use = "method returns a defaulted mask with all lanes set to false (0)"]
fn default() -> Self {
Self::splat(false)
}
Expand All @@ -256,6 +268,7 @@ where
LaneCount<LANES>: SupportedLaneCount,
{
#[inline]
#[must_use = "method returns a new bool and does not mutate the original value"]
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
Expand All @@ -267,6 +280,7 @@ where
LaneCount<LANES>: SupportedLaneCount,
{
#[inline]
#[must_use = "method returns a new Ordering and does not mutate the original value"]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.0.partial_cmp(&other.0)
}
Expand All @@ -291,6 +305,7 @@ where
{
type Output = Self;
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
fn bitand(self, rhs: Self) -> Self {
Self(self.0 & rhs.0)
}
Expand All @@ -303,6 +318,7 @@ where
{
type Output = Self;
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
fn bitand(self, rhs: bool) -> Self {
self & Self::splat(rhs)
}
Expand All @@ -315,6 +331,7 @@ where
{
type Output = Mask<T, LANES>;
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
fn bitand(self, rhs: Mask<T, LANES>) -> Mask<T, LANES> {
Mask::splat(self) & rhs
}
Expand All @@ -327,6 +344,7 @@ where
{
type Output = Self;
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
fn bitor(self, rhs: Self) -> Self {
Self(self.0 | rhs.0)
}
Expand All @@ -339,6 +357,7 @@ where
{
type Output = Self;
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
fn bitor(self, rhs: bool) -> Self {
self | Self::splat(rhs)
}
Expand All @@ -351,6 +370,7 @@ where
{
type Output = Mask<T, LANES>;
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
fn bitor(self, rhs: Mask<T, LANES>) -> Mask<T, LANES> {
Mask::splat(self) | rhs
}
Expand All @@ -363,6 +383,7 @@ where
{
type Output = Self;
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
fn bitxor(self, rhs: Self) -> Self::Output {
Self(self.0 ^ rhs.0)
}
Expand All @@ -375,6 +396,7 @@ where
{
type Output = Self;
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
fn bitxor(self, rhs: bool) -> Self::Output {
self ^ Self::splat(rhs)
}
Expand All @@ -387,6 +409,7 @@ where
{
type Output = Mask<T, LANES>;
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
fn bitxor(self, rhs: Mask<T, LANES>) -> Self::Output {
Mask::splat(self) ^ rhs
}
Expand All @@ -399,6 +422,7 @@ where
{
type Output = Mask<T, LANES>;
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
fn not(self) -> Self::Output {
Self(!self.0)
}
Expand Down
Loading

0 comments on commit 11fb21f

Please sign in to comment.