From 4637a1d293c978816ad622ba33e3a32a78640edd Mon Sep 17 00:00:00 2001 From: Francois-Xavier Coudert Date: Wed, 31 Aug 2022 19:15:20 +0200 Subject: Fortran: F2018 rounding modes changes Add the new IEEE_AWAY rounding mode. It is unsupported on all known targets, but could be supported by glibc and AIX as part of the C2x proposal. Testing for now is minimal. Add the optional RADIX argument to IEEE_SET_ROUNDING_MODE and IEEE_GET_ROUNDING_MODE. It is unused for now, because we do not support radices other than 2. 2022-08-31 Francois-Xavier Coudert gcc/fortran/ * libgfortran.h: Declare GFC_FPE_AWAY. gcc/testsuite/ * gfortran.dg/ieee/rounding_2.f90: New test. libgfortran/ * ieee/ieee_arithmetic.F90: Add RADIX argument to IEEE_SET_ROUNDING_MODE and IEEE_GET_ROUNDING_MODE. * config/fpu-387.h: Add IEEE_AWAY mode. * config/fpu-aarch64.h: Add IEEE_AWAY mode. * config/fpu-aix.h: Add IEEE_AWAY mode. * config/fpu-generic.h: Add IEEE_AWAY mode. * config/fpu-glibc.h: Add IEEE_AWAY mode. * config/fpu-sysv.h: Add IEEE_AWAY mode. --- libgfortran/config/fpu-387.h | 7 +++++-- libgfortran/config/fpu-aarch64.h | 7 +++++-- libgfortran/config/fpu-aix.h | 22 ++++++++++++++++++++-- libgfortran/config/fpu-generic.h | 11 +++++++++-- libgfortran/config/fpu-glibc.h | 18 ++++++++++++++++++ libgfortran/config/fpu-sysv.h | 7 +++++-- libgfortran/ieee/ieee_arithmetic.F90 | 7 +++++-- 7 files changed, 67 insertions(+), 12 deletions(-) (limited to 'libgfortran') diff --git a/libgfortran/config/fpu-387.h b/libgfortran/config/fpu-387.h index fd00dab..e2f4a7d 100644 --- a/libgfortran/config/fpu-387.h +++ b/libgfortran/config/fpu-387.h @@ -418,9 +418,12 @@ get_fpu_rounding_mode (void) } int -support_fpu_rounding_mode (int mode __attribute__((unused))) +support_fpu_rounding_mode (int mode) { - return 1; + if (mode == GFC_FPE_AWAY) + return 0; + else + return 1; } void diff --git a/libgfortran/config/fpu-aarch64.h b/libgfortran/config/fpu-aarch64.h index 3a2e4ba..4789390 100644 --- a/libgfortran/config/fpu-aarch64.h +++ b/libgfortran/config/fpu-aarch64.h @@ -293,9 +293,12 @@ set_fpu_rounding_mode (int round) int -support_fpu_rounding_mode (int mode __attribute__((unused))) +support_fpu_rounding_mode (int mode) { - return 1; + if (mode == GFC_FPE_AWAY) + return 0; + else + return 1; } diff --git a/libgfortran/config/fpu-aix.h b/libgfortran/config/fpu-aix.h index c643874..fb1ac80 100644 --- a/libgfortran/config/fpu-aix.h +++ b/libgfortran/config/fpu-aix.h @@ -320,6 +320,11 @@ get_fpu_rounding_mode (void) return GFC_FPE_TOWARDZERO; #endif +#ifdef FE_TONEARESTFROMZERO + case FE_TONEARESTFROMZERO: + return GFC_FPE_AWAY; +#endif + default: return 0; /* Should be unreachable. */ } @@ -357,8 +362,14 @@ set_fpu_rounding_mode (int mode) break; #endif +#ifdef FE_TONEARESTFROMZERO + case GFC_FPE_AWAY: + rnd_mode = FE_TONEARESTFROMZERO; + break; +#endif + default: - return; /* Should be unreachable. */ + return; } fesetround (rnd_mode); @@ -398,8 +409,15 @@ support_fpu_rounding_mode (int mode) return 0; #endif + case GFC_FPE_AWAY: +#ifdef FE_TONEARESTFROMZERO + return 1; +#else + return 0; +#endif + default: - return 0; /* Should be unreachable. */ + return 0; } } diff --git a/libgfortran/config/fpu-generic.h b/libgfortran/config/fpu-generic.h index 3b62228..9e976a8 100644 --- a/libgfortran/config/fpu-generic.h +++ b/libgfortran/config/fpu-generic.h @@ -66,9 +66,16 @@ get_fpu_except_flags (void) int get_fpu_rounding_mode (void) -{ +{ + return 0; +} + + +int +support_fpu_rounding_mode (int mode __attribute__((unused))) +{ return 0; -} +} void diff --git a/libgfortran/config/fpu-glibc.h b/libgfortran/config/fpu-glibc.h index 265ef69..f34b696 100644 --- a/libgfortran/config/fpu-glibc.h +++ b/libgfortran/config/fpu-glibc.h @@ -342,6 +342,11 @@ get_fpu_rounding_mode (void) return GFC_FPE_TOWARDZERO; #endif +#ifdef FE_TONEARESTFROMZERO + case FE_TONEARESTFROMZERO: + return GFC_FPE_AWAY; +#endif + default: return 0; /* Should be unreachable. */ } @@ -379,6 +384,12 @@ set_fpu_rounding_mode (int mode) break; #endif +#ifdef FE_TONEARESTFROMZERO + case GFC_FPE_AWAY: + rnd_mode = FE_TONEARESTFROMZERO; + break; +#endif + default: return; /* Should be unreachable. */ } @@ -420,6 +431,13 @@ support_fpu_rounding_mode (int mode) return 0; #endif + case GFC_FPE_AWAY: +#ifdef FE_TONEARESTFROMZERO + return 1; +#else + return 0; +#endif + default: return 0; /* Should be unreachable. */ } diff --git a/libgfortran/config/fpu-sysv.h b/libgfortran/config/fpu-sysv.h index 4de3852..4681322 100644 --- a/libgfortran/config/fpu-sysv.h +++ b/libgfortran/config/fpu-sysv.h @@ -374,9 +374,12 @@ set_fpu_rounding_mode (int mode) int -support_fpu_rounding_mode (int mode __attribute__((unused))) +support_fpu_rounding_mode (int mode) { - return 1; + if (mode == GFC_FPE_AWAY) + return 0; + else + return 1; } diff --git a/libgfortran/ieee/ieee_arithmetic.F90 b/libgfortran/ieee/ieee_arithmetic.F90 index 4e01aa5..7dce37a 100644 --- a/libgfortran/ieee/ieee_arithmetic.F90 +++ b/libgfortran/ieee/ieee_arithmetic.F90 @@ -73,6 +73,7 @@ module IEEE_ARITHMETIC IEEE_TO_ZERO = IEEE_ROUND_TYPE(GFC_FPE_TOWARDZERO), & IEEE_UP = IEEE_ROUND_TYPE(GFC_FPE_UPWARD), & IEEE_DOWN = IEEE_ROUND_TYPE(GFC_FPE_DOWNWARD), & + IEEE_AWAY = IEEE_ROUND_TYPE(GFC_FPE_AWAY), & IEEE_OTHER = IEEE_ROUND_TYPE(0) @@ -1044,9 +1045,10 @@ contains ! IEEE_GET_ROUNDING_MODE - subroutine IEEE_GET_ROUNDING_MODE (ROUND_VALUE) + subroutine IEEE_GET_ROUNDING_MODE (ROUND_VALUE, RADIX) implicit none type(IEEE_ROUND_TYPE), intent(out) :: ROUND_VALUE + integer, intent(in), optional :: RADIX interface integer function helper() & @@ -1060,9 +1062,10 @@ contains ! IEEE_SET_ROUNDING_MODE - subroutine IEEE_SET_ROUNDING_MODE (ROUND_VALUE) + subroutine IEEE_SET_ROUNDING_MODE (ROUND_VALUE, RADIX) implicit none type(IEEE_ROUND_TYPE), intent(in) :: ROUND_VALUE + integer, intent(in), optional :: RADIX interface subroutine helper(val) & -- cgit v1.1 From de40fab2f32b03c3d8f69f72c7f1e38694f93d35 Mon Sep 17 00:00:00 2001 From: Francois-Xavier Coudert Date: Sun, 4 Sep 2022 18:24:23 +0200 Subject: Fortran: add IEEE_MODES_TYPE, IEEE_GET_MODES and IEEE_SET_MODES The IEEE_MODES_TYPE type and the two functions that get and set it were added in Fortran 2018. They can be implemented using the already existing target-specific functions. A future optimization could, on some targets, set/get all modes through one or two instructions only, but that would need a new set of functions in all config/fpu-* files. 2022-09-04 Francois-Xavier Coudert libgfortran/ * ieee/ieee_exceptions.F90: Add IEEE_MODES_TYPE, IEEE_GET_MODES and IEEE_SET_MODES. * ieee/ieee_arithmetic.F90: Make them public in IEEE_ARITHMETIC as well. gcc/testsuite/ * gfortran.dg/ieee/modes_1.f90: New test. --- libgfortran/ieee/ieee_arithmetic.F90 | 3 +- libgfortran/ieee/ieee_exceptions.F90 | 63 ++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) (limited to 'libgfortran') diff --git a/libgfortran/ieee/ieee_arithmetic.F90 b/libgfortran/ieee/ieee_arithmetic.F90 index 7dce37a..ce30e4a 100644 --- a/libgfortran/ieee/ieee_arithmetic.F90 +++ b/libgfortran/ieee/ieee_arithmetic.F90 @@ -39,7 +39,8 @@ module IEEE_ARITHMETIC IEEE_DIVIDE_BY_ZERO, IEEE_UNDERFLOW, IEEE_INEXACT, IEEE_USUAL, & IEEE_ALL, IEEE_STATUS_TYPE, IEEE_GET_FLAG, IEEE_GET_HALTING_MODE, & IEEE_GET_STATUS, IEEE_SET_FLAG, IEEE_SET_HALTING_MODE, & - IEEE_SET_STATUS, IEEE_SUPPORT_FLAG, IEEE_SUPPORT_HALTING + IEEE_SET_STATUS, IEEE_SUPPORT_FLAG, IEEE_SUPPORT_HALTING, & + IEEE_MODES_TYPE, IEEE_GET_MODES, IEEE_SET_MODES ! Derived types and named constants diff --git a/libgfortran/ieee/ieee_exceptions.F90 b/libgfortran/ieee/ieee_exceptions.F90 index 77363cf..3ed2f6e 100644 --- a/libgfortran/ieee/ieee_exceptions.F90 +++ b/libgfortran/ieee/ieee_exceptions.F90 @@ -56,6 +56,13 @@ module IEEE_EXCEPTIONS character(len=GFC_FPE_STATE_BUFFER_SIZE) :: hidden end type + type, public :: IEEE_MODES_TYPE + private + integer :: rounding + integer :: underflow + integer :: halting + end type + interface IEEE_SUPPORT_FLAG module procedure IEEE_SUPPORT_FLAG_4, & IEEE_SUPPORT_FLAG_8, & @@ -72,9 +79,65 @@ module IEEE_EXCEPTIONS public :: IEEE_SET_HALTING_MODE, IEEE_GET_HALTING_MODE public :: IEEE_SET_FLAG, IEEE_GET_FLAG public :: IEEE_SET_STATUS, IEEE_GET_STATUS + public :: IEEE_SET_MODES, IEEE_GET_MODES contains +! Fortran 2018: Saving and restoring floating-point modes +! (rounding modes, underflow mode, and halting mode) +! +! For now, we only have one rounding mode for all kinds. +! Some targets could optimize getting/setting all modes at once, but for now +! we make three calls. This code must be kept in sync with: +! - IEEE_{GET,SET}_ROUNDING_MODE +! - IEEE_{GET,SET}_UNDERFLOW_MODE +! - IEEE_{GET,SET}_HALTING_MODE + + subroutine IEEE_GET_MODES (MODES) + implicit none + type(IEEE_MODES_TYPE), intent(out) :: MODES + + interface + integer function helper_rounding() & + bind(c, name="_gfortrani_get_fpu_rounding_mode") + end function + integer function helper_underflow() & + bind(c, name="_gfortrani_get_fpu_underflow_mode") + end function + pure integer function helper_halting() & + bind(c, name="_gfortrani_get_fpu_trap_exceptions") + end function + end interface + + MODES%rounding = helper_rounding() + MODES%underflow = helper_underflow() + MODES%halting = helper_halting() + end subroutine + + subroutine IEEE_SET_MODES (MODES) + implicit none + type(IEEE_MODES_TYPE), intent(in) :: MODES + + interface + subroutine helper_rounding(val) & + bind(c, name="_gfortrani_set_fpu_rounding_mode") + integer, value :: val + end subroutine + subroutine helper_underflow(val) & + bind(c, name="_gfortrani_set_fpu_underflow_mode") + integer, value :: val + end subroutine + pure subroutine helper_halting(trap, notrap) & + bind(c, name="_gfortrani_set_fpu_trap_exceptions") + integer, intent(in), value :: trap, notrap + end subroutine + end interface + + call helper_rounding(MODES%rounding) + call helper_underflow(MODES%underflow) + call helper_halting(MODES%halting, NOT(MODES%halting)) + end subroutine + ! Saving and restoring floating-point status subroutine IEEE_GET_STATUS (STATUS_VALUE) -- cgit v1.1 From 43be56c4c6fb6b7f059df832eefb1cd049ff02de Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Tue, 20 Sep 2022 00:17:49 +0000 Subject: Daily bump. --- libgfortran/ChangeLog | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'libgfortran') diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 51c9f5c..fab472e 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,21 @@ +2022-09-19 Francois-Xavier Coudert + + * ieee/ieee_exceptions.F90: Add IEEE_MODES_TYPE, IEEE_GET_MODES + and IEEE_SET_MODES. + * ieee/ieee_arithmetic.F90: Make them public in IEEE_ARITHMETIC + as well. + +2022-09-19 Francois-Xavier Coudert + + * ieee/ieee_arithmetic.F90: Add RADIX argument to + IEEE_SET_ROUNDING_MODE and IEEE_GET_ROUNDING_MODE. + * config/fpu-387.h: Add IEEE_AWAY mode. + * config/fpu-aarch64.h: Add IEEE_AWAY mode. + * config/fpu-aix.h: Add IEEE_AWAY mode. + * config/fpu-generic.h: Add IEEE_AWAY mode. + * config/fpu-glibc.h: Add IEEE_AWAY mode. + * config/fpu-sysv.h: Add IEEE_AWAY mode. + 2022-09-10 Francois-Xavier Coudert PR fortran/95644 -- cgit v1.1