DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (5b81998bb7ab)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/* compile-time and runtime tests for whether to use SSE instructions */

#ifndef mozilla_SSE_h_
#define mozilla_SSE_h_

// for definition of NS_COM_GLUE
#include "nscore.h"

/**
 * The public interface of this header consists of a set of macros and
 * functions for Intel CPU features.
 *
 * DETECTING ISA EXTENSIONS
 * ========================
 *
 * This header provides the following functions for determining whether the
 * current CPU supports a particular instruction set extension:
 *
 *    mozilla::supports_mmx
 *    mozilla::supports_sse
 *    mozilla::supports_sse2
 *    mozilla::supports_sse3
 *    mozilla::supports_ssse3
 *    mozilla::supports_sse4a
 *    mozilla::supports_sse4_1
 *    mozilla::supports_sse4_2
 *
 * If you're writing code using inline assembly, you should guard it with a
 * call to one of these functions.  For instance:
 *
 *   if (mozilla::supports_sse2()) {
 *     asm(" ... ");
 *   }
 *   else {
 *     ...
 *   }
 *
 * Note that these functions depend on cpuid intrinsics only available in gcc
 * 4.3 or later and MSVC 8.0 (Visual C++ 2005) or later, so they return false
 * in older compilers.  (This could be fixed by replacing the code with inline
 * assembly.)
 *
 *
 * USING INTRINSICS
 * ================
 *
 * This header also provides support for coding using CPU intrinsics.
 *
 * For each mozilla::supports_abc function, we define a MOZILLA_MAY_SUPPORT_ABC
 * macro which indicates that the target/compiler combination we're using is
 * compatible with the ABC extension.  For instance, x86_64 with MSVC 2003 is
 * compatible with SSE2 but not SSE3, since although there exist x86_64 CPUs
 * with SSE3 support, MSVC 2003 only supports through SSE2.
 *
 * Until gcc fixes #pragma target [1] [2] or our x86 builds require SSE2,
 * you'll need to separate code using intrinsics into a file separate from your
 * regular code.  Here's the recommended pattern:
 *
 *  #ifdef MOZILLA_MAY_SUPPORT_ABC
 *    namespace mozilla {
 *      namespace ABC {
 *        void foo();
 *      }
 *    }
 *  #endif
 *
 *  void foo() {
 *    #ifdef MOZILLA_MAY_SUPPORT_ABC
 *      if (mozilla::supports_abc()) {
 *        mozilla::ABC::foo(); // in a separate file
 *        return;
 *      }
 *    #endif
 *
 *    foo_unvectorized();
 *  }
 *
 * You'll need to define mozilla::ABC::foo() in a separate file and add the
 * -mabc flag when using gcc.
 *
 * [1] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39787 and
 * [2] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41201 being fixed.
 *
 */

#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))

#ifdef __MMX__
  // It's ok to use MMX instructions based on the -march option (or
  // the default for x86_64 or for Intel Mac).
  #define MOZILLA_PRESUME_MMX 1
#endif
#ifdef __SSE__
  // It's ok to use SSE instructions based on the -march option (or
  // the default for x86_64 or for Intel Mac).
  #define MOZILLA_PRESUME_SSE 1
#endif
#ifdef __SSE2__
  // It's ok to use SSE2 instructions based on the -march option (or
  // the default for x86_64 or for Intel Mac).
  #define MOZILLA_PRESUME_SSE2 1
#endif
#ifdef __SSE3__
  // It's ok to use SSE3 instructions based on the -march option (or the
  // default for Intel Mac).
  #define MOZILLA_PRESUME_SSE3 1
#endif
#ifdef __SSSE3__
  // It's ok to use SSSE3 instructions based on the -march option.
  #define MOZILLA_PRESUME_SSSE3 1
#endif
#ifdef __SSE4A__
  // It's ok to use SSE4A instructions based on the -march option.
  #define MOZILLA_PRESUME_SSE4A 1
#endif
#ifdef __SSE4_1__
  // It's ok to use SSE4.1 instructions based on the -march option.
  #define MOZILLA_PRESUME_SSE4_1 1
#endif
#ifdef __SSE4_2__
  // It's ok to use SSE4.2 instructions based on the -march option.
  #define MOZILLA_PRESUME_SSE4_2 1
#endif

#ifdef HAVE_CPUID_H
  #define MOZILLA_SSE_HAVE_CPUID_DETECTION
#endif

#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64))

#define MOZILLA_SSE_HAVE_CPUID_DETECTION

#if defined(_M_IX86_FP)

#if _M_IX86_FP >= 1
  // It's ok to use SSE instructions based on the /arch option
  #define MOZILLA_PRESUME_SSE
#endif
#if _M_IX86_FP >= 2
  // It's ok to use SSE2 instructions based on the /arch option
  #define MOZILLA_PRESUME_SSE2
#endif

#elif defined(_M_AMD64)
  // MSVC for AMD64 doesn't support MMX, so don't presume it here.

  // SSE is always available on AMD64.
  #define MOZILLA_PRESUME_SSE
  // SSE2 is always available on AMD64.
  #define MOZILLA_PRESUME_SSE2
#endif

#elif defined(__SUNPRO_CC) && (defined(__i386) || defined(__x86_64__))
// Sun Studio on x86 or amd64

#define MOZILLA_SSE_HAVE_CPUID_DETECTION

#if defined(__x86_64__)
  // MMX is always available on AMD64.
  #define MOZILLA_PRESUME_MMX
  // SSE is always available on AMD64.
  #define MOZILLA_PRESUME_SSE
  // SSE2 is always available on AMD64.
  #define MOZILLA_PRESUME_SSE2
#endif

#endif

namespace mozilla {

  namespace sse_private {
#if defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
#if !defined(MOZILLA_PRESUME_MMX)
    extern bool NS_COM_GLUE mmx_enabled;
#endif
#if !defined(MOZILLA_PRESUME_SSE)
    extern bool NS_COM_GLUE sse_enabled;
#endif
#if !defined(MOZILLA_PRESUME_SSE2)
    extern bool NS_COM_GLUE sse2_enabled;
#endif
#if !defined(MOZILLA_PRESUME_SSE3)
    extern bool NS_COM_GLUE sse3_enabled;
#endif
#if !defined(MOZILLA_PRESUME_SSSE3)
    extern bool NS_COM_GLUE ssse3_enabled;
#endif
#if !defined(MOZILLA_PRESUME_SSE4A)
    extern bool NS_COM_GLUE sse4a_enabled;
#endif
#if !defined(MOZILLA_PRESUME_SSE4_1)
    extern bool NS_COM_GLUE sse4_1_enabled;
#endif
#if !defined(MOZILLA_PRESUME_SSE4_2)
    extern bool NS_COM_GLUE sse4_2_enabled;
#endif
#endif
  }

#if defined(MOZILLA_PRESUME_MMX)
#define MOZILLA_MAY_SUPPORT_MMX 1
  inline bool supports_mmx() { return true; }
#elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
#if !(defined(_MSC_VER) && defined(_M_AMD64))
  // Define MOZILLA_MAY_SUPPORT_MMX only if we're not on MSVC for
  // AMD64, since that compiler doesn't support MMX.
#define MOZILLA_MAY_SUPPORT_MMX 1
#endif
  inline bool supports_mmx() { return sse_private::mmx_enabled; }
#else
  inline bool supports_mmx() { return false; }
#endif

#if defined(MOZILLA_PRESUME_SSE)
#define MOZILLA_MAY_SUPPORT_SSE 1
  inline bool supports_sse() { return true; }
#elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
#define MOZILLA_MAY_SUPPORT_SSE 1
  inline bool supports_sse() { return sse_private::sse_enabled; }
#else
  inline bool supports_sse() { return false; }
#endif

#if defined(MOZILLA_PRESUME_SSE2)
#define MOZILLA_MAY_SUPPORT_SSE2 1
  inline bool supports_sse2() { return true; }
#elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
#define MOZILLA_MAY_SUPPORT_SSE2 1
  inline bool supports_sse2() { return sse_private::sse2_enabled; }
#else
  inline bool supports_sse2() { return false; }
#endif

#if defined(MOZILLA_PRESUME_SSE3)
#define MOZILLA_MAY_SUPPORT_SSE3 1
  inline bool supports_sse3() { return true; }
#elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
#define MOZILLA_MAY_SUPPORT_SSE3 1
  inline bool supports_sse3() { return sse_private::sse3_enabled; }
#else
  inline bool supports_sse3() { return false; }
#endif

#if defined(MOZILLA_PRESUME_SSSE3)
#define MOZILLA_MAY_SUPPORT_SSSE3 1
  inline bool supports_ssse3() { return true; }
#elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
#define MOZILLA_MAY_SUPPORT_SSSE3 1
  inline bool supports_ssse3() { return sse_private::ssse3_enabled; }
#else
  inline bool supports_ssse3() { return false; }
#endif

#if defined(MOZILLA_PRESUME_SSE4A)
#define MOZILLA_MAY_SUPPORT_SSE4A 1
  inline bool supports_sse4a() { return true; }
#elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
#define MOZILLA_MAY_SUPPORT_SSE4A 1
  inline bool supports_sse4a() { return sse_private::sse4a_enabled; }
#else
  inline bool supports_sse4a() { return false; }
#endif

#if defined(MOZILLA_PRESUME_SSE4_1)
#define MOZILLA_MAY_SUPPORT_SSE4_1 1
  inline bool supports_sse4_1() { return true; }
#elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
#define MOZILLA_MAY_SUPPORT_SSE4_1 1
  inline bool supports_sse4_1() { return sse_private::sse4_1_enabled; }
#else
  inline bool supports_sse4_1() { return false; }
#endif

#if defined(MOZILLA_PRESUME_SSE4_2)
#define MOZILLA_MAY_SUPPORT_SSE4_2 1
  inline bool supports_sse4_2() { return true; }
#elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
#define MOZILLA_MAY_SUPPORT_SSE4_2 1
  inline bool supports_sse4_2() { return sse_private::sse4_2_enabled; }
#else
  inline bool supports_sse4_2() { return false; }
#endif

}

#endif /* !defined(mozilla_SSE_h_) */