diff options
author | Mikael Morin <morin-mikael@orange.fr> | 2024-07-11 21:55:58 +0200 |
---|---|---|
committer | Mikael Morin <mikael@gcc.gnu.org> | 2024-07-12 10:28:15 +0200 |
commit | a55d24b3cf7f4d07492bb8e6fcee557175b47ea3 (patch) | |
tree | 8824085b1ed930f76e7026155b17f77894fbf1e4 /gcc/fortran | |
parent | 63d7d5998e3768f6e3703c29e8774e8b54af108c (diff) | |
download | gcc-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.cc | 10 |
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); |