mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-08 14:20:07 +00:00
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:
parent
99c7adf99f
commit
f496b28e61
22
ChangeLog
22
ChangeLog
@ -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>.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user