Merge pull request #368 from rust-lang/remove-generic-const-exprs
Remove `generic_const_exprs`
This commit is contained in:
commit
3e4e13c82f
11 changed files with 157 additions and 126 deletions
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
|
|
@ -238,7 +238,7 @@ jobs:
|
|||
run: cross test --verbose --target=${{ matrix.target }} --release
|
||||
|
||||
features:
|
||||
name: "Check cargo features (${{ matrix.simd }} × ${{ matrix.features }})"
|
||||
name: "Test cargo features (${{ matrix.simd }} × ${{ matrix.features }})"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
|
@ -249,12 +249,8 @@ jobs:
|
|||
features:
|
||||
- ""
|
||||
- "--features std"
|
||||
- "--features generic_const_exprs"
|
||||
- "--features std --features generic_const_exprs"
|
||||
- "--features all_lane_counts"
|
||||
- "--features all_lane_counts --features std"
|
||||
- "--features all_lane_counts --features generic_const_exprs"
|
||||
- "--features all_lane_counts --features std --features generic_const_exprs"
|
||||
- "--all-features"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
|
@ -266,9 +262,9 @@ jobs:
|
|||
run: echo "CPU_FEATURE=$(lscpu | grep -o avx512[a-z]* | sed s/avx/+avx/ | tr '\n' ',' )" >> $GITHUB_ENV
|
||||
- name: Check build
|
||||
if: ${{ matrix.simd == '' }}
|
||||
run: RUSTFLAGS="-Dwarnings" cargo check --all-targets --no-default-features ${{ matrix.features }}
|
||||
run: RUSTFLAGS="-Dwarnings" cargo test --all-targets --no-default-features ${{ matrix.features }}
|
||||
- name: Check AVX
|
||||
if: ${{ matrix.simd == 'avx512' && contains(env.CPU_FEATURE, 'avx512') }}
|
||||
run: |
|
||||
echo "Found AVX features: $CPU_FEATURE"
|
||||
RUSTFLAGS="-Dwarnings -Ctarget-feature=$CPU_FEATURE" cargo check --all-targets --no-default-features ${{ matrix.features }}
|
||||
RUSTFLAGS="-Dwarnings -Ctarget-feature=$CPU_FEATURE" cargo test --all-targets --no-default-features ${{ matrix.features }}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ license = "MIT OR Apache-2.0"
|
|||
default = ["as_crate"]
|
||||
as_crate = []
|
||||
std = []
|
||||
generic_const_exprs = []
|
||||
all_lane_counts = []
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@
|
|||
strict_provenance,
|
||||
ptr_metadata
|
||||
)]
|
||||
#![cfg_attr(feature = "generic_const_exprs", feature(generic_const_exprs))]
|
||||
#![cfg_attr(feature = "generic_const_exprs", allow(incomplete_features))]
|
||||
#![warn(missing_docs, clippy::missing_inline_in_public_items)] // basically all items, really
|
||||
#![deny(unsafe_op_in_unsafe_fn, clippy::undocumented_unsafe_blocks)]
|
||||
#![allow(internal_features)]
|
||||
|
|
|
|||
|
|
@ -13,10 +13,7 @@
|
|||
mod mask_impl;
|
||||
|
||||
mod to_bitmask;
|
||||
pub use to_bitmask::ToBitMask;
|
||||
|
||||
#[cfg(feature = "generic_const_exprs")]
|
||||
pub use to_bitmask::{bitmask_len, ToBitMaskArray};
|
||||
pub use to_bitmask::{ToBitMask, ToBitMaskArray};
|
||||
|
||||
use crate::simd::{intrinsics, LaneCount, Simd, SimdElement, SimdPartialEq, SupportedLaneCount};
|
||||
use core::cmp::Ordering;
|
||||
|
|
|
|||
|
|
@ -119,7 +119,6 @@ where
|
|||
unsafe { Self(intrinsics::simd_bitmask(value), PhantomData) }
|
||||
}
|
||||
|
||||
#[cfg(feature = "generic_const_exprs")]
|
||||
#[inline]
|
||||
#[must_use = "method returns a new array and does not mutate the original value"]
|
||||
pub fn to_bitmask_array<const N: usize>(self) -> [u8; N] {
|
||||
|
|
@ -129,7 +128,6 @@ where
|
|||
unsafe { core::mem::transmute_copy(&self.0) }
|
||||
}
|
||||
|
||||
#[cfg(feature = "generic_const_exprs")]
|
||||
#[inline]
|
||||
#[must_use = "method returns a new mask and does not mutate the original value"]
|
||||
pub fn from_bitmask_array<const N: usize>(bitmask: [u8; N]) -> Self {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
//! Masks that take up full SIMD vector registers.
|
||||
|
||||
use super::MaskElement;
|
||||
use super::{to_bitmask::ToBitMaskArray, MaskElement};
|
||||
use crate::simd::intrinsics;
|
||||
use crate::simd::{LaneCount, Simd, SupportedLaneCount, ToBitMask};
|
||||
|
||||
#[cfg(feature = "generic_const_exprs")]
|
||||
use crate::simd::ToBitMaskArray;
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct Mask<T, const LANES: usize>(Simd<T, LANES>)
|
||||
where
|
||||
|
|
@ -145,23 +142,19 @@ where
|
|||
unsafe { Mask(intrinsics::simd_cast(self.0)) }
|
||||
}
|
||||
|
||||
#[cfg(feature = "generic_const_exprs")]
|
||||
#[inline]
|
||||
#[must_use = "method returns a new array and does not mutate the original value"]
|
||||
pub fn to_bitmask_array<const N: usize>(self) -> [u8; N]
|
||||
where
|
||||
super::Mask<T, LANES>: ToBitMaskArray,
|
||||
[(); <super::Mask<T, LANES> as ToBitMaskArray>::BYTES]: Sized,
|
||||
{
|
||||
assert_eq!(<super::Mask<T, LANES> as ToBitMaskArray>::BYTES, N);
|
||||
|
||||
// Safety: N is the correct bitmask size
|
||||
// Safety: Bytes is the right size array
|
||||
unsafe {
|
||||
// Compute the bitmask
|
||||
let bitmask: [u8; <super::Mask<T, LANES> as ToBitMaskArray>::BYTES] =
|
||||
let bitmask: <super::Mask<T, LANES> as ToBitMaskArray>::BitMaskArray =
|
||||
intrinsics::simd_bitmask(self.0);
|
||||
|
||||
// Transmute to the return type, previously asserted to be the same size
|
||||
// Transmute to the return type
|
||||
let mut bitmask: [u8; N] = core::mem::transmute_copy(&bitmask);
|
||||
|
||||
// LLVM assumes bit order should match endianness
|
||||
|
|
@ -175,17 +168,13 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "generic_const_exprs")]
|
||||
#[inline]
|
||||
#[must_use = "method returns a new mask and does not mutate the original value"]
|
||||
pub fn from_bitmask_array<const N: usize>(mut bitmask: [u8; N]) -> Self
|
||||
where
|
||||
super::Mask<T, LANES>: ToBitMaskArray,
|
||||
[(); <super::Mask<T, LANES> as ToBitMaskArray>::BYTES]: Sized,
|
||||
{
|
||||
assert_eq!(<super::Mask<T, LANES> as ToBitMaskArray>::BYTES, N);
|
||||
|
||||
// Safety: N is the correct bitmask size
|
||||
// Safety: Bytes is the right size array
|
||||
unsafe {
|
||||
// LLVM assumes bit order should match endianness
|
||||
if cfg!(target_endian = "big") {
|
||||
|
|
@ -194,8 +183,8 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
// Transmute to the bitmask type, previously asserted to be the same size
|
||||
let bitmask: [u8; <super::Mask<T, LANES> as ToBitMaskArray>::BYTES] =
|
||||
// Transmute to the bitmask
|
||||
let bitmask: <super::Mask<T, LANES> as ToBitMaskArray>::BitMaskArray =
|
||||
core::mem::transmute_copy(&bitmask);
|
||||
|
||||
// Compute the regular mask
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use super::{mask_impl, Mask, MaskElement};
|
||||
use crate::simd::{LaneCount, SupportedLaneCount};
|
||||
use core::borrow::{Borrow, BorrowMut};
|
||||
|
||||
mod sealed {
|
||||
pub trait Sealed {}
|
||||
|
|
@ -30,19 +31,26 @@ pub trait ToBitMask: Sealed {
|
|||
/// Converts masks to and from byte array bitmasks.
|
||||
///
|
||||
/// Each bit of the bitmask corresponds to a mask lane, starting with the LSB of the first byte.
|
||||
#[cfg(feature = "generic_const_exprs")]
|
||||
pub trait ToBitMaskArray: Sealed {
|
||||
/// The length of the bitmask array.
|
||||
const BYTES: usize;
|
||||
/// The bitmask array.
|
||||
type BitMaskArray: Copy
|
||||
+ Unpin
|
||||
+ Send
|
||||
+ Sync
|
||||
+ AsRef<[u8]>
|
||||
+ AsMut<[u8]>
|
||||
+ Borrow<[u8]>
|
||||
+ BorrowMut<[u8]>
|
||||
+ 'static;
|
||||
|
||||
/// Converts a mask to a bitmask.
|
||||
fn to_bitmask_array(self) -> [u8; Self::BYTES];
|
||||
fn to_bitmask_array(self) -> Self::BitMaskArray;
|
||||
|
||||
/// Converts a bitmask to a mask.
|
||||
fn from_bitmask_array(bitmask: [u8; Self::BYTES]) -> Self;
|
||||
fn from_bitmask_array(bitmask: Self::BitMaskArray) -> Self;
|
||||
}
|
||||
|
||||
macro_rules! impl_integer_intrinsic {
|
||||
macro_rules! impl_integer {
|
||||
{ $(impl ToBitMask<BitMask=$int:ty> for Mask<_, $lanes:literal>)* } => {
|
||||
$(
|
||||
impl<T: MaskElement> ToBitMask for Mask<T, $lanes> {
|
||||
|
|
@ -62,7 +70,27 @@ macro_rules! impl_integer_intrinsic {
|
|||
}
|
||||
}
|
||||
|
||||
impl_integer_intrinsic! {
|
||||
macro_rules! impl_array {
|
||||
{ $(impl ToBitMaskArray<Bytes=$int:literal> for Mask<_, $lanes:literal>)* } => {
|
||||
$(
|
||||
impl<T: MaskElement> ToBitMaskArray for Mask<T, $lanes> {
|
||||
type BitMaskArray = [u8; $int];
|
||||
|
||||
#[inline]
|
||||
fn to_bitmask_array(self) -> Self::BitMaskArray {
|
||||
self.0.to_bitmask_array()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_bitmask_array(bitmask: Self::BitMaskArray) -> Self {
|
||||
Self(mask_impl::Mask::from_bitmask_array(bitmask))
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
impl_integer! {
|
||||
impl ToBitMask<BitMask=u8> for Mask<_, 1>
|
||||
impl ToBitMask<BitMask=u8> for Mask<_, 2>
|
||||
impl ToBitMask<BitMask=u8> for Mask<_, 4>
|
||||
|
|
@ -72,27 +100,12 @@ impl_integer_intrinsic! {
|
|||
impl ToBitMask<BitMask=u64> for Mask<_, 64>
|
||||
}
|
||||
|
||||
/// Returns the minimum number of bytes in a bitmask with `lanes` lanes.
|
||||
#[cfg(feature = "generic_const_exprs")]
|
||||
#[allow(clippy::missing_inline_in_public_items)]
|
||||
pub const fn bitmask_len(lanes: usize) -> usize {
|
||||
(lanes + 7) / 8
|
||||
}
|
||||
|
||||
#[cfg(feature = "generic_const_exprs")]
|
||||
impl<T: MaskElement, const LANES: usize> ToBitMaskArray for Mask<T, LANES>
|
||||
where
|
||||
LaneCount<LANES>: SupportedLaneCount,
|
||||
{
|
||||
const BYTES: usize = bitmask_len(LANES);
|
||||
|
||||
#[inline]
|
||||
fn to_bitmask_array(self) -> [u8; Self::BYTES] {
|
||||
self.0.to_bitmask_array()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_bitmask_array(bitmask: [u8; Self::BYTES]) -> Self {
|
||||
Mask(mask_impl::Mask::from_bitmask_array(bitmask))
|
||||
}
|
||||
impl_array! {
|
||||
impl ToBitMaskArray<Bytes=1> for Mask<_, 1>
|
||||
impl ToBitMaskArray<Bytes=1> for Mask<_, 2>
|
||||
impl ToBitMaskArray<Bytes=1> for Mask<_, 4>
|
||||
impl ToBitMaskArray<Bytes=1> for Mask<_, 8>
|
||||
impl ToBitMaskArray<Bytes=2> for Mask<_, 16>
|
||||
impl ToBitMaskArray<Bytes=4> for Mask<_, 32>
|
||||
impl ToBitMaskArray<Bytes=8> for Mask<_, 64>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,6 @@ mod swizzle;
|
|||
|
||||
pub(crate) mod intrinsics;
|
||||
|
||||
#[cfg(feature = "generic_const_exprs")]
|
||||
mod to_bytes;
|
||||
|
||||
mod alias;
|
||||
mod cast;
|
||||
mod elements;
|
||||
|
|
@ -18,6 +15,7 @@ mod ops;
|
|||
mod ord;
|
||||
mod select;
|
||||
mod swizzle_dyn;
|
||||
mod to_bytes;
|
||||
mod vector;
|
||||
mod vendor;
|
||||
|
||||
|
|
@ -37,5 +35,6 @@ pub mod simd {
|
|||
pub use crate::core_simd::ord::*;
|
||||
pub use crate::core_simd::swizzle::*;
|
||||
pub use crate::core_simd::swizzle_dyn::*;
|
||||
pub use crate::core_simd::to_bytes::ToBytes;
|
||||
pub use crate::core_simd::vector::*;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,74 +1,116 @@
|
|||
use crate::simd::SimdUint;
|
||||
use crate::simd::{LaneCount, Simd, SimdElement, SimdFloat, SimdInt, SimdUint, SupportedLaneCount};
|
||||
|
||||
mod sealed {
|
||||
use super::*;
|
||||
pub trait Sealed {}
|
||||
impl<T: SimdElement, const N: usize> Sealed for Simd<T, N> where LaneCount<N>: SupportedLaneCount {}
|
||||
}
|
||||
use sealed::Sealed;
|
||||
|
||||
/// Convert SIMD vectors to vectors of bytes
|
||||
pub trait ToBytes: Sealed {
|
||||
/// This type, reinterpreted as bytes.
|
||||
type Bytes: Copy
|
||||
+ Unpin
|
||||
+ Send
|
||||
+ Sync
|
||||
+ AsRef<[u8]>
|
||||
+ AsMut<[u8]>
|
||||
+ SimdUint<Scalar = u8>
|
||||
+ 'static;
|
||||
|
||||
/// Return the memory representation of this integer as a byte array in native byte
|
||||
/// order.
|
||||
fn to_ne_bytes(self) -> Self::Bytes;
|
||||
|
||||
/// Return the memory representation of this integer as a byte array in big-endian
|
||||
/// (network) byte order.
|
||||
fn to_be_bytes(self) -> Self::Bytes;
|
||||
|
||||
/// Return the memory representation of this integer as a byte array in little-endian
|
||||
/// byte order.
|
||||
fn to_le_bytes(self) -> Self::Bytes;
|
||||
|
||||
/// Create a native endian integer value from its memory representation as a byte array
|
||||
/// in native endianness.
|
||||
fn from_ne_bytes(bytes: Self::Bytes) -> Self;
|
||||
|
||||
/// Create an integer value from its representation as a byte array in big endian.
|
||||
fn from_be_bytes(bytes: Self::Bytes) -> Self;
|
||||
|
||||
/// Create an integer value from its representation as a byte array in little endian.
|
||||
fn from_le_bytes(bytes: Self::Bytes) -> Self;
|
||||
}
|
||||
|
||||
macro_rules! 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() }
|
||||
}
|
||||
|
||||
macro_rules! impl_to_bytes {
|
||||
{ $ty:ty, $size:literal } => {
|
||||
impl<const LANES: usize> crate::simd::Simd<$ty, LANES>
|
||||
where
|
||||
crate::simd::LaneCount<LANES>: crate::simd::SupportedLaneCount,
|
||||
crate::simd::LaneCount<{{ $size * LANES }}>: crate::simd::SupportedLaneCount,
|
||||
{
|
||||
/// Return the memory representation of this integer as a byte array in native byte
|
||||
/// order.
|
||||
{ $ty:tt, 1 } => { impl_to_bytes! { $ty, 1 * [1, 2, 4, 8, 16, 32, 64] } };
|
||||
{ $ty:tt, 2 } => { impl_to_bytes! { $ty, 2 * [1, 2, 4, 8, 16, 32] } };
|
||||
{ $ty:tt, 4 } => { impl_to_bytes! { $ty, 4 * [1, 2, 4, 8, 16] } };
|
||||
{ $ty:tt, 8 } => { impl_to_bytes! { $ty, 8 * [1, 2, 4, 8] } };
|
||||
{ $ty:tt, 16 } => { impl_to_bytes! { $ty, 16 * [1, 2, 4] } };
|
||||
{ $ty:tt, 32 } => { impl_to_bytes! { $ty, 32 * [1, 2] } };
|
||||
{ $ty:tt, 64 } => { impl_to_bytes! { $ty, 64 * [1] } };
|
||||
|
||||
{ $ty:tt, $size:literal * [$($elems:literal),*] } => {
|
||||
$(
|
||||
impl ToBytes for Simd<$ty, $elems> {
|
||||
type Bytes = Simd<u8, { $size * $elems }>;
|
||||
|
||||
#[inline]
|
||||
pub fn to_ne_bytes(self) -> crate::simd::Simd<u8, {{ $size * LANES }}> {
|
||||
fn to_ne_bytes(self) -> Self::Bytes {
|
||||
// Safety: transmuting between vectors is safe
|
||||
unsafe { core::mem::transmute_copy(&self) }
|
||||
unsafe { core::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Return the memory representation of this integer as a byte array in big-endian
|
||||
/// (network) byte order.
|
||||
#[inline]
|
||||
pub fn to_be_bytes(self) -> crate::simd::Simd<u8, {{ $size * LANES }}> {
|
||||
let bytes = self.to_ne_bytes();
|
||||
fn to_be_bytes(mut self) -> Self::Bytes {
|
||||
if !cfg!(target_endian = "big") {
|
||||
self = swap_bytes!($ty, self);
|
||||
}
|
||||
self.to_ne_bytes()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_le_bytes(mut self) -> Self::Bytes {
|
||||
if !cfg!(target_endian = "little") {
|
||||
self = swap_bytes!($ty, self);
|
||||
}
|
||||
self.to_ne_bytes()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_ne_bytes(bytes: Self::Bytes) -> Self {
|
||||
// Safety: transmuting between vectors is safe
|
||||
unsafe { core::mem::transmute(bytes) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_be_bytes(bytes: Self::Bytes) -> Self {
|
||||
let ret = Self::from_ne_bytes(bytes);
|
||||
if cfg!(target_endian = "big") {
|
||||
bytes
|
||||
ret
|
||||
} else {
|
||||
bytes.swap_bytes()
|
||||
swap_bytes!($ty, ret)
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the memory representation of this integer as a byte array in little-endian
|
||||
/// byte order.
|
||||
#[inline]
|
||||
pub fn to_le_bytes(self) -> crate::simd::Simd<u8, {{ $size * LANES }}> {
|
||||
let bytes = self.to_ne_bytes();
|
||||
fn from_le_bytes(bytes: Self::Bytes) -> Self {
|
||||
let ret = Self::from_ne_bytes(bytes);
|
||||
if cfg!(target_endian = "little") {
|
||||
bytes
|
||||
ret
|
||||
} else {
|
||||
bytes.swap_bytes()
|
||||
swap_bytes!($ty, ret)
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a native endian integer value from its memory representation as a byte array
|
||||
/// in native endianness.
|
||||
#[inline]
|
||||
pub fn from_ne_bytes(bytes: crate::simd::Simd<u8, {{ $size * LANES }}>) -> Self {
|
||||
// Safety: transmuting between vectors is safe
|
||||
unsafe { core::mem::transmute_copy(&bytes) }
|
||||
}
|
||||
|
||||
/// Create an integer value from its representation as a byte array in big endian.
|
||||
#[inline]
|
||||
pub fn from_be_bytes(bytes: crate::simd::Simd<u8, {{ $size * LANES }}>) -> Self {
|
||||
let bytes = if cfg!(target_endian = "big") {
|
||||
bytes
|
||||
} else {
|
||||
bytes.swap_bytes()
|
||||
};
|
||||
Self::from_ne_bytes(bytes)
|
||||
}
|
||||
|
||||
/// Create an integer value from its representation as a byte array in little endian.
|
||||
#[inline]
|
||||
pub fn from_le_bytes(bytes: crate::simd::Simd<u8, {{ $size * LANES }}>) -> Self {
|
||||
let bytes = if cfg!(target_endian = "little") {
|
||||
bytes
|
||||
} else {
|
||||
bytes.swap_bytes()
|
||||
};
|
||||
Self::from_ne_bytes(bytes)
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -89,3 +131,6 @@ impl_to_bytes! { i64, 8 }
|
|||
impl_to_bytes! { isize, 4 }
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
impl_to_bytes! { isize, 8 }
|
||||
|
||||
impl_to_bytes! { f32, 4 }
|
||||
impl_to_bytes! { f64, 8 }
|
||||
|
|
|
|||
|
|
@ -125,7 +125,6 @@ macro_rules! test_mask_api {
|
|||
cast_impl::<isize>();
|
||||
}
|
||||
|
||||
#[cfg(feature = "generic_const_exprs")]
|
||||
#[test]
|
||||
fn roundtrip_bitmask_array_conversion() {
|
||||
use core_simd::simd::ToBitMaskArray;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
#![feature(portable_simd, generic_const_exprs, adt_const_params)]
|
||||
#![allow(incomplete_features)]
|
||||
#![cfg(feature = "generic_const_exprs")]
|
||||
#![feature(portable_simd)]
|
||||
|
||||
use core_simd::simd::Simd;
|
||||
use core_simd::simd::{Simd, ToBytes};
|
||||
|
||||
#[test]
|
||||
fn byte_convert() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue