]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
PowerPC: Suppress unnecessary FPSCR write
authorAdhemerval Zanella <azanella@linux.vnet.ibm.com>
Mon, 28 Apr 2014 19:38:24 +0000 (14:38 -0500)
committerAdhemerval Zanella <azanella@linux.vnet.ibm.com>
Tue, 29 Apr 2014 12:05:39 +0000 (07:05 -0500)
This patch optimizes the FPSCR update on exception and rounding change
functions by just updating its value if new value if different from
current one.  It also optimizes fedisableexcept and feenableexcept by
removing an unecessary FPSCR read.

ChangeLog
sysdeps/powerpc/fpu/fclrexcpt.c
sysdeps/powerpc/fpu/fedisblxcpt.c
sysdeps/powerpc/fpu/feenablxcpt.c
sysdeps/powerpc/fpu/feholdexcpt.c
sysdeps/powerpc/fpu/fenv_libc.h
sysdeps/powerpc/fpu/fesetenv.c
sysdeps/powerpc/fpu/fsetexcptflg.c

index 8b9cfb5bdb0cf53a01886d87072edc934e2cac21..40072951655391a18afca918cda923ed9c360264 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2014-04-28  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+       * sysdeps/powerpc/fpu/fclrexcpt.c (__feclearexcept): Do not update
+       FPSCR if value do not change.
+       * sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept): Likewise.
+       * sysdeps/powerpc/fpu/feenablxcpt.c (feenableexcept): Likewise.
+       * sysdeps/powerpc/fpu/feholdexcpt.c (feholdexcept): Likewise.
+       * sysdeps/powerpc/fpu/fesetenv.c (__fesetenv): Likewise.
+       * sysdeps/powerpc/fpu/fsetexcptflg.c (__fesetexceptflag): Likewise.
+       * sysdeps/powerpc/fpu/fenv_libc.h (fenv_reg_to_exceptions): New helper
+       function.
+
 2014-05-29  Carlos O'Donell  <carlos@systemhalted.org>
 
        * sysdeps/hppa: Move directory from ports/sysdeps/hppa.
index cda28101200a5a92d0afbf5b4e638196865a0740..4607f62bb1f76f31fc7990116527e1480fac7897 100644 (file)
 int
 __feclearexcept (int excepts)
 {
-  fenv_union_t u;
+  fenv_union_t u, n;
 
   /* Get the current state.  */
   u.fenv = fegetenv_register ();
 
   /* Clear the relevant bits.  */
-  u.l = u.l & ~((-(excepts >> (31 - FPSCR_VX) & 1) & FE_ALL_INVALID)
+  n.l = u.l & ~((-(excepts >> (31 - FPSCR_VX) & 1) & FE_ALL_INVALID)
                | (excepts & FPSCR_STICKY_BITS));
 
   /* Put the new state in effect.  */
-  fesetenv_register (u.fenv);
+  if (u.l != n.l)
+    fesetenv_register (n.fenv);
 
   /* Success.  */
   return 0;
index 5883e0926324d6e49a12ec298f6a36fcff1162d7..94c01abb86f4d51adf751a37c3b14c9f2175c54d 100644 (file)
 int
 fedisableexcept (int excepts)
 {
-  fenv_union_t fe;
-  int result, new;
+  fenv_union_t fe, curr;
+  int result = 0, new;
 
-  result = __fegetexcept ();
+  /* Get current exception mask to return.  */
+  fe.fenv = curr.fenv = fegetenv_register ();
+  result = fenv_reg_to_exceptions (fe.l);
 
   if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID)
     excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID;
 
-  fe.fenv = fegetenv_register ();
+  /* Sets the new exception mask.  */
   if (excepts & FE_INEXACT)
     fe.l &= ~(1 << (31 - FPSCR_XE));
   if (excepts & FE_DIVBYZERO)
@@ -41,7 +43,9 @@ fedisableexcept (int excepts)
     fe.l &= ~(1 << (31 - FPSCR_OE));
   if (excepts & FE_INVALID)
     fe.l &= ~(1 << (31 - FPSCR_VE));
-  fesetenv_register (fe.fenv);
+
+  if (fe.l != curr.l)
+    fesetenv_register (fe.fenv);
 
   new = __fegetexcept ();
   if (new == 0 && result != 0)
index 8ad0f97ac74ad575ef3e5a5e6bd71afb511da108..01a68cf08660172fdc53262160cb0561fb2f43e5 100644 (file)
 int
 feenableexcept (int excepts)
 {
-  fenv_union_t fe;
-  int result, new;
+  fenv_union_t fe, curr;
+  int result = 0, new;
 
-  result = __fegetexcept ();
+  /* Get current exception mask to return.  */
+  fe.fenv = curr.fenv = fegetenv_register ();
+  result = fenv_reg_to_exceptions (fe.l);
 
   if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID)
     excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID;
 
-  fe.fenv = fegetenv_register ();
+  /* Sets the new exception mask.  */
   if (excepts & FE_INEXACT)
     fe.l |= (1 << (31 - FPSCR_XE));
   if (excepts & FE_DIVBYZERO)
@@ -41,7 +43,9 @@ feenableexcept (int excepts)
     fe.l |= (1 << (31 - FPSCR_OE));
   if (excepts & FE_INVALID)
     fe.l |= (1 << (31 - FPSCR_VE));
-  fesetenv_register (fe.fenv);
+
+  if (fe.l != curr.l)
+    fesetenv_register (fe.fenv);
 
   new = __fegetexcept ();
   if (new != 0 && result == 0)
index 1375a2f5adb85268d2c92fb34233f356de27d0e3..764dd38f3d832f299d5e50412e5783632e124581 100644 (file)
@@ -32,6 +32,9 @@ feholdexcept (fenv_t *envp)
      flag.  */
   new.l = old.l & 0xffffffff00000007LL;
 
+  if (new.l == old.l)
+    return 0;
+
   /* If the old env had any enabled exceptions, then mask SIGFPE in the
      MSR FE0/FE1 bits.  This may allow the FPU to run faster because it
      always takes the default action and can not generate SIGFPE. */
index 28e4d1f7c966b615f92a31e1f12b0c4fd41f525e..c1df5ce09151c0c342ba549e41f0f20841496d48 100644 (file)
@@ -146,6 +146,23 @@ enum {
   /* the remaining two least-significant bits keep the rounding mode */
 };
 
+static inline int
+fenv_reg_to_exceptions (unsigned long long l)
+{
+  int result = 0;
+  if (l & (1 << (31 - FPSCR_XE)))
+    result |= FE_INEXACT;
+  if (l & (1 << (31 - FPSCR_ZE)))
+    result |= FE_DIVBYZERO;
+  if (l & (1 << (31 - FPSCR_UE)))
+    result |= FE_UNDERFLOW;
+  if (l & (1 << (31 - FPSCR_OE)))
+    result |= FE_OVERFLOW;
+  if (l & (1 << (31 - FPSCR_VE)))
+    result |= FE_INVALID;
+  return result;
+}
+
 #ifdef _ARCH_PWR6
   /* Not supported in ISA 2.05.  Provided for source compat only.  */
 # define FPSCR_NI 29
index fa99ddbd4066cdb017533d9874d09843ace3539a..138bde0685f0564ce828e68f719aad16bc307ad8 100644 (file)
@@ -29,6 +29,8 @@ __fesetenv (const fenv_t *envp)
   /* get the currently set exceptions.  */
   new.fenv = *envp;
   old.fenv = fegetenv_register ();
+  if (old.l == new.l)
+    return 0;
 
   /* If the old env has no enabled exceptions and the new env has any enabled
      exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits.  This will put the
index 95193c1010c583e7ff3f650eff41d568f09b041e..cee6682b644827523fefb74b182807d3df3cb187 100644 (file)
@@ -21,7 +21,7 @@
 int
 __fesetexceptflag (const fexcept_t *flagp, int excepts)
 {
-  fenv_union_t u;
+  fenv_union_t u, n;
   fexcept_t flag;
 
   /* Get the current state.  */
@@ -31,7 +31,7 @@ __fesetexceptflag (const fexcept_t *flagp, int excepts)
   flag = *flagp & excepts;
 
   /* Replace the exception status */
-  u.l = ((u.l & ~(FPSCR_STICKY_BITS & excepts))
+  n.l = ((u.l & ~(FPSCR_STICKY_BITS & excepts))
         | (flag & FPSCR_STICKY_BITS)
         | (flag >> ((31 - FPSCR_VX) - (31 - FPSCR_VXSOFT))
            & FE_INVALID_SOFTWARE));
@@ -39,7 +39,8 @@ __fesetexceptflag (const fexcept_t *flagp, int excepts)
   /* Store the new status word (along with the rest of the environment).
      This may cause floating-point exceptions if the restored state
      requests it.  */
-  fesetenv_register (u.fenv);
+  if (n.l != u.l)
+    fesetenv_register (u.fenv);
 
   /* Deal with FE_INVALID_SOFTWARE not being implemented on some chips.  */
   if (flag & FE_INVALID)