Hello, this is the fix for pr57798 where a variable used as scalarization loop bound was used outside the outer scalarization loop, before it was defined (inside it). To make it more clear the code generated was like this: ... toto = bad do ... bad = titi do ... ...
The patch fixes this by making sure that preliminary code generated by the scalarizer goes before the outermost loop, not only before the current loop. This moves the bad=titi before the toto=bad in the pseudo-code above. The changes are divided into two parts. - The first one is a small cleanup: gfc_conv_section_startstride has a loop argument, but only &loop->pre is used in the function. This patch changes the argument so that &loop->pre is passed directly as argument to the function. - The second part is the fix proper. It just a matter of replacing loop->pre with outermost_loop(loop)->pre. The test-case is fixed by the gfc_conv_ss_startstride hunks only, but I also added the set_loop_bounds and gfc_set_delta hunks, as these function seemed to need the same fix. Regression tested on x86_64-unknown-linux-gnu. OK for trunk/4.8? Mikael
2013-08-20 Mikael Morin <mik...@gcc.gnu.org> * trans-array.c (gfc_conv_section_startstride): Move &loop->pre access to the callers. (gfc_conv_ss_startstride, gfc_conv_expr_descriptor): Update callers.
diff --git a/trans-array.c b/trans-array.c index 1a2e508..a626d66 100644 --- a/trans-array.c +++ b/trans-array.c @@ -3715,7 +3715,7 @@ evaluate_bound (stmtblock_t *block, tree *bounds, gfc_expr ** values, /* Calculate the lower bound of an array section. */ static void -gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int dim) +gfc_conv_section_startstride (stmtblock_t * block, gfc_ss * ss, int dim) { gfc_expr *stride = NULL; tree desc; @@ -3744,12 +3744,12 @@ gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int dim) /* Calculate the start of the range. For vector subscripts this will be the range of the vector. */ - evaluate_bound (&loop->pre, info->start, ar->start, desc, dim, true); + evaluate_bound (block, info->start, ar->start, desc, dim, true); /* Similarly calculate the end. Although this is not used in the scalarizer, it is needed when checking bounds and where the end is an expression with side-effects. */ - evaluate_bound (&loop->pre, info->end, ar->end, desc, dim, false); + evaluate_bound (block, info->end, ar->end, desc, dim, false); /* Calculate the stride. */ if (stride == NULL) @@ -3758,8 +3758,8 @@ gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int dim) { gfc_init_se (&se, NULL); gfc_conv_expr_type (&se, stride, gfc_array_index_type); - gfc_add_block_to_block (&loop->pre, &se.pre); - info->stride[dim] = gfc_evaluate_now (se.expr, &loop->pre); + gfc_add_block_to_block (block, &se.pre); + info->stride[dim] = gfc_evaluate_now (se.expr, block); } } @@ -3838,7 +3838,7 @@ done: gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter); for (n = 0; n < ss->dimen; n++) - gfc_conv_section_startstride (loop, ss, ss->dim[n]); + gfc_conv_section_startstride (&loop->pre, ss, ss->dim[n]); break; case GFC_SS_INTRINSIC: @@ -6727,10 +6727,10 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr) gcc_assert (ar->dimen_type[n + ndim] == DIMEN_THIS_IMAGE); /* Make sure the call to gfc_conv_section_startstride won't - generate unnecessary code to calculate stride. */ + generate unnecessary code to calculate stride. */ gcc_assert (ar->stride[n + ndim] == NULL); - gfc_conv_section_startstride (&loop, ss, n + ndim); + gfc_conv_section_startstride (&loop.pre, ss, n + ndim); loop.from[n + loop.dimen] = info->start[n + ndim]; loop.to[n + loop.dimen] = info->end[n + ndim]; }
2013-08-20 Mikael Morin <mik...@gcc.gnu.org> PR fortran/57798 * trans-array.c (gfc_conv_ss_startstride, set_loop_bounds, gfc_set_delta): Generate preliminary code before the outermost loop. 2013-08-20 Mikael Morin <mik...@gcc.gnu.org> PR fortran/57798 * gfortran.dg/inline_sum_5.f90: New.
diff --git a/trans-array.c b/trans-array.c index a626d66..5a3cf80 100644 --- a/trans-array.c +++ b/trans-array.c @@ -3776,6 +3776,8 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop) gfc_ss *ss; tree desc; + gfc_loopinfo * const outer_loop = outermost_loop (loop); + loop->dimen = 0; /* Determine the rank of the loop. */ for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain) @@ -3835,10 +3837,11 @@ done: /* Get the descriptor for the array. If it is a cross loops array, we got the descriptor already in the outermost loop. */ if (ss->parent == NULL) - gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter); + gfc_conv_ss_descriptor (&outer_loop->pre, ss, + !loop->array_parameter); for (n = 0; n < ss->dimen; n++) - gfc_conv_section_startstride (&loop->pre, ss, ss->dim[n]); + gfc_conv_section_startstride (&outer_loop->pre, ss, ss->dim[n]); break; case GFC_SS_INTRINSIC: @@ -3874,7 +3877,7 @@ done: fold_convert (gfc_array_index_type, rank), gfc_index_one_node); - info->end[0] = gfc_evaluate_now (tmp, &loop->pre); + info->end[0] = gfc_evaluate_now (tmp, &outer_loop->pre); info->start[0] = gfc_index_zero_node; info->stride[0] = gfc_index_one_node; continue; @@ -4156,7 +4159,7 @@ done: } tmp = gfc_finish_block (&block); - gfc_add_expr_to_block (&loop->pre, tmp); + gfc_add_expr_to_block (&outer_loop->pre, tmp); } for (loop = loop->nested; loop; loop = loop->next) @@ -4439,6 +4442,8 @@ set_loop_bounds (gfc_loopinfo *loop) mpz_t i; bool nonoptional_arr; + gfc_loopinfo * const outer_loop = outermost_loop (loop); + loopspec = loop->specloop; mpz_init (i); @@ -4627,7 +4632,7 @@ set_loop_bounds (gfc_loopinfo *loop) else { /* Set the delta for this section. */ - info->delta[dim] = gfc_evaluate_now (loop->from[n], &loop->pre); + info->delta[dim] = gfc_evaluate_now (loop->from[n], &outer_loop->pre); /* Number of iterations is (end - start + step) / step. with start = 0, this simplifies to last = end / step; @@ -4639,7 +4644,7 @@ set_loop_bounds (gfc_loopinfo *loop) gfc_array_index_type, tmp, info->stride[dim]); tmp = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type, tmp, build_int_cst (gfc_array_index_type, -1)); - loop->to[n] = gfc_evaluate_now (tmp, &loop->pre); + loop->to[n] = gfc_evaluate_now (tmp, &outer_loop->pre); /* Make the loop variable start at 0. */ loop->from[n] = gfc_index_zero_node; } @@ -4715,6 +4720,8 @@ gfc_set_delta (gfc_loopinfo *loop) tree tmp; int n, dim; + gfc_loopinfo * const outer_loop = outermost_loop (loop); + loopspec = loop->specloop; /* Calculate the translation from loop variables to array indices. */ @@ -4750,7 +4757,7 @@ gfc_set_delta (gfc_loopinfo *loop) gfc_array_index_type, info->start[dim], tmp); - info->delta[dim] = gfc_evaluate_now (tmp, &loop->pre); + info->delta[dim] = gfc_evaluate_now (tmp, &outer_loop->pre); } } }
! { dg-do run } ! ! PR fortran/57798 ! The call to sum used to be inlined into a loop with an uninitialized bound ! ! Original testcase by Stephan Kramer <stephan.kra...@imperial.ac.uk> program test implicit none call sub(2, 11) contains function func(m, n) integer, intent(in):: m,n real, dimension(m, n):: func func = 1.0 end function func subroutine sub(m, n) integer, intent(in):: m, n real, dimension(m,n):: y y = 1.0 if (any(sum(y*func(m,n), dim=1) /= m)) call abort end subroutine sub end program test