Detect i586 and i686 features at run-time
Commit Message
On Tue, Aug 18, 2015 at 10:30 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Tue, Aug 18, 2015 at 9:16 AM, Joseph Myers <joseph@codesourcery.com> wrote:
>> On Tue, 18 Aug 2015, H.J. Lu wrote:
>>
>>> My change is based on sysdeps/x86/bits/string.h and
>>> sysdeps/x86/bits/byteswap.h. None of them check
>>> __i586__ nor __i686__.
>>
>> Maybe
>>
>> (a) there should be a new (installed) bits/ header for x86, say
>> bits/x86-arch.h, that defines __x86_arch to 4, 5 or 6 depending on such
>> macros, so the logic doesn't need duplicating;
>>
>
> We can add cpu-features.h to installed header to provide both
> run-time and compile-time CPU feature detection.
>
Here is a patch which does that. OK for master?
Comments
On 18 Aug 2015 11:25, H.J. Lu wrote:
> We detect i586 and i686 features at run-time by checking CX8 and CMOV
> CPUID features bits. We can use these information to select the best
> implementation in ix86 multiarch.
there are i686's w/out cmov. shouldn't multiarch implementations that use
certain insns be tied to those rather than a big knob like "i686" ?
-mike
On Tue, Aug 18, 2015 at 9:20 PM, Mike Frysinger <vapier@gentoo.org> wrote:
> On 18 Aug 2015 11:25, H.J. Lu wrote:
>> We detect i586 and i686 features at run-time by checking CX8 and CMOV
>> CPUID features bits. We can use these information to select the best
>> implementation in ix86 multiarch.
>
> there are i686's w/out cmov. shouldn't multiarch implementations that use
> certain insns be tied to those rather than a big knob like "i686" ?
> -mike
For purpose glibc build, i686 has cmov:
[hjl@gnu-tools-1 glibc]$ grep cmov sysdeps/i386/i686/*.S
sysdeps/i386/i686/strcmp.S: cmovbl %ecx, %eax
sysdeps/i386/i686/strtok.S: cmove %eax, %edx
sysdeps/i386/i686/strtok.S: cmovne %ecx, %edx
[hjl@gnu-tools-1 glibc]$
[
On 19 Aug 2015 04:19, H.J. Lu wrote:
> On Tue, Aug 18, 2015 at 9:20 PM, Mike Frysinger wrote:
> > On 18 Aug 2015 11:25, H.J. Lu wrote:
> >> We detect i586 and i686 features at run-time by checking CX8 and CMOV
> >> CPUID features bits. We can use these information to select the best
> >> implementation in ix86 multiarch.
> >
> > there are i686's w/out cmov. shouldn't multiarch implementations that use
> > certain insns be tied to those rather than a big knob like "i686" ?
>
> For purpose glibc build, i686 has cmov:
>
> [hjl@gnu-tools-1 glibc]$ grep cmov sysdeps/i386/i686/*.S
> sysdeps/i386/i686/strcmp.S: cmovbl %ecx, %eax
> sysdeps/i386/i686/strtok.S: cmove %eax, %edx
> sysdeps/i386/i686/strtok.S: cmovne %ecx, %edx
i think that deserves a comment in the source
-mike
From 2b90b962da5463421592b0d3c64b6e32f487ec5a Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 17 Aug 2015 10:19:05 -0700
Subject: [PATCH] Detect i586 and i686 features at run-time.
We detect i586 and i686 features at run-time by checking CX8 and CMOV
CPUID features bits. We can use these information to select the best
implementation in ix86 multiarch.
* sysdeps/x86/cpu-features.c (init_cpu_features): Set bit_I586
bit if CX8 is available. Set bit_I686 bit if CMOV is available.
* sysdeps/x86/cpu-features.h (bit_I586): New.
(bit_I686): Likewise.
(bit_CX8): Likewise.
(bit_CMOV): Likewise.
(index_CX8): Likewise.
(index_CMOV): Likewise.
(index_I586): Likewise.
(index_I686): Likewise.
(reg_CX8): Likewise.
(reg_CMOV): Likewise.
(HAS_I586): Defined as HAS_ARCH_FEATURE (I586) if i586 isn't
available at compile-time.
(HAS_I686): Defined as HAS_ARCH_FEATURE (I686) if i686 isn't
available at compile-time.
xx
---
sysdeps/x86/cpu-features.c | 8 ++++++++
sysdeps/x86/cpu-features.h | 20 +++++++++++++++++---
2 files changed, 25 insertions(+), 3 deletions(-)
@@ -150,6 +150,14 @@ init_cpu_features (struct cpu_features *cpu_features)
else
kind = arch_kind_other;
+ /* Support i586 if CX8 is available. */
+ if (HAS_CPU_FEATURE (CX8))
+ cpu_features->feature[index_I586] |= bit_I586;
+
+ /* Support i686 if CMOV is available. */
+ if (HAS_CPU_FEATURE (CMOV))
+ cpu_features->feature[index_I686] |= bit_I686;
+
if (cpu_features->max_cpuid >= 7)
__cpuid_count (7, 0,
cpu_features->cpuid[COMMON_CPUID_INDEX_7].eax,
@@ -31,10 +31,14 @@
#define bit_AVX_Fast_Unaligned_Load (1 << 11)
#define bit_AVX512F_Usable (1 << 12)
#define bit_AVX512DQ_Usable (1 << 13)
+#define bit_I586 (1 << 14)
+#define bit_I686 (1 << 15)
/* CPUID Feature flags. */
/* COMMON_CPUID_INDEX_1. */
+#define bit_CX8 (1 << 8)
+#define bit_CMOV (1 << 15)
#define bit_SSE2 (1 << 26)
#define bit_SSSE3 (1 << 9)
#define bit_SSE4_1 (1 << 19)
@@ -69,6 +73,8 @@
# include <ifunc-defines.h>
# include <rtld-global-offsets.h>
+# define index_CX8 COMMON_CPUID_INDEX_1*CPUID_SIZE+CPUID_EDX_OFFSET
+# define index_CMOV COMMON_CPUID_INDEX_1*CPUID_SIZE+CPUID_EDX_OFFSET
# define index_SSE2 COMMON_CPUID_INDEX_1*CPUID_SIZE+CPUID_EDX_OFFSET
# define index_SSSE3 COMMON_CPUID_INDEX_1*CPUID_SIZE+CPUID_ECX_OFFSET
# define index_SSE4_1 COMMON_CPUID_INDEX_1*CPUID_SIZE+CPUID_ECX_OFFSET
@@ -89,6 +95,8 @@
# define index_AVX_Fast_Unaligned_Load FEATURE_INDEX_1*FEATURE_SIZE
# define index_AVX512F_Usable FEATURE_INDEX_1*FEATURE_SIZE
# define index_AVX512DQ_Usable FEATURE_INDEX_1*FEATURE_SIZE
+# define index_I586 FEATURE_INDEX_1*FEATURE_SIZE
+# define index_I686 FEATURE_INDEX_1*FEATURE_SIZE
# if defined (_LIBC) && !IS_IN (nonlib)
# ifdef __x86_64__
@@ -193,6 +201,8 @@ extern const struct cpu_features *__get_cpu_features (void)
# define HAS_ARCH_FEATURE(name) \
((__get_cpu_features ()->feature[index_##name] & (bit_##name)) != 0)
+# define index_CX8 COMMON_CPUID_INDEX_1
+# define index_CMOV COMMON_CPUID_INDEX_1
# define index_SSE2 COMMON_CPUID_INDEX_1
# define index_SSSE3 COMMON_CPUID_INDEX_1
# define index_SSE4_1 COMMON_CPUID_INDEX_1
@@ -207,6 +217,8 @@ extern const struct cpu_features *__get_cpu_features (void)
# define index_POPCOUNT COMMON_CPUID_INDEX_1
# define index_OSXSAVE COMMON_CPUID_INDEX_1
+# define reg_CX8 edx
+# define reg_CMOV edx
# define reg_SSE2 edx
# define reg_SSSE3 ecx
# define reg_SSE4_1 ecx
@@ -234,6 +246,8 @@ extern const struct cpu_features *__get_cpu_features (void)
# define index_AVX_Fast_Unaligned_Load FEATURE_INDEX_1
# define index_AVX512F_Usable FEATURE_INDEX_1
# define index_AVX512DQ_Usable FEATURE_INDEX_1
+# define index_I586 FEATURE_INDEX_1
+# define index_I686 FEATURE_INDEX_1
#endif /* !__ASSEMBLER__ */
@@ -242,7 +256,7 @@ extern const struct cpu_features *__get_cpu_features (void)
#elif defined __pentium__
# define HAS_CPUID 1
# define HAS_I586 1
-# define HAS_I686 0
+# define HAS_I686 HAS_ARCH_FEATURE (I686)
#elif (defined __pentiumpro__ || defined __pentium4__ \
|| defined __nocona__ || defined __atom__ \
|| defined __core2__ || defined __corei7__ \
@@ -260,8 +274,8 @@ extern const struct cpu_features *__get_cpu_features (void)
# define HAS_I686 1
#else
# define HAS_CPUID 0
-# define HAS_I586 0
-# define HAS_I686 0
+# define HAS_I586 HAS_ARCH_FEATURE (I586)
+# define HAS_I686 HAS_ARCH_FEATURE (I686)
#endif
#endif /* cpu_features_h */
--
2.4.3