1 /* x86 CPU feature tuning.
2 This file is part of the GNU C Library.
3 Copyright (C) 2017 Free Software Foundation, Inc.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
20 # define TUNABLE_NAMESPACE tune
23 # include <unistd.h> /* Get STDOUT_FILENO for _dl_printf. */
24 # include <elf/dl-tunables.h>
26 # include <cpu-features.h>
27 # include <ldsodefs.h>
29 /* We can't use IFUNC memcmp nor strlen in init_cpu_features from libc.a
30 since IFUNC must be set up by init_cpu_features. */
31 # if defined USE_MULTIARCH && !defined SHARED
33 # define DEFAULT_MEMCMP __memcmp_sse2
35 # define DEFAULT_MEMCMP __memcmp_ia32
37 extern __typeof (memcmp
) DEFAULT_MEMCMP
;
39 # define DEFAULT_MEMCMP memcmp
42 # define CHECK_GLIBC_IFUNC_CPU_OFF(f, cpu_features, name, len) \
43 _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \
44 if (!DEFAULT_MEMCMP (f, #name, len)) \
46 cpu_features->cpuid[index_cpu_##name].reg_##name \
51 /* Disable an ARCH feature NAME. We don't enable an ARCH feature which
53 # define CHECK_GLIBC_IFUNC_ARCH_OFF(f, cpu_features, name, len) \
54 _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \
55 if (!DEFAULT_MEMCMP (f, #name, len)) \
57 cpu_features->feature[index_arch_##name] \
58 &= ~bit_arch_##name; \
62 /* Enable/disable an ARCH feature NAME. */
63 # define CHECK_GLIBC_IFUNC_ARCH_BOTH(f, cpu_features, name, disable, \
65 _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \
66 if (!DEFAULT_MEMCMP (f, #name, len)) \
69 cpu_features->feature[index_arch_##name] \
70 &= ~bit_arch_##name; \
72 cpu_features->feature[index_arch_##name] \
77 /* Enable/disable an ARCH feature NAME. Enable an ARCH feature only
78 if the ARCH feature NEED is also enabled. */
79 # define CHECK_GLIBC_IFUNC_ARCH_NEED_ARCH_BOTH(f, cpu_features, name, \
81 _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \
82 if (!DEFAULT_MEMCMP (f, #name, len)) \
85 cpu_features->feature[index_arch_##name] \
86 &= ~bit_arch_##name; \
87 else if (CPU_FEATURES_ARCH_P (cpu_features, need)) \
88 cpu_features->feature[index_arch_##name] \
93 /* Enable/disable an ARCH feature NAME. Enable an ARCH feature only
94 if the CPU feature NEED is also enabled. */
95 # define CHECK_GLIBC_IFUNC_ARCH_NEED_CPU_BOTH(f, cpu_features, name, \
97 _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \
98 if (!DEFAULT_MEMCMP (f, #name, len)) \
101 cpu_features->feature[index_arch_##name] \
102 &= ~bit_arch_##name; \
103 else if (CPU_FEATURES_CPU_P (cpu_features, need)) \
104 cpu_features->feature[index_arch_##name] \
105 |= bit_arch_##name; \
111 TUNABLE_CALLBACK (set_hwcaps
) (tunable_val_t
*valp
)
113 /* The current IFUNC selection is based on microbenchmarks in glibc.
114 It should give the best performance for most workloads. But other
115 choices may have better performance for a particular workload or on
116 the hardware which wasn't available when the selection was made.
117 The environment variable:
119 GLIBC_TUNABLES=glibc.tune.hwcaps=-xxx,yyy,-zzz,....
121 can be used to enable CPU/ARCH feature yyy, disable CPU/ARCH feature
122 yyy and zzz, where the feature name is case-sensitive and has to
123 match the ones in cpu-features.h. It can be used by glibc developers
124 to tune for a new processor or override the IFUNC selection to
125 improve performance for a particular workload.
127 NOTE: the IFUNC selection may change over time. Please check all
128 multiarch implementations when experimenting. */
130 const char *p
= valp
->strval
;
131 struct cpu_features
*cpu_features
= &GLRO(dl_x86_cpu_features
);
140 for (c
= p
; *c
!= ','; c
++)
163 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, AVX
, 3);
164 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, CX8
, 3);
165 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, FMA
, 3);
166 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, HTT
, 3);
167 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, IBT
, 3);
168 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, RTM
, 3);
174 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, AVX2
, 4);
175 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, BMI1
, 4);
176 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, BMI2
, 4);
177 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, CMOV
, 4);
178 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, ERMS
, 4);
179 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, FMA4
, 4);
180 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, SSE2
, 4);
181 CHECK_GLIBC_IFUNC_ARCH_OFF (n
, cpu_features
, I586
, 4);
182 CHECK_GLIBC_IFUNC_ARCH_OFF (n
, cpu_features
, I686
, 4);
188 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, LZCNT
, 5);
189 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, MOVBE
, 5);
190 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, SHSTK
, 5);
191 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, SSSE3
, 5);
197 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, POPCNT
, 6);
198 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, SSE4_1
, 6);
199 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, SSE4_2
, 6);
205 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, AVX512F
, 7);
206 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, OSXSAVE
, 7);
212 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, AVX512CD
, 8);
213 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, AVX512BW
, 8);
214 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, AVX512DQ
, 8);
215 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, AVX512ER
, 8);
216 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, AVX512PF
, 8);
217 CHECK_GLIBC_IFUNC_CPU_OFF (n
, cpu_features
, AVX512VL
, 8);
219 CHECK_GLIBC_IFUNC_ARCH_BOTH (n
, cpu_features
, Slow_BSF
,
225 CHECK_GLIBC_IFUNC_ARCH_OFF (n
, cpu_features
, AVX_Usable
,
227 CHECK_GLIBC_IFUNC_ARCH_OFF (n
, cpu_features
, FMA_Usable
,
234 CHECK_GLIBC_IFUNC_ARCH_OFF (n
, cpu_features
, AVX2_Usable
,
236 CHECK_GLIBC_IFUNC_ARCH_OFF (n
, cpu_features
, FMA4_Usable
,
239 CHECK_GLIBC_IFUNC_ARCH_BOTH (n
, cpu_features
, Prefer_ERMS
,
241 CHECK_GLIBC_IFUNC_ARCH_NEED_CPU_BOTH (n
, cpu_features
,
248 /* Update xsave_state_size to XSAVE state size. */
249 cpu_features
->xsave_state_size
250 = cpu_features
->xsave_state_full_size
;
251 CHECK_GLIBC_IFUNC_ARCH_OFF (n
, cpu_features
,
258 CHECK_GLIBC_IFUNC_ARCH_OFF (n
, cpu_features
,
265 CHECK_GLIBC_IFUNC_ARCH_OFF (n
, cpu_features
,
266 AVX512DQ_Usable
, 15);
268 CHECK_GLIBC_IFUNC_ARCH_BOTH (n
, cpu_features
, Fast_Rep_String
,
273 CHECK_GLIBC_IFUNC_ARCH_NEED_ARCH_BOTH
274 (n
, cpu_features
, Prefer_No_AVX512
, AVX512F_Usable
,
280 CHECK_GLIBC_IFUNC_ARCH_BOTH (n
, cpu_features
,
281 Fast_Copy_Backward
, disable
,
287 CHECK_GLIBC_IFUNC_ARCH_BOTH (n
, cpu_features
,
288 Fast_Unaligned_Load
, disable
,
290 CHECK_GLIBC_IFUNC_ARCH_BOTH (n
, cpu_features
,
291 Fast_Unaligned_Copy
, disable
,
297 CHECK_GLIBC_IFUNC_ARCH_NEED_ARCH_BOTH
298 (n
, cpu_features
, Prefer_No_VZEROUPPER
, AVX_Usable
,
304 CHECK_GLIBC_IFUNC_ARCH_BOTH (n
, cpu_features
,
305 Prefer_MAP_32BIT_EXEC
, disable
,
311 CHECK_GLIBC_IFUNC_ARCH_NEED_ARCH_BOTH
312 (n
, cpu_features
, AVX_Fast_Unaligned_Load
, AVX_Usable
,
318 CHECK_GLIBC_IFUNC_ARCH_NEED_ARCH_BOTH
319 (n
, cpu_features
, MathVec_Prefer_No_AVX512
,
320 AVX512F_Usable
, disable
, 24);
325 CHECK_GLIBC_IFUNC_ARCH_NEED_CPU_BOTH
326 (n
, cpu_features
, Prefer_PMINUB_for_stringop
, SSE2
,