Block-Structured AMR Software Framework
AMReX_Extension.H
Go to the documentation of this file.
1 #ifndef AMREX_EXTENSION_H_
2 #define AMREX_EXTENSION_H_
3 #include <AMReX_Config.H>
4 
5 #if defined(__INTEL_COMPILER) || (defined(__INTEL_LLVM_COMPILER) && !defined(SYCL_LANGUAGE_VERSION))
6 #define AMREX_CXX_INTEL
7 #elif defined(_CRAYC) || defined(__cray__)
8 #define AMREX_CXX_CRAY
9 #elif defined(__PGI)
10 #define AMREX_CXX_PGI
11 #elif defined(__NVCOMPILER)
12 #define AMREX_CXX_NVHPC
13 #elif defined(__NEC__)
14 #define AMREX_CXX_NEC
15 #elif defined(__ibmxl__)
16 #define AMREX_CXX_IBM
17 #elif defined(__clang__)
18 #define AMREX_CXX_CLANG
19 #elif defined(__GNUC__)
20 #define AMREX_CXX_GCC
21 #endif
22 
23 #if !defined(BL_LANG_FORT)
24 
25 // restrict
26 
27 #ifdef __cplusplus
28 
29 #ifdef _WIN32
30 #define AMREX_RESTRICT __restrict
31 #else
32 #define AMREX_RESTRICT __restrict__
33 #endif
34 
35 #else
36 
37 #define AMREX_RESTRICT restrict
38 
39 #endif
40 
41 // simd
42 
43 #if defined(AMREX_DEBUG)
44 #define AMREX_PRAGMA_SIMD
45 
46 #elif defined(__CUDA_ARCH__) && defined(AMREX_USE_CUDA)
47 #define AMREX_PRAGMA_SIMD
48 
49 #elif defined(__HIP_DEVICE_COMPILE__) && defined(AMREX_USE_HIP)
50 #define AMREX_PRAGMA_SIMD
51 
52 //#elif defined(AMREX_USE_OMP) && defined(_OPENMP) && (_OPENMP >= 201307) && !defined(__PGI)
53 //#define AMREX_PRAGMA_SIMD _Pragma("omp simd")
54 
55 #elif defined(AMREX_CXX_INTEL)
56 #define AMREX_PRAGMA_SIMD _Pragma("ivdep")
57 
58 #elif defined(AMREX_CXX_CRAY)
59 #define AMREX_PRAGMA_SIMD _Pragma("ivdep")
60 
61 #elif defined(AMREX_CXX_PGI)
62 #define AMREX_PRAGMA_SIMD _Pragma("loop ivdep")
63 
64 #elif defined(AMREX_CXX_NVHPC)
65 #define AMREX_PRAGMA_SIMD _Pragma("loop ivdep")
66 
67 #elif defined(AMREX_CXX_NEC)
68 #define AMREX_PRAGMA_SIMD
69 
70 #elif defined(AMREX_CXX_IBM)
71 #define AMREX_PRAGMA_SIMD _Pragma("ibm independent_loop")
72 
73 #elif defined(__clang__)
74 #define AMREX_PRAGMA_SIMD
75 
76 #elif defined(__GNUC__)
77 #define AMREX_PRAGMA_SIMD _Pragma("GCC ivdep")
78 
79 #else
80 #define AMREX_PRAGMA_SIMD
81 
82 #endif /* simd */
83 
84 // force inline
85 #if defined(__CUDA_ARCH__) && defined(AMREX_USE_CUDA)
86 #define AMREX_FORCE_INLINE __forceinline__
87 
88 #elif defined(__HIP_DEVICE_COMPILE__) && defined(AMREX_USE_HIP)
89 #define AMREX_FORCE_INLINE __forceinline__
90 
91 #elif defined(AMREX_CXX_INTEL)
92 #define AMREX_FORCE_INLINE inline __attribute__((always_inline))
93 
94 #elif defined(AMREX_CXX_CRAY)
95 #define AMREX_FORCE_INLINE inline
96 
97 #elif defined(AMREX_CXX_PGI)
98 #define AMREX_FORCE_INLINE inline
99 
100 #elif defined(AMREX_CXX_NVHPC)
101 #define AMREX_FORCE_INLINE inline
102 
103 #elif defined(AMREX_CXX_NEC)
104 #define AMREX_FORCE_INLINE inline
105 
106 #elif defined(AMREX_CXX_IBM)
107 #define AMREX_FORCE_INLINE inline __attribute__((always_inline))
108 
109 #elif defined(__clang__)
110 #define AMREX_FORCE_INLINE inline __attribute__((always_inline))
111 
112 #elif defined(__GNUC__)
113 #define AMREX_FORCE_INLINE inline __attribute__((always_inline))
114 
115 #elif defined(_MSC_VER)
116 #define AMREX_FORCE_INLINE inline __forceinline
117 
118 #else
119 #define AMREX_FORCE_INLINE inline
120 
121 #endif /* force inline */
122 
123 
124 #ifdef AMREX_USE_FORCE_INLINE
125 #define AMREX_INLINE AMREX_FORCE_INLINE
126 #else
127 #define AMREX_INLINE inline
128 #endif
129 
130 // no inline
131 #if defined(_MSC_VER)
132 #define AMREX_NO_INLINE __declspec(noinline)
133 #elif (defined(__GNUC__) || defined(__clang__) || defined(__CUDACC__) || defined(__HIP__) || defined(__INTEL_CLANG_COMPILER))
134 #define AMREX_NO_INLINE __attribute__((noinline))
135 #else
136 #define AMREX_NO_INLINE
137 #endif
138 
139 // flatten
140 #if defined(_MSC_VER)
141 #define AMREX_FLATTEN [[msvc::flatten]]
142 #elif defined(__clang__) || defined(__GNUC__)
143 #define AMREX_FLATTEN __attribute__((flatten))
144 #else
145 #define AMREX_FLATTEN
146 #endif
147 
148 #ifdef AMREX_USE_FLATTEN_FOR
149 #define AMREX_ATTRIBUTE_FLATTEN_FOR AMREX_FLATTEN
150 #else
151 #define AMREX_ATTRIBUTE_FLATTEN_FOR
152 #endif
153 
154 // unroll loop
155 #define AMREX_TO_STRING_HELPER(X) #X
156 #define AMREX_TO_STRING(X) AMREX_TO_STRING_HELPER(X)
157 
158 #if defined(__clang__) || defined(__CUDACC__) || defined(__HIP__) || defined(__INTEL_CLANG_COMPILER)
159 #define AMREX_UNROLL_LOOP(n) _Pragma(AMREX_TO_STRING(unroll n))
160 #elif defined(__GNUC__)
161 #define AMREX_UNROLL_LOOP(n) _Pragma(AMREX_TO_STRING(GCC unroll n))
162 #else
163 #define AMREX_UNROLL_LOOP(n)
164 #endif
165 
166 // __attribute__((weak))
167 
168 #if defined(AMREX_TYPECHECK)
169 #define AMREX_ATTRIBUTE_WEAK
170 #elif defined(_WIN32)
171 #define AMREX_ATTRIBUTE_WEAK
172 #elif defined(__clang__) && defined(__apple_build_version__)
173 #define AMREX_ATTRIBUTE_WEAK __attribute__((weak_import))
174 #else
175 #define AMREX_ATTRIBUTE_WEAK __attribute__((weak))
176 #endif
177 
178 // public globals
179 // https://stackoverflow.com/questions/54560832/cmake-windows-export-all-symbols-does-not-cover-global-variables/54568678#54568678
180 #if defined(_MSC_VER)
181 # if defined(AMREX_IS_DLL)
182 # if defined(AMREX_IS_DLL_BUILDING)
183 # define AMREX_EXPORT __declspec(dllexport)
184 # else
185 # define AMREX_EXPORT __declspec(dllimport)
186 # endif
187 # else
188 # define AMREX_EXPORT
189 # endif
190 #else
191 # define AMREX_EXPORT
192 #endif
193 
194 #if defined(__cplusplus) && defined(_WIN32)
195 #include <ciso646>
196 #endif
197 
198 #if defined(__INTEL_COMPILER) && defined(__EDG__) && (__cplusplus < 201703L)
199 // Classical EDG based Intel compiler does not support fallthrough when std=c++14
200 # define AMREX_FALLTHROUGH ((void)0)
201 #elif defined(__has_cpp_attribute) && __has_cpp_attribute(fallthrough) >= 201603L
202 # define AMREX_FALLTHROUGH [[fallthrough]]
203 #elif defined(__clang__)
204 # define AMREX_FALLTHROUGH [[clang::fallthrough]]
205 #elif defined(__GNUC__) && (__GNUC__ >= 7)
206 # define AMREX_FALLTHROUGH [[gnu::fallthrough]]
207 #else
208 # define AMREX_FALLTHROUGH ((void)0)
209 #endif
210 
211 // Note: following compilers support [[likely]] and [[unlikely]]
212 // - Clang >= 12.0
213 // - GCC >= 9.0
214 // - Intel >= 2021.7
215 // - MSVC >= 19.26
216 // - nvcc >= 12
217 #if defined(__has_cpp_attribute) && __has_cpp_attribute(likely) >= 201803L
218 # define AMREX_LIKELY [[likely]]
219 # define AMREX_UNLIKELY [[unlikely]]
220 #else
221 # define AMREX_LIKELY
222 # define AMREX_UNLIKELY
223 #endif
224 
225 // Note: following compilers support assumptions, at least using builtin functions:
226 // - Clang >= 3.7
227 // - GCC >= 5.1
228 // - MSVC >= 19.20
229 // - nvcc >= 11.1.0
230 // - icx >= 2021.1.2
231 #if defined(__has_cpp_attribute) && __has_cpp_attribute(assume)
232 # define AMREX_ASSUME(ASSUMPTION) [[assume(ASSUMPTION)]]
233 #else
234 # if defined(__CUDA_ARCH__) && defined(__CUDACC__) && ( (__CUDACC_VER_MAJOR__ > 11) || ((__CUDACC_VER_MAJOR__ == 11) && (__CUDACC_VER_MINOR__ >= 2)) )
235 # define AMREX_ASSUME(ASSUMPTION) __builtin_assume(ASSUMPTION)
236 # elif defined(AMREX_CXX_INTEL) || defined(__clang__)
237 # define AMREX_ASSUME(ASSUMPTION) __builtin_assume(ASSUMPTION)
238 # elif defined(_MSC_VER)
239 # define AMREX_ASSUME(ASSUMPTION) __assume(ASSUMPTION)
240 # elif defined(__GNUC__)
241 # define AMREX_ASSUME(ASSUMPTION) if (ASSUMPTION) {} else { __builtin_unreachable(); }
242 # else
243 # define AMREX_ASSUME(ASSUMPTION)
244 # endif
245 #endif
246 
247 // CI uses -Werror -Wc++17-extension, thus we need to add the __cplusplus clause
248 #if !defined(AMREX_NO_NODISCARD) && defined(__has_cpp_attribute) && __has_cpp_attribute(nodiscard) >= 201603L
249 # define AMREX_NODISCARD [[nodiscard]]
250 #else
251 # define AMREX_NODISCARD
252 #endif
253 
254 // Note: following compilers support [[no_unique_address]]
255 // - Clang >= 9.0
256 // - GCC >= 9.0
257 // - MSVC >= 19.26
258 // Using no unique address makes empty base class optimization for multiple policies much easier
259 #if !defined(AMREX_NO_NO_UNIQUE_ADDRESS) && defined(__has_cpp_attribute) && __has_cpp_attribute(no_unique_address) >= 201803L
260 # define AMREX_NO_UNIQUE_ADDRESS [[no_unique_address]]
261 # define AMREX_HAS_NO_UNIQUE_ADDRESS 1
262 #else
263 # define AMREX_NO_UNIQUE_ADDRESS
264 #endif
265 
266 #if defined(__cpp_if_constexpr) && __cpp_if_constexpr >= 201606L
267 # define AMREX_IF_CONSTEXPR if constexpr
268 #else
269 # define AMREX_IF_CONSTEXPR if
270 #endif
271 
272 #if !defined(AMREX_NO_BUILTIN_CLZ)
273 # if defined(__clang__) || defined(__GNUC__)
274 # define AMREX_HAS_BUILTIN_CLZ 1
275 # endif
276 #endif
277 
278 
279 #endif /* !BL_LANG_FORT */
280 
281 #endif