SSE.h (14054B)
1 /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 /* compile-time and runtime tests for whether to use SSE instructions */ 7 8 #ifndef mozilla_SSE_h_ 9 #define mozilla_SSE_h_ 10 11 // for definition of MFBT_DATA 12 #include "mozilla/Types.h" 13 14 #include <cstdint> 15 16 /** 17 * The public interface of this header consists of a set of macros and 18 * functions for Intel CPU features. 19 * 20 * DETECTING ISA EXTENSIONS 21 * ======================== 22 * 23 * This header provides the following functions for determining whether the 24 * current CPU supports a particular instruction set extension: 25 * 26 * mozilla::supports_mmx 27 * mozilla::supports_sse 28 * mozilla::supports_sse2 29 * mozilla::supports_sse3 30 * mozilla::supports_ssse3 31 * mozilla::supports_sse4a 32 * mozilla::supports_sse4_1 33 * mozilla::supports_sse4_2 34 * mozilla::supports_avx 35 * mozilla::supports_avx2 36 * mozilla::supports_aes 37 * mozilla::supports_sha 38 * mozilla::supports_sha512 39 * mozilla::has_constant_tsc 40 * 41 * If you're writing code using inline assembly, you should guard it with a 42 * call to one of these functions. For instance: 43 * 44 * if (mozilla::supports_sse2()) { 45 * asm(" ... "); 46 * } 47 * else { 48 * ... 49 * } 50 * 51 * Note that these functions depend on cpuid intrinsics only available in gcc 52 * 4.3 or later and MSVC 8.0 (Visual C++ 2005) or later, so they return false 53 * in older compilers. (This could be fixed by replacing the code with inline 54 * assembly.) 55 * 56 * 57 * USING INTRINSICS 58 * ================ 59 * 60 * This header also provides support for coding using CPU intrinsics. 61 * 62 * For each mozilla::supports_abc function, we define a MOZILLA_MAY_SUPPORT_ABC 63 * macro which indicates that the target/compiler combination we're using is 64 * compatible with the ABC extension. For instance, x86_64 with MSVC 2003 is 65 * compatible with SSE2 but not SSE3, since although there exist x86_64 CPUs 66 * with SSE3 support, MSVC 2003 only supports through SSE2. 67 * 68 * Until gcc fixes #pragma target [1] [2] or our x86 builds require SSE2, 69 * you'll need to separate code using intrinsics into a file separate from your 70 * regular code. Here's the recommended pattern: 71 * 72 * #ifdef MOZILLA_MAY_SUPPORT_ABC 73 * namespace mozilla { 74 * namespace ABC { 75 * void foo(); 76 * } 77 * } 78 * #endif 79 * 80 * void foo() { 81 * #ifdef MOZILLA_MAY_SUPPORT_ABC 82 * if (mozilla::supports_abc()) { 83 * mozilla::ABC::foo(); // in a separate file 84 * return; 85 * } 86 * #endif 87 * 88 * foo_unvectorized(); 89 * } 90 * 91 * You'll need to define mozilla::ABC::foo() in a separate file and add the 92 * -mabc flag when using gcc. 93 * 94 * [1] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39787 and 95 * [2] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41201 being fixed. 96 * 97 */ 98 99 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) 100 101 # ifdef __MMX__ 102 // It's ok to use MMX instructions based on the -march option (or 103 // the default for x86_64 or for Intel Mac). 104 # define MOZILLA_PRESUME_MMX 1 105 # endif 106 # ifdef __SSE__ 107 // It's ok to use SSE instructions based on the -march option (or 108 // the default for x86_64 or for Intel Mac). 109 # define MOZILLA_PRESUME_SSE 1 110 # endif 111 # ifdef __SSE2__ 112 // It's ok to use SSE2 instructions based on the -march option (or 113 // the default for x86_64 or for Intel Mac). 114 # define MOZILLA_PRESUME_SSE2 1 115 # endif 116 # ifdef __SSE3__ 117 // It's ok to use SSE3 instructions based on the -march option (or the 118 // default for Intel Mac). 119 # define MOZILLA_PRESUME_SSE3 1 120 # endif 121 # ifdef __SSSE3__ 122 // It's ok to use SSSE3 instructions based on the -march option. 123 # define MOZILLA_PRESUME_SSSE3 1 124 # endif 125 # ifdef __SSE4A__ 126 // It's ok to use SSE4A instructions based on the -march option. 127 # define MOZILLA_PRESUME_SSE4A 1 128 # endif 129 # ifdef __SSE4_1__ 130 // It's ok to use SSE4.1 instructions based on the -march option. 131 # define MOZILLA_PRESUME_SSE4_1 1 132 # endif 133 # ifdef __SSE4_2__ 134 // It's ok to use SSE4.2 instructions based on the -march option. 135 # define MOZILLA_PRESUME_SSE4_2 1 136 # endif 137 # ifdef __AVX__ 138 // It's ok to use AVX instructions based on the -march option. 139 # define MOZILLA_PRESUME_AVX 1 140 # endif 141 # ifdef __AVX2__ 142 // It's ok to use AVX instructions based on the -march option. 143 # define MOZILLA_PRESUME_AVX2 1 144 # endif 145 # ifdef __AVXVNNI__ 146 // It's ok to use AVX instructions based on the -march option. 147 # define MOZILLA_PRESUME_AVXVNNI 1 148 # endif 149 # ifdef __AES__ 150 // It's ok to use AES instructions based on the -march option. 151 # define MOZILLA_PRESUME_AES 1 152 # endif 153 # ifdef __SHA__ 154 // It's ok to use SHA-1/SHA-256 instructions based on the -march option. 155 # define MOZILLA_PRESUME_SHA 1 156 # endif 157 # ifdef __SHA512__ 158 // It's ok to use SHA-512 instructions based on the -march option. 159 # define MOZILLA_PRESUME_SHA512 1 160 # endif 161 # ifdef __BMI__ 162 // It's ok to use BMI1 instructions based on the -march option. 163 # define MOZILLA_PRESUME_BMI 1 164 # endif 165 # ifdef __BMI2__ 166 // It's ok to use BMI2 instructions based on the -march option. 167 # define MOZILLA_PRESUME_BMI2 1 168 # endif 169 170 # ifdef HAVE_CPUID_H 171 # define MOZILLA_SSE_HAVE_CPUID_DETECTION 172 # endif 173 174 #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64)) 175 176 # define MOZILLA_SSE_HAVE_CPUID_DETECTION 177 178 # if defined(_M_IX86_FP) 179 180 # if _M_IX86_FP >= 1 181 // It's ok to use SSE instructions based on the /arch option 182 # define MOZILLA_PRESUME_SSE 183 # endif 184 # if _M_IX86_FP >= 2 185 // It's ok to use SSE2 instructions based on the /arch option 186 # define MOZILLA_PRESUME_SSE2 187 # endif 188 189 # elif defined(_M_AMD64) 190 // MSVC for AMD64 doesn't support MMX, so don't presume it here. 191 192 // SSE is always available on AMD64. 193 # define MOZILLA_PRESUME_SSE 194 // SSE2 is always available on AMD64. 195 # define MOZILLA_PRESUME_SSE2 196 # endif 197 198 #elif defined(__SUNPRO_CC) && (defined(__i386) || defined(__x86_64__)) 199 // Sun Studio on x86 or amd64 200 201 # define MOZILLA_SSE_HAVE_CPUID_DETECTION 202 203 # if defined(__x86_64__) 204 // MMX is always available on AMD64. 205 # define MOZILLA_PRESUME_MMX 206 // SSE is always available on AMD64. 207 # define MOZILLA_PRESUME_SSE 208 // SSE2 is always available on AMD64. 209 # define MOZILLA_PRESUME_SSE2 210 # endif 211 212 #endif 213 214 namespace mozilla { 215 216 namespace sse_private { 217 #if defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) 218 # if !defined(MOZILLA_PRESUME_MMX) 219 extern bool MFBT_DATA mmx_enabled; 220 # endif 221 # if !defined(MOZILLA_PRESUME_SSE) 222 extern bool MFBT_DATA sse_enabled; 223 # endif 224 # if !defined(MOZILLA_PRESUME_SSE2) 225 extern bool MFBT_DATA sse2_enabled; 226 # endif 227 # if !defined(MOZILLA_PRESUME_SSE3) 228 extern bool MFBT_DATA sse3_enabled; 229 # endif 230 # if !defined(MOZILLA_PRESUME_SSSE3) 231 extern bool MFBT_DATA ssse3_enabled; 232 # endif 233 # if !defined(MOZILLA_PRESUME_SSE4A) 234 extern bool MFBT_DATA sse4a_enabled; 235 # endif 236 # if !defined(MOZILLA_PRESUME_SSE4_1) 237 extern bool MFBT_DATA sse4_1_enabled; 238 # endif 239 # if !defined(MOZILLA_PRESUME_SSE4_2) 240 extern bool MFBT_DATA sse4_2_enabled; 241 # endif 242 # if !defined(MOZILLA_PRESUME_FMA3) 243 extern bool MFBT_DATA fma3_enabled; 244 # endif 245 # if !defined(MOZILLA_PRESUME_AVX) 246 extern bool MFBT_DATA avx_enabled; 247 # endif 248 # if !defined(MOZILLA_PRESUME_AVX2) 249 extern bool MFBT_DATA avx2_enabled; 250 # endif 251 # if !defined(MOZILLA_PRESUME_AVXVNNI) 252 extern bool MFBT_DATA avxvnni_enabled; 253 # endif 254 # if !defined(MOZILLA_PRESUME_AES) 255 extern bool MFBT_DATA aes_enabled; 256 # endif 257 # if !defined(MOZILLA_PRESUME_SHA) 258 extern bool MFBT_DATA sha_enabled; 259 # endif 260 # if !defined(MOZILLA_PRESUME_SHA512) 261 extern bool MFBT_DATA sha512_enabled; 262 # endif 263 # if !defined(MOZILLA_PRESUME_BMI) 264 extern bool MFBT_DATA bmi_enabled; 265 # endif 266 # if !defined(MOZILLA_PRESUME_BMI2) 267 extern bool MFBT_DATA bmi2_enabled; 268 # endif 269 270 extern bool MFBT_DATA has_constant_tsc; 271 272 #endif 273 } // namespace sse_private 274 275 #ifdef HAVE_CPUID_H 276 MOZ_EXPORT uint64_t xgetbv(uint32_t xcr); 277 #endif 278 279 #if defined(MOZILLA_PRESUME_MMX) 280 # define MOZILLA_MAY_SUPPORT_MMX 1 281 inline bool supports_mmx() { return true; } 282 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) 283 # if !(defined(_MSC_VER) && defined(_M_AMD64)) 284 // Define MOZILLA_MAY_SUPPORT_MMX only if we're not on MSVC for 285 // AMD64, since that compiler doesn't support MMX. 286 # define MOZILLA_MAY_SUPPORT_MMX 1 287 # endif 288 inline bool supports_mmx() { return sse_private::mmx_enabled; } 289 #else 290 inline bool supports_mmx() { return false; } 291 #endif 292 293 #if defined(MOZILLA_PRESUME_SSE) 294 # define MOZILLA_MAY_SUPPORT_SSE 1 295 inline bool supports_sse() { return true; } 296 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) 297 # define MOZILLA_MAY_SUPPORT_SSE 1 298 inline bool supports_sse() { return sse_private::sse_enabled; } 299 #else 300 inline bool supports_sse() { return false; } 301 #endif 302 303 #if defined(MOZILLA_PRESUME_SSE2) 304 # define MOZILLA_MAY_SUPPORT_SSE2 1 305 inline bool supports_sse2() { return true; } 306 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) 307 # define MOZILLA_MAY_SUPPORT_SSE2 1 308 inline bool supports_sse2() { return sse_private::sse2_enabled; } 309 #else 310 inline bool supports_sse2() { return false; } 311 #endif 312 313 #if defined(MOZILLA_PRESUME_SSE3) 314 # define MOZILLA_MAY_SUPPORT_SSE3 1 315 inline bool supports_sse3() { return true; } 316 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) 317 # define MOZILLA_MAY_SUPPORT_SSE3 1 318 inline bool supports_sse3() { return sse_private::sse3_enabled; } 319 #else 320 inline bool supports_sse3() { return false; } 321 #endif 322 323 #if defined(MOZILLA_PRESUME_SSSE3) 324 # define MOZILLA_MAY_SUPPORT_SSSE3 1 325 inline bool supports_ssse3() { return true; } 326 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) 327 # define MOZILLA_MAY_SUPPORT_SSSE3 1 328 inline bool supports_ssse3() { return sse_private::ssse3_enabled; } 329 #else 330 inline bool supports_ssse3() { return false; } 331 #endif 332 333 #if defined(MOZILLA_PRESUME_SSE4A) 334 # define MOZILLA_MAY_SUPPORT_SSE4A 1 335 inline bool supports_sse4a() { return true; } 336 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) 337 # define MOZILLA_MAY_SUPPORT_SSE4A 1 338 inline bool supports_sse4a() { return sse_private::sse4a_enabled; } 339 #else 340 inline bool supports_sse4a() { return false; } 341 #endif 342 343 #if defined(MOZILLA_PRESUME_SSE4_1) 344 # define MOZILLA_MAY_SUPPORT_SSE4_1 1 345 inline bool supports_sse4_1() { return true; } 346 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) 347 # define MOZILLA_MAY_SUPPORT_SSE4_1 1 348 inline bool supports_sse4_1() { return sse_private::sse4_1_enabled; } 349 #else 350 inline bool supports_sse4_1() { return false; } 351 #endif 352 353 #if defined(MOZILLA_PRESUME_SSE4_2) 354 # define MOZILLA_MAY_SUPPORT_SSE4_2 1 355 inline bool supports_sse4_2() { return true; } 356 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) 357 # define MOZILLA_MAY_SUPPORT_SSE4_2 1 358 inline bool supports_sse4_2() { return sse_private::sse4_2_enabled; } 359 #else 360 inline bool supports_sse4_2() { return false; } 361 #endif 362 363 #if defined(MOZILLA_PRESUME_FMA3) 364 # define MOZILLA_MAY_SUPPORT_FMA3 1 365 inline bool supports_fma3() { return true; } 366 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) 367 # define MOZILLA_MAY_SUPPORT_FMA3 1 368 inline bool supports_fma3() { return sse_private::fma3_enabled; } 369 #else 370 inline bool supports_fma3() { return false; } 371 #endif 372 373 #if defined(MOZILLA_PRESUME_AVX) 374 # define MOZILLA_MAY_SUPPORT_AVX 1 375 inline bool supports_avx() { return true; } 376 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) 377 # define MOZILLA_MAY_SUPPORT_AVX 1 378 inline bool supports_avx() { return sse_private::avx_enabled; } 379 #else 380 inline bool supports_avx() { return false; } 381 #endif 382 383 #if defined(MOZILLA_PRESUME_AVX2) 384 # define MOZILLA_MAY_SUPPORT_AVX2 1 385 inline bool supports_avx2() { return true; } 386 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) 387 # define MOZILLA_MAY_SUPPORT_AVX2 1 388 inline bool supports_avx2() { return sse_private::avx2_enabled; } 389 #else 390 inline bool supports_avx2() { return false; } 391 #endif 392 393 #if defined(MOZILLA_PRESUME_AVXVNNI) 394 # define MOZILLA_MAY_SUPPORT_AVXVNNI 1 395 inline bool supports_avxvnni() { return true; } 396 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) 397 # define MOZILLA_MAY_SUPPORT_AVXVNNI 1 398 inline bool supports_avxvnni() { return sse_private::avxvnni_enabled; } 399 #else 400 inline bool supports_avxvnni() { return false; } 401 #endif 402 403 #if defined(MOZILLA_PRESUME_AES) 404 # define MOZILLA_MAY_SUPPORT_AES 1 405 inline bool supports_aes() { return true; } 406 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) 407 # define MOZILLA_MAY_SUPPORT_AES 1 408 inline bool supports_aes() { return sse_private::aes_enabled; } 409 #else 410 inline bool supports_aes() { return false; } 411 #endif 412 413 #if defined(MOZILLA_PRESUME_SHA) 414 # define MOZILLA_MAY_SUPPORT_SHA 1 415 inline bool supports_sha() { return true; } 416 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) 417 # define MOZILLA_MAY_SUPPORT_SHA 1 418 inline bool supports_sha() { return sse_private::sha_enabled; } 419 #else 420 inline bool supports_sha() { return false; } 421 #endif 422 423 #if defined(MOZILLA_PRESUME_SHA512) 424 # define MOZILLA_MAY_SUPPORT_SHA512 1 425 inline bool supports_sha512() { return true; } 426 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) 427 # define MOZILLA_MAY_SUPPORT_SHA512 1 428 inline bool supports_sha512() { return sse_private::sha512_enabled; } 429 #else 430 inline bool supports_sha512() { return false; } 431 #endif 432 433 #if defined(MOZILLA_PRESUME_BMI) 434 # define MOZILLA_MAY_SUPPORT_BMI 1 435 inline bool supports_bmi() { return true; } 436 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) 437 # define MOZILLA_MAY_SUPPORT_BMI 1 438 inline bool supports_bmi() { return sse_private::bmi_enabled; } 439 #else 440 inline bool supports_bmi() { return false; } 441 #endif 442 443 #if defined(MOZILLA_PRESUME_BMI2) 444 # define MOZILLA_MAY_SUPPORT_BMI2 1 445 inline bool supports_bmi2() { return true; } 446 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) 447 # define MOZILLA_MAY_SUPPORT_BMI2 1 448 inline bool supports_bmi2() { return sse_private::bmi2_enabled; } 449 #else 450 inline bool supports_bmi2() { return false; } 451 #endif 452 453 #ifdef MOZILLA_SSE_HAVE_CPUID_DETECTION 454 inline bool has_constant_tsc() { return sse_private::has_constant_tsc; } 455 #else 456 inline bool has_constant_tsc() { return false; } 457 #endif 458 459 } // namespace mozilla 460 461 #endif /* !defined(mozilla_SSE_h_) */