tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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_) */