1use crate::Architecture;
2
3#[doc(hidden)]
4pub enum SimdTypeImpl {
5 Float32,
6 Float64,
7 Other,
8}
9
10pub trait SimdType {
12 #[doc(hidden)]
13 const IMPL: SimdTypeImpl;
14}
15
16impl SimdType for u8 {
17 const IMPL: SimdTypeImpl = SimdTypeImpl::Other;
18}
19
20impl SimdType for u16 {
21 const IMPL: SimdTypeImpl = SimdTypeImpl::Other;
22}
23
24impl SimdType for u32 {
25 const IMPL: SimdTypeImpl = SimdTypeImpl::Other;
26}
27
28impl SimdType for u64 {
29 const IMPL: SimdTypeImpl = SimdTypeImpl::Other;
30}
31
32impl SimdType for usize {
33 const IMPL: SimdTypeImpl = SimdTypeImpl::Other;
34}
35
36impl SimdType for i8 {
37 const IMPL: SimdTypeImpl = SimdTypeImpl::Other;
38}
39
40impl SimdType for i16 {
41 const IMPL: SimdTypeImpl = SimdTypeImpl::Other;
42}
43
44impl SimdType for i32 {
45 const IMPL: SimdTypeImpl = SimdTypeImpl::Other;
46}
47
48impl SimdType for i64 {
49 const IMPL: SimdTypeImpl = SimdTypeImpl::Other;
50}
51
52impl SimdType for isize {
53 const IMPL: SimdTypeImpl = SimdTypeImpl::Other;
54}
55
56impl SimdType for f32 {
57 const IMPL: SimdTypeImpl = SimdTypeImpl::Float32;
58}
59
60impl SimdType for f64 {
61 const IMPL: SimdTypeImpl = SimdTypeImpl::Float64;
62}
63
64impl<T> SimdType for *const T {
65 const IMPL: SimdTypeImpl = SimdTypeImpl::Other;
66}
67
68impl<T> SimdType for *mut T {
69 const IMPL: SimdTypeImpl = SimdTypeImpl::Other;
70}
71
72impl crate::Target {
73 pub const fn suggested_simd_width<T: SimdType>(&self) -> Option<usize> {
82 let is_f32 = T::IMPL as u8 == SimdTypeImpl::Float32 as u8;
83 let is_f64 = T::IMPL as u8 == SimdTypeImpl::Float64 as u8;
84
85 let v128 = 16 / core::mem::size_of::<T>();
86 let v256 = 32 / core::mem::size_of::<T>();
87 let v512 = 64 / core::mem::size_of::<T>();
88 let v1024 = 128 / core::mem::size_of::<T>();
89
90 if let Architecture::Arm = self.architecture() {
91 if self.supports_feature_str("neon") && !is_f64 {
93 Some(v128)
94 } else {
95 None
96 }
97 } else if let Architecture::AArch64 = self.architecture() {
98 if self.supports_feature_str("neon") {
99 Some(v128)
100 } else {
101 None
102 }
103 } else if let Architecture::Hexagon = self.architecture() {
104 if is_f32 || is_f64 {
106 None
107 } else if self.supports_feature_str("hvx-length128b") {
108 Some(v1024)
109 } else if self.supports_feature_str("hvx") {
110 Some(v512)
111 } else {
112 None
113 }
114 } else if let Architecture::Mips = self.architecture() {
115 if self.supports_feature_str("msa") {
116 Some(v128)
117 } else {
118 None
119 }
120 } else if let Architecture::PowerPC = self.architecture() {
121 if self.supports_feature_str("vsx") || (self.supports_feature_str("altivec") && !is_f64)
123 {
124 Some(v128)
125 } else {
126 None
127 }
128 } else if let Architecture::RiscV = self.architecture() {
129 if self.supports_feature_str("v") {
131 Some(v128)
132 } else {
133 None
134 }
135 } else if let Architecture::Wasm = self.architecture() {
136 if self.supports_feature_str("simd128") {
137 Some(v128)
138 } else {
139 None
140 }
141 } else if let Architecture::X86 = self.architecture() {
142 if self.supports_feature_str("avx512f") {
143 Some(v512)
144 } else if self.supports_feature_str("avx2")
145 || (is_f32 || is_f64) && self.supports_feature_str("avx")
146 {
147 Some(v256)
149 } else if self.supports_feature_str("sse2")
150 || is_f32 && self.supports_feature_str("sse")
151 {
152 Some(v128)
154 } else {
155 None
156 }
157 } else {
158 None
159 }
160 }
161}