compilerfeatures.h (11662B)
1 /* 2 Copyright 2010-2011, D. E. Shaw Research. 3 All rights reserved. 4 5 Redistribution and use in source and binary forms, with or without 6 modification, are permitted provided that the following conditions are 7 met: 8 9 * Redistributions of source code must retain the above copyright 10 notice, this list of conditions, and the following disclaimer. 11 12 * Redistributions in binary form must reproduce the above copyright 13 notice, this list of conditions, and the following disclaimer in the 14 documentation and/or other materials provided with the distribution. 15 16 * Neither the name of D. E. Shaw Research nor the names of its 17 contributors may be used to endorse or promote products derived from 18 this software without specific prior written permission. 19 20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 /** 33 34 @page porting Preprocessor symbols for porting Random123 to different platforms. 35 36 The Random123 library is portable across C, C++, CUDA, OpenCL environments, 37 and multiple operating systems (Linux, Windows 7, Mac OS X, FreeBSD, Solaris). 38 This level of portability requires the abstraction of some features 39 and idioms that are either not standardized (e.g., asm statments), or for which 40 different vendors have their own standards (e.g., SSE intrinsics) or for 41 which vendors simply refuse to conform to well-established standards (e.g., <inttypes.h>). 42 43 Random123/features/compilerfeatures.h 44 conditionally includes a compiler-or-OS-specific Random123/featires/XXXfeatures.h file which 45 defines appropriate values for the preprocessor symbols which can be used with 46 a specific compiler or OS. Those symbols will then 47 be used by other header files and source files in the Random123 48 library (and may be used by applications) to control what actually 49 gets presented to the compiler. 50 51 Most of the symbols are boolean valued. In general, they will 52 \b always be defined with value either 1 or 0, so do 53 \b NOT use \#ifdef. Use \#if R123_USE_SOMETHING instead. 54 55 Library users can override any value by defining the pp-symbol with a compiler option, 56 e.g., 57 58 cc -DR123_USE_MULHILO64_C99 59 60 will use a strictly c99 version of the full-width 64x64->128-bit multiplication 61 function, even if it would be disabled by default. 62 63 All boolean-valued pre-processor symbols in Random123/features/compilerfeatures.h start with the prefix R123_USE_ 64 @verbatim 65 AES_NI 66 AES_OPENSSL 67 SSE4_2 68 SSE4_1 69 SSE 70 71 STD_RANDOM 72 73 GNU_UINT128 74 ASM_GNU 75 ASM_MSASM 76 77 CPUID_MSVC 78 79 CXX11_RANDOM 80 CXX11_TYPE_TRAITS 81 CXX11_STATIC_ASSERT 82 CXX11_CONSTEXPR 83 CXX11_UNRESTRICTED_UNIONS 84 CXX11_EXPLICIT_CONVERSIONS 85 CXX11_LONG_LONG 86 CXX11_STD_ARRAY 87 CXX11 88 89 X86INTRIN_H 90 IA32INTRIN_H 91 XMMINTRIN_H 92 EMMINTRIN_H 93 SMMINTRIN_H 94 WMMINTRIN_H 95 INTRIN_H 96 97 MULHILO32_ASM 98 MULHILO64_ASM 99 MULHILO64_MSVC_INTRIN 100 MULHILO64_CUDA_INTRIN 101 MULHILO64_OPENCL_INTRIN 102 MULHILO64_C99 103 104 U01_DOUBLE 105 106 @endverbatim 107 Most have obvious meanings. Some non-obvious ones: 108 109 AES_NI and AES_OPENSSL are not mutually exclusive. You can have one, 110 both or neither. 111 112 GNU_UINT128 says that it's safe to use __uint128_t, but it 113 does not require its use. In particular, it should be 114 used in mulhilo<uint64_t> only if MULHILO64_ASM is unset. 115 116 If the XXXINTRIN_H macros are true, then one should 117 @code 118 #include <xxxintrin.h> 119 @endcode 120 to gain accesss to compiler intrinsics. 121 122 The CXX11_SOME_FEATURE macros allow the code to use specific 123 features of the C++11 language and library. The catchall 124 In the absence of a specific CXX11_SOME_FEATURE, the feature 125 is controlled by the catch-all R123_USE_CXX11 macro. 126 127 U01_DOUBLE defaults on, and can be turned off (set to 0) 128 if one does not want the utility functions that convert to double 129 (i.e. u01_*_53()), e.g. on OpenCL without the cl_khr_fp64 extension. 130 131 There are a number of invariants that are always true. Application code may 132 choose to rely on these: 133 134 <ul> 135 <li>ASM_GNU and ASM_MASM are mutually exclusive 136 <li>The "higher" SSE values imply the lower ones. 137 </ul> 138 139 There are also non-boolean valued symbols: 140 141 <ul> 142 <li>R123_STATIC_INLINE - 143 According to both C99 and GNU99, the 'static inline' declaration allows 144 the compiler to not emit code if the function is not used. 145 Note that the semantics of 'inline', 'static' and 'extern' in 146 gcc have changed over time and are subject to modification by 147 command line options, e.g., -std=gnu89, -fgnu-inline. 148 Nevertheless, it appears that the meaning of 'static inline' 149 has not changed over time and (with a little luck) the use of 'static inline' 150 here will be portable between versions of gcc and to other C99 151 compilers. 152 See: http://gcc.gnu.org/onlinedocs/gcc/Inline.html 153 http://www.greenend.org.uk/rjk/2003/03/inline.html 154 155 <li>R123_FORCE_INLINE(decl) - 156 which expands to 'decl', adorned with the compiler-specific 157 embellishments to strongly encourage that the declared function be 158 inlined. If there is no such compiler-specific magic, it should 159 expand to decl, unadorned. 160 161 <li>R123_CUDA_DEVICE - which expands to __device__ (or something else with 162 sufficiently similar semantics) when CUDA is in use, and expands 163 to nothing in other cases. 164 165 <li>R123_METAL_THREAD_ADDRESS_SPACE - which expands to 'thread' (or 166 something else with sufficiently similar semantics) when compiling a 167 Metal kernel, and expands to nothing in other cases. 168 169 <li>R123_ASSERT(x) - which expands to assert(x), or maybe to nothing at 170 all if we're in an environment so feature-poor that you can't even 171 call assert (I'm looking at you, CUDA and OpenCL), or even include 172 assert.h safely (OpenCL). 173 174 <li>R123_STATIC_ASSERT(expr,msg) - which expands to 175 static_assert(expr,msg), or to an expression that 176 will raise a compile-time exception if expr is not true. 177 178 <li>R123_ULONG_LONG - which expands to a declaration of the longest available 179 unsigned integer. 180 181 <li>R123_64BIT(x) - expands to something equivalent to 182 UINT64_C(x) from <stdint.h>, even in environments where <stdint.h> 183 is not available, e.g., MSVC and OpenCL. 184 185 <li>R123_BUILTIN_EXPECT(expr,likely_value) - expands to something with 186 the semantics of gcc's __builtin_expect(expr,likely_value). If 187 the environment has nothing like __builtin_expect, it should expand 188 to just expr. 189 </ul> 190 191 192 \cond HIDDEN_FROM_DOXYGEN 193 */ 194 195 /* 196 N.B. When something is added to the list of features, it should be 197 added to each of the *features.h files, AND to examples/ut_features.cpp. 198 */ 199 200 /* N.B. most other compilers (icc, nvcc, open64, llvm) will also define __GNUC__, so order matters. */ 201 #if defined(__METAL_MACOS__) 202 #include "metalfeatures.h" 203 #elif defined(__OPENCL_VERSION__) && __OPENCL_VERSION__ > 0 204 #include "openclfeatures.h" 205 #elif defined(__CUDACC__) 206 #include "nvccfeatures.h" 207 #elif defined(__ICC) 208 #include "iccfeatures.h" 209 #elif defined(__xlC__) || defined(__ibmxl__) 210 #include "xlcfeatures.h" 211 #elif defined(__PGI) 212 #include "pgccfeatures.h" 213 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) 214 #include "sunprofeatures.h" 215 #elif defined(__OPEN64__) 216 #include "open64features.h" 217 #elif defined(__clang__) || defined(__bgclang__) 218 #include "clangfeatures.h" 219 #elif defined(__FCC_VERSION) || defined(__FUJITSU) 220 #include "fujitsufeatures.h" 221 #elif defined(__GNUC__) 222 #include "gccfeatures.h" 223 #elif defined(_MSC_FULL_VER) 224 #include "msvcfeatures.h" 225 #else 226 #error "Can't identify compiler. You'll need to add a new xxfeatures.hpp" 227 { /* maybe an unbalanced brace will terminate the compilation */ 228 #endif 229 230 #ifndef R123_USE_CXX11 231 #define R123_USE_CXX11 (__cplusplus >= 201103L) 232 #endif 233 234 #ifndef R123_USE_CXX11_UNRESTRICTED_UNIONS 235 #define R123_USE_CXX11_UNRESTRICTED_UNIONS R123_USE_CXX11 236 #endif 237 238 #ifndef R123_USE_CXX11_STATIC_ASSERT 239 #define R123_USE_CXX11_STATIC_ASSERT R123_USE_CXX11 240 #endif 241 242 #ifndef R123_USE_CXX11_CONSTEXPR 243 #define R123_USE_CXX11_CONSTEXPR R123_USE_CXX11 244 #endif 245 246 #ifndef R123_USE_CXX11_EXPLICIT_CONVERSIONS 247 #define R123_USE_CXX11_EXPLICIT_CONVERSIONS R123_USE_CXX11 248 #endif 249 250 #ifndef R123_USE_CXX11_RANDOM 251 #define R123_USE_CXX11_RANDOM R123_USE_CXX11 252 #endif 253 254 #ifndef R123_USE_CXX11_TYPE_TRAITS 255 #define R123_USE_CXX11_TYPE_TRAITS R123_USE_CXX11 256 #endif 257 258 #ifndef R123_USE_CXX11_LONG_LONG 259 #define R123_USE_CXX11_LONG_LONG R123_USE_CXX11 260 #endif 261 262 #ifndef R123_USE_CXX11_STD_ARRAY 263 #define R123_USE_CXX11_STD_ARRAY R123_USE_CXX11 264 #endif 265 266 #ifndef R123_USE_MULHILO64_C99 267 #define R123_USE_MULHILO64_C99 0 268 #endif 269 270 #ifndef R123_USE_MULHILO64_MULHI_INTRIN 271 #define R123_USE_MULHILO64_MULHI_INTRIN 0 272 #endif 273 274 #ifndef R123_USE_MULHILO32_MULHI_INTRIN 275 #define R123_USE_MULHILO32_MULHI_INTRIN 0 276 #endif 277 278 #ifndef R123_STATIC_ASSERT 279 #if R123_USE_CXX11_STATIC_ASSERT 280 #define R123_STATIC_ASSERT(expr, msg) static_assert(expr, msg) 281 #else 282 /* if msg always_looked_like_this, we could paste it into the name. Worth it? */ 283 #define R123_STATIC_ASSERT(expr, msg) typedef char static_assertion[(!!(expr))*2-1] 284 #endif 285 #endif 286 287 #ifndef R123_CONSTEXPR 288 #if R123_USE_CXX11_CONSTEXPR 289 #define R123_CONSTEXPR constexpr 290 #else 291 #define R123_CONSTEXPR 292 #endif 293 #endif 294 295 #ifndef R123_USE_64BIT 296 #define R123_USE_64BIT 1 297 #endif 298 299 #ifndef R123_USE_PHILOX_64BIT 300 #define R123_USE_PHILOX_64BIT (R123_USE_64BIT && (R123_USE_MULHILO64_ASM || R123_USE_MULHILO64_MSVC_INTRIN || R123_USE_MULHILO64_CUDA_INTRIN || R123_USE_GNU_UINT128 || R123_USE_MULHILO64_C99 || R123_USE_MULHILO64_OPENCL_INTRIN || R123_USE_MULHILO64_MULHI_INTRIN)) 301 #endif 302 303 #ifndef R123_ULONG_LONG 304 #if defined(__cplusplus) && !R123_USE_CXX11_LONG_LONG 305 /* C++98 doesn't have long long. It doesn't have uint64_t either, but 306 we will have typedef'ed uint64_t to something in the xxxfeatures.h. 307 With luck, it won't elicit complaints from -pedantic. Cross your 308 fingers... */ 309 #define R123_ULONG_LONG uint64_t 310 #else 311 #define R123_ULONG_LONG unsigned long long 312 #endif 313 #endif 314 315 /* UINT64_C should have been #defined by XXXfeatures.h, either by 316 #include <stdint.h> or through compiler-dependent hacks */ 317 #ifndef R123_64BIT 318 #define R123_64BIT(x) UINT64_C(x) 319 #endif 320 321 #ifndef R123_THROW 322 #define R123_THROW(x) throw (x) 323 #endif 324 325 #ifndef R123_METAL_THREAD_ADDRESS_SPACE 326 #define R123_METAL_THREAD_ADDRESS_SPACE 327 #endif 328 329 #ifndef R123_METAL_CONSTANT_ADDRESS_SPACE 330 #define R123_METAL_CONSTANT_ADDRESS_SPACE 331 #endif 332 333 /* 334 * Windows.h (and perhaps other "well-meaning" code define min and 335 * max, so there's a high chance that our definition of min, max 336 * methods or use of std::numeric_limits min and max will cause 337 * complaints in any program that happened to include Windows.h or 338 * suchlike first. We use the null macro below in our own header 339 * files definition or use of min, max to defensively preclude 340 * this problem. It may not be enough; one might need to #define 341 * NOMINMAX before including Windows.h or compile with -DNOMINMAX. 342 */ 343 #define R123_NO_MACRO_SUBST 344 345 /** \endcond */