Coverage Report

Created: 2026-11-12 07:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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 */