]>
Commit | Line | Data |
---|---|---|
11fdf7f2 | 1 | /* |
f67539c2 | 2 | * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. |
11fdf7f2 TL |
3 | * All rights reserved. |
4 | * | |
5 | * This source code is licensed under both the BSD-style license (found in the | |
6 | * LICENSE file in the root directory of this source tree) and the GPLv2 (found | |
7 | * in the COPYING file in the root directory of this source tree). | |
8 | * You may select, at your option, one of the above-listed licenses. | |
9 | */ | |
10 | ||
11 | #ifndef ZSTD_COMPILER_H | |
12 | #define ZSTD_COMPILER_H | |
13 | ||
14 | /*-******************************************************* | |
15 | * Compiler specifics | |
16 | *********************************************************/ | |
17 | /* force inlining */ | |
9f95a23c TL |
18 | |
19 | #if !defined(ZSTD_NO_INLINE) | |
f67539c2 | 20 | #if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ |
11fdf7f2 TL |
21 | # define INLINE_KEYWORD inline |
22 | #else | |
23 | # define INLINE_KEYWORD | |
24 | #endif | |
25 | ||
f67539c2 | 26 | #if defined(__GNUC__) || defined(__ICCARM__) |
11fdf7f2 TL |
27 | # define FORCE_INLINE_ATTR __attribute__((always_inline)) |
28 | #elif defined(_MSC_VER) | |
29 | # define FORCE_INLINE_ATTR __forceinline | |
30 | #else | |
31 | # define FORCE_INLINE_ATTR | |
32 | #endif | |
33 | ||
9f95a23c TL |
34 | #else |
35 | ||
36 | #define INLINE_KEYWORD | |
37 | #define FORCE_INLINE_ATTR | |
38 | ||
39 | #endif | |
40 | ||
11fdf7f2 TL |
41 | /** |
42 | * FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant | |
9f95a23c | 43 | * parameters. They must be inlined for the compiler to eliminate the constant |
11fdf7f2 TL |
44 | * branches. |
45 | */ | |
46 | #define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR | |
47 | /** | |
48 | * HINT_INLINE is used to help the compiler generate better code. It is *not* | |
49 | * used for "templates", so it can be tweaked based on the compilers | |
50 | * performance. | |
51 | * | |
52 | * gcc-4.8 and gcc-4.9 have been shown to benefit from leaving off the | |
53 | * always_inline attribute. | |
54 | * | |
55 | * clang up to 5.0.0 (trunk) benefit tremendously from the always_inline | |
56 | * attribute. | |
57 | */ | |
58 | #if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 && __GNUC__ < 5 | |
59 | # define HINT_INLINE static INLINE_KEYWORD | |
60 | #else | |
61 | # define HINT_INLINE static INLINE_KEYWORD FORCE_INLINE_ATTR | |
62 | #endif | |
63 | ||
f67539c2 TL |
64 | /* UNUSED_ATTR tells the compiler it is okay if the function is unused. */ |
65 | #if defined(__GNUC__) | |
66 | # define UNUSED_ATTR __attribute__((unused)) | |
67 | #else | |
68 | # define UNUSED_ATTR | |
69 | #endif | |
70 | ||
11fdf7f2 TL |
71 | /* force no inlining */ |
72 | #ifdef _MSC_VER | |
73 | # define FORCE_NOINLINE static __declspec(noinline) | |
74 | #else | |
f67539c2 | 75 | # if defined(__GNUC__) || defined(__ICCARM__) |
11fdf7f2 TL |
76 | # define FORCE_NOINLINE static __attribute__((__noinline__)) |
77 | # else | |
78 | # define FORCE_NOINLINE static | |
79 | # endif | |
80 | #endif | |
81 | ||
9f95a23c TL |
82 | /* target attribute */ |
83 | #ifndef __has_attribute | |
84 | #define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ | |
85 | #endif | |
f67539c2 | 86 | #if defined(__GNUC__) || defined(__ICCARM__) |
9f95a23c | 87 | # define TARGET_ATTRIBUTE(target) __attribute__((__target__(target))) |
11fdf7f2 | 88 | #else |
9f95a23c | 89 | # define TARGET_ATTRIBUTE(target) |
11fdf7f2 TL |
90 | #endif |
91 | ||
9f95a23c TL |
92 | /* Enable runtime BMI2 dispatch based on the CPU. |
93 | * Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default. | |
94 | */ | |
95 | #ifndef DYNAMIC_BMI2 | |
96 | #if ((defined(__clang__) && __has_attribute(__target__)) \ | |
97 | || (defined(__GNUC__) \ | |
98 | && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \ | |
99 | && (defined(__x86_64__) || defined(_M_X86)) \ | |
100 | && !defined(__BMI2__) | |
101 | # define DYNAMIC_BMI2 1 | |
102 | #else | |
103 | # define DYNAMIC_BMI2 0 | |
104 | #endif | |
105 | #endif | |
106 | ||
107 | /* prefetch | |
108 | * can be disabled, by declaring NO_PREFETCH build macro */ | |
109 | #if defined(NO_PREFETCH) | |
110 | # define PREFETCH_L1(ptr) (void)(ptr) /* disabled */ | |
111 | # define PREFETCH_L2(ptr) (void)(ptr) /* disabled */ | |
112 | #else | |
113 | # if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) /* _mm_prefetch() is not defined outside of x86/x64 */ | |
114 | # include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */ | |
115 | # define PREFETCH_L1(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0) | |
116 | # define PREFETCH_L2(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T1) | |
f67539c2 TL |
117 | # elif defined(__aarch64__) |
118 | # define PREFETCH_L1(ptr) __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr))) | |
119 | # define PREFETCH_L2(ptr) __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr))) | |
9f95a23c TL |
120 | # elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) ) |
121 | # define PREFETCH_L1(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */) | |
122 | # define PREFETCH_L2(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */) | |
123 | # else | |
124 | # define PREFETCH_L1(ptr) (void)(ptr) /* disabled */ | |
125 | # define PREFETCH_L2(ptr) (void)(ptr) /* disabled */ | |
126 | # endif | |
127 | #endif /* NO_PREFETCH */ | |
128 | ||
129 | #define CACHELINE_SIZE 64 | |
130 | ||
131 | #define PREFETCH_AREA(p, s) { \ | |
132 | const char* const _ptr = (const char*)(p); \ | |
133 | size_t const _size = (size_t)(s); \ | |
134 | size_t _pos; \ | |
135 | for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) { \ | |
136 | PREFETCH_L2(_ptr + _pos); \ | |
137 | } \ | |
138 | } | |
139 | ||
f67539c2 TL |
140 | /* vectorization |
141 | * older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax */ | |
142 | #if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__) | |
143 | # if (__GNUC__ == 4 && __GNUC_MINOR__ > 3) || (__GNUC__ >= 5) | |
144 | # define DONT_VECTORIZE __attribute__((optimize("no-tree-vectorize"))) | |
145 | # else | |
146 | # define DONT_VECTORIZE _Pragma("GCC optimize(\"no-tree-vectorize\")") | |
147 | # endif | |
148 | #else | |
149 | # define DONT_VECTORIZE | |
150 | #endif | |
151 | ||
152 | /* Tell the compiler that a branch is likely or unlikely. | |
153 | * Only use these macros if it causes the compiler to generate better code. | |
154 | * If you can remove a LIKELY/UNLIKELY annotation without speed changes in gcc | |
155 | * and clang, please do. | |
156 | */ | |
157 | #if defined(__GNUC__) | |
158 | #define LIKELY(x) (__builtin_expect((x), 1)) | |
159 | #define UNLIKELY(x) (__builtin_expect((x), 0)) | |
160 | #else | |
161 | #define LIKELY(x) (x) | |
162 | #define UNLIKELY(x) (x) | |
163 | #endif | |
164 | ||
11fdf7f2 TL |
165 | /* disable warnings */ |
166 | #ifdef _MSC_VER /* Visual Studio */ | |
167 | # include <intrin.h> /* For Visual 2005 */ | |
168 | # pragma warning(disable : 4100) /* disable: C4100: unreferenced formal parameter */ | |
169 | # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ | |
170 | # pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */ | |
171 | # pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */ | |
172 | # pragma warning(disable : 4324) /* disable: C4324: padded structure */ | |
173 | #endif | |
174 | ||
175 | #endif /* ZSTD_COMPILER_H */ |