public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/omp/gcc-11] Fix Fortran rounding issues, PR fortran/96983.
@ 2021-07-27 9:50 Tobias Burnus
0 siblings, 0 replies; only message in thread
From: Tobias Burnus @ 2021-07-27 9:50 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:389d08d93ec85d6bcabc96769800da25131835d2
commit 389d08d93ec85d6bcabc96769800da25131835d2
Author: Tobias Burnus <tobias@codesourcery.com>
Date: Tue Jul 27 11:32:32 2021 +0200
Fix Fortran rounding issues, PR fortran/96983.
I was looking at Fortran PR 96983, which fails on the PowerPC when trying to
run the test PR96711.F90. The compiler ICEs because the PowerPC does not have
a floating point type with a type precision of 128. The reason is that the
PowerPC has 3 different 128 bit floating point types (__float128/_Float128,
__ibm128, and long double). Currently long double uses the IBM extended double
type, but we would like to switch to using IEEE 128-bit long doubles in the
future.
In order to prevent the compiler from converting explicit __ibm128 types to
long double when long double uses the IEEE 128-bit representation, we have set
up the precision for __ibm128 to be 128, long double to be 127, and
__float128/_Float128 to be 126.
Originally, I was trying to see if for Fortran, I could change the precision of
long double to be 128 (Fortran doesn't access __ibm128), but it quickly became
hard to get the changes to work.
I looked at the Fortran code in build_round_expr, and I came to the conclusion
that there is no reason to promote the floating point type. If you just do a
normal round of the value using the current floating point format and then
convert it to the integer type. We don't have an appropriate built-in function
that provides the equivalent of llround for 128-bit integer types.
This patch fixes the compiler crash.
However, while with this patch, the PowerPC compiler will not crash when
building the test case, it will not run on the current default installation.
The failure is because the test is explicitly expecting 128-bit floating point
to handle 10384593717069655257060992658440192_16 (i.e. 2**113).
By default, the PowerPC uses IBM extended double used for 128-bit floating
point. The IBM extended double format is a pair of doubles that provides more
mantissa bits but does not grow the expoenent range. The value in the test is
fine for IEEE 128-bit floating point, but it is too large for the PowerPC
extended double setup.
I have built the following tests with this patch:
* I have built a bootstrap compiler on a little endian power9 Linux system
with the default long double format (IBM extended double). The
pr96711.f90 test builds, but it does not run due to the range of the
real*16 exponent. There were no other regressions in the C/C++/Fortran
tests.
* I have built a bootstrap compiler on a little endian power9 Linux system
with the default long double format set to IEEE 128-bit. I used the
Advance Toolchain 14.0-2 to provide the IEEE 128-bits. The compiler was
configured to build power9 code by default, so the test generated native
power9 IEEE 128-bit instructions. The pr96711.f90 test builds and runs
correctly in this setup.
* I have built a bootstrap compiler on a big endian power8 Linux system with
the default long double format (IBM extended double). Like the first
case, the pr96711.f90 test does not crash the compiler, but the test fails
due to the range of the real*16 exponent. There were no other
regressions in the C/C++/Fortran tests.
* I built a bootstrap compiler on my x86_64 laptop. There were no
regressions in the tests.
gcc/fortran/
2021-04-21 Michael Meissner <meissner@linux.ibm.com>
PR fortran/96983
* trans-intrinsic.c (build_round_expr): If int type is larger than
long long, do the round and convert to the integer type. Do not
try to find a floating point type the exact size of the integer
type.
(cherry picked from commit 3cf04d1afa8a4955a0a9a395dd21ce1b6484aa78)
Diff:
---
gcc/fortran/ChangeLog.omp | 11 +++++++++++
gcc/fortran/trans-intrinsic.c | 26 ++++++++------------------
2 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/gcc/fortran/ChangeLog.omp b/gcc/fortran/ChangeLog.omp
index 4d575f18777..6f1ced4bf1f 100644
--- a/gcc/fortran/ChangeLog.omp
+++ b/gcc/fortran/ChangeLog.omp
@@ -1,3 +1,14 @@
+2021-07-27 Tobias Burnus <tobias@codesourcery.com>
+
+ Backported from master:
+ 2021-04-21 Michael Meissner <meissner@linux.ibm.com>
+
+ PR fortran/96983
+ * trans-intrinsic.c (build_round_expr): If int type is larger than
+ long long, do the round and convert to the integer type. Do not
+ try to find a floating point type the exact size of the integer
+ type.
+
2021-07-21 Tobias Burnus <tobias@codesourcery.com>
Backported from master:
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index c67a9fca46f..63e22ccb19c 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -386,30 +386,20 @@ build_round_expr (tree arg, tree restype)
argprec = TYPE_PRECISION (argtype);
resprec = TYPE_PRECISION (restype);
- /* Depending on the type of the result, choose the int intrinsic
- (iround, available only as a builtin, therefore cannot use it for
- __float128), long int intrinsic (lround family) or long long
- intrinsic (llround). We might also need to convert the result
- afterwards. */
+ /* Depending on the type of the result, choose the int intrinsic (iround,
+ available only as a builtin, therefore cannot use it for __float128), long
+ int intrinsic (lround family) or long long intrinsic (llround). If we
+ don't have an appropriate function that converts directly to the integer
+ type (such as kind == 16), just use ROUND, and then convert the result to
+ an integer. We might also need to convert the result afterwards. */
if (resprec <= INT_TYPE_SIZE && argprec <= LONG_DOUBLE_TYPE_SIZE)
fn = builtin_decl_for_precision (BUILT_IN_IROUND, argprec);
else if (resprec <= LONG_TYPE_SIZE)
fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
else if (resprec <= LONG_LONG_TYPE_SIZE)
fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
- else if (resprec >= argprec && resprec == 128)
- {
- /* Search for a real kind suitable as temporary for conversion. */
- int kind = -1;
- for (int i = 0; kind < 0 && gfc_real_kinds[i].kind != 0; i++)
- if (gfc_real_kinds[i].mode_precision >= resprec)
- kind = gfc_real_kinds[i].kind;
- if (kind < 0)
- gfc_internal_error ("Could not find real kind with at least %d bits",
- resprec);
- arg = fold_convert (gfc_get_real_type (kind), arg);
- fn = gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
- }
+ else if (resprec >= argprec)
+ fn = builtin_decl_for_precision (BUILT_IN_ROUND, argprec);
else
gcc_unreachable ();
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2021-07-27 9:50 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-27 9:50 [gcc/devel/omp/gcc-11] Fix Fortran rounding issues, PR fortran/96983 Tobias Burnus
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).