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:
parent
5abebba403
commit
18f2945ae9
12
ChangeLog
12
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>
|
2014-05-29 Carlos O'Donell <carlos@systemhalted.org>
|
||||||
|
|
||||||
* sysdeps/hppa: Move directory from ports/sysdeps/hppa.
|
* sysdeps/hppa: Move directory from ports/sysdeps/hppa.
|
||||||
|
|
|
@ -22,17 +22,18 @@
|
||||||
int
|
int
|
||||||
__feclearexcept (int excepts)
|
__feclearexcept (int excepts)
|
||||||
{
|
{
|
||||||
fenv_union_t u;
|
fenv_union_t u, n;
|
||||||
|
|
||||||
/* Get the current state. */
|
/* Get the current state. */
|
||||||
u.fenv = fegetenv_register ();
|
u.fenv = fegetenv_register ();
|
||||||
|
|
||||||
/* Clear the relevant bits. */
|
/* 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));
|
| (excepts & FPSCR_STICKY_BITS));
|
||||||
|
|
||||||
/* Put the new state in effect. */
|
/* Put the new state in effect. */
|
||||||
fesetenv_register (u.fenv);
|
if (u.l != n.l)
|
||||||
|
fesetenv_register (n.fenv);
|
||||||
|
|
||||||
/* Success. */
|
/* Success. */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -22,15 +22,17 @@
|
||||||
int
|
int
|
||||||
fedisableexcept (int excepts)
|
fedisableexcept (int excepts)
|
||||||
{
|
{
|
||||||
fenv_union_t fe;
|
fenv_union_t fe, curr;
|
||||||
int result, new;
|
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)
|
if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID)
|
||||||
excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID;
|
excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID;
|
||||||
|
|
||||||
fe.fenv = fegetenv_register ();
|
/* Sets the new exception mask. */
|
||||||
if (excepts & FE_INEXACT)
|
if (excepts & FE_INEXACT)
|
||||||
fe.l &= ~(1 << (31 - FPSCR_XE));
|
fe.l &= ~(1 << (31 - FPSCR_XE));
|
||||||
if (excepts & FE_DIVBYZERO)
|
if (excepts & FE_DIVBYZERO)
|
||||||
|
@ -41,6 +43,8 @@ fedisableexcept (int excepts)
|
||||||
fe.l &= ~(1 << (31 - FPSCR_OE));
|
fe.l &= ~(1 << (31 - FPSCR_OE));
|
||||||
if (excepts & FE_INVALID)
|
if (excepts & FE_INVALID)
|
||||||
fe.l &= ~(1 << (31 - FPSCR_VE));
|
fe.l &= ~(1 << (31 - FPSCR_VE));
|
||||||
|
|
||||||
|
if (fe.l != curr.l)
|
||||||
fesetenv_register (fe.fenv);
|
fesetenv_register (fe.fenv);
|
||||||
|
|
||||||
new = __fegetexcept ();
|
new = __fegetexcept ();
|
||||||
|
|
|
@ -22,15 +22,17 @@
|
||||||
int
|
int
|
||||||
feenableexcept (int excepts)
|
feenableexcept (int excepts)
|
||||||
{
|
{
|
||||||
fenv_union_t fe;
|
fenv_union_t fe, curr;
|
||||||
int result, new;
|
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)
|
if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID)
|
||||||
excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID;
|
excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID;
|
||||||
|
|
||||||
fe.fenv = fegetenv_register ();
|
/* Sets the new exception mask. */
|
||||||
if (excepts & FE_INEXACT)
|
if (excepts & FE_INEXACT)
|
||||||
fe.l |= (1 << (31 - FPSCR_XE));
|
fe.l |= (1 << (31 - FPSCR_XE));
|
||||||
if (excepts & FE_DIVBYZERO)
|
if (excepts & FE_DIVBYZERO)
|
||||||
|
@ -41,6 +43,8 @@ feenableexcept (int excepts)
|
||||||
fe.l |= (1 << (31 - FPSCR_OE));
|
fe.l |= (1 << (31 - FPSCR_OE));
|
||||||
if (excepts & FE_INVALID)
|
if (excepts & FE_INVALID)
|
||||||
fe.l |= (1 << (31 - FPSCR_VE));
|
fe.l |= (1 << (31 - FPSCR_VE));
|
||||||
|
|
||||||
|
if (fe.l != curr.l)
|
||||||
fesetenv_register (fe.fenv);
|
fesetenv_register (fe.fenv);
|
||||||
|
|
||||||
new = __fegetexcept ();
|
new = __fegetexcept ();
|
||||||
|
|
|
@ -32,6 +32,9 @@ feholdexcept (fenv_t *envp)
|
||||||
flag. */
|
flag. */
|
||||||
new.l = old.l & 0xffffffff00000007LL;
|
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
|
/* 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
|
MSR FE0/FE1 bits. This may allow the FPU to run faster because it
|
||||||
always takes the default action and can not generate SIGFPE. */
|
always takes the default action and can not generate SIGFPE. */
|
||||||
|
|
|
@ -146,6 +146,23 @@ enum {
|
||||||
/* the remaining two least-significant bits keep the rounding mode */
|
/* 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
|
#ifdef _ARCH_PWR6
|
||||||
/* Not supported in ISA 2.05. Provided for source compat only. */
|
/* Not supported in ISA 2.05. Provided for source compat only. */
|
||||||
# define FPSCR_NI 29
|
# define FPSCR_NI 29
|
||||||
|
|
|
@ -29,6 +29,8 @@ __fesetenv (const fenv_t *envp)
|
||||||
/* get the currently set exceptions. */
|
/* get the currently set exceptions. */
|
||||||
new.fenv = *envp;
|
new.fenv = *envp;
|
||||||
old.fenv = fegetenv_register ();
|
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
|
/* 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
|
exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put the
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
int
|
int
|
||||||
__fesetexceptflag (const fexcept_t *flagp, int excepts)
|
__fesetexceptflag (const fexcept_t *flagp, int excepts)
|
||||||
{
|
{
|
||||||
fenv_union_t u;
|
fenv_union_t u, n;
|
||||||
fexcept_t flag;
|
fexcept_t flag;
|
||||||
|
|
||||||
/* Get the current state. */
|
/* Get the current state. */
|
||||||
|
@ -31,7 +31,7 @@ __fesetexceptflag (const fexcept_t *flagp, int excepts)
|
||||||
flag = *flagp & excepts;
|
flag = *flagp & excepts;
|
||||||
|
|
||||||
/* Replace the exception status */
|
/* 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 & FPSCR_STICKY_BITS)
|
||||||
| (flag >> ((31 - FPSCR_VX) - (31 - FPSCR_VXSOFT))
|
| (flag >> ((31 - FPSCR_VX) - (31 - FPSCR_VXSOFT))
|
||||||
& FE_INVALID_SOFTWARE));
|
& FE_INVALID_SOFTWARE));
|
||||||
|
@ -39,6 +39,7 @@ __fesetexceptflag (const fexcept_t *flagp, int excepts)
|
||||||
/* Store the new status word (along with the rest of the environment).
|
/* Store the new status word (along with the rest of the environment).
|
||||||
This may cause floating-point exceptions if the restored state
|
This may cause floating-point exceptions if the restored state
|
||||||
requests it. */
|
requests it. */
|
||||||
|
if (n.l != u.l)
|
||||||
fesetenv_register (u.fenv);
|
fesetenv_register (u.fenv);
|
||||||
|
|
||||||
/* Deal with FE_INVALID_SOFTWARE not being implemented on some chips. */
|
/* Deal with FE_INVALID_SOFTWARE not being implemented on some chips. */
|
||||||
|
|
Loading…
Reference in New Issue