Skip to content

Commit 58538b1

Browse files
scottmcmAmanieu
authored andcommitted
Don't field-project (.0) into SIMD types
1 parent 9426bb5 commit 58538b1

File tree

2 files changed

+54
-11
lines changed

2 files changed

+54
-11
lines changed

crates/core_arch/src/macros.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ macro_rules! types {
132132
impl crate::fmt::Debug for $name {
133133
#[inline]
134134
fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
135-
crate::core_arch::simd::debug_simd_finish(f, stringify!($name), self.0)
135+
crate::core_arch::simd::debug_simd_finish(f, stringify!($name), self.as_array())
136136
}
137137
}
138138
)*);

crates/core_arch/src/simd.rs

+53-10
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
macro_rules! simd_ty {
66
($id:ident [$elem_type:ty ; $len:literal]: $($param_name:ident),*) => {
77
#[repr(simd)]
8-
#[derive(Copy, Clone, Debug, PartialEq)]
8+
#[derive(Copy, Clone)]
99
pub(crate) struct $id([$elem_type; $len]);
1010

1111
#[allow(clippy::use_self)]
@@ -38,13 +38,32 @@ macro_rules! simd_ty {
3838
/// Use for testing only.
3939
// FIXME: Workaround rust@60637
4040
#[inline(always)]
41-
pub(crate) fn extract(self, index: usize) -> $elem_type {
42-
assert!(index < $len);
43-
// Now that we know this is in-bounds, use pointer arithmetic to access the right element.
44-
let self_ptr = &self as *const Self as *const $elem_type;
45-
unsafe {
46-
self_ptr.add(index).read()
47-
}
41+
pub(crate) fn extract(&self, index: usize) -> $elem_type {
42+
self.as_array()[index]
43+
}
44+
45+
#[inline]
46+
pub(crate) fn as_array(&self) -> &[$elem_type; $len] {
47+
let simd_ptr: *const Self = self;
48+
let array_ptr: *const [$elem_type; $len] = simd_ptr.cast();
49+
// SAFETY: We can always read the prefix of a simd type as an array.
50+
// There might be more padding afterwards for some widths, but
51+
// that's not a problem for reading less than that.
52+
unsafe { &*array_ptr }
53+
}
54+
}
55+
56+
impl core::cmp::PartialEq for $id {
57+
#[inline]
58+
fn eq(&self, other: &Self) -> bool {
59+
self.as_array() == other.as_array()
60+
}
61+
}
62+
63+
impl core::fmt::Debug for $id {
64+
#[inline]
65+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
66+
debug_simd_finish(f, stringify!($id), self.as_array())
4867
}
4968
}
5069
}
@@ -53,7 +72,7 @@ macro_rules! simd_ty {
5372
macro_rules! simd_m_ty {
5473
($id:ident [$elem_type:ident ; $len:literal]: $($param_name:ident),*) => {
5574
#[repr(simd)]
56-
#[derive(Copy, Clone, Debug, PartialEq)]
75+
#[derive(Copy, Clone)]
5776
pub(crate) struct $id([$elem_type; $len]);
5877

5978
#[allow(clippy::use_self)]
@@ -79,6 +98,30 @@ macro_rules! simd_m_ty {
7998
// a simd type with exactly one element.
8099
unsafe { simd_shuffle!(one, one, [0; $len]) }
81100
}
101+
102+
#[inline]
103+
pub(crate) fn as_array(&self) -> &[$elem_type; $len] {
104+
let simd_ptr: *const Self = self;
105+
let array_ptr: *const [$elem_type; $len] = simd_ptr.cast();
106+
// SAFETY: We can always read the prefix of a simd type as an array.
107+
// There might be more padding afterwards for some widths, but
108+
// that's not a problem for reading less than that.
109+
unsafe { &*array_ptr }
110+
}
111+
}
112+
113+
impl core::cmp::PartialEq for $id {
114+
#[inline]
115+
fn eq(&self, other: &Self) -> bool {
116+
self.as_array() == other.as_array()
117+
}
118+
}
119+
120+
impl core::fmt::Debug for $id {
121+
#[inline]
122+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
123+
debug_simd_finish(f, stringify!($id), self.as_array())
124+
}
82125
}
83126
}
84127
}
@@ -968,7 +1011,7 @@ simd_ty!(
9681011
pub(crate) fn debug_simd_finish<T: crate::fmt::Debug, const N: usize>(
9691012
formatter: &mut crate::fmt::Formatter<'_>,
9701013
type_name: &str,
971-
array: [T; N],
1014+
array: &[T; N],
9721015
) -> crate::fmt::Result {
9731016
crate::fmt::Formatter::debug_tuple_fields_finish(
9741017
formatter,

0 commit comments

Comments
 (0)