Patchwork [COMMITTED,powerpc] No need to enter "Ignore Exceptions Mode"

login
register
mail settings
Submitter Paul Clarke
Date Oct. 2, 2019, 3:46 p.m.
Message ID <1570031217-13280-1-git-send-email-pc@us.ibm.com>
Download mbox | patch
Permalink /patch/34790/
State New
Headers show

Comments

Paul Clarke - Oct. 2, 2019, 3:46 p.m.
From: "Paul A. Clarke" <pc@us.ibm.com>

Since at least POWER8, there is no performance advantage to entering
"Ignore Exceptions Mode", and doing so conditionally requires
 - the conditional logic, and
 - a system call.

Make it a no-op for uses within glibc.
---
v2: This was a new patch (#2) in the series "Various FPSCR-related changes".
v3: I was a bit uncomfortable with the approach used in v1/v2, which had
  side effects, although these were expected to be innocuous.
  I reimplemented this patch to be implemented only for uses that are
  internal to glibc.  These are all cases where the mode is to be changed
  only temporarily.  So, the state will be consistent after the code
  block is complete -- no unexpected side effects.
v4: This is the version committed.  New macro names at suggestion by Paul
  Murphy. I chose "__TEST_AND_{BEGIN,END}_NON_STOP" (instead of appending
  "P7") because it's not that the decision to independently enter or exit
  non-stop mode is architecture-specific, but that the uses of the
  functions including the new macros is to bracket a block of code in which
  we may care about transitioning temporarily to non-stop mode.  In other
  words, it's not as much a state change as a push/pop (BEGIN/END).
  And, it just happens to be on PWR8 and above we don't care.

 sysdeps/powerpc/fpu/fenv_private.h | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

Patch

diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h
index 5eedc3b..4af767b 100644
--- a/sysdeps/powerpc/fpu/fenv_private.h
+++ b/sysdeps/powerpc/fpu/fenv_private.h
@@ -23,6 +23,17 @@ 
 #include <fenv_libc.h>
 #include <fpu_control.h>
 
+#ifdef _ARCH_PWR8
+/* There is no performance advantage to non-stop mode.  */
+/* The odd syntax here is to innocuously reference the given variables
+   to prevent warnings about unused variables.  */
+#define __TEST_AND_BEGIN_NON_STOP(old, new) do {} while ((old) * (new) * 0 != 0)
+#define __TEST_AND_END_NON_STOP(old, new) do {} while ((old) * (new) * 0 != 0)
+#else
+#define __TEST_AND_BEGIN_NON_STOP __TEST_AND_ENTER_NON_STOP
+#define __TEST_AND_END_NON_STOP __TEST_AND_EXIT_NON_STOP
+#endif
+
 static __always_inline void
 libc_feholdexcept_setround_ppc (fenv_t *envp, int r)
 {
@@ -30,7 +41,7 @@  libc_feholdexcept_setround_ppc (fenv_t *envp, int r)
 
   old.fenv = *envp = fegetenv_register ();
 
-  __TEST_AND_ENTER_NON_STOP (old.l, 0ULL);
+  __TEST_AND_BEGIN_NON_STOP (old.l, 0ULL);
 
   /* Clear everything and set the rounding mode.  */
   new.l = r;
@@ -49,8 +60,8 @@  __libc_femergeenv_ppc (const fenv_t *envp, unsigned long long old_mask,
   /* Merge bits while masking unwanted bits from new and old env.  */
   new.l = (old.l & old_mask) | (new.l & new_mask);
 
-  __TEST_AND_EXIT_NON_STOP (old.l, new.l);
-  __TEST_AND_ENTER_NON_STOP (old.l, new.l);
+  __TEST_AND_END_NON_STOP (old.l, new.l);
+  __TEST_AND_BEGIN_NON_STOP (old.l, new.l);
 
   /* If requesting to keep status, replace control, and merge exceptions,
      and exceptions haven't changed, we can just set new control instead
@@ -141,7 +152,7 @@  libc_feholdsetround_noex_ppc_ctx (struct rm_ctx *ctx, int r)
   ctx->env = old.fenv;
   if (__glibc_unlikely (new.l != old.l))
     {
-      __TEST_AND_ENTER_NON_STOP (old.l, 0ULL);
+      __TEST_AND_BEGIN_NON_STOP (old.l, 0ULL);
       fesetenv_control (new.fenv);
       ctx->updated_status = true;
     }