1#[cfg(target_arch = "aarch64")]
2use crate::aarch64 as features;
3#[cfg(target_arch = "arm")]
4use crate::arm as features;
5#[cfg(target_arch = "arm64ec")]
6use crate::arm64ec as features;
7#[cfg(target_arch = "hexagon")]
8use crate::hexagon as features;
9#[cfg(target_arch = "loongarch32")]
10use crate::loongarch32 as features;
11#[cfg(target_arch = "loongarch64")]
12use crate::loongarch64 as features;
13#[cfg(target_arch = "mips")]
14use crate::mips as features;
15#[cfg(target_arch = "mips64")]
16use crate::mips64 as features;
17#[cfg(target_arch = "powerpc")]
18use crate::powerpc as features;
19#[cfg(target_arch = "powerpc64")]
20use crate::powerpc64 as features;
21#[cfg(target_arch = "riscv32")]
22use crate::riscv32 as features;
23#[cfg(target_arch = "riscv64")]
24use crate::riscv64 as features;
25#[cfg(target_arch = "s390x")]
26use crate::s390x as features;
27#[cfg(target_arch = "wasm32")]
28use crate::wasm32 as features;
29#[cfg(target_arch = "wasm64")]
30use crate::wasm64 as features;
31#[cfg(target_arch = "x86")]
32use crate::x86 as features;
33#[cfg(target_arch = "x86_64")]
34use crate::x86_64 as features;
35
36mod sealed {
37 pub trait SealedSimdElement {}
38}
39
40#[doc(hidden)]
41pub enum SimdElementImpl {
42 Float32,
43 Float64,
44 Other,
45}
46
47pub trait SimdElement: sealed::SealedSimdElement {
49 #[doc(hidden)]
50 const IMPL: SimdElementImpl;
51}
52
53macro_rules! impl_simd_element {
54 ($impl:ident: $($ty:ty),* $(,)?) => {
55 $(
56 impl sealed::SealedSimdElement for $ty {}
57 impl SimdElement for $ty {
58 const IMPL: SimdElementImpl = SimdElementImpl::$impl;
59 }
60 )*
61 };
62}
63
64impl_simd_element!(Other: u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
65impl_simd_element!(Float32: f32);
66impl_simd_element!(Float64: f64);
67
68impl<T> sealed::SealedSimdElement for *const T {}
69impl<T> SimdElement for *const T {
70 const IMPL: SimdElementImpl = SimdElementImpl::Other;
71}
72
73impl<T> sealed::SealedSimdElement for *mut T {}
74impl<T> SimdElement for *mut T {
75 const IMPL: SimdElementImpl = SimdElementImpl::Other;
76}
77
78impl crate::TargetFeatures {
79 #[allow(unused_variables)]
88 pub const fn suggested_simd_width<T: SimdElement>(&self) -> Option<usize> {
89 let is_f32 = T::IMPL as u8 == SimdElementImpl::Float32 as u8;
90 let is_f64 = T::IMPL as u8 == SimdElementImpl::Float64 as u8;
91 let is_integer = !is_f32 && !is_f64;
92 let element_size = core::mem::size_of::<T>();
93
94 let v128 = 16 / element_size;
95 let v256 = 32 / element_size;
96 let v512 = 64 / element_size;
97 let v1024 = 128 / element_size;
98
99 #[cfg(target_arch = "arm")]
100 {
101 return if (self.contains(features::NEON) && !is_f64)
102 || (is_f32 && self.contains(features::MVE_FP))
103 || (is_integer && element_size <= 4 && self.contains(features::MVE))
104 {
105 Some(v128)
106 } else {
107 None
108 };
109 }
110
111 #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))]
112 {
113 return if self.contains(features::NEON) {
114 Some(v128)
115 } else {
116 None
117 };
118 }
119
120 #[cfg(target_arch = "hexagon")]
121 {
122 return if is_f64 {
123 None
124 } else if is_f32 {
125 if self.contains(features::HVX_LENGTH128B)
126 && self.contains(features::HVXV68)
127 && self.contains(features::HVX_IEEE_FP)
128 {
129 Some(v1024)
130 } else {
131 None
132 }
133 } else if self.contains(features::HVX_LENGTH128B) {
134 Some(v1024)
135 } else if self.contains(features::HVX) {
136 Some(v512)
137 } else {
138 None
139 };
140 }
141
142 #[cfg(any(target_arch = "loongarch32", target_arch = "loongarch64"))]
143 {
144 return if self.contains(features::LASX) {
145 Some(v256)
146 } else if self.contains(features::LSX) {
147 Some(v128)
148 } else {
149 None
150 };
151 }
152
153 #[cfg(any(target_arch = "mips", target_arch = "mips64"))]
154 {
155 return if self.contains(features::MSA) {
156 Some(v128)
157 } else {
158 None
159 };
160 }
161
162 #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
163 {
164 return if self.contains(features::VSX) || (self.contains(features::ALTIVEC) && !is_f64)
165 {
166 Some(v128)
167 } else {
168 None
169 };
170 }
171
172 #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
173 {
174 let supports_element = if is_f64 {
175 self.contains(features::ZVE64D)
176 } else if is_f32 {
177 self.contains(features::ZVE32F)
178 } else if element_size <= 4 {
179 self.contains(features::ZVE32X)
180 } else if element_size <= 8 {
181 self.contains(features::ZVE64X)
182 } else {
183 false
184 };
185
186 let vector_bytes = if self.contains(features::ZVL65536B) {
187 8192
188 } else if self.contains(features::ZVL32768B) {
189 4096
190 } else if self.contains(features::ZVL16384B) {
191 2048
192 } else if self.contains(features::ZVL8192B) {
193 1024
194 } else if self.contains(features::ZVL4096B) {
195 512
196 } else if self.contains(features::ZVL2048B) {
197 256
198 } else if self.contains(features::ZVL1024B) {
199 128
200 } else if self.contains(features::ZVL512B) {
201 64
202 } else if self.contains(features::ZVL256B) {
203 32
204 } else if self.contains(features::ZVL128B) {
205 16
206 } else if self.contains(features::ZVL64B) {
207 8
208 } else if self.contains(features::ZVL32B) {
209 4
210 } else {
211 0
212 };
213
214 return if supports_element && vector_bytes != 0 {
215 Some(vector_bytes / element_size)
216 } else {
217 None
218 };
219 }
220
221 #[cfg(target_arch = "s390x")]
222 {
223 return if self.contains(features::VECTOR) {
224 Some(v128)
225 } else {
226 None
227 };
228 }
229
230 #[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))]
231 {
232 return if self.contains(features::SIMD128) {
233 Some(v128)
234 } else {
235 None
236 };
237 }
238
239 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
240 {
241 return if self.contains(features::AVX512F)
242 && (!is_integer || element_size >= 4 || self.contains(features::AVX512BW))
243 {
244 Some(v512)
245 } else if self.contains(features::AVX2)
246 || ((is_f32 || is_f64) && self.contains(features::AVX))
247 {
248 Some(v256)
249 } else if self.contains(features::SSE2) || (is_f32 && self.contains(features::SSE)) {
250 Some(v128)
251 } else {
252 None
253 };
254 }
255
256 #[allow(unreachable_code)]
257 None
258 }
259}