]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
x86-64: Properly compile ISA optimized modf and modff
authorH.J. Lu <hjl.tools@gmail.com>
Thu, 17 Jul 2025 23:00:42 +0000 (16:00 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Fri, 18 Jul 2025 17:22:19 +0000 (10:22 -0700)
There are 3 variants of modf and modff: SSE2, SSE4.1 and AVX.  s_modf.c
and s_modff.c include the generic implementation compiled with the minimum
x86 ISA level.  The IFUNC selector is used only if the minimum ISA level
is less than AVX.  SSE4.1 variant is included only if the ISA level is
less than SSE4.1.  AVX variant is included only the ISA level is less than
AVX.

AVX variant should be compiled with -mavx, not -msse2avx -DSSE2AVX which
are used to encode SSE assembly sources with EVEX encoding.

The routines that are shared between libc and libm should use different
rules to avoid using the same MODULE_NAME, to avoid potential issues
like BZ #33165 where __stack_chk_fail not being routed to the internal
symbol.

Tested with -march=x86-64, -march=x86-64-v2, -march=x86-64-v3 and
-march=x86-64-v4.

This fixes BZ #33165 and BZ #33173.

Co-authored-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
12 files changed:
sysdeps/x86/configure
sysdeps/x86/configure.ac
sysdeps/x86_64/fpu/multiarch/Makefile
sysdeps/x86_64/fpu/multiarch/ifunc-sse4_1-avx.h [new file with mode: 0644]
sysdeps/x86_64/fpu/multiarch/s_modf-avx.c
sysdeps/x86_64/fpu/multiarch/s_modf-c.c [deleted file]
sysdeps/x86_64/fpu/multiarch/s_modf-sse4_1.c
sysdeps/x86_64/fpu/multiarch/s_modf.c
sysdeps/x86_64/fpu/multiarch/s_modff-avx.c
sysdeps/x86_64/fpu/multiarch/s_modff-c.c [deleted file]
sysdeps/x86_64/fpu/multiarch/s_modff-sse4_1.c
sysdeps/x86_64/fpu/multiarch/s_modff.c

index c7ea9ac6adff19e47e0f6c11affc7e2d6b26d3d4..dff26e9b83375fa364a135282e53f829db4f1f8f 100644 (file)
@@ -171,8 +171,12 @@ fi
 config_vars="$config_vars
 have-x86-isa-level = $libc_cv_have_x86_isa_level"
 config_vars="$config_vars
+x86-isa-level-2-or-above = 2 3 4"
+config_vars="$config_vars
 x86-isa-level-3-or-above = 3 4"
 config_vars="$config_vars
+x86-isa-level-4-or-above = 4"
+config_vars="$config_vars
 enable-x86-isa-level = $libc_cv_include_x86_isa_level"
 
 
index 031f91719d0b47655f5c483c5d4be0f7b38c13e2..54960a71c95edfc3053ec588b369eba4074f12fc 100644 (file)
@@ -117,7 +117,9 @@ else
   AC_DEFINE_UNQUOTED(MINIMUM_X86_ISA_LEVEL, $libc_cv_have_x86_isa_level)
 fi
 LIBC_CONFIG_VAR([have-x86-isa-level], [$libc_cv_have_x86_isa_level])
+LIBC_CONFIG_VAR([x86-isa-level-2-or-above], [2 3 4])
 LIBC_CONFIG_VAR([x86-isa-level-3-or-above], [3 4])
+LIBC_CONFIG_VAR([x86-isa-level-4-or-above], [4])
 LIBC_CONFIG_VAR([enable-x86-isa-level], [$libc_cv_include_x86_isa_level])
 
 dnl Check if TEST_CC supports -mfpmath=387
index 81a870d3b1dbb9fc1439bbdf5ef7444175d67a04..708b14297fa553c8c7d06438c3a33063a414620a 100644 (file)
@@ -26,19 +26,21 @@ CFLAGS-s_sinf-fma.c = -mfma -mavx2
 CFLAGS-s_cosf-fma.c = -mfma -mavx2
 CFLAGS-s_sincosf-fma.c = -mfma -mavx2
 
+# Check if ISA level is 2 or above.
+ifeq (,$(filter $(have-x86-isa-level),$(x86-isa-level-2-or-above)))
+sysdep_calls += \
+  s_modf-sse4_1 \
+  s_modff-sse4_1 \
+# sysdep_calls
+endif
+
 # Check if ISA level is 3 or above.
 ifneq (,$(filter $(have-x86-isa-level),$(x86-isa-level-3-or-above)))
-sysdep_routines += \
-  s_modf-avx \
-  s_modff-avx \
-# sysdep_routines
 libm-sysdep_routines += \
   s_ceil-avx \
   s_ceilf-avx \
   s_floor-avx \
   s_floorf-avx \
-  s_modf-avx \
-  s_modff-avx \
   s_nearbyint-avx \
   s_nearbyintf-avx \
   s_rint-avx \
@@ -49,6 +51,10 @@ libm-sysdep_routines += \
   s_truncf-avx \
 # libm-sysdep_routines
 else
+sysdep_calls += \
+  s_modf-avx \
+  s_modff-avx \
+# sysdep_calls
 ifeq (no,$(have-x86-apx))
 libm-sysdep_routines += \
   e_asin-fma4 \
@@ -62,10 +68,6 @@ libm-sysdep_routines += \
   s_tan-fma4 \
 # libm-sysdep_routines
 endif
-sysdep_routines += \
-  s_modf-sse4_1 \
-  s_modff-sse4_1 \
-# sysdep_routines
 libm-sysdep_routines += \
   e_asin-fma \
   e_atan2-avx \
@@ -95,8 +97,6 @@ libm-sysdep_routines += \
   s_floor-sse4_1 \
   s_floorf-sse4_1 \
   s_log1p-fma \
-  s_modf-sse4_1 \
-  s_modff-sse4_1 \
   s_nearbyint-sse4_1 \
   s_nearbyintf-sse4_1 \
   s_rint-sse4_1 \
@@ -118,17 +118,11 @@ libm-sysdep_routines += \
   s_truncf-sse4_1 \
 # libm-sysdep_routines
 ifeq ($(have-x86-isa-level),baseline)
-sysdep_routines += \
-  s_modf-c \
-  s_modff-c \
-# sysdep-routines
 libm-sysdep_routines += \
   s_ceil-c \
   s_ceilf-c \
   s_floor-c \
   s_floorf-c \
-  s_modf-c \
-  s_modff-c \
   s_nearbyint-c \
   s_nearbyintf-c \
   s_rint-c \
@@ -139,6 +133,11 @@ libm-sysdep_routines += \
   s_truncf-c \
 # libm-sysdep_routines
 endif
+
+# $(sysdep_calls) functions are built both for libc and libm.  While the
+# libc objects have the prefix s_, the libm ones are prefixed with m_.
+sysdep_routines += $(sysdep_calls)
+libm-sysdep_routines += $(sysdep_calls:s_%=m_%)
 endif
 
 CFLAGS-e_asin-fma4.c = -mfma4
@@ -159,18 +158,11 @@ CFLAGS-s_sin-avx.c = -msse2avx -DSSE2AVX
 CFLAGS-s_tan-avx.c = -msse2avx -DSSE2AVX
 CFLAGS-s_sincos-avx.c = -msse2avx -DSSE2AVX
 
-CFLAGS-s_modf-c.c = $(no-stack-protector)
-CFLAGS-s_modff-c.c = $(no-stack-protector)
-
-CFLAGS-s_modf-sse4_1.c = -msse4.1 -fno-builtin-modff32x \
-                        -fno-builtin-modff64 $(no-stack-protector)
-CFLAGS-s_modff-sse4_1.c = -msse4.1 -fno-builtin-modff32 \
-                         $(no-stack-protector)
+CFLAGS-s_modf-sse4_1.c = -msse4.1 -fno-builtin-modff32x -fno-builtin-modff64
+CFLAGS-s_modff-sse4_1.c = -msse4.1 -fno-builtin-modff32
 
-CFLAGS-s_modf-avx.c = -msse2avx -DSSE2AVX -fno-builtin-modff32x \
-                     $(no-stack-protector) -fno-builtin-modff64
-CFLAGS-s_modff-avx.c = -msse2avx -DSSE2AVX -fno-builtin-modff32 \
-                     $(no-stack-protector)
+CFLAGS-s_modf-avx.c = -mavx -fno-builtin-modff32x -fno-builtin-modff64
+CFLAGS-s_modff-avx.c = -mavx -fno-builtin-modff32
 endif
 
 ifeq ($(subdir),mathvec)
diff --git a/sysdeps/x86_64/fpu/multiarch/ifunc-sse4_1-avx.h b/sysdeps/x86_64/fpu/multiarch/ifunc-sse4_1-avx.h
new file mode 100644 (file)
index 0000000..071595f
--- /dev/null
@@ -0,0 +1,41 @@
+/* Common definition for ifunc selections optimized with SSE4.1 and AVX.
+   Copyright (C) 2025 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <init-arch.h>
+
+extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2) attribute_hidden;
+extern __typeof (REDIRECT_NAME) OPTIMIZE (sse41) attribute_hidden;
+extern __typeof (REDIRECT_NAME) OPTIMIZE (avx) attribute_hidden;
+
+static inline void *
+IFUNC_SELECTOR (void)
+{
+  const struct cpu_features* cpu_features = __get_cpu_features ();
+
+  if (CPU_FEATURE_USABLE_P (cpu_features, AVX))
+    return OPTIMIZE (avx);
+
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+  return OPTIMIZE (sse41);
+#else
+  if (CPU_FEATURE_USABLE_P (cpu_features, SSE4_1))
+    return OPTIMIZE (sse41);
+
+  return OPTIMIZE (sse2);
+#endif
+}
index db32398b4ab56db2a149aa161a82fbd0ee274379..ab4f03db0ee19cd7249e93d4f6fc37bc645435b2 100644 (file)
@@ -1 +1,3 @@
+#define __modf __modf_avx
+
 #include <sysdeps/ieee754/dbl-64/s_modf.c>
diff --git a/sysdeps/x86_64/fpu/multiarch/s_modf-c.c b/sysdeps/x86_64/fpu/multiarch/s_modf-c.c
deleted file mode 100644 (file)
index 6679d32..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#define __modf __modf_c
-#include <sysdeps/ieee754/dbl-64/s_modf.c>
index 6ef4c19a7e7d2ed3d7408bc37d62dda0774950a1..00aa8cd7365682460eef1f9c0aa73318df2e0032 100644 (file)
@@ -1,7 +1,3 @@
-#include <sysdeps/x86/isa-level.h>
-
-#if MINIMUM_X86_ISA_LEVEL != SSE4_1_X86_ISA_LEVEL
-# define __modf __modf_sse41
-#endif
+#define __modf __modf_sse41
 
 #include <sysdeps/ieee754/dbl-64/s_modf.c>
index d65977d69aac51c64fe31883e1c351d7b3d247f8..e365bfcef7d3686f8d0b5b3bc450a225928bb29a 100644 (file)
@@ -17,7 +17,7 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include <sysdeps/x86/isa-level.h>
-#if MINIMUM_X86_ISA_LEVEL < SSE4_1_X86_ISA_LEVEL
+#if MINIMUM_X86_ISA_LEVEL < AVX_X86_ISA_LEVEL
 # define NO_MATH_REDIRECT
 # include <libm-alias-double.h>
 
 # undef __modf
 
 # define SYMBOL_NAME modf
-# include "ifunc-sse4_1.h"
+# include "ifunc-sse4_1-avx.h"
 
 libc_ifunc_redirected (__redirect_modf, __modf, IFUNC_SELECTOR ());
 libm_alias_double (__modf, modf)
+# if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+#  define __modf __modf_sse41
+# else
+#  define __modf __modf_sse2
+# endif
 #endif
+#include <sysdeps/ieee754/dbl-64/s_modf.c>
index 804b0426b73fed795e2835ef56006fe2697b5ac1..07cb9c10360387edc2ca975673bcafa7a0723910 100644 (file)
@@ -1 +1,3 @@
+#define __modff __modff_avx
+
 #include <sysdeps/ieee754/flt-32/s_modff.c>
diff --git a/sysdeps/x86_64/fpu/multiarch/s_modff-c.c b/sysdeps/x86_64/fpu/multiarch/s_modff-c.c
deleted file mode 100644 (file)
index f54f8ea..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#define __modff __modff_c
-#include <sysdeps/ieee754/flt-32/s_modff.c>
index 0437e044f33b66a7e1bb6030b8fff930c224bf27..060c5e39796f6f4a2819fbb9ae0d55992c0a64d6 100644 (file)
@@ -1,7 +1,3 @@
-#include <sysdeps/x86/isa-level.h>
-
-#if MINIMUM_X86_ISA_LEVEL != SSE4_1_X86_ISA_LEVEL
-# define __modff __modff_sse41
-#endif
+#define __modff __modff_sse41
 
 #include <sysdeps/ieee754/flt-32/s_modff.c>
index 89d0a32c23aff440163d2e6b21dd597fe0284f2b..a4b542903771577c6ee66b4722e6a01995a81823 100644 (file)
@@ -17,7 +17,7 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include <sysdeps/x86/isa-level.h>
-#if MINIMUM_X86_ISA_LEVEL < SSE4_1_X86_ISA_LEVEL
+#if MINIMUM_X86_ISA_LEVEL < AVX_X86_ISA_LEVEL
 # define NO_MATH_REDIRECT
 # include <libm-alias-float.h>
 
 # undef __modff
 
 # define SYMBOL_NAME modff
-# include "ifunc-sse4_1.h"
+# include "ifunc-sse4_1-avx.h"
 
 libc_ifunc_redirected (__redirect_modff, __modff, IFUNC_SELECTOR ());
 libm_alias_float (__modf, modf)
+# if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+#  define __modff __modff_sse41
+# else
+#  define __modff __modff_sse2
+# endif
 #endif
+#include <sysdeps/ieee754/flt-32/s_modff.c>