https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118613

--- Comment #3 from anlauf at gcc dot gnu.org ---
Adding a second temporary reduces the evaluation count for the rank-1 case
further:

diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index afbec5b2752..0cdc886a715 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -6710,6 +6710,7 @@ gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr *
expr, enum tree_code op)
   gfc_copy_loopinfo_to_se (&arrayse, &loop);
   arrayse.ss = arrayss;
   gfc_conv_expr_val (&arrayse, arrayexpr);
+  arrayse.expr = gfc_evaluate_now (arrayse.expr, &arrayse.pre);
   gfc_add_block_to_block (&block, &arrayse.pre);

   gfc_init_block (&block2);
@@ -6816,6 +6817,7 @@ gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr *
expr, enum tree_code op)
       gfc_copy_loopinfo_to_se (&arrayse, &loop);
       arrayse.ss = arrayss;
       gfc_conv_expr_val (&arrayse, arrayexpr);
+      arrayse.expr = gfc_evaluate_now (arrayse.expr, &arrayse.pre);
       gfc_add_block_to_block (&block, &arrayse.pre);

       /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or

This gives:

           4           0
           4           0
           5   0.00000000    
           4   0.00000000    
           5   0.00000000    
           4   0.00000000    

The remaining superfluous evaluation seems to be a bug in the algorithm as
described in trans-intrinsic.cc:

   2) Array mask is used and NaNs need to be supported, rank 1:
      limit = Infinity;
      nonempty = false;
      S = from;
      while (S <= to) {
        if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
        S++;
      }
      limit = nonempty ? NaN : huge (limit);
      lab:
      while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }

   3) NaNs need to be supported, but it is known at compile time or cheaply
      at runtime whether array is nonempty or not, rank 1:
      limit = Infinity;
      S = from;
      while (S <= to) { if (a[S] <= limit) goto lab; S++; }
      limit = (from <= to) ? NaN : huge (limit);
      lab:
      while (S <= to) { limit = min (a[S], limit); S++; }

We should increment S either after the comparison in the first while-loop,
or increment it directly after the label lab.

Reply via email to