Blame SOURCES/glibc-rh977887-2.patch

147e83
commit 2506109403de69bd454de27835d42e6eb6ec3abc
147e83
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
147e83
Date:   Wed Jun 12 10:36:48 2013 +0530
147e83
147e83
    Set/restore rounding mode only when needed
147e83
    
147e83
    The most common use case of math functions is with default rounding
147e83
    mode, i.e. rounding to nearest.  Setting and restoring rounding mode
147e83
    is an unnecessary overhead for this, so I've added support for a
147e83
    context, which does the set/restore only if the FP status needs a
147e83
    change.  The code is written such that only x86 uses these.  Other
147e83
    architectures should be unaffected by it, but would definitely benefit
147e83
    if the set/restore has as much overhead relative to the rest of the
147e83
    code, as the x86 bits do.
147e83
    
147e83
    Here's a summary of the performance improvement due to these
147e83
    improvements; I've only mentioned functions that use the set/restore
147e83
    and have benchmark inputs for x86_64:
147e83
    
147e83
    Before:
147e83
    
147e83
    cos(): ITERS:4.69335e+08: TOTAL:28884.6Mcy, MAX:4080.28cy, MIN:57.562cy, 16248.6 calls/Mcy
147e83
    exp(): ITERS:4.47604e+08: TOTAL:28796.2Mcy, MAX:207.721cy, MIN:62.385cy, 15543.9 calls/Mcy
147e83
    pow(): ITERS:1.63485e+08: TOTAL:28879.9Mcy, MAX:362.255cy, MIN:172.469cy, 5660.86 calls/Mcy
147e83
    sin(): ITERS:3.89578e+08: TOTAL:28900Mcy, MAX:704.859cy, MIN:47.583cy, 13480.2 calls/Mcy
147e83
    tan(): ITERS:7.0971e+07: TOTAL:28902.2Mcy, MAX:1357.79cy, MIN:388.58cy, 2455.55 calls/Mcy
147e83
    
147e83
    After:
147e83
    
147e83
    cos(): ITERS:6.0014e+08: TOTAL:28875.9Mcy, MAX:364.283cy, MIN:45.716cy, 20783.4 calls/Mcy
147e83
    exp(): ITERS:5.48578e+08: TOTAL:28764.9Mcy, MAX:191.617cy, MIN:51.011cy, 19071.1 calls/Mcy
147e83
    pow(): ITERS:1.70013e+08: TOTAL:28873.6Mcy, MAX:689.522cy, MIN:163.989cy, 5888.18 calls/Mcy
147e83
    sin(): ITERS:4.64079e+08: TOTAL:28891.5Mcy, MAX:6959.3cy, MIN:36.189cy, 16062.8 calls/Mcy
147e83
    tan(): ITERS:7.2354e+07: TOTAL:28898.9Mcy, MAX:1295.57cy, MIN:380.698cy, 2503.7 calls/Mcy
147e83
    
147e83
    So the improvements are:
147e83
    
147e83
    cos: 27.9089%
147e83
    exp: 22.6919%
147e83
    pow: 4.01564%
147e83
    sin: 19.1585%
147e83
    tan: 1.96086%
147e83
    
147e83
    The downside of the change is that it will have an adverse performance
147e83
    impact on non-default rounding modes, but I think the tradeoff is
147e83
    justified.
147e83
147e83
diff --git glibc-2.17-c758a686/include/fenv.h glibc-2.17-c758a686/include/fenv.h
147e83
index ed6d139..9f90d17 100644
147e83
--- glibc-2.17-c758a686/include/fenv.h
147e83
+++ glibc-2.17-c758a686/include/fenv.h
147e83
@@ -1,5 +1,6 @@
147e83
 #ifndef _FENV_H
147e83
 #include <math/fenv.h>
147e83
+#include <stdbool.h>
147e83
 
147e83
 #ifndef _ISOMAC
147e83
 /* Now define the internal interfaces.  */
147e83
@@ -23,4 +24,13 @@ libm_hidden_proto (fetestexcept)
147e83
 libm_hidden_proto (feclearexcept)
147e83
 #endif
147e83
 
147e83
+/* Rounding mode context.  This allows functions to set/restore rounding mode
147e83
+   only when the desired rounding mode is different from the current rounding
147e83
+   mode.  */
147e83
+struct rm_ctx
147e83
+{
147e83
+  fenv_t env;
147e83
+  bool updated_status;
147e83
+};
147e83
+
147e83
 #endif
147e83
diff --git glibc-2.17-c758a686/sysdeps/generic/math_private.h glibc-2.17-c758a686/sysdeps/generic/math_private.h
147e83
index e98360d..c0fc03d 100644
147e83
--- glibc-2.17-c758a686/sysdeps/generic/math_private.h
147e83
+++ glibc-2.17-c758a686/sysdeps/generic/math_private.h
147e83
@@ -553,35 +553,62 @@ default_libc_feupdateenv_test (fenv_t *e, int ex)
147e83
 # define libc_feresetround_noexl libc_fesetenvl
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_feresetround_noex_ctx
147e83
+#   define libc_feresetround_noex_ctx  libc_fesetenv_ctx
147e83
+# endif
147e83
+# ifndef libc_feresetround_noexf_ctx
147e83
+#   define libc_feresetround_noexf_ctx libc_fesetenvf_ctx
147e83
+# endif
147e83
+# ifndef libc_feresetround_noexl_ctx
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
+
147e83
+# ifndef libc_feresetround_53bit_ctx
147e83
+#   define libc_feresetround_53bit_ctx libc_feresetround_ctx
147e83
+# endif
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
+#endif
147e83
+
147e83
 /* Save and restore the rounding mode within a lexical block.  */
147e83
 
147e83
 #define SET_RESTORE_ROUND(RM) \
147e83
-  fenv_t __libc_save_rm __attribute__((cleanup(libc_feresetround)));	\
147e83
-  libc_feholdsetround (&__libc_save_rm, (RM))
147e83
+  SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround, libc_feresetround)
147e83
 #define SET_RESTORE_ROUNDF(RM) \
147e83
-  fenv_t __libc_save_rm __attribute__((cleanup(libc_feresetroundf)));	\
147e83
-  libc_feholdsetroundf (&__libc_save_rm, (RM))
147e83
+  SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundf, libc_feresetroundf)
147e83
 #define SET_RESTORE_ROUNDL(RM) \
147e83
-  fenv_t __libc_save_rm __attribute__((cleanup(libc_feresetroundl)));	\
147e83
-  libc_feholdsetroundl (&__libc_save_rm, (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
 
147e83
 #define SET_RESTORE_ROUND_NOEX(RM) \
147e83
-  fenv_t __libc_save_rm __attribute__((cleanup(libc_feresetround_noex))); \
147e83
-  libc_feholdsetround (&__libc_save_rm, (RM))
147e83
+  SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround, libc_feresetround_noex)
147e83
 #define SET_RESTORE_ROUND_NOEXF(RM) \
147e83
-  fenv_t __libc_save_rm __attribute__((cleanup(libc_feresetround_noexf))); \
147e83
-  libc_feholdsetroundf (&__libc_save_rm, (RM))
147e83
+  SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundf, libc_feresetround_noexf)
147e83
 #define SET_RESTORE_ROUND_NOEXL(RM) \
147e83
-  fenv_t __libc_save_rm __attribute__((cleanup(libc_feresetround_noexl))); \
147e83
-  libc_feholdsetroundl (&__libc_save_rm, (RM))
147e83
+  SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundl, libc_feresetround_noexl)
147e83
 
147e83
 /* Like SET_RESTORE_ROUND, but also set rounding precision to 53 bits.  */
147e83
 #define SET_RESTORE_ROUND_53BIT(RM) \
147e83
-  fenv_t __libc_save_rm __attribute__((cleanup(libc_feresetround_53bit))); \
147e83
-  libc_feholdsetround_53bit (&__libc_save_rm, (RM))
147e83
+  SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_53bit,	      \
147e83
+			     libc_feresetround_53bit)
147e83
 
147e83
 #define __nan(str) \
147e83
   (__builtin_constant_p (str) && str[0] == '\0' ? NAN : __nan (str))
147e83
diff --git glibc-2.17-c758a686/sysdeps/i386/fpu/fenv_private.h glibc-2.17-c758a686/sysdeps/i386/fpu/fenv_private.h
147e83
index 1f8336c..3998387 100644
147e83
--- glibc-2.17-c758a686/sysdeps/i386/fpu/fenv_private.h
147e83
+++ glibc-2.17-c758a686/sysdeps/i386/fpu/fenv_private.h
147e83
@@ -322,6 +322,179 @@ libc_feresetround_387 (fenv_t *e)
147e83
 # define libc_feholdsetround_53bit	libc_feholdsetround_387_53bit
147e83
 #endif
147e83
 
147e83
+/* We have support for rounding mode context.  */
147e83
+#define HAVE_RM_CTX 1
147e83
+
147e83
+static __always_inline void
147e83
+libc_feholdexcept_setround_sse_ctx (struct rm_ctx *ctx, int r)
147e83
+{
147e83
+  unsigned int mxcsr, new_mxcsr;
147e83
+  asm (STMXCSR " %0" : "=m" (*&mxcsr));
147e83
+  new_mxcsr = ((mxcsr | 0x1f80) & ~0x603f) | (r << 3);
147e83
+
147e83
+  ctx->env.__mxcsr = mxcsr;
147e83
+  if (__glibc_unlikely (mxcsr != new_mxcsr))
147e83
+    {
147e83
+      asm volatile (LDMXCSR " %0" : : "m" (*&new_mxcsr));
147e83
+      ctx->updated_status = true;
147e83
+    }
147e83
+  else
147e83
+    ctx->updated_status = false;
147e83
+}
147e83
+
147e83
+/* Unconditional since we want to overwrite any exceptions that occurred in the
147e83
+   context.  This is also why all fehold* functions unconditionally write into
147e83
+   ctx->env.  */
147e83
+static __always_inline void
147e83
+libc_fesetenv_sse_ctx (struct rm_ctx *ctx)
147e83
+{
147e83
+  libc_fesetenv_sse (&ctx->env);
147e83
+}
147e83
+
147e83
+static __always_inline void
147e83
+libc_feupdateenv_sse_ctx (struct rm_ctx *ctx)
147e83
+{
147e83
+  if (__glibc_unlikely (ctx->updated_status))
147e83
+    libc_feupdateenv_test_sse (&ctx->env, 0);
147e83
+}
147e83
+
147e83
+static __always_inline void
147e83
+libc_feholdexcept_setround_387_prec_ctx (struct rm_ctx *ctx, int r)
147e83
+{
147e83
+  libc_feholdexcept_387 (&ctx->env);
147e83
+
147e83
+  fpu_control_t cw = ctx->env.__control_word;
147e83
+  fpu_control_t old_cw = cw;
147e83
+  cw &= ~(_FPU_RC_ZERO | _FPU_EXTENDED);
147e83
+  cw |= r | 0x3f;
147e83
+
147e83
+  if (__glibc_unlikely (old_cw != cw))
147e83
+    {
147e83
+      _FPU_SETCW (cw);
147e83
+      ctx->updated_status = true;
147e83
+    }
147e83
+  else
147e83
+    ctx->updated_status = false;
147e83
+}
147e83
+
147e83
+static __always_inline void
147e83
+libc_feholdexcept_setround_387_ctx (struct rm_ctx *ctx, int r)
147e83
+{
147e83
+  libc_feholdexcept_setround_387_prec_ctx (ctx, r | _FPU_EXTENDED);
147e83
+}
147e83
+
147e83
+static __always_inline void
147e83
+libc_feholdexcept_setround_387_53bit_ctx (struct rm_ctx *ctx, int r)
147e83
+{
147e83
+  libc_feholdexcept_setround_387_prec_ctx (ctx, r | _FPU_DOUBLE);
147e83
+}
147e83
+
147e83
+static __always_inline void
147e83
+libc_feholdsetround_387_prec_ctx (struct rm_ctx *ctx, int r)
147e83
+{
147e83
+  fpu_control_t cw, new_cw;
147e83
+
147e83
+  _FPU_GETCW (cw);
147e83
+  new_cw = cw;
147e83
+  new_cw &= ~(_FPU_RC_ZERO | _FPU_EXTENDED);
147e83
+  new_cw |= r;
147e83
+
147e83
+  ctx->env.__control_word = cw;
147e83
+  if (__glibc_unlikely (new_cw != cw))
147e83
+    {
147e83
+      _FPU_SETCW (new_cw);
147e83
+      ctx->updated_status = true;
147e83
+    }
147e83
+  else
147e83
+    ctx->updated_status = false;
147e83
+}
147e83
+
147e83
+static __always_inline void
147e83
+libc_feholdsetround_387_ctx (struct rm_ctx *ctx, int r)
147e83
+{
147e83
+  libc_feholdsetround_387_prec_ctx (ctx, r | _FPU_EXTENDED);
147e83
+}
147e83
+
147e83
+static __always_inline void
147e83
+libc_feholdsetround_387_53bit_ctx (struct rm_ctx *ctx, int r)
147e83
+{
147e83
+  libc_feholdsetround_387_prec_ctx (ctx, r | _FPU_DOUBLE);
147e83
+}
147e83
+
147e83
+static __always_inline void
147e83
+libc_feholdsetround_sse_ctx (struct rm_ctx *ctx, int r)
147e83
+{
147e83
+  unsigned int mxcsr, new_mxcsr;
147e83
+
147e83
+  asm (STMXCSR " %0" : "=m" (*&mxcsr));
147e83
+  new_mxcsr = (mxcsr & ~0x6000) | (r << 3);
147e83
+
147e83
+  ctx->env.__mxcsr = mxcsr;
147e83
+  if (__glibc_unlikely (new_mxcsr != mxcsr))
147e83
+    {
147e83
+      asm volatile (LDMXCSR " %0" : : "m" (*&new_mxcsr));
147e83
+      ctx->updated_status = true;
147e83
+    }
147e83
+  else
147e83
+    ctx->updated_status = false;
147e83
+}
147e83
+
147e83
+static __always_inline void
147e83
+libc_feresetround_sse_ctx (struct rm_ctx *ctx)
147e83
+{
147e83
+  if (__glibc_unlikely (ctx->updated_status))
147e83
+    libc_feresetround_sse (&ctx->env);
147e83
+}
147e83
+
147e83
+static __always_inline void
147e83
+libc_feresetround_387_ctx (struct rm_ctx *ctx)
147e83
+{
147e83
+  if (__glibc_unlikely (ctx->updated_status))
147e83
+    _FPU_SETCW (ctx->env.__control_word);
147e83
+}
147e83
+
147e83
+static __always_inline void
147e83
+libc_feupdateenv_387_ctx (struct rm_ctx *ctx)
147e83
+{
147e83
+  if (__glibc_unlikely (ctx->updated_status))
147e83
+    libc_feupdateenv_test_387 (&ctx->env, 0);
147e83
+}
147e83
+
147e83
+#ifdef __SSE_MATH__
147e83
+# define libc_feholdexcept_setroundf_ctx libc_feholdexcept_setround_sse_ctx
147e83
+# define libc_fesetenvf_ctx		libc_fesetenv_sse_ctx
147e83
+# define libc_feupdateenvf_ctx		libc_feupdateenv_sse_ctx
147e83
+# define libc_feholdsetroundf_ctx	libc_feholdsetround_sse_ctx
147e83
+# define libc_feresetroundf_ctx		libc_feresetround_sse_ctx
147e83
+#else
147e83
+# define libc_feholdexcept_setroundf_ctx libc_feholdexcept_setround_387_ctx
147e83
+# define libc_feupdateenvf_ctx		libc_feupdateenv_387_ctx
147e83
+# define libc_feholdsetroundf_ctx	libc_feholdsetround_387_ctx
147e83
+# define libc_feresetroundf_ctx		libc_feresetround_387_ctx
147e83
+#endif /* __SSE_MATH__ */
147e83
+
147e83
+#ifdef __SSE2_MATH__
147e83
+# define libc_feholdexcept_setround_ctx	libc_feholdexcept_setround_sse_ctx
147e83
+# define libc_fesetenv_ctx		libc_fesetenv_sse_ctx
147e83
+# define libc_feupdateenv_ctx		libc_feupdateenv_sse_ctx
147e83
+# define libc_feholdsetround_ctx	libc_feholdsetround_sse_ctx
147e83
+# define libc_feresetround_ctx		libc_feresetround_sse_ctx
147e83
+#else
147e83
+# define libc_feholdexcept_setround_ctx	libc_feholdexcept_setround_387_ctx
147e83
+# define libc_feupdateenv_ctx		libc_feupdateenv_387_ctx
147e83
+# define libc_feresetround_ctx		libc_feresetround_387_ctx
147e83
+#endif /* __SSE2_MATH__ */
147e83
+
147e83
+#define libc_feholdexcept_setroundl_ctx	libc_feholdexcept_setround_387_ctx
147e83
+#define libc_feupdateenvl_ctx		libc_feupdateenv_387_ctx
147e83
+#define libc_feholdsetroundl_ctx	libc_feholdsetround_387_ctx
147e83
+#define libc_feresetroundl_ctx		libc_feresetround_387_ctx
147e83
+
147e83
+#ifndef __SSE2_MATH__
147e83
+# define libc_feholdsetround_53bit_ctx	libc_feholdsetround_387_53bit_ctx
147e83
+# define libc_feresetround_53bit_ctx	libc_feresetround_387_ctx
147e83
+#endif
147e83
+
147e83
 #undef __mxcsr
147e83
 
147e83
 #endif /* FENV_PRIVATE_H */