gccfeatures.h (8976B)
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 #ifndef __gccfeatures_dot_hpp 33 #define __gccfeatures_dot_hpp 34 35 #define R123_GNUC_VERSION (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__) 36 37 #if !defined(__x86_64__) && !defined(__i386__) && !defined(__powerpc__) && !defined(__arm__) && !defined(__aarch64__) && !defined(__s390x__) 38 # error "This code has only been tested on x86, powerpc and a few arm platforms." 39 #include <including_a_nonexistent_file_will_stop_some_compilers_from_continuing_with_a_hopeless_task> 40 { /* maybe an unbalanced brace will terminate the compilation */ 41 /* Feel free to try the Random123 library on other architectures by changing 42 the conditions that reach this error, but you should consider it a 43 porting exercise and expect to encounter bugs and deficiencies. 44 Please let the authors know of any successes (or failures). */ 45 #endif 46 47 #if defined(__powerpc__) && !defined(__clang__) 48 #include <ppu_intrinsics.h> 49 #endif 50 51 #ifndef R123_STATIC_INLINE 52 #define R123_STATIC_INLINE static __inline__ 53 #endif 54 55 #ifndef R123_FORCE_INLINE 56 #if R123_GNUC_VERSION >= 40000 57 #define R123_FORCE_INLINE(decl) decl __attribute__((always_inline)) 58 #else 59 #define R123_FORCE_INLINE(decl) decl 60 #endif 61 #endif 62 63 #ifndef R123_CUDA_DEVICE 64 #define R123_CUDA_DEVICE 65 #endif 66 67 #ifndef R123_ASSERT 68 #include <assert.h> 69 #define R123_ASSERT(x) assert(x) 70 #endif 71 72 #ifndef R123_BUILTIN_EXPECT 73 #define R123_BUILTIN_EXPECT(expr,likely) __builtin_expect(expr,likely) 74 #endif 75 76 /* According to the C++0x standard, we should be able to test the numeric 77 value of __cplusplus == 199701L for C++98, __cplusplus == 201103L for C++11 78 But gcc has had an open bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=1773 79 since early 2001, which was finally fixed in 4.7 (early 2012). For 80 earlier versions, the only way to detect whether --std=c++0x was requested 81 on the command line is to look at the __GCC_EXPERIMENTAL_CXX0X__ pp-symbol. 82 */ 83 #if defined(__GCC_EXPERIMENTAL_CXX0X__) 84 #define GNU_CXX11 (__cplusplus>=201103L || (R123_GNUC_VERSION<40700 && 1/* defined(__GCC_EXPERIMENTAL_CXX0X__) */)) 85 #else 86 #define GNU_CXX11 (__cplusplus>=201103L || (R123_GNUC_VERSION<40700 && 0/* defined(__GCC_EXPERIMENTAL_CXX0X__) */)) 87 #endif 88 89 #ifndef R123_USE_CXX11_UNRESTRICTED_UNIONS 90 #define R123_USE_CXX11_UNRESTRICTED_UNIONS ((R123_GNUC_VERSION >= 40600) && GNU_CXX11) 91 #endif 92 93 #ifndef R123_USE_CXX11_STATIC_ASSERT 94 #define R123_USE_CXX11_STATIC_ASSERT ((R123_GNUC_VERSION >= 40300) && GNU_CXX11) 95 #endif 96 97 #ifndef R123_USE_CXX11_CONSTEXPR 98 #define R123_USE_CXX11_CONSTEXPR ((R123_GNUC_VERSION >= 40600) && GNU_CXX11) 99 #endif 100 101 #ifndef R123_USE_CXX11_EXPLICIT_CONVERSIONS 102 #define R123_USE_CXX11_EXPLICIT_CONVERSIONS ((R123_GNUC_VERSION >= 40500) && GNU_CXX11) 103 #endif 104 105 #ifndef R123_USE_CXX11_RANDOM 106 #define R123_USE_CXX11_RANDOM ((R123_GNUC_VERSION>=40500) && GNU_CXX11) 107 #endif 108 109 #ifndef R123_USE_CXX11_TYPE_TRAITS 110 #define R123_USE_CXX11_TYPE_TRAITS ((R123_GNUC_VERSION>=40400) && GNU_CXX11) 111 #endif 112 113 #ifndef R123_USE_AES_NI 114 #ifdef __AES__ 115 #define R123_USE_AES_NI 1 116 #else 117 #define R123_USE_AES_NI 0 118 #endif 119 #endif 120 121 #ifndef R123_USE_SSE4_2 122 #ifdef __SSE4_2__ 123 #define R123_USE_SSE4_2 1 124 #else 125 #define R123_USE_SSE4_2 0 126 #endif 127 #endif 128 129 #ifndef R123_USE_SSE4_1 130 #ifdef __SSE4_1__ 131 #define R123_USE_SSE4_1 1 132 #else 133 #define R123_USE_SSE4_1 0 134 #endif 135 #endif 136 137 #ifndef R123_USE_SSE 138 /* There's no point in trying to compile SSE code in Random123 139 unless SSE2 is available. */ 140 #ifdef __SSE2__ 141 #define R123_USE_SSE 1 142 #else 143 #define R123_USE_SSE 0 144 #endif 145 #endif 146 147 #ifndef R123_USE_AES_OPENSSL 148 /* There isn't really a good way to tell at compile time whether 149 openssl is available. Without a pre-compilation configure-like 150 tool, it's less error-prone to guess that it isn't available. Add 151 -DR123_USE_AES_OPENSSL=1 and any necessary LDFLAGS or LDLIBS to 152 play with openssl */ 153 #define R123_USE_AES_OPENSSL 0 154 #endif 155 156 #ifndef R123_USE_GNU_UINT128 157 #if defined(__x86_64__) || defined(__aarch64__) 158 #define R123_USE_GNU_UINT128 1 159 #else 160 #define R123_USE_GNU_UINT128 0 161 #endif 162 #endif 163 164 #ifndef R123_USE_ASM_GNU 165 #if (defined(__x86_64__)||defined(__i386__)) 166 #define R123_USE_ASM_GNU 1 167 #else 168 #define R123_USE_ASM_GNU 1 169 #endif 170 #endif 171 172 #ifndef R123_USE_CPUID_MSVC 173 #define R123_USE_CPUID_MSVC 0 174 #endif 175 176 #ifndef R123_USE_X86INTRIN_H 177 #if (defined(__x86_64__)||defined(__i386__)) 178 #define R123_USE_X86INTRIN_H (1/* (defined(__x86_64__)||defined(__i386__)) */ && R123_GNUC_VERSION >= 40402) 179 #else 180 #define R123_USE_X86INTRIN_H (0/* (defined(__x86_64__)||defined(__i386__)) */ && R123_GNUC_VERSION >= 40402) 181 #endif 182 #endif 183 184 #ifndef R123_USE_IA32INTRIN_H 185 #define R123_USE_IA32INTRIN_H 0 186 #endif 187 188 #ifndef R123_USE_XMMINTRIN_H 189 #define R123_USE_XMMINTRIN_H 0 190 #endif 191 192 #ifndef R123_USE_EMMINTRIN_H 193 /* gcc -m64 on Solaris 10 defines __SSE2__ but doesn't have 194 emmintrin.h in the include search path. This is 195 so broken that I refuse to try to work around it. If this 196 affects you, figure out where your emmintrin.h lives and 197 add an appropriate -I to your CPPFLAGS. Or add -DR123_USE_SSE=0. */ 198 #define R123_USE_EMMINTRIN_H (R123_USE_SSE && (R123_GNUC_VERSION < 40402)) 199 #endif 200 201 #ifndef R123_USE_SMMINTRIN_H 202 #define R123_USE_SMMINTRIN_H ((R123_USE_SSE4_1 || R123_USE_SSE4_2) && (R123_GNUC_VERSION < 40402)) 203 #endif 204 205 #ifndef R123_USE_WMMINTRIN_H 206 #define R123_USE_WMMINTRIN_H 0 207 #endif 208 209 #ifndef R123_USE_INTRIN_H 210 #define R123_USE_INTRIN_H 0 211 #endif 212 213 #ifndef R123_USE_MULHILO32_ASM 214 #define R123_USE_MULHILO32_ASM 0 215 #endif 216 217 #ifndef R123_USE_MULHILO64_MSVC_INTRIN 218 #define R123_USE_MULHILO64_MSVC_INTRIN 0 219 #endif 220 221 #ifndef R123_USE_MULHILO64_CUDA_INTRIN 222 #define R123_USE_MULHILO64_CUDA_INTRIN 0 223 #endif 224 225 #ifndef R123_USE_MULHILO64_OPENCL_INTRIN 226 #define R123_USE_MULHILO64_OPENCL_INTRIN 0 227 #endif 228 229 #ifndef R123_USE_MULHILO64_MULHI_INTRIN 230 #if (defined(__powerpc64__)) 231 #define R123_USE_MULHILO64_MULHI_INTRIN 1 232 #else 233 #define R123_USE_MULHILO64_MULHI_INTRIN 0 234 #endif 235 #endif 236 237 #ifndef R123_USE_MULHILO64_ASM 238 /* Shouldn't we use asm for mulhilo64 when the #ifdefs above haven't 239 chosen something else? Everything about the mulhilo64 240 implementation is so fragile and difficult to test that I'm 241 reluctant to make this change without a compelling reason, but this 242 seems preferable to just turning off USE_MULHILO64_ASM. 243 244 #define R123_USE_MULHILO64_ASM (R123_USE_ASM_GNU && (!R123_USE_GNU_UINT128) && (!R123_USE_MULHILO64_CUDA_INTRIN) && (!R123_USE_MULHILO64_MULHI_INTRIN) && (!R123_USE_MULHILO64_OPENCL_INTRIN) && (!R123_USE_MULHILO64_MSVC_INTRIN)) 245 */ 246 #define R123_USE_MULHILO64_ASM 0 247 #endif 248 249 #if defined(__powerpc__) && defined(__clang__) 250 #ifdef __powerpc64__ 251 static inline unsigned long long __mulhdu(unsigned long long a, unsigned long long b) { 252 __uint128_t c = (__uint128_t) a * (__uint128_t) b; 253 return c >> 64; 254 } 255 #endif 256 257 static inline unsigned int __mulhwu(unsigned int a, unsigned int b) { 258 unsigned long long c = (unsigned long long) a * (unsigned long long) b; 259 return c >> 32; 260 } 261 #endif 262 263 #ifndef R123_MULHILO64_MULHI_INTRIN 264 #define R123_MULHILO64_MULHI_INTRIN __mulhdu 265 #endif 266 267 #ifndef R123_USE_MULHILO32_MULHI_INTRIN 268 #define R123_USE_MULHILO32_MULHI_INTRIN 0 269 #endif 270 271 #ifndef R123_MULHILO32_MULHI_INTRIN 272 #define R123_MULHILO32_MULHI_INTRIN __mulhwu 273 #endif 274 275 #ifndef __STDC_CONSTANT_MACROS 276 #define __STDC_CONSTANT_MACROS 277 #endif 278 #include <stdint.h> 279 #ifndef UINT64_C 280 #error UINT64_C not defined. You must define __STDC_CONSTANT_MACROS before you #include <stdint.h> 281 #endif 282 283 /* If you add something, it must go in all the other XXfeatures.hpp 284 and in ../ut_features.cpp */ 285 #endif