From ddda52b12d56b2e7f90f7a107987df3e310511bf Mon Sep 17 00:00:00 2001
From: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Date: Tue, 10 Mar 2026 13:07:50 +0000
Subject: [PATCH v1] Make Intel's ICX compiler working

Using ICX led to two issues:

1/ Issue on floating point

The tests were failing with issues such as:

@@ -225,8 +225,8 @@
 (1 row)

 SELECT date_part('epoch',       TIME '2020-05-26 13:30:25.575401');
-  date_part
---------------
- 48625.575401
+     date_part
+--------------------
+ 48625.575400999995

The reason is that ICX defaults to -fp-model=fast enabling unsafe floating-point
optimizations.

This is the same class of optimizations that we guard against by rejecting
-ffast-math in autoconf.

The commit fixes it by using the ICX -fp-model=precise flag.

2/ Issue on ICX's default runtime libraries

The tests were failing with issues such as:

postgres: postgres regression [local] CREATE SUBSCRIPTION: Relink
`/opt/intel/oneapi/compiler/2025.3/lib/libimf.so' with `/lib/x86_64-linux-gnu/libm.so.6' for IFUNC symbol `cosf'

followed by a SIGSEGV.

The reason is that ICX by default links against Intel runtime libraries such as
libimf.so, which provide IFUNC-based replacements for standard math functions (e.g.
cosf). When shared libraries built with ICX are loaded into a process that
also uses the system libm.so.6, the dynamic linker encounters conflicting
IFUNC resolvers and segfaults.

The commit fixes it by using the ICX -no-intel-lib flag.

For autoconf, ICX is detected thanks to the __INTEL_LLVM_COMPILER macro
and for meson with the compiler id "intel-llvm".
---
 configure    | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 configure.ac |  25 +++++-
 meson.build  |  33 ++++++++
 3 files changed, 275 insertions(+), 2 deletions(-)

diff --git a/configure b/configure
index 42621ecd051..741d0163b0c 100755
--- a/configure
+++ b/configure
@@ -4862,7 +4862,7 @@ fi
 fi  # have_cxx
 
 
-# Check if it's Intel's compiler, which (usually) pretends to be gcc,
+# Check if it's Intel's ICC compiler, which (usually) pretends to be gcc,
 # but has idiosyncrasies of its own.  We assume icc will define
 # __INTEL_COMPILER regardless of CFLAGS.
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4885,6 +4885,28 @@ else
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
+# Check if it's Intel's ICX compiler.
+# ICX defines __INTEL_LLVM_COMPILER but not __INTEL_COMPILER, so it
+# falls through as ICC=no above.
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __INTEL_LLVM_COMPILER
+choke me
+#endif
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ICX=yes
+else
+  ICX=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 #
 # LLVM
@@ -6901,6 +6923,201 @@ if test x"$pgac_cv_prog_CXX_cxxflags__fno_strict_aliasing" = x"yes"; then
 fi
 
 
+fi
+
+# ICX is Clang-based and takes the GCC flag path above, but also requires these
+# additional flags.
+if test "$ICX" = yes; then
+  # ICX by default links against Intel runtime libraries such as libimf.so,
+  # which provide IFUNC-based replacements for standard math functions (e.g.
+  # cosf). When shared libraries built with ICX are loaded into a process that
+  # also uses the system libm.so.6, the dynamic linker encounters conflicting
+  # IFUNC resolvers and segfaults. Use system libraries instead to avoid this.
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} supports -no-intel-lib, for CFLAGS" >&5
+$as_echo_n "checking whether ${CC} supports -no-intel-lib, for CFLAGS... " >&6; }
+if ${pgac_cv_prog_CC_cflags__no_intel_lib+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_save_CFLAGS=$CFLAGS
+pgac_save_CC=$CC
+CC=${CC}
+CFLAGS="${CFLAGS} -no-intel-lib"
+ac_save_c_werror_flag=$ac_c_werror_flag
+ac_c_werror_flag=yes
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  pgac_cv_prog_CC_cflags__no_intel_lib=yes
+else
+  pgac_cv_prog_CC_cflags__no_intel_lib=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_c_werror_flag=$ac_save_c_werror_flag
+CFLAGS="$pgac_save_CFLAGS"
+CC="$pgac_save_CC"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CC_cflags__no_intel_lib" >&5
+$as_echo "$pgac_cv_prog_CC_cflags__no_intel_lib" >&6; }
+if test x"$pgac_cv_prog_CC_cflags__no_intel_lib" = x"yes"; then
+  CFLAGS="${CFLAGS} -no-intel-lib"
+fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CXX} supports -no-intel-lib, for CXXFLAGS" >&5
+$as_echo_n "checking whether ${CXX} supports -no-intel-lib, for CXXFLAGS... " >&6; }
+if ${pgac_cv_prog_CXX_cxxflags__no_intel_lib+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_save_CXXFLAGS=$CXXFLAGS
+pgac_save_CXX=$CXX
+CXX=${CXX}
+CXXFLAGS="${CXXFLAGS} -no-intel-lib"
+ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ac_cxx_werror_flag=yes
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  pgac_cv_prog_CXX_cxxflags__no_intel_lib=yes
+else
+  pgac_cv_prog_CXX_cxxflags__no_intel_lib=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+CXXFLAGS="$pgac_save_CXXFLAGS"
+CXX="$pgac_save_CXX"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CXX_cxxflags__no_intel_lib" >&5
+$as_echo "$pgac_cv_prog_CXX_cxxflags__no_intel_lib" >&6; }
+if test x"$pgac_cv_prog_CXX_cxxflags__no_intel_lib" = x"yes"; then
+  CXXFLAGS="${CXXFLAGS} -no-intel-lib"
+fi
+
+
+  # ICX defaults to -fp-model=fast enabling unsafe floating-point optimizations.
+  # This is the same class of optimizations that we guard against by rejecting
+  # -ffast-math below. Use -fp-model=precise instead.
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} supports -fp-model=precise, for CFLAGS" >&5
+$as_echo_n "checking whether ${CC} supports -fp-model=precise, for CFLAGS... " >&6; }
+if ${pgac_cv_prog_CC_cflags__fp_model_precise+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_save_CFLAGS=$CFLAGS
+pgac_save_CC=$CC
+CC=${CC}
+CFLAGS="${CFLAGS} -fp-model=precise"
+ac_save_c_werror_flag=$ac_c_werror_flag
+ac_c_werror_flag=yes
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  pgac_cv_prog_CC_cflags__fp_model_precise=yes
+else
+  pgac_cv_prog_CC_cflags__fp_model_precise=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_c_werror_flag=$ac_save_c_werror_flag
+CFLAGS="$pgac_save_CFLAGS"
+CC="$pgac_save_CC"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CC_cflags__fp_model_precise" >&5
+$as_echo "$pgac_cv_prog_CC_cflags__fp_model_precise" >&6; }
+if test x"$pgac_cv_prog_CC_cflags__fp_model_precise" = x"yes"; then
+  CFLAGS="${CFLAGS} -fp-model=precise"
+fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CXX} supports -fp-model=precise, for CXXFLAGS" >&5
+$as_echo_n "checking whether ${CXX} supports -fp-model=precise, for CXXFLAGS... " >&6; }
+if ${pgac_cv_prog_CXX_cxxflags__fp_model_precise+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_save_CXXFLAGS=$CXXFLAGS
+pgac_save_CXX=$CXX
+CXX=${CXX}
+CXXFLAGS="${CXXFLAGS} -fp-model=precise"
+ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ac_cxx_werror_flag=yes
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  pgac_cv_prog_CXX_cxxflags__fp_model_precise=yes
+else
+  pgac_cv_prog_CXX_cxxflags__fp_model_precise=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+CXXFLAGS="$pgac_save_CXXFLAGS"
+CXX="$pgac_save_CXX"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CXX_cxxflags__fp_model_precise" >&5
+$as_echo "$pgac_cv_prog_CXX_cxxflags__fp_model_precise" >&6; }
+if test x"$pgac_cv_prog_CXX_cxxflags__fp_model_precise" = x"yes"; then
+  CXXFLAGS="${CXXFLAGS} -fp-model=precise"
+fi
+
+
 fi
 
 # If the compiler knows how to hide symbols, add the switch needed for that to
diff --git a/configure.ac b/configure.ac
index 61ec895d23c..3b0cbc3c957 100644
--- a/configure.ac
+++ b/configure.ac
@@ -428,13 +428,19 @@ fi
 fi  # have_cxx
 
 
-# Check if it's Intel's compiler, which (usually) pretends to be gcc,
+# Check if it's Intel's ICC compiler, which (usually) pretends to be gcc,
 # but has idiosyncrasies of its own.  We assume icc will define
 # __INTEL_COMPILER regardless of CFLAGS.
 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [@%:@ifndef __INTEL_COMPILER
 choke me
 @%:@endif])], [ICC=yes], [ICC=no])
 
+# Check if it's Intel's ICX compiler.
+# ICX defines __INTEL_LLVM_COMPILER but not __INTEL_COMPILER, so it
+# falls through as ICC=no above.
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [@%:@ifndef __INTEL_LLVM_COMPILER
+choke me
+@%:@endif])], [ICX=yes], [ICX=no])
 
 #
 # LLVM
@@ -649,6 +655,23 @@ elif test "$ICC" = yes; then
   PGAC_PROG_CXX_CFLAGS_OPT([-fno-strict-aliasing])
 fi
 
+# ICX is Clang-based and takes the GCC flag path above, but also requires these
+# additional flags.
+if test "$ICX" = yes; then
+  # ICX by default links against Intel runtime libraries such as libimf.so,
+  # which provide IFUNC-based replacements for standard math functions (e.g.
+  # cosf). When shared libraries built with ICX are loaded into a process that
+  # also uses the system libm.so.6, the dynamic linker encounters conflicting
+  # IFUNC resolvers and segfaults. Use system libraries instead to avoid this.
+  PGAC_PROG_CC_CFLAGS_OPT([-no-intel-lib])
+  PGAC_PROG_CXX_CFLAGS_OPT([-no-intel-lib])
+  # ICX defaults to -fp-model=fast enabling unsafe floating-point optimizations.
+  # This is the same class of optimizations that we guard against by rejecting
+  # -ffast-math below. Use -fp-model=precise instead.
+  PGAC_PROG_CC_CFLAGS_OPT([-fp-model=precise])
+  PGAC_PROG_CXX_CFLAGS_OPT([-fp-model=precise])
+fi
+
 # If the compiler knows how to hide symbols, add the switch needed for that to
 # CFLAGS_SL_MODULE and define HAVE_VISIBILITY_ATTRIBUTE.
 #
diff --git a/meson.build b/meson.build
index 2df54409ca6..2a5c35f4072 100644
--- a/meson.build
+++ b/meson.build
@@ -2183,6 +2183,26 @@ if have_cxx
   cxxflags += cxx.get_supported_arguments(common_functional_flags)
 endif
 
+# ICX is Clang-based and takes the flags above, but also requires these
+# additional flags.
+if cc.get_id() == 'intel-llvm'
+  # ICX by default links against Intel runtime libraries such as libimf.so,
+  # which provide IFUNC-based replacements for standard math functions (e.g.
+  # cosf). When shared libraries built with ICX are loaded into a process that
+  # also uses the system libm.so.6, the dynamic linker encounters conflicting
+  # IFUNC resolvers and segfaults. Use system libraries instead to avoid this.
+  cflags += cc.get_supported_arguments(['-no-intel-lib'])
+  if have_cxx
+    cxxflags += cxx.get_supported_arguments(['-no-intel-lib'])
+  endif
+  # ICX defaults to -fp-model=fast enabling unsafe floating-point optimizations.
+  # Use -fp-model=precise instead.
+  cflags += cc.get_supported_arguments(['-fp-model=precise'])
+  if have_cxx
+    cxxflags += cxx.get_supported_arguments(['-fp-model=precise'])
+  endif
+endif
+
 vectorize_cflags = cc.get_supported_arguments(['-ftree-vectorize'])
 unroll_loops_cflags = cc.get_supported_arguments(['-funroll-loops'])
 
@@ -3182,6 +3202,19 @@ add_project_arguments(cppflags, language: ['cpp'])
 add_project_arguments(cxxflags_warn, language: ['cpp'])
 add_project_link_arguments(ldflags, language: ['c', 'cpp'])
 
+# ICX by default links against Intel runtime libraries such as libimf.so,
+# which provide IFUNC-based replacements for standard math functions (e.g.
+# cosf). When shared libraries built with ICX are loaded into a process that
+# also uses the system libm.so.6, the dynamic linker encounters conflicting
+# IFUNC resolvers and segfaults. Use system libraries instead to avoid this.
+if cc.get_id() == 'intel-llvm'
+  add_project_link_arguments(
+    cc.get_supported_link_arguments(['-no-intel-lib']), language: 'c')
+  if have_cxx and cxx.get_id() == 'intel-llvm'
+    add_project_link_arguments(
+      cxx.get_supported_link_arguments(['-no-intel-lib']), language: 'cpp')
+  endif
+endif
 
 # Collect a number of lists of things while recursing through the source
 # tree. Later steps then can use those.
-- 
2.34.1

