------- 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