1 //! This module implements minimal run-time feature detection for x86.
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).
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`).
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.
18 /// A macro to test at *runtime* whether a CPU feature is available on
19 /// x86/x86-64 platforms.
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.
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].
30 /// ## Supported arguments
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.
37 /// Supported arguments are:
64 /// * `"avx512vpopcntdq"`
81 /// [docs]: https://software.intel.com/sites/landingpage/IntrinsicsGuide
83 #[stable(feature = "simd_x86", since = "1.27.0")]
84 #[allow_internal_unstable(stdsimd_internal,stdsimd)]
85 macro_rules! is_x86_feature_detected {
87 cfg!(target_feature = "aes") || $crate::detect::check_for(
88 $crate::detect::Feature::aes) };
90 cfg!(target_feature = "pclmulqdq") || $crate::detect::check_for(
91 $crate::detect::Feature::pclmulqdq) };
93 cfg!(target_feature = "rdrand") || $crate::detect::check_for(
94 $crate::detect::Feature::rdrand) };
96 cfg!(target_feature = "rdseed") || $crate::detect::check_for(
97 $crate::detect::Feature::rdseed) };
99 cfg!(target_feature = "tsc") || $crate::detect::check_for(
100 $crate::detect::Feature::tsc) };
102 cfg!(target_feature = "mmx") || $crate::detect::check_for(
103 $crate::detect::Feature::mmx) };
105 cfg!(target_feature = "sse") || $crate::detect::check_for(
106 $crate::detect::Feature::sse) };
108 cfg!(target_feature = "sse2") || $crate::detect::check_for(
109 $crate::detect::Feature::sse2)
112 cfg!(target_feature = "sse3") || $crate::detect::check_for(
113 $crate::detect::Feature::sse3)
116 cfg!(target_feature = "ssse3") || $crate::detect::check_for(
117 $crate::detect::Feature::ssse3)
120 cfg!(target_feature = "sse4.1") || $crate::detect::check_for(
121 $crate::detect::Feature::sse4_1)
124 cfg!(target_feature = "sse4.2") || $crate::detect::check_for(
125 $crate::detect::Feature::sse4_2)
128 cfg!(target_feature = "sse4a") || $crate::detect::check_for(
129 $crate::detect::Feature::sse4a)
132 cfg!(target_feature = "sha") || $crate::detect::check_for(
133 $crate::detect::Feature::sha)
136 cfg!(target_feature = "avx") || $crate::detect::check_for(
137 $crate::detect::Feature::avx)
140 cfg!(target_feature = "avx2") || $crate::detect::check_for(
141 $crate::detect::Feature::avx2)
144 cfg!(target_feature = "avx512f") || $crate::detect::check_for(
145 $crate::detect::Feature::avx512f)
148 cfg!(target_feature = "avx512cd") || $crate::detect::check_for(
149 $crate::detect::Feature::avx512cd)
152 cfg!(target_feature = "avx512er") || $crate::detect::check_for(
153 $crate::detect::Feature::avx512er)
156 cfg!(target_feature = "avx512pf") || $crate::detect::check_for(
157 $crate::detect::Feature::avx512pf)
160 cfg!(target_feature = "avx512bw") || $crate::detect::check_for(
161 $crate::detect::Feature::avx512bw)
164 cfg!(target_feature = "avx512dq") || $crate::detect::check_for(
165 $crate::detect::Feature::avx512dq)
168 cfg!(target_Feature = "avx512vl") || $crate::detect::check_for(
169 $crate::detect::Feature::avx512vl)
172 cfg!(target_feature = "avx512ifma") || $crate::detect::check_for(
173 $crate::detect::Feature::avx512_ifma)
176 cfg!(target_feature = "avx512vbmi") || $crate::detect::check_for(
177 $crate::detect::Feature::avx512_vbmi)
179 ("avx512vpopcntdq") => {
180 cfg!(target_feature = "avx512vpopcntdq") || $crate::detect::check_for(
181 $crate::detect::Feature::avx512_vpopcntdq)
184 cfg!(target_feature = "f16c") || $crate::detect::check_for(
185 $crate::detect::Feature::f16c)
188 cfg!(target_feature = "fma") || $crate::detect::check_for(
189 $crate::detect::Feature::fma)
192 cfg!(target_feature = "bmi1") || $crate::detect::check_for(
193 $crate::detect::Feature::bmi)
196 cfg!(target_feature = "bmi2") || $crate::detect::check_for(
197 $crate::detect::Feature::bmi2)
200 cfg!(target_feature = "abm") || $crate::detect::check_for(
201 $crate::detect::Feature::abm)
204 cfg!(target_feature = "lzcnt") || $crate::detect::check_for(
205 $crate::detect::Feature::abm)
208 cfg!(target_feature = "tbm") || $crate::detect::check_for(
209 $crate::detect::Feature::tbm)
212 cfg!(target_feature = "popcnt") || $crate::detect::check_for(
213 $crate::detect::Feature::popcnt)
216 cfg!(target_feature = "fxsr") || $crate::detect::check_for(
217 $crate::detect::Feature::fxsr)
220 cfg!(target_feature = "xsave") || $crate::detect::check_for(
221 $crate::detect::Feature::xsave)
224 cfg!(target_feature = "xsaveopt") || $crate::detect::check_for(
225 $crate::detect::Feature::xsaveopt)
228 cfg!(target_feature = "xsaves") || $crate::detect::check_for(
229 $crate::detect::Feature::xsaves)
232 cfg!(target_feature = "xsavec") || $crate::detect::check_for(
233 $crate::detect::Feature::xsavec)
236 cfg!(target_feature = "cmpxchg16b") || $crate::detect::check_for(
237 $crate::detect::Feature::cmpxchg16b)
240 cfg!(target_feature = "adx") || $crate::detect::check_for(
241 $crate::detect::Feature::adx)
244 cfg!(target_feature = "rtm") || $crate::detect::check_for(
245 $crate::detect::Feature::rtm)
248 is_x86_feature_detected!($t);
251 compile_error!(concat!("unknown target feature: ", $t))
255 /// X86 CPU Feature enum. Each variant denotes a position in a bitset for a
256 /// particular feature.
258 /// This is an unstable implementation detail subject to change.
259 #[allow(non_camel_case_types)]
262 #[unstable(feature = "stdsimd_internal", issue = "0")]
264 /// AES (Advanced Encryption Standard New Instructions AES-NI)
266 /// CLMUL (Carry-less Multiplication)
272 /// TSC (Time Stamp Counter)
276 /// SSE (Streaming SIMD Extensions)
278 /// SSE2 (Streaming SIMD Extensions 2)
280 /// SSE3 (Streaming SIMD Extensions 3)
282 /// SSSE3 (Supplemental Streaming SIMD Extensions 3)
284 /// SSE4.1 (Streaming SIMD Extensions 4.1)
286 /// SSE4.2 (Streaming SIMD Extensions 4.2)
288 /// SSE4a (Streaming SIMD Extensions 4a)
292 /// AVX (Advanced Vector Extensions)
294 /// AVX2 (Advanced Vector Extensions 2)
296 /// AVX-512 F (Foundation)
298 /// AVX-512 CD (Conflict Detection Instructions)
300 /// AVX-512 ER (Exponential and Reciprocal Instructions)
302 /// AVX-512 PF (Prefetch Instructions)
304 /// AVX-512 BW (Byte and Word Instructions)
306 /// AVX-512 DQ (Doubleword and Quadword)
308 /// AVX-512 VL (Vector Length Extensions)
310 /// AVX-512 IFMA (Integer Fused Multiply Add)
312 /// AVX-512 VBMI (Vector Byte Manipulation Instructions)
314 /// AVX-512 VPOPCNTDQ (Vector Population Count Doubleword and
317 /// F16C (Conversions between IEEE-754 `binary16` and `binary32` formats)
319 /// FMA (Fused Multiply Add)
321 /// BMI1 (Bit Manipulation Instructions 1)
323 /// BMI1 (Bit Manipulation Instructions 2)
325 /// ABM (Advanced Bit Manipulation) on AMD / LZCNT (Leading Zero
328 /// TBM (Trailing Bit Manipulation)
330 /// POPCNT (Population Count)
332 /// FXSR (Floating-point context fast save and restor)
334 /// XSAVE (Save Processor Extended States)
336 /// XSAVEOPT (Save Processor Extended States Optimized)
338 /// XSAVES (Save Processor Extended States Supervisor)
340 /// XSAVEC (Save Processor Extended States Compacted)
342 /// CMPXCH16B, a 16-byte compare-and-swap instruction
344 /// ADX, Intel ADX (Multi-Precision Add-Carry Instruction Extensions)
346 /// RTM, Intel (Restricted Transactional Memory)