------- Comment #15 from tkoenig at gcc dot gnu dot org  2007-04-19 21:03 
-------
(In reply to comment #14)
> (In reply to comment #13)
> > The tree stuff is hard, btw.  Still trying :-)
> 
> Tree stuff? Do we generate inline code?

We generate inline code for rank 0 minval and minloc, i.e.

  real :: a(3)
  print *,minloc(a,dim=1)

Here's a partial patch for this case:

Index: gfortran.h
===================================================================
--- gfortran.h  (revision 123958)
+++ gfortran.h  (working copy)
@@ -1351,7 +1351,7 @@ extern gfc_logical_info gfc_logical_kind

 typedef struct
 {
-  mpfr_t epsilon, huge, tiny, subnormal;
+  mpfr_t epsilon, huge, tiny, subnormal, infinity;
   int kind, radix, digits, min_exponent, max_exponent;
   int range, precision;

Index: arith.c
===================================================================
--- arith.c     (revision 123958)
+++ arith.c     (working copy)
@@ -247,6 +247,10 @@ gfc_arith_init_1 (void)
        if (i == real_info->radix)
          real_info->precision++;

+      /* Infinity.  */
+      mpfr_init (real_info->infinity);
+      mpfr_set_inf (real_info->infinity, 1);
+
       mpfr_clear (a);
       mpfr_clear (b);
       mpfr_clear (c);
@@ -277,6 +281,7 @@ gfc_arith_done_1 (void)
       mpfr_clear (rp->huge);
       mpfr_clear (rp->tiny);
       mpfr_clear (rp->subnormal);
+      mpfr_clear (rp->infinity);
     }
 }

Index: trans-intrinsic.c
===================================================================
--- trans-intrinsic.c   (revision 123958)
+++ trans-intrinsic.c   (working copy)
@@ -1926,8 +1926,10 @@ gfc_conv_intrinsic_minmaxloc (gfc_se * s
   tree limit;
   tree type;
   tree tmp;
+  tree tmp2;
   tree elsetmp;
   tree ifbody;
+  tree execute_loop;
   gfc_loopinfo loop;
   gfc_actual_arglist *actual;
   gfc_ss *arrayss;
@@ -1967,11 +1969,14 @@ gfc_conv_intrinsic_minmaxloc (gfc_se * s
     maskss = NULL;

   limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
+  execute_loop = gfc_create_var (boolean_type_node, "execute_loop");
+
   n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
   switch (arrayexpr->ts.type)
     {
     case BT_REAL:
-      tmp = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
arrayexpr->ts.kind);+      tmp = gfc_conv_mpfr_to_tree
(gfc_real_kinds[n].infinity,
+                                  arrayexpr->ts.kind);
       break;

     case BT_INTEGER:
@@ -2007,14 +2012,18 @@ gfc_conv_intrinsic_minmaxloc (gfc_se * s

   gcc_assert (loop.dimen == 1);

-  /* Initialize the position to zero, following Fortran 2003.  We are free
-     to do this because Fortran 95 allows the result of an entirely false
-     mask to be processor dependent.  */
-  gfc_add_modify_expr (&loop.pre, pos, gfc_index_zero_node);
+  /* Initialize the position to one.  */
+  gfc_add_modify_expr (&loop.pre, pos, gfc_index_one_node);

   gfc_mark_ss_chain_used (arrayss, 1);
   if (maskss)
     gfc_mark_ss_chain_used (maskss, 1);
+
+  /* Check whether the loop is evaluated at all.  */
+
+  tmp2 = fold_build2 (GE_EXPR, boolean_type_node, loop.to[0], loop.from[0]);
+  gfc_add_modify_expr (&se->pre, execute_loop, tmp2);
+
   /* Generate the loop body.  */
   gfc_start_scalarized_body (&loop, &body);

@@ -2050,10 +2059,9 @@ gfc_conv_intrinsic_minmaxloc (gfc_se * s

   ifbody = gfc_finish_block (&ifblock);

-  /* If it is a more extreme value or pos is still zero.  */
-  tmp = build2 (TRUTH_OR_EXPR, boolean_type_node,
-                 build2 (op, boolean_type_node, arrayse.expr, limit),
-                 build2 (EQ_EXPR, boolean_type_node, pos,
gfc_index_zero_node));
+  /* If it is a more extreme value.  */
+  tmp =  build2 (op, boolean_type_node, arrayse.expr, limit);
+
   tmp = build3_v (COND_EXPR, tmp, ifbody, build_empty_stmt ());
   gfc_add_expr_to_block (&block, tmp);

@@ -2066,36 +2074,41 @@ gfc_conv_intrinsic_minmaxloc (gfc_se * s
     }
   else
     tmp = gfc_finish_block (&block);
+
   gfc_add_expr_to_block (&body, tmp);

   gfc_trans_scalarizing_loops (&loop, &body);

-  /* For a scalar mask, enclose the loop in an if statement.  */
+  /* Enclose the loop in an if statement.  We don't execute it if the
+     trip count would be zero, or if a scalar mask is false.  */
+
   if (maskexpr && maskss == NULL)
     {
       gfc_init_se (&maskse, NULL);
       gfc_conv_expr_val (&maskse, maskexpr);
-      gfc_init_block (&block);
-      gfc_add_block_to_block (&block, &loop.pre);
-      gfc_add_block_to_block (&block, &loop.post);
-      tmp = gfc_finish_block (&block);

-      /* For the else part of the scalar mask, just initialize
-        the pos variable the same way as above.  */
+      execute_loop = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
execute_loop,
+                                 maskse.expr);
+    }
+
+  gfc_init_block (&block);
+  gfc_add_block_to_block (&block, &loop.pre);
+  gfc_add_block_to_block (&block, &loop.post);

-      gfc_init_block (&elseblock);
-      gfc_add_modify_expr (&elseblock, pos, gfc_index_zero_node);
-      elsetmp = gfc_finish_block (&elseblock);
+  tmp = gfc_finish_block (&block);
+
+  /* For the else part of the scalar mask, just initialize
+     the pos variable the same way as above.  */
+
+  gfc_init_block (&elseblock);
+  gfc_add_modify_expr (&elseblock, pos, gfc_index_zero_node);
+  elsetmp = gfc_finish_block (&elseblock);
+
+  tmp = build3_v (COND_EXPR, execute_loop, tmp, elsetmp);
+  gfc_add_expr_to_block (&block, tmp);
+
+  gfc_add_block_to_block (&se->pre, &block);

-      tmp = build3_v (COND_EXPR, maskse.expr, tmp, elsetmp);
-      gfc_add_expr_to_block (&block, tmp);
-      gfc_add_block_to_block (&se->pre, &block);
-    }
-  else
-    {
-      gfc_add_block_to_block (&se->pre, &loop.pre);
-      gfc_add_block_to_block (&se->pre, &loop.post);
-    }
   gfc_cleanup_loop (&loop);

   /* Return a value in the range 1..SIZE(array).  */

The problem with this is that it doesn't handle the loop

    do n=1, size(a)
       if (mask(n)) then
          real_minloc_mask(1) = n
          exit
       end if
    end do

at all, and my attempts to generate it using the scalarizer
have ended in ICEs (so far).


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30694

Reply via email to