diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index e6ce54a3f42..9bb4edccf54 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,14 @@ +2006-03-24 Roger Sayle + + * gfortran.h (gfc_symbol): Add a new "forall_index" bit field. + * match.c (match_forall_iterator): Set forall_index field on + the iteration variable's symbol. + * dependency.c (contains_forall_index_p): New function to + traverse a gfc_expr to check whether it contains a variable + with forall_index set in it's symbol. + (gfc_check_element_vs_element): Return GFC_DEP_EQUAL for scalar + constant expressions that don't variables used as FORALL indices. + 2006-03-22 Volker Reichelt PR driver/22600 diff --git a/gcc/fortran/dependency.c b/gcc/fortran/dependency.c index 03cabf05be9..2c528824055 100644 --- a/gcc/fortran/dependency.c +++ b/gcc/fortran/dependency.c @@ -794,6 +794,84 @@ gfc_check_element_vs_section( gfc_ref * lref, gfc_ref * rref, int n) } +/* Traverse expr, checking all EXPR_VARIABLE symbols for their + forall_index attribute. Return true if any variable may be + being used as a FORALL index. Its safe to pessimistically + return true, and assume a dependency. */ + +static bool +contains_forall_index_p (gfc_expr * expr) +{ + gfc_actual_arglist *arg; + gfc_constructor *c; + gfc_ref *ref; + int i; + + if (!expr) + return false; + + switch (expr->expr_type) + { + case EXPR_VARIABLE: + if (expr->symtree->n.sym->forall_index) + return true; + break; + + case EXPR_OP: + if (contains_forall_index_p (expr->value.op.op1) + || contains_forall_index_p (expr->value.op.op2)) + return true; + break; + + case EXPR_FUNCTION: + for (arg = expr->value.function.actual; arg; arg = arg->next) + if (contains_forall_index_p (arg->expr)) + return true; + break; + + case EXPR_CONSTANT: + case EXPR_NULL: + case EXPR_SUBSTRING: + break; + + case EXPR_STRUCTURE: + case EXPR_ARRAY: + for (c = expr->value.constructor; c; c = c->next) + if (contains_forall_index_p (c->expr)) + return true; + break; + + default: + gcc_unreachable (); + } + + for (ref = expr->ref; ref; ref = ref->next) + switch (ref->type) + { + case REF_ARRAY: + for (i = 0; i < ref->u.ar.dimen; i++) + if (contains_forall_index_p (ref->u.ar.start[i]) + || contains_forall_index_p (ref->u.ar.end[i]) + || contains_forall_index_p (ref->u.ar.stride[i])) + return true; + break; + + case REF_COMPONENT: + break; + + case REF_SUBSTRING: + if (contains_forall_index_p (ref->u.ss.start) + || contains_forall_index_p (ref->u.ss.end)) + return true; + break; + + default: + gcc_unreachable (); + } + + return false; +} + /* Determines overlapping for two single element array references. */ static gfc_dependency @@ -812,9 +890,23 @@ gfc_check_element_vs_element (gfc_ref * lref, gfc_ref * rref, int n) i = gfc_dep_compare_expr (r_start, l_start); if (i == 0) return GFC_DEP_EQUAL; - if (i == -2) + if (i != -2) + return GFC_DEP_NODEP; + + /* Treat two scalar variables as potentially equal. This allows + us to prove that a(i,:) and a(j,:) have no dependency. See + Gerald Roth, "Evaluation of Array Syntax Dependence Analysis", + Proceedings of the International Conference on Parallel and + Distributed Processing Techniques and Applications (PDPTA2001), + Las Vegas, Nevada, June 2001. */ + /* However, we need to be careful when either scalar expression + contains a FORALL index, as these can potentially change value + during the scalarization/traversal of this array reference. */ + if (contains_forall_index_p (r_start) + || contains_forall_index_p (l_start)) return GFC_DEP_OVERLAP; - return GFC_DEP_NODEP; + + return GFC_DEP_EQUAL; } diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 3e673a8ccf5..a7b84b1a2e3 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -852,6 +852,8 @@ typedef struct gfc_symbol /* Nonzero if all equivalences associated with this symbol have been processed. */ unsigned equiv_built:1; + /* Set if this variable is used as an index name in a FORALL. */ + unsigned forall_index:1; int refs; struct gfc_namespace *ns; /* namespace containing this symbol */ diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c index 4c2fe1b71ce..865781f9f86 100644 --- a/gcc/fortran/match.c +++ b/gcc/fortran/match.c @@ -3370,6 +3370,9 @@ match_forall_iterator (gfc_forall_iterator ** result) goto cleanup; } + /* Mark the iteration variable's symbol as used as a FORALL index. */ + iter->var->symtree->n.sym->forall_index = true; + *result = iter; return MATCH_YES; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f85f232bf8a..aa61c522aa4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2006-03-24 Roger Sayle + + * gfortran.dg/dependency_9.f90: New (resurected) test case. + 2006-03-24 Jeff Law * gcc.c-torture/pr26840.c: New test. diff --git a/gcc/testsuite/gfortran.dg/dependency_9.f90 b/gcc/testsuite/gfortran.dg/dependency_9.f90 new file mode 100644 index 00000000000..d1f6f5e3fed --- /dev/null +++ b/gcc/testsuite/gfortran.dg/dependency_9.f90 @@ -0,0 +1,13 @@ +! { dg-do compile } +! { dg-options "-O2 -fdump-tree-original" } +subroutine foo(a,i,j) + integer, dimension (4,4) :: a + integer :: i + integer :: j + + where (a(i,:) .ne. 0) + a(j,:) = 1 + endwhere +end subroutine +! { dg-final { scan-tree-dump-times "malloc" 0 "original" } } +! { dg-final { cleanup-tree-dump "original" } }