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); }