Skip to content

Commit ad5ee52

Browse files
committed
Don't field-project (.0) into SIMD types
1 parent f3be311 commit ad5ee52

File tree

2 files changed

+52
-11
lines changed

2 files changed

+52
-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

+51-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,31 @@ 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+
fn eq(&self, other: &Self) -> bool {
58+
self.as_array() == other.as_array()
59+
}
60+
}
61+
62+
impl core::fmt::Debug for $id {
63+
#[inline]
64+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
65+
debug_simd_finish(f, stringify!($id), self.as_array())
4866
}
4967
}
5068
}
@@ -53,7 +71,7 @@ macro_rules! simd_ty {
5371
macro_rules! simd_m_ty {
5472
($id:ident [$elem_type:ident ; $len:literal]: $($param_name:ident),*) => {
5573
#[repr(simd)]
56-
#[derive(Copy, Clone, Debug, PartialEq)]
74+
#[derive(Copy, Clone)]
5775
pub(crate) struct $id([$elem_type; $len]);
5876

5977
#[allow(clippy::use_self)]
@@ -79,6 +97,29 @@ macro_rules! simd_m_ty {
7997
// a simd type with exactly one element.
8098
unsafe { simd_shuffle!(one, one, [0; $len]) }
8199
}
100+
101+
#[inline]
102+
pub(crate) fn as_array(&self) -> &[$elem_type; $len] {
103+
let simd_ptr: *const Self = self;
104+
let array_ptr: *const [$elem_type; $len] = simd_ptr.cast();
105+
// SAFETY: We can always read the prefix of a simd type as an array.
106+
// There might be more padding afterwards for some widths, but
107+
// that's not a problem for reading less than that.
108+
unsafe { &*array_ptr }
109+
}
110+
}
111+
112+
impl core::cmp::PartialEq for $id {
113+
fn eq(&self, other: &Self) -> bool {
114+
self.as_array() == other.as_array()
115+
}
116+
}
117+
118+
impl core::fmt::Debug for $id {
119+
#[inline]
120+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
121+
debug_simd_finish(f, stringify!($id), self.as_array())
122+
}
82123
}
83124
}
84125
}
@@ -968,7 +1009,7 @@ simd_ty!(
9681009
pub(crate) fn debug_simd_finish<T: crate::fmt::Debug, const N: usize>(
9691010
formatter: &mut crate::fmt::Formatter<'_>,
9701011
type_name: &str,
971-
array: [T; N],
1012+
array: &[T; N],
9721013
) -> crate::fmt::Result {
9731014
crate::fmt::Formatter::debug_tuple_fields_finish(
9741015
formatter,

0 commit comments

Comments
 (0)