Dear all, my fix for PR fortran/96711 adds a testcase that failed on powerpc64-*-* as well as sparc*-sun-solaris2.11. This is a consequence of the, say, mess, on x86, where we have real kinds 4,8,10,16, with kind=10 being long double and kind=16 being represented as float128, while on sparc real(16) is mapped to long double. I'm not going to comment on power, see PR for details.
A minimal solution to the issue would extend an intermediate conversion that is done for e.g. x86 to float128 to a conversion to long double on platforms where the TYPE_PRECISION of long double equals 128. This solves the issue on sparc*-sun-solaris2.11, as confirmed by Rainer. The attached patch does just this, and disables the testcase for target powerpc*-*-*. I expect a more sophisticated solution being needed for that platform. That said, the patch regtests cleanly on x86_64-pc-linux-gnu, and as reported in the PR, sparc-sun-solaris2.11 and i386-pc-solaris2.11. OK for master? Or does anyone with better knowledge of the affected platforms want to take over? As this is a technical regression, it should and could be fixed before the gcc-11 release. My intention to either close the PR after committing, or changing it into some appropriate state (SUSPENDED?) so that it can be handled later, or to rather open a new PR that is finally a target issue. Thanks, Harald PR/fortran 96983 - ICE compiling gfortran.dg/pr96711.f90 The fix for PR fortran/96711 introduced an intermediate conversion to the float128 type that is used e.g. on x86 but not on some other targets. Use a conversion to long double on targets where this type has a type precision of 128 bit. gcc/fortran/ChangeLog: * trans-intrinsic.c (build_round_expr): Use conversion to long double when this type has a type precision of 128 bit. gcc/testsuite/ChangeLog: * gfortran.dg/pr96711.f90: Skip testcase for target powerpc*-*-*.
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index 32fe9886c57..552cdf5f19c 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -395,6 +395,13 @@ build_round_expr (tree arg, tree restype) 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 == TYPE_PRECISION (long_double_type_node) + && resprec >= argprec) + { + int kind = TYPE_PRECISION (long_double_type_node) / 8; + arg = fold_convert (long_double_type_node, arg); + fn = gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind); + } else if (resprec >= argprec && resprec == 128) { /* Search for a real kind suitable as temporary for conversion. */ diff --git a/gcc/testsuite/gfortran.dg/pr96711.f90 b/gcc/testsuite/gfortran.dg/pr96711.f90 index 3761a8ea416..13b6e829ed6 100644 --- a/gcc/testsuite/gfortran.dg/pr96711.f90 +++ b/gcc/testsuite/gfortran.dg/pr96711.f90 @@ -3,6 +3,8 @@ ! { dg-require-effective-target fortran_real_16 } ! { dg-additional-options "-fdump-tree-original" } ! { dg-final { scan-tree-dump-times "_gfortran_stop_numeric" 2 "original" } } +! { dg-skip-if "" { "powerpc*-*-*" } } +! This test expects a target that supports IEEE128. ! ! PR fortran/96711 - ICE on NINT() Function