[PATCH] i386: Fix fmod/fmof/remainder/remainderf for gcc-12

H.J. Lu hjl.tools@gmail.com
Tue Dec 2 23:34:08 GMT 2025


On Wed, Dec 3, 2025 at 1:39 AM Adhemerval Zanella Netto
<adhemerval.zanella@linaro.org> wrote:
>
>
>
> On 01/12/25 20:09, H.J. Lu wrote:
> > On Thu, Nov 20, 2025 at 8:21 PM Adhemerval Zanella
> > <adhemerval.zanella@linaro.org> wrote:
> >>
> >> The __builtin_fmod{f} and __builtin_remainder{f} were added on gcc 13,
> >> and the minimum supported gcc is 12.  This patch adds a configure test
> >> to check whether the compiler enables inlining for fmod/remainder, and
> >> uses inline assembly if not.
> >>
> >> Checked on i686-linux-gnu wih gcc-12.
> >> ---
> >>  config.h.in                     |  3 +++
> >>  sysdeps/i386/fpu/e_fmod.c       | 14 ++++++++++
> >>  sysdeps/i386/fpu/e_fmodf.c      | 14 ++++++++++
> >>  sysdeps/i386/fpu/e_remainder.c  | 14 ++++++++++
> >>  sysdeps/i386/fpu/e_remainderf.c | 14 ++++++++++
> >>  sysdeps/x86/configure           | 48 +++++++++++++++++++++++++++++++++
> >>  sysdeps/x86/configure.ac        | 27 +++++++++++++++++++
> >>  7 files changed, 134 insertions(+)
> >>
> >> diff --git a/config.h.in b/config.h.in
> >> index a7cc17df8e..bfcd29bcdf 100644
> >> --- a/config.h.in
> >> +++ b/config.h.in
> >> @@ -317,6 +317,9 @@
> >>  /* Define if trunc is inlined on x86.  */
> >>  #undef HAVE_X86_INLINE_TRUNC
> >>
> >> +/* Define if __builtin_fmod/__builtin_remainder is inlined on x86.  */
> >> +#undef HAVE_X86_INLINE_FMOD
> >> +
> >>  /* Define if compiler allows add attribute after function declaration.  */
> >>  #undef ATTR_AFTER_FUNC_DECL
> >>
> >> diff --git a/sysdeps/i386/fpu/e_fmod.c b/sysdeps/i386/fpu/e_fmod.c
> >> index 281b23dffc..93b6f9d698 100644
> >> --- a/sysdeps/i386/fpu/e_fmod.c
> >> +++ b/sysdeps/i386/fpu/e_fmod.c
> >> @@ -33,7 +33,21 @@ __fmod (double x, double y)
> >>                         && !is_nan (hx)))
> >>      return __math_invalid (x);
> >>
> >> +#if HAVE_X86_INLINE_FMOD
> >>    return __builtin_fmod (x, y);
> >> +#else
> >> +  double result;
> >> +  asm ("1:\n"
> >> +       "fprem\n"
> >> +       "fnstsw %%ax\n"
> >> +       "sahf\n"
> >> +       "jp     1b\n"
> >> +       : "=t" (result)
> >> +       : "0" (x), "u" (y)
> >> +       : "ax", "cc"
> >> +    );
> >> +  return result;
> >> +#endif
> >
> > Please define INLINE_FMOD in x86/fpu/math-inline-asm.h, depending on
> > HAVE_X86_INLINE_FMOD.
>
> Ok, although I modeled this patch on your recent 1fa5773eb1c that
> added a similar flag (HAVE_X86_INLINE_TRUNC). That's why I used this
> directly.

When GCC 13 is required to build glibc, we only need to change
sysdeps/x86/fpu/math-inline-asm.h.

BTW, we can consolidate x86 inline decisions in
sysdeps/x86/fpu/math-inline-asm.h.

> >
> >>  }
> >>  strong_alias (__fmod, __ieee754_fmod)
> >>  libm_alias_finite (__ieee754_fmod, __fmod)
> >> diff --git a/sysdeps/i386/fpu/e_fmodf.c b/sysdeps/i386/fpu/e_fmodf.c
> >> index 5b05d0fd95..e94ef89534 100644
> >> --- a/sysdeps/i386/fpu/e_fmodf.c
> >> +++ b/sysdeps/i386/fpu/e_fmodf.c
> >> @@ -33,7 +33,21 @@ __fmodf (float x, float y)
> >>                         && !is_nan (hx)))
> >>      return __math_invalidf (x);
> >>
> >> +#if HAVE_X86_INLINE_FMOD
> >>    return __builtin_fmodf (x, y);
> >> +#else
> >> +  float result;
> >> +  asm ("1:\n"
> >> +       "fprem\n"
> >> +       "fnstsw %%ax\n"
> >> +       "sahf\n"
> >> +       "jp     1b\n"
> >> +       : "=t" (result)
> >> +       : "0" (x), "u" (y)
> >> +       : "ax", "cc"
> >> +    );
> >> +  return result;
> >> +#endif
> >>  }
> >>  strong_alias (__fmodf, __ieee754_fmodf)
> >>  versioned_symbol (libm, __fmodf, fmodf, GLIBC_2_43);
> >> diff --git a/sysdeps/i386/fpu/e_remainder.c b/sysdeps/i386/fpu/e_remainder.c
> >> index ec907ecaf9..4c3be1165a 100644
> >> --- a/sysdeps/i386/fpu/e_remainder.c
> >> +++ b/sysdeps/i386/fpu/e_remainder.c
> >> @@ -33,7 +33,21 @@ __remainder (double x, double y)
> >>                         && !is_nan (hx)))
> >>      return __math_invalid (x);
> >>
> >> +#if HAVE_X86_INLINE_FMOD
> >>    return __builtin_remainder (x, y);
> >> +#else
> >> +  double result;
> >> +  asm ("1:\n"
> >> +       "fprem1\n"
> >> +       "fnstsw %%ax\n"
> >> +       "sahf\n"
> >> +       "jp     1b\n"
> >> +       : "=t" (result)
> >> +       : "0" (x), "u" (y)
> >> +       : "ax", "cc"
> >> +    );
> >> +  return result;
> >> +#endif
> >>  }
> >>  strong_alias (__remainder, __ieee754_remainder)
> >>  versioned_symbol (libm, __remainder, remainder, GLIBC_2_43);
> >> diff --git a/sysdeps/i386/fpu/e_remainderf.c b/sysdeps/i386/fpu/e_remainderf.c
> >> index 30ca4d3600..e725f892cf 100644
> >> --- a/sysdeps/i386/fpu/e_remainderf.c
> >> +++ b/sysdeps/i386/fpu/e_remainderf.c
> >> @@ -33,7 +33,21 @@ __remainderf (float x, float y)
> >>                         && !is_nan (hx)))
> >>      return __math_invalidf (x);
> >>
> >> +#if HAVE_X86_INLINE_FMOD
> >>    return __builtin_remainderf (x, y);
> >> +#else
> >> +  float result;
> >> +  asm ("1:\n"
> >> +       "fprem1\n"
> >> +       "fnstsw %%ax\n"
> >> +       "sahf\n"
> >> +       "jp     1b\n"
> >> +       : "=t" (result)
> >> +       : "0" (x), "u" (y)
> >> +       : "ax", "cc"
> >> +    );
> >> +  return result;
> >> +#endif
> >>  }
> >>  strong_alias (__remainderf, __ieee754_remainderf)
> >>  versioned_symbol (libm, __remainderf, remainderf, GLIBC_2_43);
> >> diff --git a/sysdeps/x86/configure b/sysdeps/x86/configure
> >> index e530a18f54..0798f194b6 100644
> >> --- a/sysdeps/x86/configure
> >> +++ b/sysdeps/x86/configure
> >> @@ -430,6 +430,54 @@ else
> >>
> >>  fi
> >>
> >> +conftest_code="
> >> +double foo (double x, double y)
> >> +{
> >> +  return __builtin_fmod (x, y);
> >> +}
> >> +"
> >> +
> >> +cat > conftest.c <<EOF
> >> +$conftest_code
> >> +EOF
> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler inlines __builtin_fmod/__builtin_remainder" >&5
> >> +printf %s "checking if compiler inlines __builtin_fmod/__builtin_remainder... " >&6; }
> >> +if test ${libc_cv_cc_x86_inline_fmod+y}
> >> +then :
> >> +  printf %s "(cached) " >&6
> >> +else case e in #(
> >> +  e)   if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $CFLAGS -fno-math-errno -S conftest.c -o conftest 1>&5'
> >> +  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
> >> +  (eval $ac_try) 2>&5
> >> +  ac_status=$?
> >> +  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> >> +  test $ac_status = 0; }; }
> >> +  then
> >> +
> >> +libc_cv_cc_x86_inline_fmod=no
> >> +if grep -E -q "fprem" conftest; then
> >> +  libc_cv_cc_x86_inline_fmod=yes
> >> +fi
> >> +
> >> +  else
> >> +
> >> +echo "failed to check if CC inlines fmod."
> >> +rm -f conftest*
> >> +exit 1
> >> +
> >> +  fi ;;
> >> +esac
> >> +fi
> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_cc_x86_inline_fmod" >&5
> >> +printf "%s\n" "$libc_cv_cc_x86_inline_fmod" >&6; }
> >> +rm -f conftest*
> >> +if test "$libc_cv_cc_x86_inline_fmod" = yes; then
> >> +  printf "%s\n" "#define HAVE_X86_INLINE_FMOD 1" >>confdefs.h
> >> +
> >> +else
> >> +  printf "%s\n" "#define HAVE_X86_INLINE_FMOD 0" >>confdefs.h
> >> +
> >> +fi
> >>
> >>  if test "${libc_cv_cc_no_direct_extern_access}${libc_cv_test_cc_cflags_no_direct_extern_access}" = yes; then
> >>    libc_cv_protected_data=no
> >> diff --git a/sysdeps/x86/configure.ac b/sysdeps/x86/configure.ac
> >> index c440b6bf5c..1e9c4d86db 100644
> >> --- a/sysdeps/x86/configure.ac
> >> +++ b/sysdeps/x86/configure.ac
> >> @@ -240,6 +240,33 @@ else
> >>    AC_DEFINE(HAVE_X86_LIBGCC_CMP_RETURN_ATTR, 0)
> >>  fi
> >>
> >> +conftest_code="
> >> +double foo (double x, double y)
> >> +{
> >> +  return __builtin_fmod (x, y);
> >> +}
> >> +"
> >> +dnl Check if CC inlines __builtin_fmod/__builtin_remainder
> >> +LIBC_TRY_CC_COMMAND([if compiler inlines __builtin_fmod/__builtin_remainder],
> >> +  [$conftest_code],
> >> +  [$CFLAGS -fno-math-errno -S],
> >> +  libc_cv_cc_x86_inline_fmod,
> >> +  [
> >> +libc_cv_cc_x86_inline_fmod=no
> >> +if grep -E -q "fprem" conftest; then
> >> +  libc_cv_cc_x86_inline_fmod=yes
> >> +fi
> >> +],
> >> +[
> >> +echo "failed to check if CC inlines fmod."
> >> +rm -f conftest*
> >> +exit 1
> >> +])
> >> +if test "$libc_cv_cc_x86_inline_fmod" = yes; then
> >> +  AC_DEFINE(HAVE_X86_INLINE_FMOD, 1)
> >> +else
> >> +  AC_DEFINE(HAVE_X86_INLINE_FMOD, 0)
> >> +fi
> >>
> >>  dnl If the building compiler enables no direct external data access by
> >>  dnl default, access to protected data in shared libraries from executables
> >> --
> >> 2.43.0
> >>
> >
> >
>


-- 
H.J.


More information about the Libc-alpha mailing list