/src/libdeflate/lib/x86/cpu_features.h
Line | Count | Source |
1 | | /* |
2 | | * x86/cpu_features.h - feature detection for x86 CPUs |
3 | | * |
4 | | * Copyright 2016 Eric Biggers |
5 | | * |
6 | | * Permission is hereby granted, free of charge, to any person |
7 | | * obtaining a copy of this software and associated documentation |
8 | | * files (the "Software"), to deal in the Software without |
9 | | * restriction, including without limitation the rights to use, |
10 | | * copy, modify, merge, publish, distribute, sublicense, and/or sell |
11 | | * copies of the Software, and to permit persons to whom the |
12 | | * Software is furnished to do so, subject to the following |
13 | | * conditions: |
14 | | * |
15 | | * The above copyright notice and this permission notice shall be |
16 | | * included in all copies or substantial portions of the Software. |
17 | | * |
18 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
19 | | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
20 | | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
21 | | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
22 | | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
23 | | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
24 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
25 | | * OTHER DEALINGS IN THE SOFTWARE. |
26 | | */ |
27 | | |
28 | | #ifndef LIB_X86_CPU_FEATURES_H |
29 | | #define LIB_X86_CPU_FEATURES_H |
30 | | |
31 | | #include "../lib_common.h" |
32 | | |
33 | | #if defined(ARCH_X86_32) || defined(ARCH_X86_64) |
34 | | |
35 | 6 | #define X86_CPU_FEATURE_SSE2 (1 << 0) |
36 | 6 | #define X86_CPU_FEATURE_PCLMULQDQ (1 << 1) |
37 | 6 | #define X86_CPU_FEATURE_AVX (1 << 2) |
38 | 16 | #define X86_CPU_FEATURE_AVX2 (1 << 3) |
39 | 12 | #define X86_CPU_FEATURE_BMI2 (1 << 4) |
40 | | /* |
41 | | * ZMM indicates whether 512-bit vectors (zmm registers) should be used. On |
42 | | * some CPUs, to avoid downclocking issues we don't set ZMM even if the CPU and |
43 | | * operating system support AVX-512. On these CPUs, we may still use AVX-512 |
44 | | * instructions, but only with xmm and ymm registers. |
45 | | */ |
46 | 5 | #define X86_CPU_FEATURE_ZMM (1 << 5) |
47 | 5 | #define X86_CPU_FEATURE_AVX512BW (1 << 6) |
48 | 0 | #define X86_CPU_FEATURE_AVX512VL (1 << 7) |
49 | 0 | #define X86_CPU_FEATURE_VPCLMULQDQ (1 << 8) |
50 | 0 | #define X86_CPU_FEATURE_AVX512VNNI (1 << 9) |
51 | 5 | #define X86_CPU_FEATURE_AVXVNNI (1 << 10) |
52 | | |
53 | | #if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) |
54 | | /* Runtime x86 CPU feature detection is supported. */ |
55 | | # define X86_CPU_FEATURES_KNOWN (1U << 31) |
56 | | extern LIBDEFLATE_ATOMIC(u32) libdeflate_x86_cpu_features; |
57 | | |
58 | | void libdeflate_init_x86_cpu_features(void); |
59 | | |
60 | | static inline u32 get_x86_cpu_features(void) |
61 | 11 | { |
62 | 11 | u32 features = LIBDEFLATE_ATOMIC_LOAD_RELAXED(&libdeflate_x86_cpu_features); |
63 | | |
64 | 11 | if (features == 0) { |
65 | 6 | libdeflate_init_x86_cpu_features(); |
66 | 6 | features = LIBDEFLATE_ATOMIC_LOAD_RELAXED(&libdeflate_x86_cpu_features); |
67 | 6 | } |
68 | 11 | return features; |
69 | 11 | } Unexecuted instantiation: deflate_compress.c:get_x86_cpu_features Unexecuted instantiation: cpu_features.c:get_x86_cpu_features deflate_decompress.c:get_x86_cpu_features Line | Count | Source | 61 | 6 | { | 62 | 6 | u32 features = LIBDEFLATE_ATOMIC_LOAD_RELAXED(&libdeflate_x86_cpu_features); | 63 | | | 64 | 6 | if (features == 0) { | 65 | 6 | libdeflate_init_x86_cpu_features(); | 66 | | features = LIBDEFLATE_ATOMIC_LOAD_RELAXED(&libdeflate_x86_cpu_features); | 67 | 6 | } | 68 | 6 | return features; | 69 | 6 | } |
adler32.c:get_x86_cpu_features Line | Count | Source | 61 | 5 | { | 62 | 5 | u32 features = LIBDEFLATE_ATOMIC_LOAD_RELAXED(&libdeflate_x86_cpu_features); | 63 | | | 64 | 5 | if (features == 0) { | 65 | 0 | libdeflate_init_x86_cpu_features(); | 66 | | features = LIBDEFLATE_ATOMIC_LOAD_RELAXED(&libdeflate_x86_cpu_features); | 67 | 0 | } | 68 | 5 | return features; | 69 | 5 | } |
|
70 | | /* |
71 | | * x86 intrinsics are also supported. Include the headers needed to use them. |
72 | | * Normally just immintrin.h suffices. With clang in MSVC compatibility mode, |
73 | | * immintrin.h incorrectly skips including sub-headers, so include those too. |
74 | | */ |
75 | | # include <immintrin.h> |
76 | | # if defined(_MSC_VER) && defined(__clang__) |
77 | | # include <tmmintrin.h> |
78 | | # include <smmintrin.h> |
79 | | # include <wmmintrin.h> |
80 | | # include <avxintrin.h> |
81 | | # include <avx2intrin.h> |
82 | | # include <avx512fintrin.h> |
83 | | # include <avx512bwintrin.h> |
84 | | # include <avx512vlintrin.h> |
85 | | # if __has_include(<avx512vlbwintrin.h>) |
86 | | # include <avx512vlbwintrin.h> |
87 | | # endif |
88 | | # if __has_include(<vpclmulqdqintrin.h>) |
89 | | # include <vpclmulqdqintrin.h> |
90 | | # endif |
91 | | # if __has_include(<avx512vnniintrin.h>) |
92 | | # include <avx512vnniintrin.h> |
93 | | # endif |
94 | | # if __has_include(<avx512vlvnniintrin.h>) |
95 | | # include <avx512vlvnniintrin.h> |
96 | | # endif |
97 | | # if __has_include(<avxvnniintrin.h>) |
98 | | # include <avxvnniintrin.h> |
99 | | # endif |
100 | | # endif |
101 | | #else |
102 | | static inline u32 get_x86_cpu_features(void) { return 0; } |
103 | | #endif |
104 | | |
105 | | #if defined(__SSE2__) || \ |
106 | | (defined(_MSC_VER) && \ |
107 | | (defined(ARCH_X86_64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2))) |
108 | 0 | # define HAVE_SSE2(features) 1 |
109 | | # define HAVE_SSE2_NATIVE 1 |
110 | | #else |
111 | | # define HAVE_SSE2(features) ((features) & X86_CPU_FEATURE_SSE2) |
112 | | # define HAVE_SSE2_NATIVE 0 |
113 | | #endif |
114 | | |
115 | | #if (defined(__PCLMUL__) && defined(__SSE4_1__)) || \ |
116 | | (defined(_MSC_VER) && defined(__AVX2__)) |
117 | | # define HAVE_PCLMULQDQ(features) 1 |
118 | | #else |
119 | | # define HAVE_PCLMULQDQ(features) ((features) & X86_CPU_FEATURE_PCLMULQDQ) |
120 | | #endif |
121 | | |
122 | | #ifdef __AVX__ |
123 | | # define HAVE_AVX(features) 1 |
124 | | #else |
125 | | # define HAVE_AVX(features) ((features) & X86_CPU_FEATURE_AVX) |
126 | | #endif |
127 | | |
128 | | #ifdef __AVX2__ |
129 | | # define HAVE_AVX2(features) 1 |
130 | | #else |
131 | 15 | # define HAVE_AVX2(features) ((features) & X86_CPU_FEATURE_AVX2) |
132 | | #endif |
133 | | |
134 | | #if defined(__BMI2__) || (defined(_MSC_VER) && defined(__AVX2__)) |
135 | | # define HAVE_BMI2(features) 1 |
136 | | # define HAVE_BMI2_NATIVE 1 |
137 | | #else |
138 | 6 | # define HAVE_BMI2(features) ((features) & X86_CPU_FEATURE_BMI2) |
139 | | # define HAVE_BMI2_NATIVE 0 |
140 | | #endif |
141 | | |
142 | | #ifdef __AVX512BW__ |
143 | | # define HAVE_AVX512BW(features) 1 |
144 | | #else |
145 | 15 | # define HAVE_AVX512BW(features) ((features) & X86_CPU_FEATURE_AVX512BW) |
146 | | #endif |
147 | | |
148 | | #ifdef __AVX512VL__ |
149 | | # define HAVE_AVX512VL(features) 1 |
150 | | #else |
151 | 5 | # define HAVE_AVX512VL(features) ((features) & X86_CPU_FEATURE_AVX512VL) |
152 | | #endif |
153 | | |
154 | | #ifdef __VPCLMULQDQ__ |
155 | | # define HAVE_VPCLMULQDQ(features) 1 |
156 | | #else |
157 | | # define HAVE_VPCLMULQDQ(features) ((features) & X86_CPU_FEATURE_VPCLMULQDQ) |
158 | | #endif |
159 | | |
160 | | #ifdef __AVX512VNNI__ |
161 | | # define HAVE_AVX512VNNI(features) 1 |
162 | | #else |
163 | 0 | # define HAVE_AVX512VNNI(features) ((features) & X86_CPU_FEATURE_AVX512VNNI) |
164 | | #endif |
165 | | |
166 | | #ifdef __AVXVNNI__ |
167 | | # define HAVE_AVXVNNI(features) 1 |
168 | | #else |
169 | 5 | # define HAVE_AVXVNNI(features) ((features) & X86_CPU_FEATURE_AVXVNNI) |
170 | | #endif |
171 | | |
172 | | #endif /* ARCH_X86_32 || ARCH_X86_64 */ |
173 | | |
174 | | #endif /* LIB_X86_CPU_FEATURES_H */ |