]> git.proxmox.com Git - rustc.git/blob - src/stdsimd/stdsimd/arch/detect/arch/x86.rs
New upstream version 1.33.0+dfsg1
[rustc.git] / src / stdsimd / stdsimd / arch / detect / arch / x86.rs
1 //! This module implements minimal run-time feature detection for x86.
2 //!
3 //! The features are detected using the `detect_features` function below.
4 //! This function uses the CPUID instruction to read the feature flags from the
5 //! CPU and encodes them in an `usize` where each bit position represents
6 //! whether a feature is available (bit is set) or unavaiable (bit is cleared).
7 //!
8 //! The enum `Feature` is used to map bit positions to feature names, and the
9 //! the `__crate::arch::detect::check_for!` macro is used to map string literals (e.g.
10 //! "avx") to these bit positions (e.g. `Feature::avx`).
11 //!
12 //!
13 //! The run-time feature detection is performed by the
14 //! `__crate::arch::detect::check_for(Feature) -> bool` function. On its first call,
15 //! this functions queries the CPU for the available features and stores them
16 //! in a global `AtomicUsize` variable. The query is performed by just checking
17 //! whether the feature bit in this global variable is set or cleared.
18
19 /// A macro to test at *runtime* whether a CPU feature is available on
20 /// x86/x86-64 platforms.
21 ///
22 /// This macro is provided in the standard library and will detect at runtime
23 /// whether the specified CPU feature is detected. This does *not* resolve at
24 /// compile time unless the specified feature is already enabled for the entire
25 /// crate. Runtime detection currently relies mostly on the `cpuid` instruction.
26 ///
27 /// This macro only takes one argument which is a string literal of the feature
28 /// being tested for. The feature names supported are the lowercase versions of
29 /// the ones defined by Intel in [their documentation][docs].
30 ///
31 /// ## Supported arguments
32 ///
33 /// This macro supports the same names that `#[target_feature]` supports. Unlike
34 /// `#[target_feature]`, however, this macro does not support names separated
35 /// with a comma. Instead testing for multiple features must be done through
36 /// separate macro invocations for now.
37 ///
38 /// Supported arguments are:
39 ///
40 /// * `"aes"`
41 /// * `"pclmulqdq"`
42 /// * `"rdrand"`
43 /// * `"rdseed"`
44 /// * `"tsc"`
45 /// * `"mmx"`
46 /// * `"sse"`
47 /// * `"sse2"`
48 /// * `"sse3"`
49 /// * `"ssse3"`
50 /// * `"sse4.1"`
51 /// * `"sse4.2"`
52 /// * `"sse4a"`
53 /// * `"sha"`
54 /// * `"avx"`
55 /// * `"avx2"`
56 /// * `"avx512f"`
57 /// * `"avx512cd"`
58 /// * `"avx512er"`
59 /// * `"avx512pf"`
60 /// * `"avx512bw"`
61 /// * `"avx512dq"`
62 /// * `"avx512vl"`
63 /// * `"avx512ifma"`
64 /// * `"avx512vbmi"`
65 /// * `"avx512vpopcntdq"`
66 /// * `"fma"`
67 /// * `"bmi1"`
68 /// * `"bmi2"`
69 /// * `"abm"`
70 /// * `"lzcnt"`
71 /// * `"tbm"`
72 /// * `"popcnt"`
73 /// * `"fxsr"`
74 /// * `"xsave"`
75 /// * `"xsaveopt"`
76 /// * `"xsaves"`
77 /// * `"xsavec"`
78 ///
79 /// [docs]: https://software.intel.com/sites/landingpage/IntrinsicsGuide
80 #[macro_export]
81 #[stable(feature = "simd_x86", since = "1.27.0")]
82 #[allow_internal_unstable]
83 macro_rules! is_x86_feature_detected {
84 ("aes") => {
85 cfg!(target_feature = "aes") || $crate::arch::detect::check_for(
86 $crate::arch::detect::Feature::aes) };
87 ("pclmulqdq") => {
88 cfg!(target_feature = "pclmulqdq") || $crate::arch::detect::check_for(
89 $crate::arch::detect::Feature::pclmulqdq) };
90 ("rdrand") => {
91 cfg!(target_feature = "rdrand") || $crate::arch::detect::check_for(
92 $crate::arch::detect::Feature::rdrand) };
93 ("rdseed") => {
94 cfg!(target_feature = "rdseed") || $crate::arch::detect::check_for(
95 $crate::arch::detect::Feature::rdseed) };
96 ("tsc") => {
97 cfg!(target_feature = "tsc") || $crate::arch::detect::check_for(
98 $crate::arch::detect::Feature::tsc) };
99 ("mmx") => {
100 cfg!(target_feature = "mmx") || $crate::arch::detect::check_for(
101 $crate::arch::detect::Feature::mmx) };
102 ("sse") => {
103 cfg!(target_feature = "sse") || $crate::arch::detect::check_for(
104 $crate::arch::detect::Feature::sse) };
105 ("sse2") => {
106 cfg!(target_feature = "sse2") || $crate::arch::detect::check_for(
107 $crate::arch::detect::Feature::sse2)
108 };
109 ("sse3") => {
110 cfg!(target_feature = "sse3") || $crate::arch::detect::check_for(
111 $crate::arch::detect::Feature::sse3)
112 };
113 ("ssse3") => {
114 cfg!(target_feature = "ssse3") || $crate::arch::detect::check_for(
115 $crate::arch::detect::Feature::ssse3)
116 };
117 ("sse4.1") => {
118 cfg!(target_feature = "sse4.1") || $crate::arch::detect::check_for(
119 $crate::arch::detect::Feature::sse4_1)
120 };
121 ("sse4.2") => {
122 cfg!(target_feature = "sse4.2") || $crate::arch::detect::check_for(
123 $crate::arch::detect::Feature::sse4_2)
124 };
125 ("sse4a") => {
126 cfg!(target_feature = "sse4a") || $crate::arch::detect::check_for(
127 $crate::arch::detect::Feature::sse4a)
128 };
129 ("sha") => {
130 cfg!(target_feature = "sha") || $crate::arch::detect::check_for(
131 $crate::arch::detect::Feature::sha)
132 };
133 ("avx") => {
134 cfg!(target_feature = "avx") || $crate::arch::detect::check_for(
135 $crate::arch::detect::Feature::avx)
136 };
137 ("avx2") => {
138 cfg!(target_feature = "avx2") || $crate::arch::detect::check_for(
139 $crate::arch::detect::Feature::avx2)
140 };
141 ("avx512f") => {
142 cfg!(target_feature = "avx512f") || $crate::arch::detect::check_for(
143 $crate::arch::detect::Feature::avx512f)
144 };
145 ("avx512cd") => {
146 cfg!(target_feature = "avx512cd") || $crate::arch::detect::check_for(
147 $crate::arch::detect::Feature::avx512cd)
148 };
149 ("avx512er") => {
150 cfg!(target_feature = "avx512er") || $crate::arch::detect::check_for(
151 $crate::arch::detect::Feature::avx512er)
152 };
153 ("avx512pf") => {
154 cfg!(target_feature = "avx512pf") || $crate::arch::detect::check_for(
155 $crate::arch::detect::Feature::avx512pf)
156 };
157 ("avx512bw") => {
158 cfg!(target_feature = "avx512bw") || $crate::arch::detect::check_for(
159 $crate::arch::detect::Feature::avx512bw)
160 };
161 ("avx512dq") => {
162 cfg!(target_feature = "avx512dq") || $crate::arch::detect::check_for(
163 $crate::arch::detect::Feature::avx512dq)
164 };
165 ("avx512vl") => {
166 cfg!(target_Feature = "avx512vl") || $crate::arch::detect::check_for(
167 $crate::arch::detect::Feature::avx512vl)
168 };
169 ("avx512ifma") => {
170 cfg!(target_feature = "avx512ifma") || $crate::arch::detect::check_for(
171 $crate::arch::detect::Feature::avx512_ifma)
172 };
173 ("avx512vbmi") => {
174 cfg!(target_feature = "avx512vbmi") || $crate::arch::detect::check_for(
175 $crate::arch::detect::Feature::avx512_vbmi)
176 };
177 ("avx512vpopcntdq") => {
178 cfg!(target_feature = "avx512vpopcntdq") || $crate::arch::detect::check_for(
179 $crate::arch::detect::Feature::avx512_vpopcntdq)
180 };
181 ("fma") => {
182 cfg!(target_feature = "fma") || $crate::arch::detect::check_for(
183 $crate::arch::detect::Feature::fma)
184 };
185 ("bmi1") => {
186 cfg!(target_feature = "bmi1") || $crate::arch::detect::check_for(
187 $crate::arch::detect::Feature::bmi)
188 };
189 ("bmi2") => {
190 cfg!(target_feature = "bmi2") || $crate::arch::detect::check_for(
191 $crate::arch::detect::Feature::bmi2)
192 };
193 ("abm") => {
194 cfg!(target_feature = "abm") || $crate::arch::detect::check_for(
195 $crate::arch::detect::Feature::abm)
196 };
197 ("lzcnt") => {
198 cfg!(target_feature = "lzcnt") || $crate::arch::detect::check_for(
199 $crate::arch::detect::Feature::abm)
200 };
201 ("tbm") => {
202 cfg!(target_feature = "tbm") || $crate::arch::detect::check_for(
203 $crate::arch::detect::Feature::tbm)
204 };
205 ("popcnt") => {
206 cfg!(target_feature = "popcnt") || $crate::arch::detect::check_for(
207 $crate::arch::detect::Feature::popcnt)
208 };
209 ("fxsr") => {
210 cfg!(target_feature = "fxsr") || $crate::arch::detect::check_for(
211 $crate::arch::detect::Feature::fxsr)
212 };
213 ("xsave") => {
214 cfg!(target_feature = "xsave") || $crate::arch::detect::check_for(
215 $crate::arch::detect::Feature::xsave)
216 };
217 ("xsaveopt") => {
218 cfg!(target_feature = "xsaveopt") || $crate::arch::detect::check_for(
219 $crate::arch::detect::Feature::xsaveopt)
220 };
221 ("xsaves") => {
222 cfg!(target_feature = "xsaves") || $crate::arch::detect::check_for(
223 $crate::arch::detect::Feature::xsaves)
224 };
225 ("xsavec") => {
226 cfg!(target_feature = "xsavec") || $crate::arch::detect::check_for(
227 $crate::arch::detect::Feature::xsavec)
228 };
229 ("cmpxchg16b") => {
230 cfg!(target_feature = "cmpxchg16b") || $crate::arch::detect::check_for(
231 $crate::arch::detect::Feature::cmpxchg16b)
232 };
233 ("adx") => {
234 cfg!(target_feature = "adx") || $crate::arch::detect::check_for(
235 $crate::arch::detect::Feature::adx)
236 };
237 ($t:tt) => {
238 compile_error!(concat!("unknown target feature: ", $t))
239 };
240 }
241
242 /// X86 CPU Feature enum. Each variant denotes a position in a bitset for a
243 /// particular feature.
244 ///
245 /// This is an unstable implementation detail subject to change.
246 #[allow(non_camel_case_types)]
247 #[repr(u8)]
248 #[doc(hidden)]
249 #[unstable(feature = "stdsimd_internal", issue = "0")]
250 pub enum Feature {
251 /// AES (Advanced Encryption Standard New Instructions AES-NI)
252 aes,
253 /// CLMUL (Carry-less Multiplication)
254 pclmulqdq,
255 /// RDRAND
256 rdrand,
257 /// RDSEED
258 rdseed,
259 /// TSC (Time Stamp Counter)
260 tsc,
261 /// MMX
262 mmx,
263 /// SSE (Streaming SIMD Extensions)
264 sse,
265 /// SSE2 (Streaming SIMD Extensions 2)
266 sse2,
267 /// SSE3 (Streaming SIMD Extensions 3)
268 sse3,
269 /// SSSE3 (Supplemental Streaming SIMD Extensions 3)
270 ssse3,
271 /// SSE4.1 (Streaming SIMD Extensions 4.1)
272 sse4_1,
273 /// SSE4.2 (Streaming SIMD Extensions 4.2)
274 sse4_2,
275 /// SSE4a (Streaming SIMD Extensions 4a)
276 sse4a,
277 /// SHA
278 sha,
279 /// AVX (Advanced Vector Extensions)
280 avx,
281 /// AVX2 (Advanced Vector Extensions 2)
282 avx2,
283 /// AVX-512 F (Foundation)
284 avx512f,
285 /// AVX-512 CD (Conflict Detection Instructions)
286 avx512cd,
287 /// AVX-512 ER (Exponential and Reciprocal Instructions)
288 avx512er,
289 /// AVX-512 PF (Prefetch Instructions)
290 avx512pf,
291 /// AVX-512 BW (Byte and Word Instructions)
292 avx512bw,
293 /// AVX-512 DQ (Doubleword and Quadword)
294 avx512dq,
295 /// AVX-512 VL (Vector Length Extensions)
296 avx512vl,
297 /// AVX-512 IFMA (Integer Fused Multiply Add)
298 avx512_ifma,
299 /// AVX-512 VBMI (Vector Byte Manipulation Instructions)
300 avx512_vbmi,
301 /// AVX-512 VPOPCNTDQ (Vector Population Count Doubleword and
302 /// Quadword)
303 avx512_vpopcntdq,
304 /// FMA (Fused Multiply Add)
305 fma,
306 /// BMI1 (Bit Manipulation Instructions 1)
307 bmi,
308 /// BMI1 (Bit Manipulation Instructions 2)
309 bmi2,
310 /// ABM (Advanced Bit Manipulation) on AMD / LZCNT (Leading Zero
311 /// Count) on Intel
312 abm,
313 /// TBM (Trailing Bit Manipulation)
314 tbm,
315 /// POPCNT (Population Count)
316 popcnt,
317 /// FXSR (Floating-point context fast save and restor)
318 fxsr,
319 /// XSAVE (Save Processor Extended States)
320 xsave,
321 /// XSAVEOPT (Save Processor Extended States Optimized)
322 xsaveopt,
323 /// XSAVES (Save Processor Extended States Supervisor)
324 xsaves,
325 /// XSAVEC (Save Processor Extended States Compacted)
326 xsavec,
327 /// CMPXCH16B, a 16-byte compare-and-swap instruction
328 cmpxchg16b,
329 /// ADX, Intel ADX (Multi-Precision Add-Carry Instruction Extensions)
330 adx,
331 }