]> sourceware.org Git - glibc.git/commitdiff
Detect and select i586/i686 implementation at run-time fedora/master
authorH.J. Lu <hjl.tools@gmail.com>
Thu, 27 Aug 2015 16:06:26 +0000 (09:06 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Thu, 27 Aug 2015 16:06:44 +0000 (09:06 -0700)
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.  HAS_I586/HAS_I686 is true if i586/i686
instructions are available on the processor.

Due to the reordering and the other nifty extensions in i686, it is not
really good to use heavily i586 optimized code on an i686.  It's better
to use i486 code if it isn't an i586.  USE_I586/USE_I686 is true if
i586/i686 implementation should be used for the processor.  USE_I586
is true only if i686 instructions aren't available.  If i686 instructions
are available, we always choose i686 or i486 implementation, in that order,
and we never choose i586 implementation for i686-class processors.

* sysdeps/i386/init-arch.h: New file.
* sysdeps/i386/i586/init-arch.h: Likewise.
* sysdeps/i386/i686/init-arch.h: Likewise.
* 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.
* sysdeps/x86/init-arch.h (USE_I586): New macro.
(USE_I686): Likewise.

ChangeLog
sysdeps/i386/i586/init-arch.h [new file with mode: 0644]
sysdeps/i386/i686/init-arch.h [new file with mode: 0644]
sysdeps/i386/init-arch.h [new file with mode: 0644]
sysdeps/x86/cpu-features.c
sysdeps/x86/cpu-features.h
sysdeps/x86/init-arch.h

index df391c2a780ae57353fa360dc5b8789b158bd7b2..844bbf7eef64d0165fac641ad4ef4e077d1f0e17 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2015-08-27  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * sysdeps/i386/init-arch.h: New file.
+       * sysdeps/i386/i586/init-arch.h: Likewise.
+       * sysdeps/i386/i686/init-arch.h: Likewise.
+       * 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.
+       * sysdeps/x86/init-arch.h (USE_I586): New macro.
+       (USE_I686): Likewise.
+
 2015-08-27  H.J. Lu  <hongjiu.lu@intel.com>
 
        * sysdeps/i386/bcopy.S: New file.
diff --git a/sysdeps/i386/i586/init-arch.h b/sysdeps/i386/i586/init-arch.h
new file mode 100644 (file)
index 0000000..50c43a2
--- /dev/null
@@ -0,0 +1,19 @@
+/* Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define MINIMUM_ISA 586
+#include <sysdeps/x86/init-arch.h>
diff --git a/sysdeps/i386/i686/init-arch.h b/sysdeps/i386/i686/init-arch.h
new file mode 100644 (file)
index 0000000..b4a2735
--- /dev/null
@@ -0,0 +1,19 @@
+/* Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define MINIMUM_ISA 686
+#include <sysdeps/x86/init-arch.h>
diff --git a/sysdeps/i386/init-arch.h b/sysdeps/i386/init-arch.h
new file mode 100644 (file)
index 0000000..0c74ddc
--- /dev/null
@@ -0,0 +1,19 @@
+/* Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define MINIMUM_ISA 486
+#include <sysdeps/x86/init-arch.h>
index 40575de611ca251ea2ba70893bc5619f46d00ec8..b03451dde1bc76857d1c653daec1038925d80d8b 100644 (file)
@@ -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,
index 6e706241adc49a84ff94b3317164f69693207eec..80edbee75cbda1d69198fb52f2038b56287737a2 100644 (file)
 #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 __i586__ || defined __pentium__
 # define HAS_CPUID 1
 # define HAS_I586 1
-# define HAS_I686 0
+# define HAS_I686 HAS_ARCH_FEATURE (I686)
 #elif (defined __i686__ || defined __pentiumpro__              \
        || defined __pentium4__ || defined __nocona__           \
        || defined __atom__ || defined __core2__                        \
@@ -261,8 +275,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 */
index 2b9988ebc3f5c67ebd1a88ac3a610f3008d30a96..55897fabf2aea98583f42d7f179254c97f327fec 100644 (file)
 #else
 # include <ldsodefs.h>
 #endif
+
+#ifndef __x86_64__
+/* Due to the reordering and the other nifty extensions in i686, it is
+   not really good to use heavily i586 optimized code on an i686.  It's
+   better to use i486 code if it isn't an i586.  */
+# if MINIMUM_ISA == 686
+#  define USE_I586 0
+#  define USE_I686 1
+# else
+#  define USE_I586 (HAS_ARCH_FEATURE (I586) && !HAS_ARCH_FEATURE (I686))
+#  define USE_I686 HAS_ARCH_FEATURE (I686)
+# endif
+#endif
This page took 0.104128 seconds and 5 git commands to generate.