On 20.04.21 08:58, Richard Biener via Fortran wrote:
On Mon, Apr 19, 2021 at 9:40 PM Michael Meissner via Fortran
<fort...@gcc.gnu.org>  wrote:
Is there any reason to not only send the email to fortran@ _and_
gcc-patches@ but sending it to 13 Fortran maintainers explicitly? (Now
removed)
Fix Fortran rounding issues, PR fortran/96983.

Can I check this change into the GCC trunk?
The patch looks fine technically and is definitely an improvement since the
intermediate conversion looks odd.  But it might be that the standard
requires such dance though the preceeding cases handled don't seem to
care.  I'm thinking of a FP format where round(1.6) == 3 because of lack
of precision but using an intermediate FP format with higher precision
would "correctly" compute 2.

The patched build_round_expr is only called by ANINT / NINT;
NINT is real → integer; ANINT is real → real
[And the modified code is only called for NINT, reason: see comment far below.]

NINT (A[, KIND]) is described (F2018) as "Nearest integer":
* Result Characteristics. Integer. If KIND is present, the kind type parameter
  is that specified by the value of KIND;
  otherwise, the kind type parameter is that of default integer type.
* The result is the integer nearest A, or if there are two
  integers equally near A, the result is whichever such integer has the greater
  magnitude.
* Example. NINT (2.783) has the value 3.

ANINT (A[, KIND]) as "Nearest whole number":
* The result is of type real. If KIND is present, the kind type parameter is 
that
  specified by the value of KIND; otherwise, the kind type parameter is that of 
A.
* The result is the integer nearest A, or if there are two integers equally 
near A,
  the result is whichever such integer has the greater magnitude.
* Examples. ANINT (2.783) has the value 3.0. ANINT (−2.783) has the value −3.0.

Of course the current code doesn't handle this correctly for the
case if llroundf either.
I've not contributed to the Fortran front end before.  If the maintainers like
the patch, can somebody point out if I need to do additional things to commit
the patch?
Nothing special: a testcase already exists, committing is done as usual
and a PR to update you have as well.
gcc/fortran/
2021-04-19  Michael Meissner<meiss...@linux.ibm.com>

         PR gfortran/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.
LGTM. (Minor remark below.)
---
  gcc/fortran/trans-intrinsic.c | 26 ++++++++------------------
  1 file changed, 8 insertions(+), 18 deletions(-)

diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index 5e53d1162fa..cceef8f34ac 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.  */

I think that's fine.

Small comment for completeness:
  "and convert the result to an integer"
Technically, this function can be called for both 'anint' and 'nint'
and for 'anint' it needs a real – and wouldn't convert to an integer.
However, as  gfc_conv_intrinsic_aint  only calls this function when
  gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
is NULL_TREE. I think the new code can not be reached – and if, it
would give an ICE as the same call is used.

As effectively the comment is correct, you can leave it as is.

Tobias

    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 ();

--
2.22.0


--
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email:meiss...@linux.ibm.com, phone: +1 (978) 899-4797
-----------------
Mentor Graphics (Deutschland) GmbH, Arnulfstrasse 201, 80634 München 
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Frank 
Thürauf

Reply via email to