arrfab / rpms / glibc

Forked from rpms/glibc 5 years ago
Clone

Blame SOURCES/glibc-rh1302086-10.patch

147e83
commit e6d90d675d4cae810be76a5ff41b8ae8bd6bc914
147e83
Author: Wilco Dijkstra <wdijkstr@arm.com>
147e83
Date:   Mon Jun 23 17:15:41 2014 +0100
147e83
147e83
    Add generic HAVE_RM_CTX implementation
147e83
    
147e83
    This patch adds a generic implementation of HAVE_RM_CTX using standard
147e83
    fenv calls. As a result math functions using SET_RESTORE_ROUND* macros
147e83
    do not suffer from a large slowdown on targets which do not implement
147e83
    optimized libc_fe*_ctx inline functions. Most of the libc_fe* inline
147e83
    functions are now unused and could be removed in the future (there are
147e83
    a few math functions left which use a mixture of standard fenv calls
147e83
    and libc_fe* inline functions - they could be updated to use
147e83
    SET_RESTORE_ROUND or improved to avoid expensive fenv manipulations
147e83
    across just a few FP instructions).
147e83
    
147e83
    libc_feholdsetround*_noex_ctx is added to enable better optimization of
147e83
    SET_RESTORE_ROUND_NOEX* implementations.
147e83
    
147e83
    Performance measurements on ARM and x86 of sin() show significant gains
147e83
    over the current default, fairly close to a highly optimized fenv_private:
147e83
    
147e83
                            ARM   x86
147e83
    no fenv_private      : 100%  100%
147e83
    generic HAVE_RM_CTX  : 250%  350%
147e83
    fenv_private (CTX)   : 250%  450%
147e83
    
147e83
    2014-06-23  Will Newton  <will.newton@linaro.org>
147e83
    	    Wilco  <wdijkstr@arm.com>
147e83
    
147e83
    	* sysdeps/generic/math_private.h: Add generic HAVE_RM_CTX
147e83
    	implementation.  Include get-rounding-mode.h.
147e83
    	[!HAVE_RM_CTX]: Define HAVE_RM_CTX to zero.
147e83
    	[!libc_feholdsetround_noex_ctx]: Define
147e83
    	libc_feholdsetround_noex_ctx.
147e83
    	[!libc_feholdsetround_noexf_ctx]: Define
147e83
    	libc_feholdsetround_noexf_ctx.
147e83
    	[!libc_feholdsetround_noexl_ctx]: Define
147e83
    	libc_feholdsetround_noexl_ctx.
147e83
    	(libc_feholdsetround_ctx): New function.
147e83
    	(libc_feresetround_ctx): New function.
147e83
    	(libc_feholdsetround_noex_ctx): New function.
147e83
    	(libc_feresetround_noex_ctx): New function.
147e83
147e83
diff --git a/sysdeps/generic/math_private.h b/sysdeps/generic/math_private.h
147e83
index 9b881a3..94c1e4a 100644
147e83
--- a/sysdeps/generic/math_private.h
147e83
+++ b/sysdeps/generic/math_private.h
147e83
@@ -20,6 +20,7 @@
147e83
 #include <stdint.h>
147e83
 #include <sys/types.h>
147e83
 #include <fenv.h>
147e83
+#include <get-rounding-mode.h>
147e83
 
147e83
 /* The original fdlibm code used statements like:
147e83
 	n0 = ((*(int*)&one)>>29)^1;		* index of high word *
147e83
@@ -551,12 +552,26 @@ default_libc_feupdateenv_test (fenv_t *e, int ex)
147e83
 # define libc_feresetround_noexl libc_fesetenvl
147e83
 #endif
147e83
 
147e83
+#ifndef HAVE_RM_CTX
147e83
+# define HAVE_RM_CTX 0
147e83
+#endif
147e83
+
147e83
 #if HAVE_RM_CTX
147e83
 /* Set/Restore Rounding Modes only when necessary.  If defined, these functions
147e83
    set/restore floating point state only if the state needed within the lexical
147e83
    block is different from the current state.  This saves a lot of time when
147e83
    the floating point unit is much slower than the fixed point units.  */
147e83
 
147e83
+# ifndef libc_feholdsetround_noex_ctx
147e83
+#   define libc_feholdsetround_noex_ctx  libc_feholdsetround_ctx
147e83
+# endif
147e83
+# ifndef libc_feholdsetround_noexf_ctx
147e83
+#   define libc_feholdsetround_noexf_ctx libc_feholdsetroundf_ctx
147e83
+# endif
147e83
+# ifndef libc_feholdsetround_noexl_ctx
147e83
+#   define libc_feholdsetround_noexl_ctx libc_feholdsetroundl_ctx
147e83
+# endif
147e83
+
147e83
 # ifndef libc_feresetround_noex_ctx
147e83
 #   define libc_feresetround_noex_ctx  libc_fesetenv_ctx
147e83
 # endif
147e83
@@ -567,24 +582,80 @@ default_libc_feupdateenv_test (fenv_t *e, int ex)
147e83
 #   define libc_feresetround_noexl_ctx libc_fesetenvl_ctx
147e83
 # endif
147e83
 
147e83
-# ifndef libc_feholdsetround_53bit_ctx
147e83
-#   define libc_feholdsetround_53bit_ctx libc_feholdsetround_ctx
147e83
-# endif
147e83
+#else
147e83
 
147e83
-# ifndef libc_feresetround_53bit_ctx
147e83
-#   define libc_feresetround_53bit_ctx libc_feresetround_ctx
147e83
-# endif
147e83
+/* Default implementation using standard fenv functions.
147e83
+   Avoid unnecessary rounding mode changes by first checking the
147e83
+   current rounding mode.  Note the use of __glibc_unlikely is
147e83
+   important for performance.  */
147e83
 
147e83
-# define SET_RESTORE_ROUND_GENERIC(RM,ROUNDFUNC,CLEANUPFUNC) \
147e83
-  struct rm_ctx ctx __attribute__((cleanup(CLEANUPFUNC ## _ctx)));	      \
147e83
-  ROUNDFUNC ## _ctx (&ctx, (RM))
147e83
-#else
147e83
-# define SET_RESTORE_ROUND_GENERIC(RM, ROUNDFUNC, CLEANUPFUNC) \
147e83
-  fenv_t __libc_save_rm __attribute__((cleanup(CLEANUPFUNC)));	\
147e83
-  ROUNDFUNC (&__libc_save_rm, (RM))
147e83
+static __always_inline void
147e83
+libc_feholdsetround_ctx (struct rm_ctx *ctx, int round)
147e83
+{
147e83
+  ctx->updated_status = false;
147e83
+
147e83
+  /* Update rounding mode only if different.  */
147e83
+  if (__glibc_unlikely (round != get_rounding_mode ()))
147e83
+    {
147e83
+      ctx->updated_status = true;
147e83
+      fegetenv (&ctx->env);
147e83
+      fesetround (round);
147e83
+    }
147e83
+}
147e83
+
147e83
+static __always_inline void
147e83
+libc_feresetround_ctx (struct rm_ctx *ctx)
147e83
+{
147e83
+  /* Restore the rounding mode if updated.  */
147e83
+  if (__glibc_unlikely (ctx->updated_status))
147e83
+    feupdateenv (&ctx->env);
147e83
+}
147e83
+
147e83
+static __always_inline void
147e83
+libc_feholdsetround_noex_ctx (struct rm_ctx *ctx, int round)
147e83
+{
147e83
+  /* Save exception flags and rounding mode.  */
147e83
+  fegetenv (&ctx->env);
147e83
+
147e83
+  /* Update rounding mode only if different.  */
147e83
+  if (__glibc_unlikely (round != get_rounding_mode ()))
147e83
+    fesetround (round);
147e83
+}
147e83
+
147e83
+static __always_inline void
147e83
+libc_feresetround_noex_ctx (struct rm_ctx *ctx)
147e83
+{
147e83
+  /* Restore exception flags and rounding mode.  */
147e83
+  fesetenv (&ctx->env);
147e83
+}
147e83
+
147e83
+# define libc_feholdsetroundf_ctx libc_feholdsetround_ctx
147e83
+# define libc_feholdsetroundl_ctx libc_feholdsetround_ctx
147e83
+# define libc_feresetroundf_ctx   libc_feresetround_ctx
147e83
+# define libc_feresetroundl_ctx   libc_feresetround_ctx
147e83
+
147e83
+# define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_ctx
147e83
+# define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_ctx
147e83
+# define libc_feresetround_noexf_ctx   libc_feresetround_noex_ctx
147e83
+# define libc_feresetround_noexl_ctx   libc_feresetround_noex_ctx
147e83
+
147e83
+#endif
147e83
+
147e83
+#ifndef libc_feholdsetround_53bit_ctx
147e83
+#  define libc_feholdsetround_53bit_ctx libc_feholdsetround_ctx
147e83
+#endif
147e83
+#ifndef libc_feresetround_53bit_ctx
147e83
+#  define libc_feresetround_53bit_ctx libc_feresetround_ctx
147e83
 #endif
147e83
 
147e83
-/* Save and restore the rounding mode within a lexical block.  */
147e83
+#define SET_RESTORE_ROUND_GENERIC(RM,ROUNDFUNC,CLEANUPFUNC) \
147e83
+  struct rm_ctx ctx __attribute__((cleanup (CLEANUPFUNC ## _ctx))); \
147e83
+  ROUNDFUNC ## _ctx (&ctx, (RM))
147e83
+
147e83
+/* Set the rounding mode within a lexical block.  Restore the rounding mode to
147e83
+   the value at the start of the block.  The exception mode must be preserved.
147e83
+   Exceptions raised within the block must be set in the exception flags.
147e83
+   Non-stop mode may be enabled inside the block.  */
147e83
 
147e83
 #define SET_RESTORE_ROUND(RM) \
147e83
   SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround, libc_feresetround)
147e83
@@ -593,15 +664,21 @@ default_libc_feupdateenv_test (fenv_t *e, int ex)
147e83
 #define SET_RESTORE_ROUNDL(RM) \
147e83
   SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundl, libc_feresetroundl)
147e83
 
147e83
-/* Save and restore the rounding mode within a lexical block, and also
147e83
-   the set of exceptions raised within the block may be discarded.  */
147e83
+/* Set the rounding mode within a lexical block.  Restore the rounding mode to
147e83
+   the value at the start of the block.  The exception mode must be preserved.
147e83
+   Exceptions raised within the block must be discarded, and exception flags
147e83
+   are restored to the value at the start of the block.
147e83
+   Non-stop mode may be enabled inside the block.  */
147e83
 
147e83
 #define SET_RESTORE_ROUND_NOEX(RM) \
147e83
-  SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround, libc_feresetround_noex)
147e83
+  SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noex, \
147e83
+			     libc_feresetround_noex)
147e83
 #define SET_RESTORE_ROUND_NOEXF(RM) \
147e83
-  SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundf, libc_feresetround_noexf)
147e83
+  SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexf, \
147e83
+			     libc_feresetround_noexf)
147e83
 #define SET_RESTORE_ROUND_NOEXL(RM) \
147e83
-  SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundl, libc_feresetround_noexl)
147e83
+  SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexl, \
147e83
+			     libc_feresetround_noexl)
147e83
 
147e83
 /* Like SET_RESTORE_ROUND, but also set rounding precision to 53 bits.  */
147e83
 #define SET_RESTORE_ROUND_53BIT(RM) \