X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ffortran%2Ftrans-array.c;h=d918fa820093edb19f100364faafd4f4839083e8;hb=7e7e695867898829e5026279ef986271a18a66c7;hp=d386a228a0e4a4b97fa6f71c477340ecee2ebd52;hpb=fc09773a52dc0ffe8235e4d6608a1469eaa39158;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index d386a228a0e..d918fa82009 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -688,41 +688,54 @@ void gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping, gfc_se * se, gfc_array_spec * as) { - int n, dim; + int n, dim, total_dim; gfc_se tmpse; + gfc_ss *ss; tree lower; tree upper; tree tmp; - if (as && as->type == AS_EXPLICIT) - for (n = 0; n < se->loop->dimen; n++) - { - dim = se->ss->dim[n]; - gcc_assert (dim < as->rank); - gcc_assert (se->loop->dimen == as->rank); - if (se->loop->to[n] == NULL_TREE) - { - /* Evaluate the lower bound. */ - gfc_init_se (&tmpse, NULL); - gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]); - gfc_add_block_to_block (&se->pre, &tmpse.pre); - gfc_add_block_to_block (&se->post, &tmpse.post); - lower = fold_convert (gfc_array_index_type, tmpse.expr); - - /* ...and the upper bound. */ - gfc_init_se (&tmpse, NULL); - gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]); - gfc_add_block_to_block (&se->pre, &tmpse.pre); - gfc_add_block_to_block (&se->post, &tmpse.post); - upper = fold_convert (gfc_array_index_type, tmpse.expr); - - /* Set the upper bound of the loop to UPPER - LOWER. */ - tmp = fold_build2_loc (input_location, MINUS_EXPR, - gfc_array_index_type, upper, lower); - tmp = gfc_evaluate_now (tmp, &se->pre); - se->loop->to[n] = tmp; - } - } + total_dim = 0; + + if (!as || as->type != AS_EXPLICIT) + return; + + for (ss = se->ss; ss; ss = ss->parent) + { + total_dim += ss->loop->dimen; + for (n = 0; n < ss->loop->dimen; n++) + { + /* The bound is known, nothing to do. */ + if (ss->loop->to[n] != NULL_TREE) + continue; + + dim = ss->dim[n]; + gcc_assert (dim < as->rank); + gcc_assert (ss->loop->dimen <= as->rank); + + /* Evaluate the lower bound. */ + gfc_init_se (&tmpse, NULL); + gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]); + gfc_add_block_to_block (&se->pre, &tmpse.pre); + gfc_add_block_to_block (&se->post, &tmpse.post); + lower = fold_convert (gfc_array_index_type, tmpse.expr); + + /* ...and the upper bound. */ + gfc_init_se (&tmpse, NULL); + gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]); + gfc_add_block_to_block (&se->pre, &tmpse.pre); + gfc_add_block_to_block (&se->post, &tmpse.post); + upper = fold_convert (gfc_array_index_type, tmpse.expr); + + /* Set the upper bound of the loop to UPPER - LOWER. */ + tmp = fold_build2_loc (input_location, MINUS_EXPR, + gfc_array_index_type, upper, lower); + tmp = gfc_evaluate_now (tmp, &se->pre); + ss->loop->to[n] = tmp; + } + } + + gcc_assert (total_dim == as->rank); } @@ -855,28 +868,62 @@ gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post, } -/* Get the array reference dimension corresponding to the given loop dimension. - It is different from the true array dimension given by the dim array in - the case of a partial array reference - It is different from the loop dimension in the case of a transposed array. - */ +/* Get the scalarizer array dimension corresponding to actual array dimension + given by ARRAY_DIM. + + For example, if SS represents the array ref a(1,:,:,1), it is a + bidimensional scalarizer array, and the result would be 0 for ARRAY_DIM=1, + and 1 for ARRAY_DIM=2. + If SS represents transpose(a(:,1,1,:)), it is again a bidimensional + scalarizer array, and the result would be 1 for ARRAY_DIM=0 and 0 for + ARRAY_DIM=3. + If SS represents sum(a(:,:,:,1), dim=1), it is a 2+1-dimensional scalarizer + array. If called on the inner ss, the result would be respectively 0,1,2 for + ARRAY_DIM=0,1,2. If called on the outer ss, the result would be 0,1 + for ARRAY_DIM=1,2. */ static int -get_array_ref_dim (gfc_ss *ss, int loop_dim) +get_scalarizer_dim_for_array_dim (gfc_ss *ss, int array_dim) { - int n, array_dim, array_ref_dim; + int array_ref_dim; + int n; array_ref_dim = 0; - array_dim = ss->dim[loop_dim]; - for (n = 0; n < ss->dimen; n++) - if (ss->dim[n] < array_dim) - array_ref_dim++; + for (; ss; ss = ss->parent) + for (n = 0; n < ss->dimen; n++) + if (ss->dim[n] < array_dim) + array_ref_dim++; return array_ref_dim; } +static gfc_ss * +innermost_ss (gfc_ss *ss) +{ + while (ss->nested_ss != NULL) + ss = ss->nested_ss; + + return ss; +} + + + +/* Get the array reference dimension corresponding to the given loop dimension. + It is different from the true array dimension given by the dim array in + the case of a partial array reference (i.e. a(:,:,1,:) for example) + It is different from the loop dimension in the case of a transposed array. + */ + +static int +get_array_ref_dim_for_loop_dim (gfc_ss *ss, int loop_dim) +{ + return get_scalarizer_dim_for_array_dim (innermost_ss (ss), + ss->dim[loop_dim]); +} + + /* Generate code to create and initialize the descriptor for a temporary array. This is used for both temporaries needed by the scalarizer, and functions returning arrays. Adjusts the loop variables to be @@ -946,7 +993,7 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss, to the n'th dimension of the array. We need to reconstruct loop infos in the right order before using it to set the descriptor bounds. */ - tmp_dim = get_array_ref_dim (ss, n); + tmp_dim = get_scalarizer_dim_for_array_dim (ss, dim); from[tmp_dim] = loop->from[n]; to[tmp_dim] = loop->to[n]; @@ -998,7 +1045,7 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss, { for (n = 0; n < loop->dimen; n++) { - dim = ss->dim[n]; + dim = get_scalarizer_dim_for_array_dim (ss, ss->dim[n]); /* For a callee allocated array express the loop bounds in terms of the descriptor fields. */ @@ -1940,6 +1987,7 @@ trans_constant_array_constructor (gfc_ss * ss, tree type) } } + /* Helper routine of gfc_trans_array_constructor to determine if the bounds of the loop specified by LOOP are constant and simple enough to use with trans_constant_array_constructor. Returns the @@ -1997,6 +2045,7 @@ trans_array_constructor (gfc_ss * ss, locus * where) gfc_loopinfo *loop; gfc_ss_info *ss_info; gfc_expr *expr; + gfc_ss *s; /* Save the old values for nested checking. */ old_first_len = first_len; @@ -2065,16 +2114,20 @@ trans_array_constructor (gfc_ss * ss, locus * where) if (expr->shape && loop->dimen > 1 && loop->to[0] == NULL_TREE) { /* We have a multidimensional parameter. */ - int n; - for (n = 0; n < expr->rank; n++) - { - loop->from[n] = gfc_index_zero_node; - loop->to[n] = gfc_conv_mpz_to_tree (expr->shape [n], - gfc_index_integer_kind); - loop->to[n] = fold_build2_loc (input_location, MINUS_EXPR, - gfc_array_index_type, - loop->to[n], gfc_index_one_node); - } + for (s = ss; s; s = s->parent) + { + int n; + for (n = 0; n < s->loop->dimen; n++) + { + s->loop->from[n] = gfc_index_zero_node; + s->loop->to[n] = gfc_conv_mpz_to_tree (expr->shape[s->dim[n]], + gfc_index_integer_kind); + s->loop->to[n] = fold_build2_loc (input_location, MINUS_EXPR, + gfc_array_index_type, + s->loop->to[n], + gfc_index_one_node); + } + } } if (loop->to[0] == NULL_TREE) @@ -2178,14 +2231,18 @@ set_vector_loop_bounds (gfc_ss * ss) int dim; info = &ss->info->data.array; - loop = ss->loop; - for (n = 0; n < loop->dimen; n++) + for (; ss; ss = ss->parent) { - dim = ss->dim[n]; - if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR - && loop->to[n] == NULL) + loop = ss->loop; + + for (n = 0; n < loop->dimen; n++) { + dim = ss->dim[n]; + if (info->ref->u.ar.dimen_type[dim] != DIMEN_VECTOR + || loop->to[n] != NULL) + continue; + /* Loop variable N indexes vector dimension DIM, and we don't yet know the upper bound of loop variable N. Set it to the difference between the vector's upper and lower bounds. */ @@ -3193,7 +3250,8 @@ gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body) /* Clear all the used flags. */ for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain) - ss->info->useflags = 0; + if (ss->parent == NULL) + ss->info->useflags = 0; } @@ -4102,7 +4160,7 @@ set_loop_bounds (gfc_loopinfo *loop) && INTEGER_CST_P (info->stride[dim])) { loop->from[n] = info->start[dim]; - mpz_set (i, cshape[get_array_ref_dim (loopspec[n], n)]); + mpz_set (i, cshape[get_array_ref_dim_for_loop_dim (loopspec[n], n)]); mpz_sub_ui (i, i, 1); /* To = from + (size - 1) * stride. */ tmp = gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);