i386: Use generic division to generate INEXACT exception
authorUros Bizjak <ubizjak@gmail.com>
Wed, 6 May 2020 21:01:32 +0000 (23:01 +0200)
committerUros Bizjak <ubizjak@gmail.com>
Wed, 6 May 2020 21:01:32 +0000 (23:01 +0200)
Introduce math_force_eval_div to use generic division to generate
INEXACT as well as INVALID and DIVZERO exceptions.

libgcc/ChangeLog:

* config/i386/sfp-exceptions.c (__math_force_eval): Remove.
(__math_force_eval_div): New define.
(__sfp_handle_exceptions): Use __math_force_eval_div to use
generic division to generate INVALID, DIVZERO and INEXACT
exceptions.

libatomic/ChangeLog:

* config/x86/fenv.c (__math_force_eval): Remove.
(__math_force_eval_div): New define.
(__atomic_deraiseexcept): Use __math_force_eval_div to use
generic division to generate INVALID, DIVZERO and INEXACT
exceptions.

libgfortran/ChangeLog:

* config/fpu-387.h (__math_force_eval): Remove.
(__math_force_eval_div): New define.
(local_feraiseexcept): Use __math_force_eval_div to use
generic division to generate INVALID, DIVZERO and INEXACT
exceptions.
(struct fenv): Define named struct instead of typedef.

libatomic/ChangeLog
libatomic/config/x86/fenv.c
libgcc/ChangeLog
libgcc/config/i386/sfp-exceptions.c
libgfortran/ChangeLog
libgfortran/config/fpu-387.h

index 48c115de49f2b35149ef1dc630c33f1d9c873bf7..e8ab8ecb047607643193e9e8be54d579690f798e 100644 (file)
@@ -1,7 +1,15 @@
+2020-05-06  Uroš Bizjak  <ubizjak@gmail.com>
+
+       * config/x86/fenv.c (__math_force_eval): Remove.
+       (__math_force_eval_div): New define.
+       (__atomic_deraiseexcept): Use __math_force_eval_div to use
+       generic division to generate INVALID, DIVZERO and INEXACT
+       exceptions.
+
 2020-05-01  Uroš Bizjak  <ubizjak@gmail.com>
 
        * config/x86/fenv.c (__math_force_eval): New define.
-       (__atomic_feraiseexcept): Use __math_force_eval to evaluete
+       (__atomic_feraiseexcept): Use __math_force_eval to evaluate
        generic division to generate INVALID and DIVZERO exceptions.
 
 2020-04-19  Uroš Bizjak  <ubizjak@gmail.com>
index d972a99f5943bfa0b6016823bb3a41185dae9b46..88622c613f318c9f304466dae2fb4a6be91da39d 100644 (file)
@@ -48,9 +48,11 @@ struct fenv
 };
 
 #ifdef __SSE_MATH__
-# define __math_force_eval(x) asm volatile ("" : : "x" (x));
+# define __math_force_eval_div(x, y) \
+  do { asm ("" : "+x" (x)); asm volatile ("" : : "x" (x / y)); } while (0)
 #else
-# define __math_force_eval(x) asm volatile ("" : : "f" (x));
+# define __math_force_eval_div(x, y) \
+  do { asm ("" : "+t" (x)); asm volatile ("" : : "f" (x / y)); } while (0)
 #endif
 
 /* Raise the supported floating-point exceptions from EXCEPTS.  Other
@@ -59,14 +61,15 @@ struct fenv
 void
 __atomic_feraiseexcept (int excepts)
 {
+  struct fenv temp;
+
   if (excepts & FE_INVALID)
     {
       float f = 0.0f;
-      __math_force_eval (f / f);
+      __math_force_eval_div (f, f);
     }
   if (excepts & FE_DENORM)
     {
-      struct fenv temp;
       asm volatile ("fnstenv\t%0" : "=m" (temp));
       temp.__status_word |= FE_DENORM;
       asm volatile ("fldenv\t%0" : : "m" (temp));
@@ -75,11 +78,10 @@ __atomic_feraiseexcept (int excepts)
   if (excepts & FE_DIVBYZERO)
     {
       float f = 1.0f, g = 0.0f;
-      __math_force_eval (f / g);
+      __math_force_eval_div (f, g);
     }
   if (excepts & FE_OVERFLOW)
     {
-      struct fenv temp;
       asm volatile ("fnstenv\t%0" : "=m" (temp));
       temp.__status_word |= FE_OVERFLOW;
       asm volatile ("fldenv\t%0" : : "m" (temp));
@@ -87,7 +89,6 @@ __atomic_feraiseexcept (int excepts)
     }
   if (excepts & FE_UNDERFLOW)
     {
-      struct fenv temp;
       asm volatile ("fnstenv\t%0" : "=m" (temp));
       temp.__status_word |= FE_UNDERFLOW;
       asm volatile ("fldenv\t%0" : : "m" (temp));
@@ -96,11 +97,6 @@ __atomic_feraiseexcept (int excepts)
   if (excepts & FE_INEXACT)
     {
       float f = 1.0f, g = 3.0f;
-#ifdef __SSE_MATH__
-      asm volatile ("%vdivss\t{%1, %d0|%d0, %1}" : "+x" (f) : "xm" (g));
-#else
-      asm volatile ("fdivs\t%1" : "+t" (f) : "m" (g));
-      /* No need for fwait, exception is triggered by emitted fstp.  */
-#endif
+      __math_force_eval_div (f, g);
     }
 }
index 8e63e43b756f4b3aa0eef3aba55bead65ed36fe4..33e8929f16a9301d9eb2747eefbb98be1f1c8c6e 100644 (file)
@@ -1,3 +1,11 @@
+2020-05-06  Uroš Bizjak  <ubizjak@gmail.com>
+
+       * config/i386/sfp-exceptions.c (__math_force_eval): Remove.
+       (__math_force_eval_div): New define.
+       (__sfp_handle_exceptions): Use __math_force_eval_div to use
+       generic division to generate INVALID, DIVZERO and INEXACT
+       exceptions.
+
 2020-05-06  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * config/aarch64/lse-init.c (init_have_lse_atomics): Use __getauxval
@@ -54,7 +62,7 @@
 2020-05-01  Uroš Bizjak  <ubizjak@gmail.com>
 
        * config/i386/sfp-exceptions.c (__math_force_eval): New define.
-       (__sfp_handle_exceptions): Use __math_force_eval to evaluete
+       (__sfp_handle_exceptions): Use __math_force_eval to evaluate
        generic division to generate INVALID and DIVZERO exceptions.
 
 2020-04-27  Sebastian Huber  <sebastian.huber@embedded-brains.de>
index 4b3a7a08da124dcee465384d56138ac8822ab1f2..72cb0f4d3bb3bc5cbc2b960aeea25101f3f1ed14 100644 (file)
@@ -42,22 +42,25 @@ struct fenv
 };
 
 #ifdef __SSE_MATH__
-# define __math_force_eval(x) asm volatile ("" : : "x" (x));
+# define __math_force_eval_div(x, y) \
+  do { asm ("" : "+x" (x)); asm volatile ("" : : "x" (x / y)); } while (0)
 #else
-# define __math_force_eval(x) asm volatile ("" : : "f" (x));
+# define __math_force_eval_div(x, y) \
+  do { asm ("" : "+t" (x)); asm volatile ("" : : "f" (x / y)); } while (0)
 #endif
 
 void
 __sfp_handle_exceptions (int _fex)
 {
+  struct fenv temp;
+
   if (_fex & FP_EX_INVALID)
     {
       float f = 0.0f;
-      __math_force_eval (f / f);
+      __math_force_eval_div (f, f);
     }
   if (_fex & FP_EX_DENORM)
     {
-      struct fenv temp;
       asm volatile ("fnstenv\t%0" : "=m" (temp));
       temp.__status_word |= FP_EX_DENORM;
       asm volatile ("fldenv\t%0" : : "m" (temp));
@@ -66,11 +69,10 @@ __sfp_handle_exceptions (int _fex)
   if (_fex & FP_EX_DIVZERO)
     {
       float f = 1.0f, g = 0.0f;
-      __math_force_eval (f / g);
+      __math_force_eval_div (f, g);
     }
   if (_fex & FP_EX_OVERFLOW)
     {
-      struct fenv temp;
       asm volatile ("fnstenv\t%0" : "=m" (temp));
       temp.__status_word |= FP_EX_OVERFLOW;
       asm volatile ("fldenv\t%0" : : "m" (temp));
@@ -78,7 +80,6 @@ __sfp_handle_exceptions (int _fex)
     }
   if (_fex & FP_EX_UNDERFLOW)
     {
-      struct fenv temp;
       asm volatile ("fnstenv\t%0" : "=m" (temp));
       temp.__status_word |= FP_EX_UNDERFLOW;
       asm volatile ("fldenv\t%0" : : "m" (temp));
@@ -87,12 +88,7 @@ __sfp_handle_exceptions (int _fex)
   if (_fex & FP_EX_INEXACT)
     {
       float f = 1.0f, g = 3.0f;
-#ifdef __SSE_MATH__
-      asm volatile ("%vdivss\t{%1, %d0|%d0, %1}" : "+x" (f) : "xm" (g));
-#else
-      asm volatile ("fdivs\t%1" : "+t" (f) : "m" (g));
-      /* No need for fwait, exception is triggered by emitted fstp.  */
-#endif
+      __math_force_eval_div (f, g);
     }
 }
 #endif
index eecfb904f551767c9f4a266cb70fe5f2c029c788..94c7e0f105da0c348281bd9891802d427e3bcf15 100644 (file)
@@ -1,7 +1,16 @@
+2020-05-06  Uroš Bizjak  <ubizjak@gmail.com>
+
+       * config/fpu-387.h (__math_force_eval): Remove.
+       (__math_force_eval_div): New define.
+       (local_feraiseexcept): Use __math_force_eval_div to use
+       generic division to generate INVALID, DIVZERO and INEXACT
+       exceptions.
+       (struct fenv): Define named struct instead of typedef.
+
 2020-05-01  Uroš Bizjak  <ubizjak@gmail.com>
 
        * config/fpu-387.h (__math_force_eval): New define.
-       (local_feraiseexcept): Use __math_force_eval to evaluete
+       (local_feraiseexcept): Use __math_force_eval to evaluate
        generic division to generate INVALID and DIVZERO exceptions.
 
 2020-04-22  Fritz Reese  <foreese@gcc.gnu.org>
index 41b82bc809858ef170ca3760e3e3af4b2912cfc2..8b5e758c2caa0b44f39b9baf9ede8117056b6d35 100644 (file)
@@ -69,7 +69,7 @@ has_sse (void)
 
 /* This structure corresponds to the layout of the block
    written by FSTENV.  */
-typedef struct
+struct fenv
 {
   unsigned short int __control_word;
   unsigned short int __unused1;
@@ -79,22 +79,28 @@ typedef struct
   unsigned short int __unused3;
   unsigned int __eip;
   unsigned short int __cs_selector;
-  unsigned short int __opcode;
+  unsigned int __opcode:11;
+  unsigned int __unused4:5;
   unsigned int __data_offset;
   unsigned short int __data_selector;
   unsigned short int __unused5;
   unsigned int __mxcsr;
-}
-my_fenv_t;
+};
 
 /* Check we can actually store the FPU state in the allocated size.  */
-_Static_assert (sizeof(my_fenv_t) <= (size_t) GFC_FPE_STATE_BUFFER_SIZE,
+_Static_assert (sizeof(struct fenv) <= (size_t) GFC_FPE_STATE_BUFFER_SIZE,
                "GFC_FPE_STATE_BUFFER_SIZE is too small");
 
 #ifdef __SSE_MATH__
-# define __math_force_eval(x) __asm__ __volatile__ ("" : : "x" (x));
+# define __math_force_eval_div(x, y)                                   \
+  do {                                                                 \
+    __asm__ ("" : "+x" (x)); __asm__ __volatile__ ("" : : "x" (x / y));        \
+  } while (0)
 #else
-# define __math_force_eval(x) __asm__ __volatile__ ("" : : "f" (x));
+# define __math_force_eval_div(x, y)                                   \
+  do {                                                                 \
+    __asm__ ("" : "+t" (x)); __asm__ __volatile__ ("" : : "f" (x / y));        \
+  } while (0)
 #endif
 
 /* Raise the supported floating-point exceptions from EXCEPTS.  Other
@@ -104,14 +110,15 @@ _Static_assert (sizeof(my_fenv_t) <= (size_t) GFC_FPE_STATE_BUFFER_SIZE,
 static void
 local_feraiseexcept (int excepts)
 {
+  struct fenv temp;
+
   if (excepts & _FPU_MASK_IM)
     {
       float f = 0.0f;
-      __math_force_eval (f / f);
+      __math_force_eval_div (f, f);
     }
   if (excepts & _FPU_MASK_DM)
     {
-      my_fenv_t temp;
       __asm__ __volatile__ ("fnstenv\t%0" : "=m" (temp));
       temp.__status_word |= _FPU_MASK_DM;
       __asm__ __volatile__ ("fldenv\t%0" : : "m" (temp));
@@ -120,11 +127,10 @@ local_feraiseexcept (int excepts)
   if (excepts & _FPU_MASK_ZM)
     {
       float f = 1.0f, g = 0.0f;
-      __math_force_eval (f / g);
+      __math_force_eval_div (f, g);
     }
   if (excepts & _FPU_MASK_OM)
     {
-      my_fenv_t temp;
       __asm__ __volatile__ ("fnstenv\t%0" : "=m" (temp));
       temp.__status_word |= _FPU_MASK_OM;
       __asm__ __volatile__ ("fldenv\t%0" : : "m" (temp));
@@ -132,7 +138,6 @@ local_feraiseexcept (int excepts)
     }
   if (excepts & _FPU_MASK_UM)
     {
-      my_fenv_t temp;
       __asm__ __volatile__ ("fnstenv\t%0" : "=m" (temp));
       temp.__status_word |= _FPU_MASK_UM;
       __asm__ __volatile__ ("fldenv\t%0" : : "m" (temp));
@@ -141,12 +146,7 @@ local_feraiseexcept (int excepts)
   if (excepts & _FPU_MASK_PM)
     {
       float f = 1.0f, g = 3.0f;
-#ifdef __SSE_MATH__
-      __asm__ __volatile__ ("%vdivss\t{%1, %d0|%d0, %1}" : "+x" (f) : "xm" (g));
-#else
-      __asm__ __volatile__ ("fdivs\t%1" : "+t" (f) : "m" (g));
-      /* No need for fwait, exception is triggered by emitted fstp.  */
-#endif
+      __math_force_eval_div (f, g);
     }
 }
 
@@ -272,7 +272,7 @@ get_fpu_except_flags (void)
 void
 set_fpu_except_flags (int set, int clear)
 {
-  my_fenv_t temp;
+  struct fenv temp;
   int exc_set = 0, exc_clr = 0;
 
   /* Translate from GFC_PE_* values to _FPU_MASK_* values.  */
@@ -426,7 +426,7 @@ support_fpu_rounding_mode (int mode __attribute__((unused)))
 void
 get_fpu_state (void *state)
 {
-  my_fenv_t *envp = state;
+  struct fenv *envp = state;
 
   __asm__ __volatile__ ("fnstenv\t%0" : "=m" (*envp));
 
@@ -441,7 +441,7 @@ get_fpu_state (void *state)
 void
 set_fpu_state (void *state)
 {
-  my_fenv_t *envp = state;
+  struct fenv *envp = state;
 
   /* glibc sources (sysdeps/x86_64/fpu/fesetenv.c) do something more
      complex than this, but I think it suffices in our case.  */