aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorFrancois-Xavier Coudert <fxcoudert@gcc.gnu.org>2022-01-10 17:04:34 +0100
committerFrancois-Xavier Coudert <fxcoudert@gmail.com>2022-01-16 22:57:45 +0100
commit90045c5df5b3c8853e7740fb72a11aead1c489bb (patch)
tree5a59d689ecb0d21bb9aa1cb3e3a1d2e479a5f07b /gcc
parentbca1c431affee41ecadb7f29d8d65142a73e0ebf (diff)
downloadgcc-90045c5df5b3c8853e7740fb72a11aead1c489bb.zip
gcc-90045c5df5b3c8853e7740fb72a11aead1c489bb.tar.gz
gcc-90045c5df5b3c8853e7740fb72a11aead1c489bb.tar.bz2
Fortran: allow IEEE_VALUE to correctly return signaling NaNs
I moved the library implementation of IEEE_VALUE in libgfortran from Fortran to C code, which gives us access to GCC's built-ins for NaN generation (both quiet and signalling). It will be perform better than the current Fortran implementation. libgfortran/ChangeLog: PR fortran/82207 * mk-kinds-h.sh: Add values for TINY. * ieee/ieee_arithmetic.F90: Call C helper functions for IEEE_VALUE. * ieee/ieee_helper.c: New functions ieee_value_helper_N for each floating-point type. gcc/testsuite/ChangeLog: PR fortran/82207 * gfortran.dg/ieee/ieee_10.f90: Do not create signaling NaNs. * gfortran.dg/ieee/signaling_2.f90: New test. * gfortran.dg/ieee/signaling_2_c.c: New file.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/gfortran.dg/ieee/ieee_10.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/ieee/signaling_2.f9070
-rw-r--r--gcc/testsuite/gfortran.dg/ieee/signaling_2_c.c8
3 files changed, 86 insertions, 4 deletions
diff --git a/gcc/testsuite/gfortran.dg/ieee/ieee_10.f90 b/gcc/testsuite/gfortran.dg/ieee/ieee_10.f90
index c3ffffc..a596504 100644
--- a/gcc/testsuite/gfortran.dg/ieee/ieee_10.f90
+++ b/gcc/testsuite/gfortran.dg/ieee/ieee_10.f90
@@ -12,8 +12,10 @@ program foo
real x
real(8) y
- x = ieee_value(x, ieee_signaling_nan)
- if (.not. ieee_is_nan(x)) stop 1
+ ! At this point it is unclear what the behavior should be
+ ! for -ffpe-trap=invalid with a signaling NaN
+ !x = ieee_value(x, ieee_signaling_nan)
+ !if (.not. ieee_is_nan(x)) stop 1
x = ieee_value(x, ieee_quiet_nan)
if (.not. ieee_is_nan(x)) stop 2
@@ -22,8 +24,10 @@ program foo
x = ieee_value(x, ieee_negative_inf)
if (ieee_is_finite(x)) stop 4
- y = ieee_value(y, ieee_signaling_nan)
- if (.not. ieee_is_nan(y)) stop 5
+ ! At this point it is unclear what the behavior should be
+ ! for -ffpe-trap=invalid with a signaling NaN
+ !y = ieee_value(y, ieee_signaling_nan)
+ !if (.not. ieee_is_nan(y)) stop 5
y = ieee_value(y, ieee_quiet_nan)
if (.not. ieee_is_nan(y)) stop 6
diff --git a/gcc/testsuite/gfortran.dg/ieee/signaling_2.f90 b/gcc/testsuite/gfortran.dg/ieee/signaling_2.f90
new file mode 100644
index 0000000..e7e7a4a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/ieee/signaling_2.f90
@@ -0,0 +1,70 @@
+! { dg-do run }
+! { dg-require-effective-target issignaling } */
+! { dg-additional-sources signaling_2_c.c }
+! { dg-additional-options "-w" }
+! the -w option is needed to make cc1 not report a warning for
+! the -fintrinsic-modules-path option passed by ieee.exp
+!
+program test
+ use, intrinsic :: iso_c_binding
+ use, intrinsic :: ieee_arithmetic
+ implicit none
+
+ interface
+ integer(kind=c_int) function isnansf (x) bind(c)
+ import :: c_float, c_int
+ real(kind=c_float), value :: x
+ end function
+
+ integer(kind=c_int) function isnans (x) bind(c)
+ import :: c_double, c_int
+ real(kind=c_double), value :: x
+ end function
+
+ integer(kind=c_int) function isnansl (x) bind(c)
+ import :: c_long_double, c_int
+ real(kind=c_long_double), value :: x
+ end function
+ end interface
+
+ real(kind=c_float) :: x
+ real(kind=c_double) :: y
+ real(kind=c_long_double) :: z
+
+ if (ieee_support_nan(x)) then
+ x = ieee_value(x, ieee_signaling_nan)
+ if (ieee_class(x) /= ieee_signaling_nan) stop 100
+ if (.not. ieee_is_nan(x)) stop 101
+ if (isnansf(x) /= 1) stop 102
+
+ x = ieee_value(x, ieee_quiet_nan)
+ if (ieee_class(x) /= ieee_quiet_nan) stop 103
+ if (.not. ieee_is_nan(x)) stop 104
+ if (isnansf(x) /= 0) stop 105
+ end if
+
+ if (ieee_support_nan(y)) then
+ y = ieee_value(y, ieee_signaling_nan)
+ if (ieee_class(y) /= ieee_signaling_nan) stop 100
+ if (.not. ieee_is_nan(y)) stop 101
+ if (isnans(y) /= 1) stop 102
+
+ y = ieee_value(y, ieee_quiet_nan)
+ if (ieee_class(y) /= ieee_quiet_nan) stop 103
+ if (.not. ieee_is_nan(y)) stop 104
+ if (isnans(y) /= 0) stop 105
+ end if
+
+ if (ieee_support_nan(z)) then
+ z = ieee_value(z, ieee_signaling_nan)
+ if (ieee_class(z) /= ieee_signaling_nan) stop 100
+ if (.not. ieee_is_nan(z)) stop 101
+ if (isnansl(z) /= 1) stop 102
+
+ z = ieee_value(z, ieee_quiet_nan)
+ if (ieee_class(z) /= ieee_quiet_nan) stop 103
+ if (.not. ieee_is_nan(z)) stop 104
+ if (isnansl(z) /= 0) stop 105
+ end if
+
+end program test
diff --git a/gcc/testsuite/gfortran.dg/ieee/signaling_2_c.c b/gcc/testsuite/gfortran.dg/ieee/signaling_2_c.c
new file mode 100644
index 0000000..ea7fc04
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/ieee/signaling_2_c.c
@@ -0,0 +1,8 @@
+#define _GNU_SOURCE
+#include <math.h>
+#include <float.h>
+
+int isnansf (float x) { return issignaling (x) ? 1 : 0; }
+int isnans (double x) { return issignaling (x) ? 1 : 0; }
+int isnansl (long double x) { return issignaling (x) ? 1 : 0; }
+