[PATCH] i386: Fix fmod/fmof/remainder/remainderf for gcc-12
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Tue Dec 2 17:39:32 GMT 2025
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.
>
>> }
>> 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
>>
>
>
More information about the Libc-alpha
mailing list