00db10
commit 656b84c2ef525e3b69802c9057c5897e327b0332
00db10
Author: Wilco Dijkstra <wdijkstr@arm.com>
00db10
Date:   Thu Aug 7 16:29:55 2014 +0000
00db10
00db10
    This patch adds new function libc_feholdsetround_noex_aarch64_ctx, enabling
00db10
    further optimization. libc_feholdsetround_aarch64_ctx now only needs to
00db10
    read the FPCR in the typical case, avoiding a redundant FPSR read.
00db10
    Performance results show a good improvement (5-10% on sin()) on cores with
00db10
    expensive FPCR/FPSR instructions.
00db10
00db10
diff --git a/ports/sysdeps/aarch64/fpu/math_private.h b/ports/sysdeps/aarch64/fpu/math_private.h
00db10
index 023c9d0..b13c030 100644
00db10
--- a/ports/sysdeps/aarch64/fpu/math_private.h
00db10
+++ b/ports/sysdeps/aarch64/fpu/math_private.h
00db10
@@ -228,12 +228,9 @@ static __always_inline void
00db10
 libc_feholdsetround_aarch64_ctx (struct rm_ctx *ctx, int r)
00db10
 {
00db10
   fpu_control_t fpcr;
00db10
-  fpu_fpsr_t fpsr;
00db10
   int round;
00db10
 
00db10
   _FPU_GETCW (fpcr);
00db10
-  _FPU_GETFPSR (fpsr);
00db10
-  ctx->env.__fpsr = fpsr;
00db10
 
00db10
   /* Check whether rounding modes are different.  */
00db10
   round = (fpcr ^ r) & _FPU_FPCR_RM_MASK;
00db10
@@ -264,6 +261,33 @@ libc_feresetround_aarch64_ctx (struct rm_ctx *ctx)
00db10
 #define libc_feresetroundl_ctx		libc_feresetround_aarch64_ctx
00db10
 
00db10
 static __always_inline void
00db10
+libc_feholdsetround_noex_aarch64_ctx (struct rm_ctx *ctx, int r)
00db10
+{
00db10
+  fpu_control_t fpcr;
00db10
+  fpu_fpsr_t fpsr;
00db10
+  int round;
00db10
+
00db10
+  _FPU_GETCW (fpcr);
00db10
+  _FPU_GETFPSR (fpsr);
00db10
+  ctx->env.__fpsr = fpsr;
00db10
+
00db10
+  /* Check whether rounding modes are different.  */
00db10
+  round = (fpcr ^ r) & _FPU_FPCR_RM_MASK;
00db10
+  ctx->updated_status = round != 0;
00db10
+
00db10
+  /* Set the rounding mode if changed.  */
00db10
+  if (__glibc_unlikely (round != 0))
00db10
+    {
00db10
+      ctx->env.__fpcr = fpcr;
00db10
+      _FPU_SETCW (fpcr ^ round);
00db10
+    }
00db10
+}
00db10
+
00db10
+#define libc_feholdsetround_noex_ctx	libc_feholdsetround_noex_aarch64_ctx
00db10
+#define libc_feholdsetround_noexf_ctx	libc_feholdsetround_noex_aarch64_ctx
00db10
+#define libc_feholdsetround_noexl_ctx	libc_feholdsetround_noex_aarch64_ctx
00db10
+
00db10
+static __always_inline void
00db10
 libc_feresetround_noex_aarch64_ctx (struct rm_ctx *ctx)
00db10
 {
00db10
   /* Restore the rounding mode if updated.  */