diff options
author | Roger Sayle <roger@eyesopen.com> | 2006-03-17 00:02:53 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2006-03-17 00:02:53 +0000 |
commit | 37311e710c998b30f5d535b0cd98b5aa88db14cc (patch) | |
tree | 8b3497c0385f850e087ede30b150e5e567d20343 | |
parent | 620b87b3cede2575e47da115ab8d1a6047dc5c06 (diff) | |
download | gcc-37311e710c998b30f5d535b0cd98b5aa88db14cc.zip gcc-37311e710c998b30f5d535b0cd98b5aa88db14cc.tar.gz gcc-37311e710c998b30f5d535b0cd98b5aa88db14cc.tar.bz2 |
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
-rw-r--r-- | gcc/fortran/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/fortran/dependency.c | 38 | ||||
-rw-r--r-- | gcc/fortran/gfortran.h | 1 | ||||
-rw-r--r-- | gcc/fortran/trans-common.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/dependency_13.f90 | 13 |
6 files changed, 57 insertions, 8 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index b09d32e..61bbcfd 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,11 @@ +2006-03-16 Roger Sayle <roger@eyesopen.com> + + * 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. + 2006-03-14 Jerry DeLisle <jvdelisle@gcc.gnu.org> PR fortran/19101 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; } diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 2a5d01c..24c92b3 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -1352,6 +1352,7 @@ typedef struct gfc_equiv_info { gfc_symbol *sym; HOST_WIDE_INT offset; + HOST_WIDE_INT length; struct gfc_equiv_info *next; } gfc_equiv_info; diff --git a/gcc/fortran/trans-common.c b/gcc/fortran/trans-common.c index 3b34b334..3b16e5e 100644 --- a/gcc/fortran/trans-common.c +++ b/gcc/fortran/trans-common.c @@ -169,6 +169,7 @@ copy_equiv_list_to_ns (segment_info *c) l->equiv = s; s->sym = f->sym; s->offset = f->offset; + s->length = f->length; } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 90dc700..63fa39d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2006-03-16 Roger Sayle <roger@eyesopen.com> + * gfortran.dg/dependency_13.f90: New test case. + +2006-03-16 Roger Sayle <roger@eyesopen.com> + PR middle-end/21781 * gcc.dg/real-const-1.c: New test case. diff --git a/gcc/testsuite/gfortran.dg/dependency_13.f90 b/gcc/testsuite/gfortran.dg/dependency_13.f90 new file mode 100644 index 0000000..85fb977 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/dependency_13.f90 @@ -0,0 +1,13 @@ +! { dg-do compile } +! { dg-options "-O2 -fdump-tree-original" } + integer :: i(5) + real(4) :: x(5) + equivalence(x,i) + + i = (/ 1, 0, 3, 5, 0 /) + where (i(1:4) .ne. 0) + x(2:5) = -42. + end where + end +! { dg-final { scan-tree-dump-times "malloc" 1 "original" } } +! { dg-final { cleanup-tree-dump "original" } } |