diff mbox series

[BACKPORT] Backport PR fortran/96983 fix to GCC 11

Message ID YjKYJCrkU5++YX6a@toto.the-meissners.org
State New
Headers show
Series [BACKPORT] Backport PR fortran/96983 fix to GCC 11 | expand

Commit Message

Michael Meissner March 17, 2022, 2:08 a.m. UTC
Backport PR fortran/96983 patch to GCC 11.

I applied a patch on the trunk in April 22nd, 2021 that fixes an issue (PR
fortran/66983) where we could fail for 128-bit floating point types
because we don't have a built-in function that is equivalent to llround
for 128-bit integer types.  Instead, the patch does a round operation
followed by conversion to the appropriate integer size if we don't have
the specialized round to specific integer type built-in functions.

When I checked in the change, I was told to wait until after GCC 11.1
shipped before doing the backport.  I forgot about the change until
recently.  Before checking it in, I did bootstraps and ran regression
tests on:

    1)	little endian power9 using 128-bit IBM long double
    2)	little endian power9 using 128-bit IEEE long double
    3)	big endian power8 (both 64-bit and 32-bit) (and)
    4)	x86_64 native build

There were no new regressions.  The test gfortran.dg/pr96711.f90 now
passes on PowerPC.

In the 10 months or so since the change was made on the trunk, the code in
build_round_expr did not change.

2022-03-16   Michael Meissner  <meissner@linux.ibm.com>

gcc/fortran/
	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.  Backport patch from 2021-04-22 on the trunk.

---
 gcc/fortran/trans-intrinsic.c | 26 ++++++++------------------
 1 file changed, 8 insertions(+), 18 deletions(-)
diff mbox series

Patch

diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index bd6e6039429..313440d7022 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 ();