diff options
author | Paul A. Clarke <pc@us.ibm.com> | 2019-06-20 11:57:18 -0500 |
---|---|---|
committer | Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> | 2019-06-30 08:40:44 -0300 |
commit | 3db85a9814784a74536a1f0e7b7ddbfef7dc84bb (patch) | |
tree | 38c7cbbeae1d517b1fd54e723bf55e0d8887abe1 /sysdeps/powerpc/fpu | |
parent | d064591266634a8ff55b645181167b8626c793c9 (diff) | |
download | glibc-3db85a9814784a74536a1f0e7b7ddbfef7dc84bb.zip glibc-3db85a9814784a74536a1f0e7b7ddbfef7dc84bb.tar.gz glibc-3db85a9814784a74536a1f0e7b7ddbfef7dc84bb.tar.bz2 |
powerpc: Use faster means to access FPSCR when possible in some cases
Using 'mffs' instruction to read the Floating Point Status Control Register
(FPSCR) can force a processor flush in some cases, with undesirable
performance impact. If the values of the bits in the FPSCR which force the
flush are not needed, an instruction that is new to POWER9 (ISA version 3.0),
'mffsl' can be used instead.
Cases included: get_rounding_mode, fegetround, fegetmode, fegetexcept.
* sysdeps/powerpc/bits/fenvinline.h (__fegetround): Use
__fegetround_ISA300() or __fegetround_ISA2() as appropriate.
(__fegetround_ISA300) New.
(__fegetround_ISA2) New.
* sysdeps/powerpc/fpu_control.h (IS_ISA300): New.
(_FPU_MFFS): Move implementation...
(_FPU_GETCW): Here.
(_FPU_MFFSL): Move implementation....
(_FPU_GET_RC_ISA300): Here. New.
(_FPU_GET_RC): Use _FPU_GET_RC_ISA300() or _FPU_GETCW() as appropriate.
* sysdeps/powerpc/fpu/fenv_libc.h (fegetenv_status_ISA300): New.
(fegetenv_status): New.
* sysdeps/powerpc/fpu/fegetmode.c (fegetmode): Use fegetenv_status()
instead of fegetenv_register().
* sysdeps/powerpc/fpu/fegetexcept.c (__fegetexcept): Likewise.
Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
Diffstat (limited to 'sysdeps/powerpc/fpu')
-rw-r--r-- | sysdeps/powerpc/fpu/fegetexcept.c | 2 | ||||
-rw-r--r-- | sysdeps/powerpc/fpu/fegetmode.c | 2 | ||||
-rw-r--r-- | sysdeps/powerpc/fpu/fenv_libc.h | 21 |
3 files changed, 23 insertions, 2 deletions
diff --git a/sysdeps/powerpc/fpu/fegetexcept.c b/sysdeps/powerpc/fpu/fegetexcept.c index 2173d77..10a37f0 100644 --- a/sysdeps/powerpc/fpu/fegetexcept.c +++ b/sysdeps/powerpc/fpu/fegetexcept.c @@ -24,7 +24,7 @@ __fegetexcept (void) { fenv_union_t fe; - fe.fenv = fegetenv_register (); + fe.fenv = fegetenv_status (); return fenv_reg_to_exceptions (fe.l); } diff --git a/sysdeps/powerpc/fpu/fegetmode.c b/sysdeps/powerpc/fpu/fegetmode.c index f43ab60..466f5b7 100644 --- a/sysdeps/powerpc/fpu/fegetmode.c +++ b/sysdeps/powerpc/fpu/fegetmode.c @@ -21,6 +21,6 @@ int fegetmode (femode_t *modep) { - *modep = fegetenv_register (); + *modep = fegetenv_status (); return 0; } diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h index f66bf24..55b1697 100644 --- a/sysdeps/powerpc/fpu/fenv_libc.h +++ b/sysdeps/powerpc/fpu/fenv_libc.h @@ -34,6 +34,27 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden; pointer. */ #define fegetenv_register() __builtin_mffs() +/* Equivalent to fegetenv_register, but only returns bits for + status, exception enables, and mode. */ + +#define fegetenv_status_ISA300() \ + ({register double __fr; \ + __asm__ __volatile__ ( \ + ".machine push; .machine \"power9\"; mffsl %0; .machine pop" \ + : "=f" (__fr)); \ + __fr; \ + }) + +#ifdef _ARCH_PWR9 +# define fegetenv_status() fegetenv_status_ISA300() +#else +# define fegetenv_status() \ + (__glibc_likely (__builtin_cpu_supports ("arch_3_00")) \ + ? fegetenv_status_ISA300() \ + : fegetenv_register() \ + ) +#endif + /* Equivalent to fesetenv, but takes a fenv_t instead of a pointer. */ #define fesetenv_register(env) \ do { \ |