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