Hello!

When changing trap masks, it is necessary to clear pending traps to
prevent firing spurious interrupts.  Attached patch also optimizes
set_fpu_trap_exceptions function considerably to only call
feenableexcept and fedisableexcept functions each once.

2019-01-29  Uroš Bizjak  <ubiz...@gmail.com>

    * config/fpu-glibc.h (set_fpu_trap_exceptions): Clear stalled
    exception flags before changing trap mode.  Optimize to call
    feenableexcept and fedisableexcept only once.

Patch was bootstrapped and regression tested on alphaev68-linux-gnu,
where it fixes gfortran.dg/ieee/ieee_10.f90 failures.

OK for mainline?

Uros.
Index: config/fpu-glibc.h
===================================================================
--- config/fpu-glibc.h  (revision 268248)
+++ config/fpu-glibc.h  (working copy)
@@ -39,48 +39,56 @@
 
 void set_fpu_trap_exceptions (int trap, int notrap)
 {
+  int mode_set = 0, mode_clr = 0;
+
 #ifdef FE_INVALID
   if (trap & GFC_FPE_INVALID)
-    feenableexcept (FE_INVALID);
+    mode_set |= FE_INVALID;
   if (notrap & GFC_FPE_INVALID)
-    fedisableexcept (FE_INVALID);
+    mode_clr |= FE_INVALID;
 #endif
 
 /* Some glibc targets (like alpha) have FE_DENORMAL, but not many.  */
 #ifdef FE_DENORMAL
   if (trap & GFC_FPE_DENORMAL)
-    feenableexcept (FE_DENORMAL);
+    mode_set |= FE_DENORMAL;
   if (notrap & GFC_FPE_DENORMAL)
-    fedisableexcept (FE_DENORMAL);
+    mode_clr |= FE_DENORMAL;
 #endif
 
 #ifdef FE_DIVBYZERO
   if (trap & GFC_FPE_ZERO)
-    feenableexcept (FE_DIVBYZERO);
+    mode_set |= FE_DIVBYZERO;
   if (notrap & GFC_FPE_ZERO)
-    fedisableexcept (FE_DIVBYZERO);
+    mode_clr |= FE_DIVBYZERO;
 #endif
 
 #ifdef FE_OVERFLOW
   if (trap & GFC_FPE_OVERFLOW)
-    feenableexcept (FE_OVERFLOW);
+    mode_set |= FE_OVERFLOW;
   if (notrap & GFC_FPE_OVERFLOW)
-    fedisableexcept (FE_OVERFLOW);
+    mode_clr |= FE_OVERFLOW;
 #endif
 
 #ifdef FE_UNDERFLOW
   if (trap & GFC_FPE_UNDERFLOW)
-    feenableexcept (FE_UNDERFLOW);
+    mode_set |= FE_UNDERFLOW;
   if (notrap & GFC_FPE_UNDERFLOW)
-    fedisableexcept (FE_UNDERFLOW);
+    mode_clr |= FE_UNDERFLOW;
 #endif
 
 #ifdef FE_INEXACT
   if (trap & GFC_FPE_INEXACT)
-    feenableexcept (FE_INEXACT);
+    mode_set |= FE_INEXACT;
   if (notrap & GFC_FPE_INEXACT)
-    fedisableexcept (FE_INEXACT);
+    mode_clr |= FE_INEXACT;
 #endif
+
+  /* Clear stalled exception flags.  */
+  feclearexcept (FE_ALL_EXCEPT);
+
+  feenableexcept (mode_set);
+  fedisableexcept (mode_clr);
 }
 
 

Reply via email to