| 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 | features! { |
| 19 | @TARGET: x86; |
| 20 | @CFG: any(target_arch = "x86" , target_arch = "x86_64" ); |
| 21 | @MACRO_NAME: is_x86_feature_detected; |
| 22 | @MACRO_ATTRS: |
| 23 | /// A macro to test at *runtime* whether a CPU feature is available on |
| 24 | /// x86/x86-64 platforms. |
| 25 | /// |
| 26 | /// This macro is provided in the standard library and will detect at runtime |
| 27 | /// whether the specified CPU feature is detected. This does **not** resolve at |
| 28 | /// compile time unless the specified feature is already enabled for the entire |
| 29 | /// crate. Runtime detection currently relies mostly on the `cpuid` instruction. |
| 30 | /// |
| 31 | /// This macro only takes one argument which is a string literal of the feature |
| 32 | /// being tested for. The feature names supported are the lowercase versions of |
| 33 | /// the ones defined by Intel in [their documentation][docs]. |
| 34 | /// |
| 35 | /// ## Supported arguments |
| 36 | /// |
| 37 | /// This macro supports the same names that `#[target_feature]` supports. Unlike |
| 38 | /// `#[target_feature]`, however, this macro does not support names separated |
| 39 | /// with a comma. Instead testing for multiple features must be done through |
| 40 | /// separate macro invocations for now. |
| 41 | /// |
| 42 | /// Supported arguments are: |
| 43 | /// |
| 44 | /// * `"aes"` |
| 45 | /// * `"pclmulqdq"` |
| 46 | /// * `"rdrand"` |
| 47 | /// * `"rdseed"` |
| 48 | /// * `"tsc"` |
| 49 | /// * `"mmx"` |
| 50 | /// * `"sse"` |
| 51 | /// * `"sse2"` |
| 52 | /// * `"sse3"` |
| 53 | /// * `"ssse3"` |
| 54 | /// * `"sse4.1"` |
| 55 | /// * `"sse4.2"` |
| 56 | /// * `"sse4a"` |
| 57 | /// * `"sha"` |
| 58 | /// * `"avx"` |
| 59 | /// * `"avx2"` |
| 60 | /// * `"sha512"` |
| 61 | /// * `"sm3"` |
| 62 | /// * `"sm4"` |
| 63 | /// * `"avx512f"` |
| 64 | /// * `"avx512cd"` |
| 65 | /// * `"avx512er"` |
| 66 | /// * `"avx512pf"` |
| 67 | /// * `"avx512bw"` |
| 68 | /// * `"avx512dq"` |
| 69 | /// * `"avx512vl"` |
| 70 | /// * `"avx512ifma"` |
| 71 | /// * `"avx512vbmi"` |
| 72 | /// * `"avx512vpopcntdq"` |
| 73 | /// * `"avx512vbmi2"` |
| 74 | /// * `"gfni"` |
| 75 | /// * `"vaes"` |
| 76 | /// * `"vpclmulqdq"` |
| 77 | /// * `"avx512vnni"` |
| 78 | /// * `"avx512bitalg"` |
| 79 | /// * `"avx512bf16"` |
| 80 | /// * `"avx512vp2intersect"` |
| 81 | /// * `"avx512fp16"` |
| 82 | /// * `"avxvnni"` |
| 83 | /// * `"avxifma"` |
| 84 | /// * `"avxneconvert"` |
| 85 | /// * `"avxvnniint8"` |
| 86 | /// * `"avxvnniint16"` |
| 87 | /// * `"amx-tile"` |
| 88 | /// * `"amx-int8"` |
| 89 | /// * `"amx-bf16"` |
| 90 | /// * `"amx-fp16"` |
| 91 | /// * `"amx-complex"` |
| 92 | /// * `"amx-avx512"` |
| 93 | /// * `"amx-fp8"` |
| 94 | /// * `"amx-movrs"` |
| 95 | /// * `"amx-tf32"` |
| 96 | /// * `"amx-transpose"` |
| 97 | /// * `"f16c"` |
| 98 | /// * `"fma"` |
| 99 | /// * `"bmi1"` |
| 100 | /// * `"bmi2"` |
| 101 | /// * `"abm"` |
| 102 | /// * `"lzcnt"` |
| 103 | /// * `"tbm"` |
| 104 | /// * `"popcnt"` |
| 105 | /// * `"fxsr"` |
| 106 | /// * `"xsave"` |
| 107 | /// * `"xsaveopt"` |
| 108 | /// * `"xsaves"` |
| 109 | /// * `"xsavec"` |
| 110 | /// * `"cmpxchg16b"` |
| 111 | /// * `"kl"` |
| 112 | /// * `"widekl"` |
| 113 | /// * `"adx"` |
| 114 | /// * `"rtm"` |
| 115 | /// * `"movbe"` |
| 116 | /// * `"ermsb"` |
| 117 | /// * `"movrs"` |
| 118 | /// * `"xop"` |
| 119 | /// |
| 120 | /// [docs]: https://software.intel.com/sites/landingpage/IntrinsicsGuide |
| 121 | #[stable (feature = "simd_x86" , since = "1.27.0" )] |
| 122 | @BIND_FEATURE_NAME: "abm" ; "lzcnt" ; // abm is a synonym for lzcnt |
| 123 | @BIND_FEATURE_NAME: "avx512gfni" ; "gfni" ; #[deprecated(since = "1.67.0" , note = "the `avx512gfni` feature has been renamed to `gfni`" )]; |
| 124 | @BIND_FEATURE_NAME: "avx512vaes" ; "vaes" ; #[deprecated(since = "1.67.0" , note = "the `avx512vaes` feature has been renamed to `vaes`" )]; |
| 125 | @BIND_FEATURE_NAME: "avx512vpclmulqdq" ; "vpclmulqdq" ; #[deprecated(since = "1.67.0" , note = "the `avx512vpclmulqdq` feature has been renamed to `vpclmulqdq`" )]; |
| 126 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] aes: "aes" ; |
| 127 | /// AES (Advanced Encryption Standard New Instructions AES-NI) |
| 128 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] pclmulqdq: "pclmulqdq" ; |
| 129 | /// CLMUL (Carry-less Multiplication) |
| 130 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] rdrand: "rdrand" ; |
| 131 | /// RDRAND |
| 132 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] rdseed: "rdseed" ; |
| 133 | /// RDSEED |
| 134 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] tsc: "tsc" ; |
| 135 | without cfg check: true; |
| 136 | /// TSC (Time Stamp Counter) |
| 137 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] mmx: "mmx" ; |
| 138 | without cfg check: true; |
| 139 | /// MMX (MultiMedia eXtensions) |
| 140 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] sse: "sse" ; |
| 141 | /// SSE (Streaming SIMD Extensions) |
| 142 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] sse2: "sse2" ; |
| 143 | /// SSE2 (Streaming SIMD Extensions 2) |
| 144 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] sse3: "sse3" ; |
| 145 | /// SSE3 (Streaming SIMD Extensions 3) |
| 146 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] ssse3: "ssse3" ; |
| 147 | /// SSSE3 (Supplemental Streaming SIMD Extensions 3) |
| 148 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] sse4_1: "sse4.1" ; |
| 149 | /// SSE4.1 (Streaming SIMD Extensions 4.1) |
| 150 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] sse4_2: "sse4.2" ; |
| 151 | /// SSE4.2 (Streaming SIMD Extensions 4.2) |
| 152 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] sse4a: "sse4a" ; |
| 153 | /// SSE4a (Streaming SIMD Extensions 4a) |
| 154 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] sha: "sha" ; |
| 155 | /// SHA |
| 156 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] avx: "avx" ; |
| 157 | /// AVX (Advanced Vector Extensions) |
| 158 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] avx2: "avx2" ; |
| 159 | /// AVX2 (Advanced Vector Extensions 2) |
| 160 | @FEATURE: #[stable (feature = "sha512_sm_x86" , since = "CURRENT_RUSTC_VERSION" )] sha512: "sha512" ; |
| 161 | /// SHA512 |
| 162 | @FEATURE: #[stable (feature = "sha512_sm_x86" , since = "CURRENT_RUSTC_VERSION" )] sm3: "sm3" ; |
| 163 | /// SM3 |
| 164 | @FEATURE: #[stable (feature = "sha512_sm_x86" , since = "CURRENT_RUSTC_VERSION" )] sm4: "sm4" ; |
| 165 | /// SM4 |
| 166 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] avx512f: "avx512f" ; |
| 167 | /// AVX-512 F (Foundation) |
| 168 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] avx512cd: "avx512cd" ; |
| 169 | /// AVX-512 CD (Conflict Detection Instructions) |
| 170 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] avx512er: "avx512er" ; |
| 171 | without cfg check: true; |
| 172 | /// AVX-512 ER (Expo nential and Reciprocal Instructions) |
| 173 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] avx512pf: "avx512pf" ; |
| 174 | without cfg check: true; |
| 175 | /// AVX-512 PF (Prefetch Instructions) |
| 176 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] avx512bw: "avx512bw" ; |
| 177 | /// AVX-512 BW (Byte and Word Instructions) |
| 178 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] avx512dq: "avx512dq" ; |
| 179 | /// AVX-512 DQ (Doubleword and Quadword) |
| 180 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] avx512vl: "avx512vl" ; |
| 181 | /// AVX-512 VL (Vector Length Extensions) |
| 182 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] avx512ifma: "avx512ifma" ; |
| 183 | /// AVX-512 IFMA (Integer Fused Multiply Add) |
| 184 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] avx512vbmi: "avx512vbmi" ; |
| 185 | /// AVX-512 VBMI (Vector Byte Manipulation Instructions) |
| 186 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] avx512vpopcntdq: "avx512vpopcntdq" ; |
| 187 | /// AVX-512 VPOPCNTDQ (Vector Population Count Doubleword and Quadword) |
| 188 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] avx512vbmi2: "avx512vbmi2" ; |
| 189 | /// AVX-512 VBMI2 (Additional byte, word, dword and qword capabilities) |
| 190 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] gfni: "gfni" ; |
| 191 | /// AVX-512 GFNI (Galois Field New Instruction) |
| 192 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] vaes: "vaes" ; |
| 193 | /// AVX-512 VAES (Vector AES instruction) |
| 194 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] vpclmulqdq: "vpclmulqdq" ; |
| 195 | /// AVX-512 VPCLMULQDQ (Vector PCLMULQDQ instructions) |
| 196 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] avx512vnni: "avx512vnni" ; |
| 197 | /// AVX-512 VNNI (Vector Neural Network Instructions) |
| 198 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] avx512bitalg: "avx512bitalg" ; |
| 199 | /// AVX-512 BITALG (Support for VPOPCNT\[B,W\] and VPSHUFBITQMB) |
| 200 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] avx512bf16: "avx512bf16" ; |
| 201 | /// AVX-512 BF16 (BFLOAT16 instructions) |
| 202 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] avx512vp2intersect: "avx512vp2intersect" ; |
| 203 | /// AVX-512 P2INTERSECT |
| 204 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] avx512fp16: "avx512fp16" ; |
| 205 | /// AVX-512 FP16 (FLOAT16 instructions) |
| 206 | @FEATURE: #[stable (feature = "avx512_target_feature" , since = "1.89.0" )] avxifma: "avxifma" ; |
| 207 | /// AVX-IFMA (Integer Fused Multiply Add) |
| 208 | @FEATURE: #[stable (feature = "avx512_target_feature" , since = "1.89.0" )] avxneconvert: "avxneconvert" ; |
| 209 | /// AVX-NE-CONVERT (Exceptionless Convert) |
| 210 | @FEATURE: #[stable (feature = "avx512_target_feature" , since = "1.89.0" )] avxvnni: "avxvnni" ; |
| 211 | /// AVX-VNNI (Vector Neural Network Instructions) |
| 212 | @FEATURE: #[stable (feature = "avx512_target_feature" , since = "1.89.0" )] avxvnniint16: "avxvnniint16" ; |
| 213 | /// AVX-VNNI_INT8 (VNNI with 16-bit Integers) |
| 214 | @FEATURE: #[stable (feature = "avx512_target_feature" , since = "1.89.0" )] avxvnniint8: "avxvnniint8" ; |
| 215 | /// AVX-VNNI_INT16 (VNNI with 8-bit integers) |
| 216 | @FEATURE: #[unstable (feature = "x86_amx_intrinsics" , issue = "126622" )] amx_tile: "amx-tile" ; |
| 217 | /// AMX (Advanced Matrix Extensions) - Tile load/store |
| 218 | @FEATURE: #[unstable (feature = "x86_amx_intrinsics" , issue = "126622" )] amx_int8: "amx-int8" ; |
| 219 | /// AMX-INT8 (Operations on 8-bit integers) |
| 220 | @FEATURE: #[unstable (feature = "x86_amx_intrinsics" , issue = "126622" )] amx_bf16: "amx-bf16" ; |
| 221 | /// AMX-BF16 (BFloat16 Operations) |
| 222 | @FEATURE: #[unstable (feature = "x86_amx_intrinsics" , issue = "126622" )] amx_fp16: "amx-fp16" ; |
| 223 | /// AMX-FP16 (Float16 Operations) |
| 224 | @FEATURE: #[unstable (feature = "x86_amx_intrinsics" , issue = "126622" )] amx_complex: "amx-complex" ; |
| 225 | /// AMX-COMPLEX (Complex number Operations) |
| 226 | @FEATURE: #[unstable (feature = "x86_amx_intrinsics" , issue = "126622" )] amx_avx512: "amx-avx512" ; |
| 227 | /// AMX-AVX512 (AVX512 operations extended to matrices) |
| 228 | @FEATURE: #[unstable (feature = "x86_amx_intrinsics" , issue = "126622" )] amx_fp8: "amx-fp8" ; |
| 229 | /// AMX-FP8 (Float8 Operations) |
| 230 | @FEATURE: #[unstable (feature = "x86_amx_intrinsics" , issue = "126622" )] amx_movrs: "amx-movrs" ; |
| 231 | /// AMX-MOVRS (Matrix MOVERS operations) |
| 232 | @FEATURE: #[unstable (feature = "x86_amx_intrinsics" , issue = "126622" )] amx_tf32: "amx-tf32" ; |
| 233 | /// AMX-TF32 (TensorFloat32 Operations) |
| 234 | @FEATURE: #[unstable (feature = "x86_amx_intrinsics" , issue = "126622" )] amx_transpose: "amx-transpose" ; |
| 235 | /// AMX-TRANSPOSE (Matrix Transpose Operations) |
| 236 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] f16c: "f16c" ; |
| 237 | /// F16C (Conversions between IEEE-754 `binary16` and `binary32` formats) |
| 238 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] fma: "fma" ; |
| 239 | /// FMA (Fused Multiply Add) |
| 240 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] bmi1: "bmi1" ; |
| 241 | /// BMI1 (Bit Manipulation Instructions 1) |
| 242 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] bmi2: "bmi2" ; |
| 243 | /// BMI2 (Bit Manipulation Instructions 2) |
| 244 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] lzcnt: "lzcnt" ; |
| 245 | /// ABM (Advanced Bit Manipulation) / LZCNT (Leading Zero Count) |
| 246 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] tbm: "tbm" ; |
| 247 | /// TBM (Trailing Bit Manipulation) |
| 248 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] popcnt: "popcnt" ; |
| 249 | /// POPCNT (Population Count) |
| 250 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] fxsr: "fxsr" ; |
| 251 | /// FXSR (Floating-point context fast save and restore) |
| 252 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] xsave: "xsave" ; |
| 253 | /// XSAVE (Save Processor Extended States) |
| 254 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] xsaveopt: "xsaveopt" ; |
| 255 | /// XSAVEOPT (Save Processor Extended States Optimized) |
| 256 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] xsaves: "xsaves" ; |
| 257 | /// XSAVES (Save Processor Extended States Supervisor) |
| 258 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] xsavec: "xsavec" ; |
| 259 | /// XSAVEC (Save Processor Extended States Compacted) |
| 260 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] cmpxchg16b: "cmpxchg16b" ; |
| 261 | /// CMPXCH16B (16-byte compare-and-swap instruction) |
| 262 | @FEATURE: #[stable (feature = "keylocker_x86" , since = "CURRENT_RUSTC_VERSION" )] kl: "kl" ; |
| 263 | /// Intel Key Locker |
| 264 | @FEATURE: #[stable (feature = "keylocker_x86" , since = "CURRENT_RUSTC_VERSION" )] widekl: "widekl" ; |
| 265 | /// Intel Key Locker Wide |
| 266 | @FEATURE: #[stable (feature = "simd_x86_adx" , since = "1.33.0" )] adx: "adx" ; |
| 267 | /// ADX, Intel ADX (Multi-Precision Add-Carry Instruction Extensions) |
| 268 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] rtm: "rtm" ; |
| 269 | /// RTM, Intel (Restricted Transactional Memory) |
| 270 | @FEATURE: #[stable (feature = "movbe_target_feature" , since = "1.67.0" )] movbe: "movbe" ; |
| 271 | /// MOVBE (Move Data After Swapping Bytes) |
| 272 | @FEATURE: #[unstable (feature = "movrs_target_feature" , issue = "137976" )] movrs: "movrs" ; |
| 273 | /// MOVRS (Move data with the read-shared hint) |
| 274 | @FEATURE: #[stable (feature = "simd_x86" , since = "1.27.0" )] ermsb: "ermsb" ; |
| 275 | /// ERMSB, Enhanced REP MOVSB and STOSB |
| 276 | @FEATURE: #[unstable (feature = "xop_target_feature" , issue = "127208" )] xop: "xop" ; |
| 277 | /// XOP: eXtended Operations (AMD) |
| 278 | } |
| 279 | |