PowerPC: Suppress unnecessary FPSCR write

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.
This commit is contained in:
Adhemerval Zanella 2014-04-28 14:38:24 -05:00
parent 5abebba403
commit 18f2945ae9
8 changed files with 60 additions and 16 deletions

View File

@ -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.

View File

@ -22,17 +22,18 @@
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;

View File

@ -22,15 +22,17 @@
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)

View File

@ -22,15 +22,17 @@
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)

View 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. */

View 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

View 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

View 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)