diff mbox series

[6/7] fortran: Check for empty MINLOC/MAXLOC ARRAY along DIM only

Message ID 20241014150816.315478-7-morin-mikael@orange.fr
State New
Headers show
Series fortran: Inline MINLOC/MAXLOC with DIM [PR90608] | expand

Commit Message

Mikael Morin Oct. 14, 2024, 3:08 p.m. UTC
From: Mikael Morin <mikael@gcc.gnu.org>

Bootstrapped and regression-tested on x86_64-pc-linux-gnu.
OK for master?

-- >8 --

In the function generating inline code to implement MINLOC and MAXLOC, only
check for ARRAY size along DIM if DIM is present.

The check for ARRAY emptyness had been checking the size of the full array,
which is correct for MINLOC and MAXLOC without DIM.  But if DIM is
present, the reduction is along DIM only so the check for emptyness
should consider that dimension only as well.

This sounds like a correctness issue, but fortunately the cases where it
makes a difference are cases where ARRAY is empty, so even if the value
calculated for MINLOC or MAXLOC is wrong, it's wrapped in a zero iteration
loop, and the wrong values are not actually used.  In the end this just
avoids unnecessary calculations.

A previous version of this patch regressed on non-constant DIM with rank 1
ARRAY.  The new testcase checks that that case is supported.

gcc/fortran/ChangeLog:

	* trans-intrinsic.cc (gfc_conv_intrinsic_minmaxloc): Only get the size
	along DIM instead of the full size if DIM is present.

gcc/testsuite/ChangeLog:

	* gfortran.dg/minmaxloc_22.f90: New test.
---
 gcc/fortran/trans-intrinsic.cc             | 19 +++++++++++++++-
 gcc/testsuite/gfortran.dg/minmaxloc_22.f90 | 26 ++++++++++++++++++++++
 2 files changed, 44 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gfortran.dg/minmaxloc_22.f90
diff mbox series

Patch

diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index b77183ab11e..e1a5fdef26c 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -5641,7 +5641,24 @@  gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
   if (!(maskexpr && maskexpr->rank > 0))
     {
       mpz_t asize;
-      if (gfc_array_size (arrayexpr, &asize))
+      bool reduction_size_known;
+
+      if (dim_present)
+	{
+	  int reduction_dim;
+	  if (dim_arg->expr->expr_type == EXPR_CONSTANT)
+	    reduction_dim = mpz_get_si (dim_arg->expr->value.integer) - 1;
+	  else if (arrayexpr->rank == 1)
+	    reduction_dim = 0;
+	  else
+	    gcc_unreachable ();
+	  reduction_size_known = gfc_array_dimen_size (arrayexpr, reduction_dim,
+						       &asize);
+	}
+      else
+	reduction_size_known = gfc_array_size (arrayexpr, &asize);
+
+      if (reduction_size_known)
 	{
 	  nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
 	  mpz_clear (asize);
diff --git a/gcc/testsuite/gfortran.dg/minmaxloc_22.f90 b/gcc/testsuite/gfortran.dg/minmaxloc_22.f90
new file mode 100644
index 00000000000..ec97d1435af
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/minmaxloc_22.f90
@@ -0,0 +1,26 @@ 
+! { dg-do compile }
+! { dg-additional-options "-O" }
+!
+! Check that the inline code generated for MINLOC and MAXLOC supports
+! a non-constant DIM argument if ARRAY has rank 1.
+
+program p
+  implicit none
+  integer, parameter :: n = 5
+  integer :: a(n), i
+  a = (/ (i**2, i=1,n) /)
+  print *, f(a, 1), g(a, 1)
+contains
+  function f(a, d)
+    integer :: a(n)
+    integer :: d
+    integer :: f
+    f = minloc(a, dim=d) 
+  end function
+  function g(a, d)
+    integer :: a(n)
+    integer :: d
+    integer :: g
+    g = maxloc(a, dim=d) 
+  end function
+end program p