diff --git a/ChangeLog b/ChangeLog index a514dd69a6..ff5cbeb265 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2018-06-21 Florian Weimer + + [BZ #23253] + * sysdeps/generic/math_private.h (default_libc_feholdsetround_ctx): + Renamed from libc_feholdsetround_ctx. + (default_libc_feresetround_ctx): Renamed from + libc_feresetround_ctx. + (default_libc_feholdsetround_noex_ctx): Renamed from + libc_feholdsetround_noex_ctx. + (default_libc_feresetround_noex_ctx): Renamed from + libc_feresetround_noex_ctx. + [!HAVE_RM_CTX] (libc_feholdsetround_ctx, libc_feresetround_ctx) + (libc_feholdsetround_noex_ctx, libc_feresetround_noex_ctx): Macros + forwardning to the old implementations under the new names. + * sysdeps/i386/fpu/fenv_private.h [__SSE_MATH__] + (libc_feholdexcept_setround_ctx, libc_fesetenv_ctx) + (libc_feupdateenv_ctx, libc_feholdsetround_ctx) + (libc_feresetround_ctx): Forward to default implements for i386 + and MATH_SET_BOTH_ROUNDING_MODES. + * sysdeps/i386/Makefile [$(subdir) == math] (CFLAGS-e_gamma_r.c): + Add -DMATH_SET_BOTH_ROUNDING_MODES. + 2018-06-20 Joseph Myers * string/tst-cmp.c: Include . diff --git a/sysdeps/generic/math_private.h b/sysdeps/generic/math_private.h index b6612ba6bf..1212abaf47 100644 --- a/sysdeps/generic/math_private.h +++ b/sysdeps/generic/math_private.h @@ -428,6 +428,53 @@ default_libc_feupdateenv_test (fenv_t *e, int ex) # define HAVE_RM_CTX 0 #endif + +/* Default implementation using standard fenv functions. + Avoid unnecessary rounding mode changes by first checking the + current rounding mode. Note the use of __glibc_unlikely is + important for performance. */ + +static __always_inline void +default_libc_feholdsetround_ctx (struct rm_ctx *ctx, int round) +{ + ctx->updated_status = false; + + /* Update rounding mode only if different. */ + if (__glibc_unlikely (round != get_rounding_mode ())) + { + ctx->updated_status = true; + __fegetenv (&ctx->env); + __fesetround (round); + } +} + +static __always_inline void +default_libc_feresetround_ctx (struct rm_ctx *ctx) +{ + /* Restore the rounding mode if updated. */ + if (__glibc_unlikely (ctx->updated_status)) + __feupdateenv (&ctx->env); +} + +static __always_inline void +default_libc_feholdsetround_noex_ctx (struct rm_ctx *ctx, int round) +{ + /* Save exception flags and rounding mode, and disable exception + traps. */ + __feholdexcept (&ctx->env); + + /* Update rounding mode only if different. */ + if (__glibc_unlikely (round != get_rounding_mode ())) + __fesetround (round); +} + +static __always_inline void +default_libc_feresetround_noex_ctx (struct rm_ctx *ctx) +{ + /* Restore exception flags and rounding mode. */ + __fesetenv (&ctx->env); +} + #if HAVE_RM_CTX /* Set/Restore Rounding Modes only when necessary. If defined, these functions set/restore floating point state only if the state needed within the lexical @@ -456,51 +503,10 @@ default_libc_feupdateenv_test (fenv_t *e, int ex) #else -/* Default implementation using standard fenv functions. - Avoid unnecessary rounding mode changes by first checking the - current rounding mode. Note the use of __glibc_unlikely is - important for performance. */ - -static __always_inline void -libc_feholdsetround_ctx (struct rm_ctx *ctx, int round) -{ - ctx->updated_status = false; - - /* Update rounding mode only if different. */ - if (__glibc_unlikely (round != get_rounding_mode ())) - { - ctx->updated_status = true; - __fegetenv (&ctx->env); - __fesetround (round); - } -} - -static __always_inline void -libc_feresetround_ctx (struct rm_ctx *ctx) -{ - /* Restore the rounding mode if updated. */ - if (__glibc_unlikely (ctx->updated_status)) - __feupdateenv (&ctx->env); -} - -static __always_inline void -libc_feholdsetround_noex_ctx (struct rm_ctx *ctx, int round) -{ - /* Save exception flags and rounding mode, and disable exception - traps. */ - __feholdexcept (&ctx->env); - - /* Update rounding mode only if different. */ - if (__glibc_unlikely (round != get_rounding_mode ())) - __fesetround (round); -} - -static __always_inline void -libc_feresetround_noex_ctx (struct rm_ctx *ctx) -{ - /* Restore exception flags and rounding mode. */ - __fesetenv (&ctx->env); -} +# define libc_feholdsetround_ctx default_libc_feholdsetround_ctx +# define libc_feresetround_ctx default_libc_feresetround_ctx +# define libc_feholdsetround_noex_ctx default_libc_feholdsetround_noex_ctx +# define libc_feresetround_noex_ctx default_libc_feresetround_noex_ctx # define libc_feholdsetroundf_ctx libc_feholdsetround_ctx # define libc_feholdsetroundl_ctx libc_feholdsetround_ctx diff --git a/sysdeps/i386/Makefile b/sysdeps/i386/Makefile index 1682394e76..c0a4fe15d4 100644 --- a/sysdeps/i386/Makefile +++ b/sysdeps/i386/Makefile @@ -5,6 +5,14 @@ asm-CPPFLAGS += -DGAS_SYNTAX # The i386 `long double' is a distinct type we support. long-double-fcts = yes +ifeq ($(subdir),math) +# These functions change the rounding mode internally and need to +# update both the SSE2 rounding mode and the 387 rounding mode. See +# the handling of MATH_SET_BOTH_ROUNDING_MODES in +# sysdeps/i386/fpu/fenv_private.h. +CFLAGS-e_gamma_r.c += -DMATH_SET_BOTH_ROUNDING_MODES +endif + ifeq ($(subdir),string) sysdep_routines += cacheinfo endif diff --git a/sysdeps/i386/fpu/fenv_private.h b/sysdeps/i386/fpu/fenv_private.h index 59e83d858a..637dae5f05 100644 --- a/sysdeps/i386/fpu/fenv_private.h +++ b/sysdeps/i386/fpu/fenv_private.h @@ -460,11 +460,19 @@ libc_feupdateenv_387_ctx (struct rm_ctx *ctx) #endif /* __SSE_MATH__ */ #ifdef __SSE2_MATH__ -# define libc_feholdexcept_setround_ctx libc_feholdexcept_setround_sse_ctx -# define libc_fesetenv_ctx libc_fesetenv_sse_ctx -# define libc_feupdateenv_ctx libc_feupdateenv_sse_ctx -# define libc_feholdsetround_ctx libc_feholdsetround_sse_ctx -# define libc_feresetround_ctx libc_feresetround_sse_ctx +# if defined (__x86_64__) || !defined (MATH_SET_BOTH_ROUNDING_MODES) +# define libc_feholdexcept_setround_ctx libc_feholdexcept_setround_sse_ctx +# define libc_fesetenv_ctx libc_fesetenv_sse_ctx +# define libc_feupdateenv_ctx libc_feupdateenv_sse_ctx +# define libc_feholdsetround_ctx libc_feholdsetround_sse_ctx +# define libc_feresetround_ctx libc_feresetround_sse_ctx +# else +# define libc_feholdexcept_setround_ctx default_libc_feholdexcept_setround_ctx +# define libc_fesetenv_ctx default_libc_fesetenv_ctx +# define libc_feupdateenv_ctx default_libc_feupdateenv_ctx +# define libc_feholdsetround_ctx default_libc_feholdsetround_ctx +# define libc_feresetround_ctx default_libc_feresetround_ctx +# endif #else # define libc_feholdexcept_setround_ctx libc_feholdexcept_setround_387_ctx # define libc_feupdateenv_ctx libc_feupdateenv_387_ctx