aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2006-03-17 00:02:53 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2006-03-17 00:02:53 +0000
commit37311e710c998b30f5d535b0cd98b5aa88db14cc (patch)
tree8b3497c0385f850e087ede30b150e5e567d20343
parent620b87b3cede2575e47da115ab8d1a6047dc5c06 (diff)
downloadgcc-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/ChangeLog8
-rw-r--r--gcc/fortran/dependency.c38
-rw-r--r--gcc/fortran/gfortran.h1
-rw-r--r--gcc/fortran/trans-common.c1
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gfortran.dg/dependency_13.f9013
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" } }