aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorMikael Morin <morin-mikael@orange.fr>2024-07-11 21:55:58 +0200
committerMikael Morin <mikael@gcc.gnu.org>2024-07-12 10:28:15 +0200
commita55d24b3cf7f4d07492bb8e6fcee557175b47ea3 (patch)
tree8824085b1ed930f76e7026155b17f77894fbf1e4 /gcc/fortran
parent63d7d5998e3768f6e3703c29e8774e8b54af108c (diff)
downloadgcc-a55d24b3cf7f4d07492bb8e6fcee557175b47ea3.zip
gcc-a55d24b3cf7f4d07492bb8e6fcee557175b47ea3.tar.gz
gcc-a55d24b3cf7f4d07492bb8e6fcee557175b47ea3.tar.bz2
fortran: Factor the evaluation of MINLOC/MAXLOC's BACK argument
Move the evaluation of the BACK argument out of the loop in the inline code generated for MINLOC or MAXLOC. For that, add a new (scalar) element associated with BACK to the scalarization loop chain, evaluate the argument with the context of that element, and let the scalarizer do its job. The problem was not only a missed optimisation, but also a wrong code one in the cases where the expression associated with BACK is not free of side-effects, making multiple evaluations observable. The new tests check the evaluation count of the BACK argument, and try to cover all the variations (integral or floating-point type, constant or unknown shape, absent or scalar or array MASK) supported by the inline implementation of the functions. Care has been taken to not check the case of a constant .FALSE. MASK, for which the evaluation of BACK can be elided. gcc/fortran/ChangeLog: * trans-intrinsic.cc (gfc_conv_intrinsic_minmaxloc): Create a new scalar scalarization chain element if BACK is present. Add it to the loop. Set the scalarization chain before evaluating the argument. gcc/testsuite/ChangeLog: * gfortran.dg/maxloc_5.f90: New test. * gfortran.dg/minloc_5.f90: New test.
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/trans-intrinsic.cc10
1 files changed, 10 insertions, 0 deletions
diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index 5ea10e8..cadbd17 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -5325,6 +5325,7 @@ gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
gfc_actual_arglist *actual;
gfc_ss *arrayss;
gfc_ss *maskss;
+ gfc_ss *backss;
gfc_se arrayse;
gfc_se maskse;
gfc_expr *arrayexpr;
@@ -5390,6 +5391,11 @@ gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
&& maskexpr->symtree->n.sym->attr.dummy
&& maskexpr->symtree->n.sym->attr.optional;
backexpr = actual->next->next->expr;
+ if (backexpr)
+ backss = gfc_get_scalar_ss (gfc_ss_terminator, backexpr);
+ else
+ backss = nullptr;
+
nonempty = NULL;
if (maskexpr && maskexpr->rank != 0)
{
@@ -5449,6 +5455,9 @@ gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
if (maskss)
gfc_add_ss_to_loop (&loop, maskss);
+ if (backss)
+ gfc_add_ss_to_loop (&loop, backss);
+
gfc_add_ss_to_loop (&loop, arrayss);
/* Initialize the loop. */
@@ -5535,6 +5544,7 @@ gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
gfc_add_block_to_block (&block, &arrayse.pre);
gfc_init_se (&backse, NULL);
+ backse.ss = backss;
gfc_conv_expr_val (&backse, backexpr);
gfc_add_block_to_block (&block, &backse.pre);