NEURON
compilerfeatures.h
Go to the documentation of this file.
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
87 
88  X86INTRIN_H
89  IA32INTRIN_H
90  XMMINTRIN_H
91  EMMINTRIN_H
92  SMMINTRIN_H
93  WMMINTRIN_H
94  INTRIN_H
95 
96  MULHILO32_ASM
97  MULHILO64_ASM
98  MULHILO64_MSVC_INTRIN
99  MULHILO64_CUDA_INTRIN
100  MULHILO64_OPENCL_INTRIN
101  MULHILO64_C99
102 
103  U01_DOUBLE
104 
105 @endverbatim
106 Most have obvious meanings. Some non-obvious ones:
107 
108 AES_NI and AES_OPENSSL are not mutually exclusive. You can have one,
109 both or neither.
110 
111 GNU_UINT128 says that it's safe to use __uint128_t, but it
112 does not require its use. In particular, it should be
113 used in mulhilo<uint64_t> only if MULHILO64_ASM is unset.
114 
115 If the XXXINTRIN_H macros are true, then one should
116 @code
117 #include <xxxintrin.h>
118 @endcode
119 to gain accesss to compiler intrinsics.
120 
121 The CXX11_SOME_FEATURE macros allow the code to use specific
122 features of the C++11 language and library. The catchall
123 In the absence of a specific CXX11_SOME_FEATURE, the feature
124 is controlled by the catch-all R123_USE_CXX11 macro.
125 
126 U01_DOUBLE defaults on, and can be turned off (set to 0)
127 if one does not want the utility functions that convert to double
128 (i.e. u01_*_53()), e.g. on OpenCL without the cl_khr_fp64 extension.
129 
130 There are a number of invariants that are always true. Application code may
131 choose to rely on these:
132 
133 <ul>
134 <li>ASM_GNU and ASM_MASM are mutually exclusive
135 <li>The "higher" SSE values imply the lower ones.
136 </ul>
137 
138 There are also non-boolean valued symbols:
139 
140 <ul>
141 <li>R123_STATIC_INLINE -
142  According to both C99 and GNU99, the 'static inline' declaration allows
143  the compiler to not emit code if the function is not used.
144  Note that the semantics of 'inline', 'static' and 'extern' in
145  gcc have changed over time and are subject to modification by
146  command line options, e.g., -std=gnu89, -fgnu-inline.
147  Nevertheless, it appears that the meaning of 'static inline'
148  has not changed over time and (with a little luck) the use of 'static inline'
149  here will be portable between versions of gcc and to other C99
150  compilers.
151  See: http://gcc.gnu.org/onlinedocs/gcc/Inline.html
152  http://www.greenend.org.uk/rjk/2003/03/inline.html
153 
154 <li>R123_FORCE_INLINE(decl) -
155  which expands to 'decl', adorned with the compiler-specific
156  embellishments to strongly encourage that the declared function be
157  inlined. If there is no such compiler-specific magic, it should
158  expand to decl, unadorned.
159 
160 <li>R123_CUDA_DEVICE - which expands to __device__ (or something else with
161  sufficiently similar semantics) when CUDA is in use, and expands
162  to nothing in other cases.
163 
164 <li>R123_ASSERT(x) - which expands to assert(x), or maybe to nothing at
165  all if we're in an environment so feature-poor that you can't even
166  call assert (I'm looking at you, CUDA and OpenCL), or even include
167  assert.h safely (OpenCL).
168 
169 <li>R123_STATIC_ASSERT(expr,msg) - which expands to
170  static_assert(expr,msg), or to an expression that
171  will raise a compile-time exception if expr is not true.
172 
173 <li>R123_ULONG_LONG - which expands to a declaration of the longest available
174  unsigned integer.
175 
176 <li>R123_64BIT(x) - expands to something equivalent to
177  UINT64_C(x) from <stdint.h>, even in environments where <stdint.h>
178  is not available, e.g., MSVC and OpenCL.
179 
180 <li>R123_BUILTIN_EXPECT(expr,likely_value) - expands to something with
181  the semantics of gcc's __builtin_expect(expr,likely_value). If
182  the environment has nothing like __builtin_expect, it should expand
183  to just expr.
184 </ul>
185 
186 
187 \cond HIDDEN_FROM_DOXYGEN
188 */
189 
190 /*
191 N.B. When something is added to the list of features, it should be
192 added to each of the *features.h files, AND to examples/ut_features.cpp.
193 */
194 
195 /* N.B. most other compilers (icc, nvcc, open64, llvm) will also define __GNUC__, so order matters. */
196 #if defined(__METAL_MACOS__)
197 #include "metalfeatures.h"
198 #elif defined(__OPENCL_VERSION__) && __OPENCL_VERSION__ > 0
199 #include "openclfeatures.h"
200 #elif defined(__CUDACC__)
201 #include "nvccfeatures.h"
202 #elif defined(__ICC)
203 #include "iccfeatures.h"
204 #elif defined(__xlC__)
205 #include "xlcfeatures.h"
206 #elif defined(__PGI)
207 #include "pgccfeatures.h"
208 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
209 #include "sunprofeatures.h"
210 #elif defined(__OPEN64__)
211 #include "open64features.h"
212 #elif defined(__clang__) || defined(__bgclang__)
213 #include "clangfeatures.h"
214 #elif defined(_CRAYC)
215 #include "crayfeatures.h"
216 #elif defined(__FCC_VERSION) || defined(__FUJITSU)
217 #include "fujitsufeatures.h"
218 #elif defined(__GNUC__)
219 #include "gccfeatures.h"
220 #elif defined(_MSC_FULL_VER)
221 #include "msvcfeatures.h"
222 #else
223 #error "Can't identify compiler. You'll need to add a new xxfeatures.hpp"
224 { /* maybe an unbalanced brace will terminate the compilation */
225 #endif
226 
227 #ifndef R123_USE_CXX11
228 #define R123_USE_CXX11 (__cplusplus >= 201103L)
229 #endif
230 
231 #ifndef R123_USE_CXX11_UNRESTRICTED_UNIONS
232 #define R123_USE_CXX11_UNRESTRICTED_UNIONS R123_USE_CXX11
233 #endif
234 
235 #ifndef R123_USE_CXX11_STATIC_ASSERT
236 #define R123_USE_CXX11_STATIC_ASSERT R123_USE_CXX11
237 #endif
238 
239 #ifndef R123_USE_CXX11_CONSTEXPR
240 #define R123_USE_CXX11_CONSTEXPR R123_USE_CXX11
241 #endif
242 
243 #ifndef R123_USE_CXX11_EXPLICIT_CONVERSIONS
244 #define R123_USE_CXX11_EXPLICIT_CONVERSIONS R123_USE_CXX11
245 #endif
246 
247 #ifndef R123_USE_CXX11_RANDOM
248 #define R123_USE_CXX11_RANDOM R123_USE_CXX11
249 #endif
250 
251 #ifndef R123_USE_CXX11_TYPE_TRAITS
252 #define R123_USE_CXX11_TYPE_TRAITS R123_USE_CXX11
253 #endif
254 
255 #ifndef R123_USE_CXX11_LONG_LONG
256 #define R123_USE_CXX11_LONG_LONG R123_USE_CXX11
257 #endif
258 
259 #ifndef R123_USE_MULHILO64_C99
260 #define R123_USE_MULHILO64_C99 0
261 #endif
262 
263 #ifndef R123_USE_MULHILO64_MULHI_INTRIN
264 #define R123_USE_MULHILO64_MULHI_INTRIN 0
265 #endif
266 
267 #ifndef R123_USE_MULHILO32_MULHI_INTRIN
268 #define R123_USE_MULHILO32_MULHI_INTRIN 0
269 #endif
270 
271 #ifndef R123_STATIC_ASSERT
272 #if R123_USE_CXX11_STATIC_ASSERT
273 #define R123_STATIC_ASSERT(expr, msg) static_assert(expr, msg)
274 #else
275  /* if msg always_looked_like_this, we could paste it into the name. Worth it? */
276 #define R123_STATIC_ASSERT(expr, msg) typedef char static_assertion[(!!(expr))*2-1]
277 #endif
278 #endif
279 
280 #ifndef R123_CONSTEXPR
281 #if R123_USE_CXX11_CONSTEXPR
282 #define R123_CONSTEXPR constexpr
283 #else
284 #define R123_CONSTEXPR
285 #endif
286 #endif
287 
288 #ifndef R123_USE_PHILOX_64BIT
289 #define R123_USE_PHILOX_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)
290 #endif
291 
292 #ifndef R123_ULONG_LONG
293 #if defined(__cplusplus) && !R123_USE_CXX11_LONG_LONG
294 /* C++98 doesn't have long long. It doesn't have uint64_t either, but
295  we will have typedef'ed uint64_t to something in the xxxfeatures.h.
296  With luck, it won't elicit complaints from -pedantic. Cross your
297  fingers... */
298 #define R123_ULONG_LONG uint64_t
299 #else
300 #define R123_ULONG_LONG unsigned long long
301 #endif
302 #endif
303 
304 /* UINT64_C should have been #defined by XXXfeatures.h, either by
305  #include <stdint.h> or through compiler-dependent hacks */
306 #ifndef R123_64BIT
307 #define R123_64BIT(x) UINT64_C(x)
308 #endif
309 
310 #ifndef R123_THROW
311 #define R123_THROW(x) throw (x)
312 #endif
313 
314 /*
315  * Windows.h (and perhaps other "well-meaning" code define min and
316  * max, so there's a high chance that our definition of min, max
317  * methods or use of std::numeric_limits min and max will cause
318  * complaints in any program that happened to include Windows.h or
319  * suchlike first. We use the null macro below in our own header
320  * files definition or use of min, max to defensively preclude
321  * this problem. It may not be enough; one might need to #define
322  * NOMINMAX before including Windows.h or compile with -DNOMINMAX.
323  */
324 #define R123_NO_MACRO_SUBST
325 
326 /** \endcond */