Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions beginners-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ Most of the portable SIMD API is designed to allow the user to gloss over the de

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.

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`].
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`].

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.

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

2 changes: 1 addition & 1 deletion crates/core_simd/src/masks/full_masks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ macro_rules! impl_reverse_bits {
#[inline(always)]
fn reverse_bits(self, n: usize) -> Self {
let rev = <$int>::reverse_bits(self);
let bitsize = core::mem::size_of::<$int>() * 8;
let bitsize = size_of::<$int>() * 8;
if n < bitsize {
// Shift things back to the right
rev >> (bitsize - n)
Expand Down
4 changes: 2 additions & 2 deletions crates/core_simd/src/simd/num/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,14 +302,14 @@ macro_rules! impl_trait {

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

#[inline]
fn from_bits(bits: Simd<$bits_ty, N>) -> Self {
assert_eq!(core::mem::size_of::<Self>(), core::mem::size_of::<Self::Bits>());
assert_eq!(size_of::<Self>(), size_of::<Self::Bits>());
// Safety: transmuting between vector types is safe
unsafe { core::mem::transmute_copy(&bits) }
}
Expand Down
2 changes: 1 addition & 1 deletion crates/core_simd/src/simd/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ where
fn cast<U>(self) -> Self::CastPtr<U> {
// SimdElement currently requires zero-sized metadata, so this should never fail.
// If this ever changes, `simd_cast_ptr` should produce a post-mono error.
use core::{mem::size_of, ptr::Pointee};
use core::ptr::Pointee;
assert_eq!(size_of::<<T as Pointee>::Metadata>(), 0);
assert_eq!(size_of::<<U as Pointee>::Metadata>(), 0);

Expand Down
2 changes: 1 addition & 1 deletion crates/core_simd/src/simd/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ where
fn cast<U>(self) -> Self::CastPtr<U> {
// SimdElement currently requires zero-sized metadata, so this should never fail.
// If this ever changes, `simd_cast_ptr` should produce a post-mono error.
use core::{mem::size_of, ptr::Pointee};
use core::ptr::Pointee;
assert_eq!(size_of::<<T as Pointee>::Metadata>(), 0);
assert_eq!(size_of::<<U as Pointee>::Metadata>(), 0);

Expand Down
2 changes: 1 addition & 1 deletion crates/core_simd/src/vector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ use crate::simd::{
/// converting `[T]` to `[Simd<T, N>]`, and allows soundly operating on an aligned SIMD body,
/// but it may cost more time when handling the scalar head and tail.
/// If these are not enough, it is most ideal to design data structures to be already aligned
/// to `mem::align_of::<Simd<T, N>>()` before using `unsafe` Rust to read or write.
/// to `align_of::<Simd<T, N>>()` before using `unsafe` Rust to read or write.
/// Other ways to compensate for these facts, like materializing `Simd` to or from an array first,
/// are handled by safe methods like [`Simd::from_array`] and [`Simd::from_slice`].
///
Expand Down
4 changes: 2 additions & 2 deletions crates/core_simd/tests/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ macro_rules! layout_tests {
test_helpers::test_lanes! {
fn no_padding<const LANES: usize>() {
assert_eq!(
core::mem::size_of::<core_simd::simd::Simd::<$ty, LANES>>(),
core::mem::size_of::<[$ty; LANES]>(),
size_of::<core_simd::simd::Simd::<$ty, LANES>>(),
size_of::<[$ty; LANES]>(),
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/core_simd/tests/round.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ macro_rules! float_rounding_test {
// all of the mantissa digits set to 1, pushed up to the MSB.
const ALL_MANTISSA_BITS: IntScalar = ((1 << <Scalar>::MANTISSA_DIGITS) - 1);
const MAX_REPRESENTABLE_VALUE: Scalar =
(ALL_MANTISSA_BITS << (core::mem::size_of::<Scalar>() * 8 - <Scalar>::MANTISSA_DIGITS as usize - 1)) as Scalar;
(ALL_MANTISSA_BITS << (size_of::<Scalar>() * 8 - <Scalar>::MANTISSA_DIGITS as usize - 1)) as Scalar;

let mut runner = test_helpers::make_runner();
runner.run(
Expand Down
2 changes: 1 addition & 1 deletion crates/test_helpers/src/subnormals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ macro_rules! impl_float {
$(
impl FlushSubnormals for $ty {
fn flush(self) -> Self {
let is_f32 = core::mem::size_of::<Self>() == 4;
let is_f32 = size_of::<Self>() == 4;
let ppc_flush = is_f32 && cfg!(all(
any(target_arch = "powerpc", all(target_arch = "powerpc64", target_endian = "big")),
target_feature = "altivec",
Expand Down