Commit bfcabc6c by Roger Sayle Committed by Roger Sayle

re PR fortran/30404 ([4.1 only] Wrong FORALL result)

2007-01-16  Roger Sayle  <roger@eyesopen.com>

	PR fortran/30404
	* trans-stmt.c (forall_info): Remove pmask field.
	(gfc_trans_forall_loop): Remove NVAR argument, instead assume that
	NVAR covers all the interation variables in the current forall_info.
	Add an extra OUTER parameter, which specified the loop header in
	which to place mask index initializations.
	(gfc_trans_nested_forall_loop): Remove NEST_FLAG argument.
	Change the semantics of MASK_FLAG to only control the mask in the
	innermost loop.
	(compute_overall_iter_number): Optimize the trivial case of a
	top-level loop having a constant number of iterations.  Update
	call to gfc_trans_nested_forall_loop.  Calculate the number of
	times the inner loop will be executed, not to size of the 
	iteration space.
	(allocate_temp_for_forall_nest_1): Reuse SIZE as BYTESIZE when
	sizeof(type) == 1.  Tidy up.
	(gfc_trans_assign_need_temp): Remove NEST_FLAG argument from calls
	to gfc_trans_nested_forall_loop.
	(gfc_trans_pointer_assign_need_temp): Likewise.
	(gfc_trans_forall_1): Remove unused BYTESIZE, TMPVAR, SIZEVAR and
	LENVAR local variables.  Split mask allocation into a separate
	hunk/pass from mask population.  Use allocate_temp_for_forall_nest
	to allocate the FORALL mask with the correct size.  Update calls
	to gfc_trans_nested_forall_loop.
	(gfc_evaluate_where_mask): Update call to
	gfc_trans_nested_forall_loop.
	(gfc_trans_where_2): Likewise.

	* gfortran.dg/forall_6.f90: New test case.
	* gfortran.dg/dependency_8.f90: Update test to find "temp" array.
	* gfortran.dg/dependency_13.f90: Likewise.


Co-Authored-By: Paul Thomas <pault@gcc.gnu.org>
Co-Authored-By: Steven G. Kargl <kargl@gcc.gnu.org>

From-SVN: r120829
parent d0768f19
2007-01-16 Roger Sayle <roger@eyesopen.com>
PR fortran/30404
* trans-stmt.c (forall_info): Remove pmask field.
(gfc_trans_forall_loop): Remove NVAR argument, instead assume that
NVAR covers all the interation variables in the current forall_info.
Add an extra OUTER parameter, which specified the loop header in
which to place mask index initializations.
(gfc_trans_nested_forall_loop): Remove NEST_FLAG argument.
Change the semantics of MASK_FLAG to only control the mask in the
innermost loop.
(compute_overall_iter_number): Optimize the trivial case of a
top-level loop having a constant number of iterations. Update
call to gfc_trans_nested_forall_loop. Calculate the number of
times the inner loop will be executed, not to size of the
iteration space.
(allocate_temp_for_forall_nest_1): Reuse SIZE as BYTESIZE when
sizeof(type) == 1. Tidy up.
(gfc_trans_assign_need_temp): Remove NEST_FLAG argument from calls
to gfc_trans_nested_forall_loop.
(gfc_trans_pointer_assign_need_temp): Likewise.
(gfc_trans_forall_1): Remove unused BYTESIZE, TMPVAR, SIZEVAR and
LENVAR local variables. Split mask allocation into a separate
hunk/pass from mask population. Use allocate_temp_for_forall_nest
to allocate the FORALL mask with the correct size. Update calls
to gfc_trans_nested_forall_loop.
(gfc_evaluate_where_mask): Update call to
gfc_trans_nested_forall_loop.
(gfc_trans_where_2): Likewise.
2007-01-15 Paul Thomas <pault@gcc.gnu.org> 2007-01-15 Paul Thomas <pault@gcc.gnu.org>
PR fortran/28172 PR fortran/28172
......
/* Statement translation -- generate GCC trees from gfc_code. /* Statement translation -- generate GCC trees from gfc_code.
Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
Inc. Free Software Foundation, Inc.
Contributed by Paul Brook <paul@nowt.org> Contributed by Paul Brook <paul@nowt.org>
and Steven Bosscher <s.bosscher@student.tudelft.nl> and Steven Bosscher <s.bosscher@student.tudelft.nl>
...@@ -54,7 +54,6 @@ typedef struct forall_info ...@@ -54,7 +54,6 @@ typedef struct forall_info
{ {
iter_info *this_loop; iter_info *this_loop;
tree mask; tree mask;
tree pmask;
tree maskindex; tree maskindex;
int nvar; int nvar;
tree size; tree size;
...@@ -1526,7 +1525,13 @@ gfc_trans_select (gfc_code * code) ...@@ -1526,7 +1525,13 @@ gfc_trans_select (gfc_code * code)
} }
/* Generate the loops for a FORALL block. The normal loop format: /* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY
is the contents of the FORALL block/stmt to be iterated. MASK_FLAG
indicates whether we should generate code to test the FORALLs mask
array. OUTER is the loop header to be used for initializing mask
indices.
The generated loop format is:
count = (end - start + step) / step count = (end - start + step) / step
loopvar = start loopvar = start
while (1) while (1)
...@@ -1540,9 +1545,10 @@ gfc_trans_select (gfc_code * code) ...@@ -1540,9 +1545,10 @@ gfc_trans_select (gfc_code * code)
end_of_loop: */ end_of_loop: */
static tree static tree
gfc_trans_forall_loop (forall_info *forall_tmp, int nvar, tree body, int mask_flag) gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
int mask_flag, stmtblock_t *outer)
{ {
int n; int n, nvar;
tree tmp; tree tmp;
tree cond; tree cond;
stmtblock_t block; stmtblock_t block;
...@@ -1551,7 +1557,12 @@ gfc_trans_forall_loop (forall_info *forall_tmp, int nvar, tree body, int mask_fl ...@@ -1551,7 +1557,12 @@ gfc_trans_forall_loop (forall_info *forall_tmp, int nvar, tree body, int mask_fl
tree var, start, end, step; tree var, start, end, step;
iter_info *iter; iter_info *iter;
/* Initialize the mask index outside the FORALL nest. */
if (mask_flag && forall_tmp->mask)
gfc_add_modify_expr (outer, forall_tmp->maskindex, gfc_index_zero_node);
iter = forall_tmp->this_loop; iter = forall_tmp->this_loop;
nvar = forall_tmp->nvar;
for (n = 0; n < nvar; n++) for (n = 0; n < nvar; n++)
{ {
var = iter->var; var = iter->var;
...@@ -1603,11 +1614,6 @@ gfc_trans_forall_loop (forall_info *forall_tmp, int nvar, tree body, int mask_fl ...@@ -1603,11 +1614,6 @@ gfc_trans_forall_loop (forall_info *forall_tmp, int nvar, tree body, int mask_fl
gfc_init_block (&block); gfc_init_block (&block);
gfc_add_modify_expr (&block, var, start); gfc_add_modify_expr (&block, var, start);
/* Initialize maskindex counter. Only do this before the
outermost loop. */
if (n == nvar - 1 && mask_flag && forall_tmp->mask)
gfc_add_modify_expr (&block, forall_tmp->maskindex,
gfc_index_zero_node);
/* Initialize the loop counter. */ /* Initialize the loop counter. */
tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (var), step, start); tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (var), step, start);
...@@ -1630,60 +1636,47 @@ gfc_trans_forall_loop (forall_info *forall_tmp, int nvar, tree body, int mask_fl ...@@ -1630,60 +1636,47 @@ gfc_trans_forall_loop (forall_info *forall_tmp, int nvar, tree body, int mask_fl
} }
/* Generate the body and loops according to MASK_FLAG and NEST_FLAG. /* Generate the body and loops according to MASK_FLAG. If MASK_FLAG
if MASK_FLAG is nonzero, the body is controlled by maskes in forall is nonzero, the body is controlled by all masks in the forall nest.
nest, otherwise, the body is not controlled by maskes. Otherwise, the innermost loop is not controlled by it's mask. This
if NEST_FLAG is nonzero, generate loops for nested forall, otherwise, is used for initializing that mask. */
only generate loops for the current forall level. */
static tree static tree
gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body, gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
int mask_flag, int nest_flag) int mask_flag)
{ {
tree tmp; tree tmp;
int nvar; stmtblock_t header;
forall_info *forall_tmp; forall_info *forall_tmp;
tree pmask, mask, maskindex; tree mask, maskindex;
gfc_start_block (&header);
forall_tmp = nested_forall_info; forall_tmp = nested_forall_info;
/* Generate loops for nested forall. */ while (forall_tmp->next_nest != NULL)
if (nest_flag) forall_tmp = forall_tmp->next_nest;
while (forall_tmp != NULL)
{ {
while (forall_tmp->next_nest != NULL) /* Generate body with masks' control. */
forall_tmp = forall_tmp->next_nest; if (mask_flag)
while (forall_tmp != NULL)
{ {
/* Generate body with masks' control. */ mask = forall_tmp->mask;
if (mask_flag) maskindex = forall_tmp->maskindex;
{
pmask = forall_tmp->pmask;
mask = forall_tmp->mask;
maskindex = forall_tmp->maskindex;
if (mask) /* If a mask was specified make the assignment conditional. */
{ if (mask)
/* If a mask was specified make the assignment conditional. */ {
if (pmask) tmp = gfc_build_array_ref (mask, maskindex);
tmp = build_fold_indirect_ref (mask); body = build3_v (COND_EXPR, tmp, body, build_empty_stmt ());
else
tmp = mask;
tmp = gfc_build_array_ref (tmp, maskindex);
body = build3_v (COND_EXPR, tmp, body, build_empty_stmt ());
}
} }
nvar = forall_tmp->nvar;
body = gfc_trans_forall_loop (forall_tmp, nvar, body, mask_flag);
forall_tmp = forall_tmp->outer;
} }
} body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
else forall_tmp = forall_tmp->outer;
{ mask_flag = 1;
nvar = forall_tmp->nvar;
body = gfc_trans_forall_loop (forall_tmp, nvar, body, mask_flag);
} }
return body; gfc_add_expr_to_block (&header, body);
return gfc_finish_block (&header);
} }
...@@ -2041,6 +2034,10 @@ compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size, ...@@ -2041,6 +2034,10 @@ compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
tree tmp, number; tree tmp, number;
stmtblock_t body; stmtblock_t body;
/* Optimize the case for an outer-most loop with constant bounds. */
if (INTEGER_CST_P (inner_size) && !nested_forall_info)
return inner_size;
/* TODO: optimizing the computing process. */ /* TODO: optimizing the computing process. */
number = gfc_create_var (gfc_array_index_type, "num"); number = gfc_create_var (gfc_array_index_type, "num");
gfc_add_modify_expr (block, number, gfc_index_zero_node); gfc_add_modify_expr (block, number, gfc_index_zero_node);
...@@ -2058,7 +2055,7 @@ compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size, ...@@ -2058,7 +2055,7 @@ compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
/* Generate loops. */ /* Generate loops. */
if (nested_forall_info != NULL) if (nested_forall_info != NULL)
tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 0, 1); tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
gfc_add_expr_to_block (block, tmp); gfc_add_expr_to_block (block, tmp);
...@@ -2073,22 +2070,21 @@ static tree ...@@ -2073,22 +2070,21 @@ static tree
allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block, allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
tree * ptemp1) tree * ptemp1)
{ {
tree bytesize;
tree unit; tree unit;
tree temp1;
tree tmp; tree tmp;
tree bytesize;
unit = TYPE_SIZE_UNIT (type); unit = TYPE_SIZE_UNIT (type);
bytesize = fold_build2 (MULT_EXPR, gfc_array_index_type, size, unit); if (!integer_onep (unit))
bytesize = fold_build2 (MULT_EXPR, gfc_array_index_type, size, unit);
else
bytesize = size;
*ptemp1 = NULL; *ptemp1 = NULL;
temp1 = gfc_do_allocate (bytesize, size, ptemp1, block, type); tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
if (*ptemp1) if (*ptemp1)
tmp = build_fold_indirect_ref (temp1); tmp = build_fold_indirect_ref (tmp);
else
tmp = temp1;
return tmp; return tmp;
} }
...@@ -2193,7 +2189,7 @@ gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2, ...@@ -2193,7 +2189,7 @@ gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
/* Generate body and loops according to the information in /* Generate body and loops according to the information in
nested_forall_info. */ nested_forall_info. */
tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1); tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
gfc_add_expr_to_block (block, tmp); gfc_add_expr_to_block (block, tmp);
/* Reset count1. */ /* Reset count1. */
...@@ -2209,7 +2205,7 @@ gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2, ...@@ -2209,7 +2205,7 @@ gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
/* Generate body and loops according to the information in /* Generate body and loops according to the information in
nested_forall_info. */ nested_forall_info. */
tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1); tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
gfc_add_expr_to_block (block, tmp); gfc_add_expr_to_block (block, tmp);
if (ptemp1) if (ptemp1)
...@@ -2278,7 +2274,7 @@ gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2, ...@@ -2278,7 +2274,7 @@ gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
/* Generate body and loops according to the information in /* Generate body and loops according to the information in
nested_forall_info. */ nested_forall_info. */
tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1); tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
gfc_add_expr_to_block (block, tmp); gfc_add_expr_to_block (block, tmp);
/* Reset count. */ /* Reset count. */
...@@ -2301,7 +2297,7 @@ gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2, ...@@ -2301,7 +2297,7 @@ gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
/* Generate body and loops according to the information in /* Generate body and loops according to the information in
nested_forall_info. */ nested_forall_info. */
tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1); tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
gfc_add_expr_to_block (block, tmp); gfc_add_expr_to_block (block, tmp);
} }
else else
...@@ -2346,7 +2342,7 @@ gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2, ...@@ -2346,7 +2342,7 @@ gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
/* Generate body and loops according to the information in /* Generate body and loops according to the information in
nested_forall_info. */ nested_forall_info. */
tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1); tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
gfc_add_expr_to_block (block, tmp); gfc_add_expr_to_block (block, tmp);
/* Reset count. */ /* Reset count. */
...@@ -2368,7 +2364,7 @@ gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2, ...@@ -2368,7 +2364,7 @@ gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
tmp = gfc_finish_block (&body); tmp = gfc_finish_block (&body);
tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1); tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
gfc_add_expr_to_block (block, tmp); gfc_add_expr_to_block (block, tmp);
} }
/* Free the temporary. */ /* Free the temporary. */
...@@ -2432,10 +2428,6 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info) ...@@ -2432,10 +2428,6 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
tree tmp; tree tmp;
tree assign; tree assign;
tree size; tree size;
tree bytesize;
tree tmpvar;
tree sizevar;
tree lenvar;
tree maskindex; tree maskindex;
tree mask; tree mask;
tree pmask; tree pmask;
...@@ -2446,10 +2438,8 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info) ...@@ -2446,10 +2438,8 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
gfc_se se; gfc_se se;
gfc_code *c; gfc_code *c;
gfc_saved_var *saved_vars; gfc_saved_var *saved_vars;
iter_info *this_forall, *iter_tmp; iter_info *this_forall;
forall_info *info, *forall_tmp; forall_info *info;
gfc_start_block (&block);
n = 0; n = 0;
/* Count the FORALL index number. */ /* Count the FORALL index number. */
...@@ -2467,12 +2457,15 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info) ...@@ -2467,12 +2457,15 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
/* Allocate the space for info. */ /* Allocate the space for info. */
info = (forall_info *) gfc_getmem (sizeof (forall_info)); info = (forall_info *) gfc_getmem (sizeof (forall_info));
gfc_start_block (&block);
n = 0; n = 0;
for (fa = code->ext.forall_iterator; fa; fa = fa->next) for (fa = code->ext.forall_iterator; fa; fa = fa->next)
{ {
gfc_symbol *sym = fa->var->symtree->n.sym; gfc_symbol *sym = fa->var->symtree->n.sym;
/* allocate space for this_forall. */ /* Allocate space for this_forall. */
this_forall = (iter_info *) gfc_getmem (sizeof (iter_info)); this_forall = (iter_info *) gfc_getmem (sizeof (iter_info));
/* Create a temporary variable for the FORALL index. */ /* Create a temporary variable for the FORALL index. */
...@@ -2513,31 +2506,24 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info) ...@@ -2513,31 +2506,24 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
/* Set the NEXT field of this_forall to NULL. */ /* Set the NEXT field of this_forall to NULL. */
this_forall->next = NULL; this_forall->next = NULL;
/* Link this_forall to the info construct. */ /* Link this_forall to the info construct. */
if (info->this_loop == NULL) if (info->this_loop)
info->this_loop = this_forall;
else
{ {
iter_tmp = info->this_loop; iter_info *iter_tmp = info->this_loop;
while (iter_tmp->next != NULL) while (iter_tmp->next != NULL)
iter_tmp = iter_tmp->next; iter_tmp = iter_tmp->next;
iter_tmp->next = this_forall; iter_tmp->next = this_forall;
} }
else
info->this_loop = this_forall;
n++; n++;
} }
nvar = n; nvar = n;
/* Work out the number of elements in the mask array. */ /* Calculate the size needed for the current forall level. */
tmpvar = NULL_TREE;
lenvar = NULL_TREE;
size = gfc_index_one_node; size = gfc_index_one_node;
sizevar = NULL_TREE;
for (n = 0; n < nvar; n++) for (n = 0; n < nvar; n++)
{ {
if (lenvar && TREE_TYPE (lenvar) != TREE_TYPE (start[n]))
lenvar = NULL_TREE;
/* size = (end + step - start) / step. */ /* size = (end + step - start) / step. */
tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (start[n]), tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (start[n]),
step[n], start[n]); step[n], start[n]);
...@@ -2553,39 +2539,44 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info) ...@@ -2553,39 +2539,44 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
info->nvar = nvar; info->nvar = nvar;
info->size = size; info->size = size;
/* Link the current forall level to nested_forall_info. */ /* First we need to allocate the mask. */
forall_tmp = nested_forall_info; if (code->expr)
if (forall_tmp == NULL) {
nested_forall_info = info; /* As the mask array can be very big, prefer compact boolean types. */
tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
size, NULL, &block, &pmask);
maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
/* Record them in the info structure. */
info->maskindex = maskindex;
info->mask = mask;
}
else else
{ {
/* No mask was specified. */
maskindex = NULL_TREE;
mask = pmask = NULL_TREE;
}
/* Link the current forall level to nested_forall_info. */
if (nested_forall_info)
{
forall_info *forall_tmp = nested_forall_info;
while (forall_tmp->next_nest != NULL) while (forall_tmp->next_nest != NULL)
forall_tmp = forall_tmp->next_nest; forall_tmp = forall_tmp->next_nest;
info->outer = forall_tmp; info->outer = forall_tmp;
forall_tmp->next_nest = info; forall_tmp->next_nest = info;
} }
else
nested_forall_info = info;
/* Copy the mask into a temporary variable if required. /* Copy the mask into a temporary variable if required.
For now we assume a mask temporary is needed. */ For now we assume a mask temporary is needed. */
if (code->expr) if (code->expr)
{ {
/* As the mask array can be very big, prefer compact /* As the mask array can be very big, prefer compact boolean types. */
boolean types. */ tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
tree smallest_boolean_type_node
= gfc_get_logical_type (gfc_logical_kinds[0].kind);
/* Allocate the mask temporary. */
bytesize = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
TYPE_SIZE_UNIT (smallest_boolean_type_node));
mask = gfc_do_allocate (bytesize, size, &pmask, &block,
smallest_boolean_type_node);
maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
/* Record them in the info structure. */
info->pmask = pmask;
info->mask = mask;
info->maskindex = maskindex;
gfc_add_modify_expr (&block, maskindex, gfc_index_zero_node); gfc_add_modify_expr (&block, maskindex, gfc_index_zero_node);
...@@ -2598,31 +2589,21 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info) ...@@ -2598,31 +2589,21 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
gfc_add_block_to_block (&body, &se.pre); gfc_add_block_to_block (&body, &se.pre);
/* Store the mask. */ /* Store the mask. */
se.expr = convert (smallest_boolean_type_node, se.expr); se.expr = convert (mask_type, se.expr);
if (pmask) tmp = gfc_build_array_ref (mask, maskindex);
tmp = build_fold_indirect_ref (mask);
else
tmp = mask;
tmp = gfc_build_array_ref (tmp, maskindex);
gfc_add_modify_expr (&body, tmp, se.expr); gfc_add_modify_expr (&body, tmp, se.expr);
/* Advance to the next mask element. */ /* Advance to the next mask element. */
tmp = build2 (PLUS_EXPR, gfc_array_index_type, tmp = build2 (PLUS_EXPR, gfc_array_index_type,
maskindex, gfc_index_one_node); maskindex, gfc_index_one_node);
gfc_add_modify_expr (&body, maskindex, tmp); gfc_add_modify_expr (&body, maskindex, tmp);
/* Generate the loops. */ /* Generate the loops. */
tmp = gfc_finish_block (&body); tmp = gfc_finish_block (&body);
tmp = gfc_trans_nested_forall_loop (info, tmp, 0, 0); tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
gfc_add_expr_to_block (&block, tmp); gfc_add_expr_to_block (&block, tmp);
} }
else
{
/* No mask was specified. */
maskindex = NULL_TREE;
mask = pmask = NULL_TREE;
}
c = code->block->next; c = code->block->next;
...@@ -2646,7 +2627,8 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info) ...@@ -2646,7 +2627,8 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
assign = gfc_trans_assignment (c->expr, c->expr2, false); assign = gfc_trans_assignment (c->expr, c->expr2, false);
/* Generate body and loops. */ /* Generate body and loops. */
tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1, 1); tmp = gfc_trans_nested_forall_loop (nested_forall_info,
assign, 1);
gfc_add_expr_to_block (&block, tmp); gfc_add_expr_to_block (&block, tmp);
} }
...@@ -2669,8 +2651,8 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info) ...@@ -2669,8 +2651,8 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
assign = gfc_trans_pointer_assignment (c->expr, c->expr2); assign = gfc_trans_pointer_assignment (c->expr, c->expr2);
/* Generate body and loops. */ /* Generate body and loops. */
tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, tmp = gfc_trans_nested_forall_loop (nested_forall_info,
1, 1); assign, 1);
gfc_add_expr_to_block (&block, tmp); gfc_add_expr_to_block (&block, tmp);
} }
break; break;
...@@ -2684,7 +2666,7 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info) ...@@ -2684,7 +2666,7 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
assignments can legitimately produce them. */ assignments can legitimately produce them. */
case EXEC_ASSIGN_CALL: case EXEC_ASSIGN_CALL:
assign = gfc_trans_call (c, true); assign = gfc_trans_call (c, true);
tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1, 1); tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
gfc_add_expr_to_block (&block, tmp); gfc_add_expr_to_block (&block, tmp);
break; break;
...@@ -2858,7 +2840,7 @@ gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info, ...@@ -2858,7 +2840,7 @@ gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
tmp1 = gfc_finish_block (&body); tmp1 = gfc_finish_block (&body);
/* If the WHERE construct is inside FORALL, fill the full temporary. */ /* If the WHERE construct is inside FORALL, fill the full temporary. */
if (nested_forall_info != NULL) if (nested_forall_info != NULL)
tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1, 1); tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
gfc_add_expr_to_block (block, tmp1); gfc_add_expr_to_block (block, tmp1);
} }
...@@ -3230,7 +3212,7 @@ gfc_trans_where_2 (gfc_code * code, tree mask, bool invert, ...@@ -3230,7 +3212,7 @@ gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
count1, count2); count1, count2);
tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp = gfc_trans_nested_forall_loop (nested_forall_info,
tmp, 1, 1); tmp, 1);
gfc_add_expr_to_block (block, tmp); gfc_add_expr_to_block (block, tmp);
} }
} }
......
2007-01-16 Roger Sayle <roger@eyesopen.com>
Paul Thomas <pault@gcc.gnu.org>
Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/30404
* gfortran.dg/forall_6.f90: New test case.
* gfortran.dg/dependency_8.f90: Update test to find "temp" array.
* gfortran.dg/dependency_13.f90: Likewise.
2007-01-15 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 2007-01-15 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
PR testsuite/12325 PR testsuite/12325
...@@ -9,5 +9,5 @@ ...@@ -9,5 +9,5 @@
x(2:5) = -42. x(2:5) = -42.
end where end where
end end
! { dg-final { scan-tree-dump-times "malloc" 1 "original" } } ! { dg-final { scan-tree-dump-times "temp" 3 "original" } }
! { dg-final { cleanup-tree-dump "original" } } ! { dg-final { cleanup-tree-dump "original" } }
...@@ -9,5 +9,5 @@ subroutine foo(a,i,j) ...@@ -9,5 +9,5 @@ subroutine foo(a,i,j)
a(j,2:4) = 1 a(j,2:4) = 1
endwhere endwhere
end subroutine end subroutine
! { dg-final { scan-tree-dump-times "malloc" 1 "original" } } ! { dg-final { scan-tree-dump-times "temp" 3 "original" } }
! { dg-final { cleanup-tree-dump "original" } } ! { dg-final { cleanup-tree-dump "original" } }
! PR fortran/30404
! Checks that we correctly handle nested masks in nested FORALL blocks.
! Contributed by Paul Thomas <pault@gcc.gnu.org>
!
! { dg-do run }
logical :: l1(2,2)
integer :: it(2,2)
l1(:,:) = reshape ((/.false.,.true.,.true.,.false./), (/2,2/))
it(:,:) = reshape ((/1,2,3,4/), (/2,2/))
forall (i = 1:2, i < 3)
forall (j = 1:2, l1(i,j))
it(i, j) = 0
end forall
end forall
! print *, l1
! print '(4i2)', it
if (any (it .ne. reshape ((/1, 0, 0, 4/), (/2, 2/)))) call abort ()
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment