xref: /linux/lib/zstd/common/compiler.h (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
1e0c1b49fSNick Terrell /*
2e0c1b49fSNick Terrell  * Copyright (c) Yann Collet, Facebook, Inc.
3e0c1b49fSNick Terrell  * All rights reserved.
4e0c1b49fSNick Terrell  *
5e0c1b49fSNick Terrell  * This source code is licensed under both the BSD-style license (found in the
6e0c1b49fSNick Terrell  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7e0c1b49fSNick Terrell  * in the COPYING file in the root directory of this source tree).
8e0c1b49fSNick Terrell  * You may select, at your option, one of the above-listed licenses.
9e0c1b49fSNick Terrell  */
10e0c1b49fSNick Terrell 
11e0c1b49fSNick Terrell #ifndef ZSTD_COMPILER_H
12e0c1b49fSNick Terrell #define ZSTD_COMPILER_H
13e0c1b49fSNick Terrell 
14*2aa14b1aSNick Terrell #include "portability_macros.h"
15*2aa14b1aSNick Terrell 
16e0c1b49fSNick Terrell /*-*******************************************************
17e0c1b49fSNick Terrell *  Compiler specifics
18e0c1b49fSNick Terrell *********************************************************/
19e0c1b49fSNick Terrell /* force inlining */
20e0c1b49fSNick Terrell 
211974990cSNick Terrell #if !defined(ZSTD_NO_INLINE)
22e0c1b49fSNick Terrell #if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */
23e0c1b49fSNick Terrell #  define INLINE_KEYWORD inline
24e0c1b49fSNick Terrell #else
25e0c1b49fSNick Terrell #  define INLINE_KEYWORD
26e0c1b49fSNick Terrell #endif
27e0c1b49fSNick Terrell 
28e0c1b49fSNick Terrell #define FORCE_INLINE_ATTR __attribute__((always_inline))
29e0c1b49fSNick Terrell 
301974990cSNick Terrell #else
311974990cSNick Terrell 
321974990cSNick Terrell #define INLINE_KEYWORD
331974990cSNick Terrell #define FORCE_INLINE_ATTR
341974990cSNick Terrell 
351974990cSNick Terrell #endif
36e0c1b49fSNick Terrell 
37e0c1b49fSNick Terrell /*
38e0c1b49fSNick Terrell   On MSVC qsort requires that functions passed into it use the __cdecl calling conversion(CC).
39*2aa14b1aSNick Terrell   This explicitly marks such functions as __cdecl so that the code will still compile
40e0c1b49fSNick Terrell   if a CC other than __cdecl has been made the default.
41e0c1b49fSNick Terrell */
42e0c1b49fSNick Terrell #define WIN_CDECL
43e0c1b49fSNick Terrell 
44e0c1b49fSNick Terrell /*
45e0c1b49fSNick Terrell  * FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant
46e0c1b49fSNick Terrell  * parameters. They must be inlined for the compiler to eliminate the constant
47e0c1b49fSNick Terrell  * branches.
48e0c1b49fSNick Terrell  */
49e0c1b49fSNick Terrell #define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR
50e0c1b49fSNick Terrell /*
51e0c1b49fSNick Terrell  * HINT_INLINE is used to help the compiler generate better code. It is *not*
52e0c1b49fSNick Terrell  * used for "templates", so it can be tweaked based on the compilers
53e0c1b49fSNick Terrell  * performance.
54e0c1b49fSNick Terrell  *
55e0c1b49fSNick Terrell  * gcc-4.8 and gcc-4.9 have been shown to benefit from leaving off the
56e0c1b49fSNick Terrell  * always_inline attribute.
57e0c1b49fSNick Terrell  *
58e0c1b49fSNick Terrell  * clang up to 5.0.0 (trunk) benefit tremendously from the always_inline
59e0c1b49fSNick Terrell  * attribute.
60e0c1b49fSNick Terrell  */
61e0c1b49fSNick Terrell #if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 && __GNUC__ < 5
62e0c1b49fSNick Terrell #  define HINT_INLINE static INLINE_KEYWORD
63e0c1b49fSNick Terrell #else
64e0c1b49fSNick Terrell #  define HINT_INLINE static INLINE_KEYWORD FORCE_INLINE_ATTR
65e0c1b49fSNick Terrell #endif
66e0c1b49fSNick Terrell 
67e0c1b49fSNick Terrell /* UNUSED_ATTR tells the compiler it is okay if the function is unused. */
68e0c1b49fSNick Terrell #define UNUSED_ATTR __attribute__((unused))
69e0c1b49fSNick Terrell 
70e0c1b49fSNick Terrell /* force no inlining */
71e0c1b49fSNick Terrell #define FORCE_NOINLINE static __attribute__((__noinline__))
72e0c1b49fSNick Terrell 
73e0c1b49fSNick Terrell 
74e0c1b49fSNick Terrell /* target attribute */
75e0c1b49fSNick Terrell #define TARGET_ATTRIBUTE(target) __attribute__((__target__(target)))
76e0c1b49fSNick Terrell 
77*2aa14b1aSNick Terrell /* Target attribute for BMI2 dynamic dispatch.
78*2aa14b1aSNick Terrell  * Enable lzcnt, bmi, and bmi2.
79*2aa14b1aSNick Terrell  * We test for bmi1 & bmi2. lzcnt is included in bmi1.
80e0c1b49fSNick Terrell  */
81*2aa14b1aSNick Terrell #define BMI2_TARGET_ATTRIBUTE TARGET_ATTRIBUTE("lzcnt,bmi,bmi2")
82e0c1b49fSNick Terrell 
83e0c1b49fSNick Terrell /* prefetch
84e0c1b49fSNick Terrell  * can be disabled, by declaring NO_PREFETCH build macro */
85e0c1b49fSNick Terrell #if ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) )
86e0c1b49fSNick Terrell #  define PREFETCH_L1(ptr)  __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */)
87e0c1b49fSNick Terrell #  define PREFETCH_L2(ptr)  __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */)
88e0c1b49fSNick Terrell #elif defined(__aarch64__)
89e0c1b49fSNick Terrell #  define PREFETCH_L1(ptr)  __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr)))
90e0c1b49fSNick Terrell #  define PREFETCH_L2(ptr)  __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr)))
91e0c1b49fSNick Terrell #else
92e0c1b49fSNick Terrell #  define PREFETCH_L1(ptr) (void)(ptr)  /* disabled */
93e0c1b49fSNick Terrell #  define PREFETCH_L2(ptr) (void)(ptr)  /* disabled */
94e0c1b49fSNick Terrell #endif  /* NO_PREFETCH */
95e0c1b49fSNick Terrell 
96e0c1b49fSNick Terrell #define CACHELINE_SIZE 64
97e0c1b49fSNick Terrell 
98e0c1b49fSNick Terrell #define PREFETCH_AREA(p, s)  {            \
99e0c1b49fSNick Terrell     const char* const _ptr = (const char*)(p);  \
100e0c1b49fSNick Terrell     size_t const _size = (size_t)(s);     \
101e0c1b49fSNick Terrell     size_t _pos;                          \
102e0c1b49fSNick Terrell     for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) {  \
103e0c1b49fSNick Terrell         PREFETCH_L2(_ptr + _pos);         \
104e0c1b49fSNick Terrell     }                                     \
105e0c1b49fSNick Terrell }
106e0c1b49fSNick Terrell 
107e0c1b49fSNick Terrell /* vectorization
108*2aa14b1aSNick Terrell  * older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax,
109*2aa14b1aSNick Terrell  * and some compilers, like Intel ICC and MCST LCC, do not support it at all. */
110*2aa14b1aSNick Terrell #if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__) && !defined(__LCC__)
111e0c1b49fSNick Terrell #  if (__GNUC__ == 4 && __GNUC_MINOR__ > 3) || (__GNUC__ >= 5)
112e0c1b49fSNick Terrell #    define DONT_VECTORIZE __attribute__((optimize("no-tree-vectorize")))
113e0c1b49fSNick Terrell #  else
114e0c1b49fSNick Terrell #    define DONT_VECTORIZE _Pragma("GCC optimize(\"no-tree-vectorize\")")
115e0c1b49fSNick Terrell #  endif
116e0c1b49fSNick Terrell #else
117e0c1b49fSNick Terrell #  define DONT_VECTORIZE
118e0c1b49fSNick Terrell #endif
119e0c1b49fSNick Terrell 
120e0c1b49fSNick Terrell /* Tell the compiler that a branch is likely or unlikely.
121e0c1b49fSNick Terrell  * Only use these macros if it causes the compiler to generate better code.
122e0c1b49fSNick Terrell  * If you can remove a LIKELY/UNLIKELY annotation without speed changes in gcc
123e0c1b49fSNick Terrell  * and clang, please do.
124e0c1b49fSNick Terrell  */
125e0c1b49fSNick Terrell #define LIKELY(x) (__builtin_expect((x), 1))
126e0c1b49fSNick Terrell #define UNLIKELY(x) (__builtin_expect((x), 0))
127e0c1b49fSNick Terrell 
128*2aa14b1aSNick Terrell #if __has_builtin(__builtin_unreachable) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)))
129*2aa14b1aSNick Terrell #  define ZSTD_UNREACHABLE { assert(0), __builtin_unreachable(); }
130*2aa14b1aSNick Terrell #else
131*2aa14b1aSNick Terrell #  define ZSTD_UNREACHABLE { assert(0); }
132*2aa14b1aSNick Terrell #endif
133*2aa14b1aSNick Terrell 
134e0c1b49fSNick Terrell /* disable warnings */
135e0c1b49fSNick Terrell 
136e0c1b49fSNick Terrell /*Like DYNAMIC_BMI2 but for compile time determination of BMI2 support*/
137e0c1b49fSNick Terrell 
138e0c1b49fSNick Terrell 
139*2aa14b1aSNick Terrell /* compile time determination of SIMD support */
140e0c1b49fSNick Terrell 
141e0c1b49fSNick Terrell /* C-language Attributes are added in C23. */
142e0c1b49fSNick Terrell #if defined(__STDC_VERSION__) && (__STDC_VERSION__ > 201710L) && defined(__has_c_attribute)
143e0c1b49fSNick Terrell # define ZSTD_HAS_C_ATTRIBUTE(x) __has_c_attribute(x)
144e0c1b49fSNick Terrell #else
145e0c1b49fSNick Terrell # define ZSTD_HAS_C_ATTRIBUTE(x) 0
146e0c1b49fSNick Terrell #endif
147e0c1b49fSNick Terrell 
148e0c1b49fSNick Terrell /* Only use C++ attributes in C++. Some compilers report support for C++
149e0c1b49fSNick Terrell  * attributes when compiling with C.
150e0c1b49fSNick Terrell  */
151e0c1b49fSNick Terrell #define ZSTD_HAS_CPP_ATTRIBUTE(x) 0
152e0c1b49fSNick Terrell 
153e0c1b49fSNick Terrell /* Define ZSTD_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute.
154e0c1b49fSNick Terrell  * - C23: https://en.cppreference.com/w/c/language/attributes/fallthrough
155e0c1b49fSNick Terrell  * - CPP17: https://en.cppreference.com/w/cpp/language/attributes/fallthrough
156e0c1b49fSNick Terrell  * - Else: __attribute__((__fallthrough__))
157e0c1b49fSNick Terrell  */
158e0c1b49fSNick Terrell #define ZSTD_FALLTHROUGH fallthrough
159e0c1b49fSNick Terrell 
160*2aa14b1aSNick Terrell /*-**************************************************************
161*2aa14b1aSNick Terrell *  Alignment check
162*2aa14b1aSNick Terrell *****************************************************************/
163e0c1b49fSNick Terrell 
164*2aa14b1aSNick Terrell /* this test was initially positioned in mem.h,
165*2aa14b1aSNick Terrell  * but this file is removed (or replaced) for linux kernel
166*2aa14b1aSNick Terrell  * so it's now hosted in compiler.h,
167*2aa14b1aSNick Terrell  * which remains valid for both user & kernel spaces.
168*2aa14b1aSNick Terrell  */
169e0c1b49fSNick Terrell 
170*2aa14b1aSNick Terrell #ifndef ZSTD_ALIGNOF
171*2aa14b1aSNick Terrell /* covers gcc, clang & MSVC */
172*2aa14b1aSNick Terrell /* note : this section must come first, before C11,
173*2aa14b1aSNick Terrell  * due to a limitation in the kernel source generator */
174*2aa14b1aSNick Terrell #  define ZSTD_ALIGNOF(T) __alignof(T)
175*2aa14b1aSNick Terrell 
176*2aa14b1aSNick Terrell #endif /* ZSTD_ALIGNOF */
177*2aa14b1aSNick Terrell 
178*2aa14b1aSNick Terrell /*-**************************************************************
179*2aa14b1aSNick Terrell *  Sanitizer
180*2aa14b1aSNick Terrell *****************************************************************/
181*2aa14b1aSNick Terrell 
182e0c1b49fSNick Terrell 
183e0c1b49fSNick Terrell 
184e0c1b49fSNick Terrell #endif /* ZSTD_COMPILER_H */
185