On Wed, 22 Jun 2011, Michael Matz wrote: > Hi, > > On Tue, 21 Jun 2011, Richard Guenther wrote: > > > I failed to see where the scalarizer inserts the temporary vars it > > creates into the scope blocks (thus the gimplify.c hunk ...). Any help > > here is welcome. > > The scoping of the scalarizer is a bit funny. gfc_start_scalarized_body > sets up scopes for all dimensions and leaves with the 'body' scope open. > The bound expressions are inserted (for your testcase) into the 'block' > scope. In between there are the loop->code[n] scopes. > > You can't decide to not go into gfc_start_scalarized_body early, because > lse.expr will only be set later, so you have to > properly finish_block all these in-between blocks and wire them into > loop.pre and then block, like gfc_trans_scalarizing_loops would do. Of > course you don't want to actually generate loops, which > gfc_trans_scalarizing_loops does. So you have to manually unwind the > blocks. If you do that, then you also don't need the ??? marked > gfc_add_block_to_block (&block, &loop.pre). > > So, the code in the VLA_VIEW_EXPR case should be roughly this: > > else if (TREE_CODE (lse.expr) == VLA_VIEW_EXPR) > { > int dim; > stmtblock_t *pblock; > > pblock = &body; > for (dim = 0; dim < loop.dimen + loop.codimen; dim++) > { > n = loop.order[dim]; > tmp = gfc_finish_block (pblock); > gfc_add_expr_to_block (&loop.code[n], tmp); > loop.loopvar[n] = NULL_TREE; > pblock = &loop.code[n]; > } > > tmp = gfc_finish_block (pblock); > gfc_add_expr_to_block (&loop.pre, tmp); > gfc_add_block_to_block (&block, &loop.pre); > gfc_add_block_to_block (&block, &loop.post); > gfc_cleanup_loop (&loop); > } > > Sorry, no real patch, my quilt queue is busted somehow.
Thanks, that seems to work. The following is an updated Fortran patch (requiring an updated middle-end patch as well) which also adds code to handle intrinsic ALL/ANY (in the hope more runtime tests get coverage that way). Richard. Index: trunk/gcc/fortran/trans-array.c =================================================================== *** trunk.orig/gcc/fortran/trans-array.c 2011-06-22 14:28:27.000000000 +0200 --- trunk/gcc/fortran/trans-array.c 2011-06-22 14:39:40.000000000 +0200 *************** gfc_conv_scalarized_array_ref (gfc_se * *** 2570,2575 **** --- 2570,2637 ---- int n; info = &se->ss->data.info; + + { + tree vv = build_vl_exp (VLA_VIEW_EXPR, 2 + 2 * info->dimen); + tree vi = build_vl_exp (VLA_IDX_EXPR, 2 + info->dimen); + tree offset = NULL_TREE; + tree elt_type; + tree type; + tree tem; + elt_type = TREE_TYPE (se->expr); + if (POINTER_TYPE_P (elt_type)) + elt_type = TREE_TYPE (elt_type); + while (TREE_CODE (elt_type) == ARRAY_TYPE) + elt_type = TREE_TYPE (elt_type); + type = elt_type; + for (n = 0; n < info->dimen; ++n) + { + TREE_OPERAND (vv, 2 + 2 * n) /* extent */ + = build2 (MINUS_EXPR, TREE_TYPE (info->end[n]), + info->end[n], info->start[n]); + TREE_OPERAND (vv, 3 + 2 * n) /* stride */ + = info->stride[n]; + /* Accumulate start offset. */ + if (offset) + offset = fold_build2_loc (input_location, + PLUS_EXPR, TREE_TYPE (offset), + offset, + fold_build2_loc (input_location, + MULT_EXPR, TREE_TYPE (offset), + info->start[n], + info->stride[n])); + else + offset = fold_build2_loc (input_location, + MULT_EXPR, TREE_TYPE (info->start[n]), + info->start[n], + info->stride[n]); + type = build_array_type (type, build_index_type + (TREE_OPERAND (vv, 2 + 2 * n))); + } + /* Start address. */ + tem = info->descriptor; + if (!POINTER_TYPE_P (TREE_TYPE (tem))) + tem = build_fold_addr_expr (tem); + TREE_OPERAND (vv, 1) + = fold_build2 (MEM_REF, type, + fold_build2_loc (input_location, + POINTER_PLUS_EXPR, + TREE_TYPE (tem), tem, + fold_convert (sizetype, offset)), + build_int_cst (build_pointer_type (elt_type), 0)); + /* Type. */ + TREE_TYPE (vv) = type; + TREE_OPERAND (vi, 1) = vv; + for (n = 0; n < info->dimen; ++n) + { + TREE_OPERAND (vi, 2 + n) /* Index placeholder. */ + = se->loop->loopvar[n]; + } + TREE_TYPE (vi) = elt_type; + se->expr = vi; + return; + } + if (ar) n = se->loop->order[0]; else Index: trunk/gcc/fortran/trans-expr.c =================================================================== *** trunk.orig/gcc/fortran/trans-expr.c 2011-06-22 14:28:27.000000000 +0200 --- trunk/gcc/fortran/trans-expr.c 2011-06-22 14:35:59.000000000 +0200 *************** gfc_trans_assignment_1 (gfc_expr * expr1 *** 6126,6131 **** --- 6126,6142 ---- else gfc_conv_expr (&lse, expr1); + /* ??? Fixup array LHS. */ + if (TREE_CODE (lse.expr) == VLA_IDX_EXPR) + { + tree vi = lse.expr; + lse.expr = TREE_OPERAND (vi, 1); + TREE_OPERAND (vi, 1) = rse.expr; + TREE_SET_CODE (vi, VLA_RIDX_EXPR); + TREE_TYPE (vi) = TREE_TYPE (lse.expr); + rse.expr = vi; + } + /* Assignments of scalar derived types with allocatable components to arrays must be done with a deep copy and the rhs temporary must have its components deallocated afterwards. */ *************** gfc_trans_assignment_1 (gfc_expr * expr1 *** 6170,6175 **** --- 6181,6208 ---- /* Use the scalar assignment as is. */ gfc_add_block_to_block (&block, &body); } + /* ??? Skip regular scalarization. */ + else if (TREE_CODE (lse.expr) == VLA_VIEW_EXPR) + { + int dim; + stmtblock_t *pblock; + + pblock = &body; + for (dim = 0; dim < loop.dimen + loop.codimen; dim++) + { + n = loop.order[dim]; + tmp = gfc_finish_block (pblock); + gfc_add_expr_to_block (&loop.code[n], tmp); + loop.loopvar[n] = NULL_TREE; + pblock = &loop.code[n]; + } + + tmp = gfc_finish_block (pblock); + gfc_add_expr_to_block (&loop.pre, tmp); + gfc_add_block_to_block (&block, &loop.pre); + gfc_add_block_to_block (&block, &loop.post); + gfc_cleanup_loop (&loop); + } else { gcc_assert (lse.ss == gfc_ss_terminator Index: trunk/gcc/fortran/trans-intrinsic.c =================================================================== *** trunk.orig/gcc/fortran/trans-intrinsic.c 2011-06-22 14:28:27.000000000 +0200 --- trunk/gcc/fortran/trans-intrinsic.c 2011-06-22 15:03:11.000000000 +0200 *************** gfc_conv_intrinsic_anyall (gfc_se * se, *** 2392,2397 **** --- 2392,2398 ---- tree resvar; stmtblock_t block; stmtblock_t body; + stmtblock_t *pblock; tree type; tree tmp; tree found; *************** gfc_conv_intrinsic_anyall (gfc_se * se, *** 2400,2405 **** --- 2401,2407 ---- gfc_ss *arrayss; gfc_se arrayse; tree exit_label; + int dim; if (se->ss) { *************** gfc_conv_intrinsic_anyall (gfc_se * se, *** 2455,2468 **** arrayse.ss = arrayss; gfc_conv_expr_val (&arrayse, actual->expr); ! gfc_add_block_to_block (&body, &arrayse.pre); ! tmp = fold_build2_loc (input_location, op, boolean_type_node, arrayse.expr, ! build_int_cst (TREE_TYPE (arrayse.expr), 0)); tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location)); gfc_add_expr_to_block (&body, tmp); gfc_add_block_to_block (&body, &arrayse.post); ! gfc_trans_scalarizing_loops (&loop, &body); /* Add the exit label. */ tmp = build1_v (LABEL_EXPR, exit_label); --- 2457,2490 ---- arrayse.ss = arrayss; gfc_conv_expr_val (&arrayse, actual->expr); ! tmp = arrayse.expr; ! for (dim = 0; dim < loop.dimen; ++dim) ! { ! tree saved = tmp; ! tmp = build_vl_exp (VLA_DELTA_EXPR, 5); ! TREE_TYPE (tmp) = TREE_TYPE (arrayse.expr); ! TREE_OPERAND (tmp, 1) ! = size_int ((int) (op == NE_EXPR ? BIT_IOR_EXPR : BIT_AND_EXPR)); ! TREE_OPERAND (tmp, 2) = saved; ! TREE_OPERAND (tmp, 3) = fold_build2_loc (input_location, MINUS_EXPR, ! TREE_TYPE (loop.to[dim]), ! loop.to[dim], loop.from[dim]); ! TREE_OPERAND (tmp, 4) = loop.loopvar[dim]; ! } ! tmp = fold_build2_loc (input_location, op, boolean_type_node, tmp, ! build_int_cst (TREE_TYPE (tmp), 0)); tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location)); gfc_add_expr_to_block (&body, tmp); gfc_add_block_to_block (&body, &arrayse.post); ! pblock = &body; ! for (dim = 0; dim < loop.dimen; ++dim) ! { ! gfc_add_expr_to_block (&loop.code[loop.order[dim]], ! gfc_finish_block (pblock)); ! pblock = &loop.code[loop.order[dim]]; ! } ! gfc_add_expr_to_block (&loop.pre, gfc_finish_block (pblock)); /* Add the exit label. */ tmp = build1_v (LABEL_EXPR, exit_label);