math: Set 387 and SSE2 rounding mode for tgamma on i386 [BZ #23253]

Previously, only the SSE2 rounding mode was set, so the assembler
implementations using 387 were not following the expecting rounding
mode.
This commit is contained in:
Florian Weimer 2018-06-21 08:04:29 +02:00
parent 99c7adf99f
commit f496b28e61
4 changed files with 94 additions and 50 deletions

View File

@ -1,3 +1,25 @@
2018-06-21 Florian Weimer <fweimer@redhat.com>
[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 <joseph@codesourcery.com>
* string/tst-cmp.c: Include <libc-diag.h>.

View File

@ -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

View File

@ -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

View File

@ -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