2010-06-10 Martin Jambor <mjambor@suse.cz>
authorjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 10 Jun 2010 16:49:09 +0000 (16:49 +0000)
committerjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 10 Jun 2010 16:49:09 +0000 (16:49 +0000)
PR tree-optimization/44258
* tree-sra.c (build_access_subtree): Return false iff there is a
partial overlap.
(build_access_trees): Likewise.
(analyze_all_variable_accesses): Disqualify candidates if
build_access_trees returns true for them.

* testsuite/gcc.dg/tree-ssa/pr44258.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@160561 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr44258.c [new file with mode: 0644]
gcc/tree-sra.c

index 685a346..0380a96 100644 (file)
@@ -1,3 +1,12 @@
+2010-06-10  Martin Jambor  <mjambor@suse.cz>
+
+       PR tree-optimization/44258
+       * tree-sra.c (build_access_subtree): Return false iff there is a
+       partial overlap.
+       (build_access_trees): Likewise.
+       (analyze_all_variable_accesses): Disqualify candidates if
+       build_access_trees returns true for them.
+
 2010-06-10  Alexandre Oliva  <aoliva@redhat.com>
 
        PR debug/41371
index e72a684..eff5ab6 100644 (file)
@@ -1,3 +1,8 @@
+2010-06-10  Martin Jambor  <mjambor@suse.cz>
+
+       PR tree-optimization/44258
+       * gcc.dg/tree-ssa/pr44258.c: New test.
+
 2010-06-10  Daniel Kraft  <d@domob.eu>
 
        PR fortran/38936
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr44258.c b/gcc/testsuite/gcc.dg/tree-ssa/pr44258.c
new file mode 100644 (file)
index 0000000..a98d3ce
--- /dev/null
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-esra-details" } */
+
+struct blah
+{
+  char a[4];
+};
+
+struct str
+{
+  struct blah b1;
+  char x;
+};
+
+struct val
+{
+  char y;
+  struct blah b2;
+};
+
+union U
+{
+  struct str str;
+  struct val val;
+};
+
+
+extern struct blah e_b1, e_b2;
+extern union U *e_u;
+
+int foo (int b)
+{
+  union U u;
+
+  u.str.b1 = e_b1;
+  u.val.b2 = e_b2;
+  u.str.b1.a[3] = 0;
+
+  *e_u = u;
+}
+
+/* { dg-final { scan-tree-dump-times "Created a replacement" 0 "esra"} } */
+/* { dg-final { cleanup-tree-dump "esra" } } */
index 5387a19..3fc1164 100644 (file)
@@ -1689,9 +1689,10 @@ get_unrenamed_access_replacement (struct access *access)
 
 /* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
    linked list along the way.  Stop when *ACCESS is NULL or the access pointed
-   to it is not "within" the root.  */
+   to it is not "within" the root.  Return false iff some accesses partially
+   overlap.  */
 
-static void
+static bool
 build_access_subtree (struct access **access)
 {
   struct access *root = *access, *last_child = NULL;
@@ -1706,24 +1707,32 @@ build_access_subtree (struct access **access)
        last_child->next_sibling = *access;
       last_child = *access;
 
-      build_access_subtree (access);
+      if (!build_access_subtree (access))
+       return false;
     }
+
+  if (*access && (*access)->offset < limit)
+    return false;
+
+  return true;
 }
 
 /* Build a tree of access representatives, ACCESS is the pointer to the first
-   one, others are linked in a list by the next_grp field.  Decide about scalar
-   replacements on the way, return true iff any are to be created.  */
+   one, others are linked in a list by the next_grp field.  Return false iff
+   some accesses partially overlap.  */
 
-static void
+static bool
 build_access_trees (struct access *access)
 {
   while (access)
     {
       struct access *root = access;
 
-      build_access_subtree (&access);
+      if (!build_access_subtree (&access))
+       return false;
       root->next_grp = access;
     }
+  return true;
 }
 
 /* Return true if expr contains some ARRAY_REFs into a variable bounded
@@ -2062,9 +2071,7 @@ analyze_all_variable_accesses (void)
       struct access *access;
 
       access = sort_and_splice_var_accesses (var);
-      if (access)
-       build_access_trees (access);
-      else
+      if (!access || !build_access_trees (access))
        disqualify_candidate (var,
                              "No or inhibitingly overlapping accesses.");
     }