From 37311e710c998b30f5d535b0cd98b5aa88db14cc Mon Sep 17 00:00:00 2001 From: Roger Sayle Date: Fri, 17 Mar 2006 00:02:53 +0000 Subject: gfortran.h (gfc_equiv_info): Add length field. * gfortran.h (gfc_equiv_info): Add length field. * trans-common.c (copy_equiv_list_to_ns): Set the length field. * dependency.c (gfc_are_equivalenced_arrays): Use both the offset and length fields to determine whether the two equivalenced symbols overlap in memory. * gfortran.dg/dependency_13.f90: New test case. From-SVN: r112162 --- gcc/fortran/dependency.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) (limited to 'gcc/fortran/dependency.c') diff --git a/gcc/fortran/dependency.c b/gcc/fortran/dependency.c index d60b7eb..03cabf0 100644 --- a/gcc/fortran/dependency.c +++ b/gcc/fortran/dependency.c @@ -414,10 +414,13 @@ gfc_check_fncall_dependency (gfc_expr * other, sym_intent intent, directly or indirectly; ie. equivalence (a,b) for a and b or equivalence (a,c),(b,c). This function uses the equiv_ lists, generated in trans-common(add_equivalences), that are - guaranteed to pick up indirect equivalences. A rudimentary - use is made of the offset to ensure that cases where the - source elements are moved down to the destination are not - identified as dependencies. */ + guaranteed to pick up indirect equivalences. We explicitly + check for overlap using the offset and length of the equivalence. + This function is symmetric. + TODO: This function only checks whether the full top-level + symbols overlap. An improved implementation could inspect + e1->ref and e2->ref to determine whether the actually accessed + portions of these variables/arrays potentially overlap. */ int gfc_are_equivalenced_arrays (gfc_expr *e1, gfc_expr *e2) @@ -444,14 +447,33 @@ gfc_are_equivalenced_arrays (gfc_expr *e1, gfc_expr *e2) for (s = l->equiv; s; s = s->next) { if (s->sym == e1->symtree->n.sym) - fl1 = s; + { + fl1 = s; + if (fl2) + break; + } if (s->sym == e2->symtree->n.sym) - fl2 = s; - if (fl1 && fl2 && (fl1->offset > fl2->offset)) + { + fl2 = s; + if (fl1) + break; + } + } + + if (s) + { + /* Can these lengths be zero? */ + if (fl1->length <= 0 || fl2->length <= 0) + return 1; + /* These can't overlap if [f11,fl1+length] is before + [fl2,fl2+length], or [fl2,fl2+length] is before + [fl1,fl1+length], otherwise they do overlap. */ + if (fl1->offset + fl1->length > fl2->offset + && fl2->offset + fl2->length > fl1->offset) return 1; } } -return 0; + return 0; } -- cgit v1.1