59 lines
2.6 KiB
Diff
59 lines
2.6 KiB
Diff
|
commit 7413c188c77adb26a15cf0e98e0a991d09d73c65
|
||
|
Author: Paul A. Clarke <pc@us.ibm.com>
|
||
|
Date: Thu Sep 19 11:18:33 2019 -0500
|
||
|
|
||
|
[powerpc] libc_feupdateenv_test: optimize FPSCR access
|
||
|
|
||
|
ROUND_TO_ODD and a couple of other places use libc_feupdateenv_test to
|
||
|
restore the rounding mode and exception enables, preserve exception flags,
|
||
|
and test whether given exception(s) were generated.
|
||
|
|
||
|
If the exception flags haven't changed, then it is sufficient and a bit
|
||
|
more efficient to just restore the rounding mode and enables, rather than
|
||
|
writing the full Floating-Point Status and Control Register (FPSCR).
|
||
|
|
||
|
Reviewed-by: Paul E. Murphy <murphyp@linux.ibm.com>
|
||
|
|
||
|
diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h
|
||
|
index 36b639c3939586f6..86ae7fda016abd8b 100644
|
||
|
--- a/sysdeps/powerpc/fpu/fenv_libc.h
|
||
|
+++ b/sysdeps/powerpc/fpu/fenv_libc.h
|
||
|
@@ -257,6 +257,10 @@ enum {
|
||
|
(FPSCR_VE_MASK|FPSCR_OE_MASK|FPSCR_UE_MASK|FPSCR_ZE_MASK|FPSCR_XE_MASK)
|
||
|
#define FPSCR_BASIC_EXCEPTIONS_MASK \
|
||
|
(FPSCR_VX_MASK|FPSCR_OX_MASK|FPSCR_UX_MASK|FPSCR_ZX_MASK|FPSCR_XX_MASK)
|
||
|
+#define FPSCR_EXCEPTIONS_MASK (FPSCR_BASIC_EXCEPTIONS_MASK| \
|
||
|
+ FPSCR_VXSNAN_MASK|FPSCR_VXISI_MASK|FPSCR_VXIDI_MASK|FPSCR_VXZDZ_MASK| \
|
||
|
+ FPSCR_VXIMZ_MASK|FPSCR_VXVC_MASK|FPSCR_VXSOFT_MASK|FPSCR_VXSQRT_MASK| \
|
||
|
+ FPSCR_VXCVI_MASK)
|
||
|
#define FPSCR_FPRF_MASK \
|
||
|
(FPSCR_FPRF_C_MASK|FPSCR_FPRF_FL_MASK|FPSCR_FPRF_FG_MASK| \
|
||
|
FPSCR_FPRF_FE_MASK|FPSCR_FPRF_FU_MASK)
|
||
|
diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h
|
||
|
index c236d45db2f399a4..86a3611b3ef41759 100644
|
||
|
--- a/sysdeps/powerpc/fpu/fenv_private.h
|
||
|
+++ b/sysdeps/powerpc/fpu/fenv_private.h
|
||
|
@@ -52,8 +52,20 @@ __libc_femergeenv_ppc (const fenv_t *envp, unsigned long long old_mask,
|
||
|
__TEST_AND_EXIT_NON_STOP (old.l, new.l);
|
||
|
__TEST_AND_ENTER_NON_STOP (old.l, new.l);
|
||
|
|
||
|
- /* Atomically enable and raise (if appropriate) exceptions set in `new'. */
|
||
|
- fesetenv_register (new.fenv);
|
||
|
+ /* If requesting to keep status, replace control, and merge exceptions,
|
||
|
+ and exceptions haven't changed, we can just set new control instead
|
||
|
+ of the whole FPSCR. */
|
||
|
+ if ((old_mask & (FPSCR_CONTROL_MASK|FPSCR_STATUS_MASK|FPSCR_EXCEPTIONS_MASK))
|
||
|
+ == (FPSCR_STATUS_MASK|FPSCR_EXCEPTIONS_MASK) &&
|
||
|
+ (new_mask & (FPSCR_CONTROL_MASK|FPSCR_STATUS_MASK|FPSCR_EXCEPTIONS_MASK))
|
||
|
+ == (FPSCR_CONTROL_MASK|FPSCR_EXCEPTIONS_MASK) &&
|
||
|
+ (old.l & FPSCR_EXCEPTIONS_MASK) == (new.l & FPSCR_EXCEPTIONS_MASK))
|
||
|
+ {
|
||
|
+ fesetenv_mode (new.fenv);
|
||
|
+ }
|
||
|
+ else
|
||
|
+ /* Atomically enable and raise (if appropriate) exceptions set in `new'. */
|
||
|
+ fesetenv_register (new.fenv);
|
||
|
|
||
|
return old.l;
|
||
|
}
|