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 <fxcoudert@gcc.gnu.org>

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.
This commit is contained in:
Francois-Xavier Coudert 2022-08-31 19:15:20 +02:00 committed by Francois-Xavier Coudert
parent 0b5b8ac5cb
commit 4637a1d293
9 changed files with 88 additions and 12 deletions

View File

@ -60,6 +60,7 @@ along with GCC; see the file COPYING3. If not see
#define GFC_FPE_TONEAREST 2
#define GFC_FPE_TOWARDZERO 3
#define GFC_FPE_UPWARD 4
#define GFC_FPE_AWAY 5
/* Size of the buffer required to store FPU state for any target.
In particular, this has to be larger than fenv_t on all glibc targets.

View File

@ -0,0 +1,20 @@
! { dg-do run }
use, intrinsic :: ieee_arithmetic
implicit none
real :: sx1, sx2, sx3
double precision :: dx1, dx2, dx3
! IEEE_AWAY was added in Fortran 2018 and not supported by any target
! at the moment. Just check we can query for its support.
! We should support at least C float and C double types
if (ieee_support_rounding(ieee_away) &
.or. ieee_support_rounding(ieee_away, 0.) &
.or. ieee_support_rounding(ieee_away, 0.d0)) then
print *, "If a target / libc now supports this, we need to add a proper check!"
stop 1
end if
end

View File

@ -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

View File

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

View File

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

View File

@ -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

View File

@ -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. */
}

View File

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

View File

@ -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) &