diff options
Diffstat (limited to 'src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs')
-rw-r--r-- | src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs new file mode 100644 index 000000000..02d5eed1c --- /dev/null +++ b/src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs @@ -0,0 +1,333 @@ +//! This module implements minimal run-time feature detection for x86. +//! +//! The features are detected using the `detect_features` function below. +//! This function uses the CPUID instruction to read the feature flags from the +//! CPU and encodes them in a `usize` where each bit position represents +//! whether a feature is available (bit is set) or unavailable (bit is cleared). +//! +//! The enum `Feature` is used to map bit positions to feature names, and the +//! the `__crate::detect::check_for!` macro is used to map string literals (e.g., +//! "avx") to these bit positions (e.g., `Feature::avx`). +//! +//! The run-time feature detection is performed by the +//! `__crate::detect::check_for(Feature) -> bool` function. On its first call, +//! this functions queries the CPU for the available features and stores them +//! in a global `AtomicUsize` variable. The query is performed by just checking +//! whether the feature bit in this global variable is set or cleared. + +/// A macro to test at *runtime* whether a CPU feature is available on +/// x86/x86-64 platforms. +/// +/// This macro is provided in the standard library and will detect at runtime +/// whether the specified CPU feature is detected. This does **not** resolve at +/// compile time unless the specified feature is already enabled for the entire +/// crate. Runtime detection currently relies mostly on the `cpuid` instruction. +/// +/// This macro only takes one argument which is a string literal of the feature +/// being tested for. The feature names supported are the lowercase versions of +/// the ones defined by Intel in [their documentation][docs]. +/// +/// ## Supported arguments +/// +/// This macro supports the same names that `#[target_feature]` supports. Unlike +/// `#[target_feature]`, however, this macro does not support names separated +/// with a comma. Instead testing for multiple features must be done through +/// separate macro invocations for now. +/// +/// Supported arguments are: +/// +/// * `"aes"` +/// * `"pclmulqdq"` +/// * `"rdrand"` +/// * `"rdseed"` +/// * `"tsc"` +/// * `"mmx"` +/// * `"sse"` +/// * `"sse2"` +/// * `"sse3"` +/// * `"ssse3"` +/// * `"sse4.1"` +/// * `"sse4.2"` +/// * `"sse4a"` +/// * `"sha"` +/// * `"avx"` +/// * `"avx2"` +/// * `"avx512f"` +/// * `"avx512cd"` +/// * `"avx512er"` +/// * `"avx512pf"` +/// * `"avx512bw"` +/// * `"avx512dq"` +/// * `"avx512vl"` +/// * `"avx512ifma"` +/// * `"avx512vbmi"` +/// * `"avx512vpopcntdq"` +/// * `"f16c"` +/// * `"fma"` +/// * `"bmi1"` +/// * `"bmi2"` +/// * `"abm"` +/// * `"lzcnt"` +/// * `"tbm"` +/// * `"popcnt"` +/// * `"fxsr"` +/// * `"xsave"` +/// * `"xsaveopt"` +/// * `"xsaves"` +/// * `"xsavec"` +/// * `"adx"` +/// * `"rtm"` +/// +/// [docs]: https://software.intel.com/sites/landingpage/IntrinsicsGuide +#[macro_export] +#[stable(feature = "simd_x86", since = "1.27.0")] +#[allow_internal_unstable(stdsimd_internal, stdsimd)] +macro_rules! is_x86_feature_detected { + ("aes") => { + cfg!(target_feature = "aes") || $crate::detect::check_for($crate::detect::Feature::aes) + }; + ("pclmulqdq") => { + cfg!(target_feature = "pclmulqdq") + || $crate::detect::check_for($crate::detect::Feature::pclmulqdq) + }; + ("rdrand") => { + cfg!(target_feature = "rdrand") + || $crate::detect::check_for($crate::detect::Feature::rdrand) + }; + ("rdseed") => { + cfg!(target_feature = "rdseed") + || $crate::detect::check_for($crate::detect::Feature::rdseed) + }; + ("tsc") => { + cfg!(target_feature = "tsc") || $crate::detect::check_for($crate::detect::Feature::tsc) + }; + ("mmx") => { + cfg!(target_feature = "mmx") || $crate::detect::check_for($crate::detect::Feature::mmx) + }; + ("sse") => { + cfg!(target_feature = "sse") || $crate::detect::check_for($crate::detect::Feature::sse) + }; + ("sse2") => { + cfg!(target_feature = "sse2") || $crate::detect::check_for($crate::detect::Feature::sse2) + }; + ("sse3") => { + cfg!(target_feature = "sse3") || $crate::detect::check_for($crate::detect::Feature::sse3) + }; + ("ssse3") => { + cfg!(target_feature = "ssse3") || $crate::detect::check_for($crate::detect::Feature::ssse3) + }; + ("sse4.1") => { + cfg!(target_feature = "sse4.1") + || $crate::detect::check_for($crate::detect::Feature::sse4_1) + }; + ("sse4.2") => { + cfg!(target_feature = "sse4.2") + || $crate::detect::check_for($crate::detect::Feature::sse4_2) + }; + ("sse4a") => { + cfg!(target_feature = "sse4a") || $crate::detect::check_for($crate::detect::Feature::sse4a) + }; + ("sha") => { + cfg!(target_feature = "sha") || $crate::detect::check_for($crate::detect::Feature::sha) + }; + ("avx") => { + cfg!(target_feature = "avx") || $crate::detect::check_for($crate::detect::Feature::avx) + }; + ("avx2") => { + cfg!(target_feature = "avx2") || $crate::detect::check_for($crate::detect::Feature::avx2) + }; + ("avx512f") => { + cfg!(target_feature = "avx512f") + || $crate::detect::check_for($crate::detect::Feature::avx512f) + }; + ("avx512cd") => { + cfg!(target_feature = "avx512cd") + || $crate::detect::check_for($crate::detect::Feature::avx512cd) + }; + ("avx512er") => { + cfg!(target_feature = "avx512er") + || $crate::detect::check_for($crate::detect::Feature::avx512er) + }; + ("avx512pf") => { + cfg!(target_feature = "avx512pf") + || $crate::detect::check_for($crate::detect::Feature::avx512pf) + }; + ("avx512bw") => { + cfg!(target_feature = "avx512bw") + || $crate::detect::check_for($crate::detect::Feature::avx512bw) + }; + ("avx512dq") => { + cfg!(target_feature = "avx512dq") + || $crate::detect::check_for($crate::detect::Feature::avx512dq) + }; + ("avx512vl") => { + cfg!(target_Feature = "avx512vl") + || $crate::detect::check_for($crate::detect::Feature::avx512vl) + }; + ("avx512ifma") => { + cfg!(target_feature = "avx512ifma") + || $crate::detect::check_for($crate::detect::Feature::avx512_ifma) + }; + ("avx512vbmi") => { + cfg!(target_feature = "avx512vbmi") + || $crate::detect::check_for($crate::detect::Feature::avx512_vbmi) + }; + ("avx512vpopcntdq") => { + cfg!(target_feature = "avx512vpopcntdq") + || $crate::detect::check_for($crate::detect::Feature::avx512_vpopcntdq) + }; + ("f16c") => { + cfg!(target_feature = "f16c") || $crate::detect::check_for($crate::detect::Feature::f16c) + }; + ("fma") => { + cfg!(target_feature = "fma") || $crate::detect::check_for($crate::detect::Feature::fma) + }; + ("bmi1") => { + cfg!(target_feature = "bmi1") || $crate::detect::check_for($crate::detect::Feature::bmi) + }; + ("bmi2") => { + cfg!(target_feature = "bmi2") || $crate::detect::check_for($crate::detect::Feature::bmi2) + }; + ("abm") => { + cfg!(target_feature = "abm") || $crate::detect::check_for($crate::detect::Feature::abm) + }; + ("lzcnt") => { + cfg!(target_feature = "lzcnt") || $crate::detect::check_for($crate::detect::Feature::abm) + }; + ("tbm") => { + cfg!(target_feature = "tbm") || $crate::detect::check_for($crate::detect::Feature::tbm) + }; + ("popcnt") => { + cfg!(target_feature = "popcnt") + || $crate::detect::check_for($crate::detect::Feature::popcnt) + }; + ("fxsr") => { + cfg!(target_feature = "fxsr") || $crate::detect::check_for($crate::detect::Feature::fxsr) + }; + ("xsave") => { + cfg!(target_feature = "xsave") || $crate::detect::check_for($crate::detect::Feature::xsave) + }; + ("xsaveopt") => { + cfg!(target_feature = "xsaveopt") + || $crate::detect::check_for($crate::detect::Feature::xsaveopt) + }; + ("xsaves") => { + cfg!(target_feature = "xsaves") + || $crate::detect::check_for($crate::detect::Feature::xsaves) + }; + ("xsavec") => { + cfg!(target_feature = "xsavec") + || $crate::detect::check_for($crate::detect::Feature::xsavec) + }; + ("cmpxchg16b") => { + cfg!(target_feature = "cmpxchg16b") + || $crate::detect::check_for($crate::detect::Feature::cmpxchg16b) + }; + ("adx") => { + cfg!(target_feature = "adx") || $crate::detect::check_for($crate::detect::Feature::adx) + }; + ("rtm") => { + cfg!(target_feature = "rtm") || $crate::detect::check_for($crate::detect::Feature::rtm) + }; + ($t:tt,) => { + is_x86_feature_detected!($t); + }; + ($t:tt) => { + compile_error!(concat!("unknown target feature: ", $t)) + }; +} + +/// X86 CPU Feature enum. Each variant denotes a position in a bitset for a +/// particular feature. +/// +/// This is an unstable implementation detail subject to change. +#[allow(non_camel_case_types)] +#[repr(u8)] +#[doc(hidden)] +#[unstable(feature = "stdsimd_internal", issue = "0")] +pub enum Feature { + /// AES (Advanced Encryption Standard New Instructions AES-NI) + aes, + /// CLMUL (Carry-less Multiplication) + pclmulqdq, + /// RDRAND + rdrand, + /// RDSEED + rdseed, + /// TSC (Time Stamp Counter) + tsc, + /// MMX + mmx, + /// SSE (Streaming SIMD Extensions) + sse, + /// SSE2 (Streaming SIMD Extensions 2) + sse2, + /// SSE3 (Streaming SIMD Extensions 3) + sse3, + /// SSSE3 (Supplemental Streaming SIMD Extensions 3) + ssse3, + /// SSE4.1 (Streaming SIMD Extensions 4.1) + sse4_1, + /// SSE4.2 (Streaming SIMD Extensions 4.2) + sse4_2, + /// SSE4a (Streaming SIMD Extensions 4a) + sse4a, + /// SHA + sha, + /// AVX (Advanced Vector Extensions) + avx, + /// AVX2 (Advanced Vector Extensions 2) + avx2, + /// AVX-512 F (Foundation) + avx512f, + /// AVX-512 CD (Conflict Detection Instructions) + avx512cd, + /// AVX-512 ER (Exponential and Reciprocal Instructions) + avx512er, + /// AVX-512 PF (Prefetch Instructions) + avx512pf, + /// AVX-512 BW (Byte and Word Instructions) + avx512bw, + /// AVX-512 DQ (Doubleword and Quadword) + avx512dq, + /// AVX-512 VL (Vector Length Extensions) + avx512vl, + /// AVX-512 IFMA (Integer Fused Multiply Add) + avx512_ifma, + /// AVX-512 VBMI (Vector Byte Manipulation Instructions) + avx512_vbmi, + /// AVX-512 VPOPCNTDQ (Vector Population Count Doubleword and + /// Quadword) + avx512_vpopcntdq, + /// F16C (Conversions between IEEE-754 `binary16` and `binary32` formats) + f16c, + /// FMA (Fused Multiply Add) + fma, + /// BMI1 (Bit Manipulation Instructions 1) + bmi, + /// BMI1 (Bit Manipulation Instructions 2) + bmi2, + /// ABM (Advanced Bit Manipulation) on AMD / LZCNT (Leading Zero + /// Count) on Intel + abm, + /// TBM (Trailing Bit Manipulation) + tbm, + /// POPCNT (Population Count) + popcnt, + /// FXSR (Floating-point context fast save and restor) + fxsr, + /// XSAVE (Save Processor Extended States) + xsave, + /// XSAVEOPT (Save Processor Extended States Optimized) + xsaveopt, + /// XSAVES (Save Processor Extended States Supervisor) + xsaves, + /// XSAVEC (Save Processor Extended States Compacted) + xsavec, + /// CMPXCH16B, a 16-byte compare-and-swap instruction + cmpxchg16b, + /// ADX, Intel ADX (Multi-Precision Add-Carry Instruction Extensions) + adx, + /// RTM, Intel (Restricted Transactional Memory) + rtm, +} |