[PR80803 2/2] Diligent queuing in SRA grp_write prop
authorMartin Jambor <mjambor@suse.cz>
Tue, 13 Jun 2017 11:40:24 +0000 (13:40 +0200)
committerMartin Jambor <jamborm@gcc.gnu.org>
Tue, 13 Jun 2017 11:40:24 +0000 (13:40 +0200)
2017-06-13  Martin Jambor  <mjambor@suse.cz>

PR tree-optimization/80803
PR tree-optimization/81063
* tree-sra.c (subtree_mark_written_and_enqueue): Move up in the file.
(propagate_subaccesses_across_link): Enqueue subtree whneve necessary
instead of relying on the caller.

testsuite/
gcc.dg/tree-ssa/pr80803.c: New test.
gcc.dg/tree-ssa/pr81063.c: Likewise.

From-SVN: r249154

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

index 4dec155ad86aa3bb9c454f457b2585f08aa464a3..bf2efd50e64ccf844d898f837b3f33baebc65758 100644 (file)
@@ -1,3 +1,11 @@
+2017-06-13  Martin Jambor  <mjambor@suse.cz>
+
+       PR tree-optimization/80803
+       PR tree-optimization/81063
+       * tree-sra.c (subtree_mark_written_and_enqueue): Move up in the file.
+       (propagate_subaccesses_across_link): Enqueue subtree whneve necessary
+       instead of relying on the caller.
+
 2017-06-13  Martin Jambor  <mjambor@suse.cz>
 
        * tree-sra.c (add_access_to_work_queue): Only enqueue accesses
index 71b89de0fbdb4f40b72a4de2c1c40f1a83e56f43..d9a9fb2fa654e2e62dd1a6321c33f172c2eb8c38 100644 (file)
@@ -1,3 +1,10 @@
+2017-06-13  Martin Jambor  <mjambor@suse.cz>
+
+       PR tree-optimization/80803
+       PR tree-optimization/81063
+       gcc.dg/tree-ssa/pr80803.c: New test.
+       gcc.dg/tree-ssa/pr81063.c: Likewise.
+
 2017-06-12  Yury Gribov  <tetra2005@gmail.com>
 
        * c-c++-common/fold-masked-cmp-3.c: New test.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr80803.c b/gcc/testsuite/gcc.dg/tree-ssa/pr80803.c
new file mode 100644 (file)
index 0000000..66834fb
--- /dev/null
@@ -0,0 +1,72 @@
+/* { dg-do run } */
+/* { dg-options "-O" } */
+
+struct S0
+{
+  unsigned a : 15;
+  int b;
+  int c;
+};
+
+struct S1
+{
+  struct S0 s0;
+  int e;
+};
+
+struct Z
+{
+  char c;
+  int z;
+} __attribute__((packed));
+
+union U
+{
+  struct S1 s1;
+  struct Z z;
+};
+
+
+int __attribute__((noinline, noclone))
+return_zero (void)
+{
+  return 0;
+}
+
+volatile union U gu;
+struct S0 gs;
+
+int __attribute__((noinline, noclone))
+check_outcome ()
+{
+  if (gs.a != 6
+      || gs.b != 80000)
+    __builtin_abort ();
+}
+
+int
+main (int argc, char *argv[])
+{
+  union U u;
+  struct S1 m,n;
+  struct S0 l;
+
+  if (return_zero ())
+    u.z.z = 20000;
+  else
+    {
+      u.s1.s0.a = 6;
+      u.s1.s0.b = 80000;
+      u.s1.e = 2;
+
+      n = u.s1;
+      m = n;
+      m.s0.c = 0;
+      l = m.s0;
+      gs = l;
+    }
+
+  gu = u;
+  check_outcome ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr81063.c b/gcc/testsuite/gcc.dg/tree-ssa/pr81063.c
new file mode 100644 (file)
index 0000000..399e2d1
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+/* { dg-options "-O" } */
+
+struct A
+{
+  int b;
+  int c:2;
+};
+
+struct B
+{
+  int e;
+  struct A f;
+} g = {0, {0, 1}}, j;
+
+struct A *h = &g.f;
+
+int main ()
+{
+  struct A k;
+  struct B l = j, i = l;
+  if (!i.f.b)
+    k = i.f;
+  *h = k;
+  if (g.f.c != 0)
+    __builtin_abort ();
+  return 0;
+}
index 05bc3d0e806f14629a7fd0215a5b694bf322d20d..c9865c6eb318cd00f3e9db5a2ec47527f4a1eb1f 100644 (file)
@@ -2558,9 +2558,28 @@ create_artificial_child_access (struct access *parent, struct access *model,
 }
 
 
-/* Propagate all subaccesses of RACC across an assignment link to LACC. Return
-   true if any new subaccess was created.  Additionally, if RACC is a scalar
-   access but LACC is not, change the type of the latter, if possible.  */
+/* Beginning with ACCESS, traverse its whole access subtree and mark all
+   sub-trees as written to.  If any of them has not been marked so previously
+   and has assignment links leading from it, re-enqueue it.  */
+
+static void
+subtree_mark_written_and_enqueue (struct access *access)
+{
+  if (access->grp_write)
+    return;
+  access->grp_write = true;
+  add_access_to_work_queue (access);
+
+  struct access *child;
+  for (child = access->first_child; child; child = child->next_sibling)
+    subtree_mark_written_and_enqueue (child);
+}
+
+/* Propagate subaccesses and grp_write flags of RACC across an assignment link
+   to LACC.  Enqueue sub-accesses as necessary so that the write flag is
+   propagated transitively.  Return true if anything changed.  Additionally, if
+   RACC is a scalar access but LACC is not, change the type of the latter, if
+   possible.  */
 
 static bool
 propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
@@ -2576,7 +2595,7 @@ propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
       gcc_checking_assert (!comes_initialized_p (racc->base));
       if (racc->grp_write)
        {
-         lacc->grp_write = true;
+         subtree_mark_written_and_enqueue (lacc);
          ret = true;
        }
     }
@@ -2585,13 +2604,21 @@ propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
       || lacc->grp_unscalarizable_region
       || racc->grp_unscalarizable_region)
     {
-      ret |= !lacc->grp_write;
-      lacc->grp_write = true;
+      if (!lacc->grp_write)
+       {
+         ret = true;
+         subtree_mark_written_and_enqueue (lacc);
+       }
       return ret;
     }
 
   if (is_gimple_reg_type (racc->type))
     {
+      if (!lacc->grp_write)
+       {
+         ret = true;
+         subtree_mark_written_and_enqueue (lacc);
+       }
       if (!lacc->first_child && !racc->first_child)
        {
          tree t = lacc->base;
@@ -2616,21 +2643,15 @@ propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
       struct access *new_acc = NULL;
       HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
 
-      if (rchild->grp_unscalarizable_region)
-       {
-         lacc->grp_write = true;
-         continue;
-       }
-
       if (child_would_conflict_in_lacc (lacc, norm_offset, rchild->size,
                                        &new_acc))
        {
          if (new_acc)
            {
-             if (!new_acc->grp_write
-                 && (lacc->grp_write || rchild->grp_write))
+             if (!new_acc->grp_write && rchild->grp_write)
                {
-                 new_acc ->grp_write = true;
+                 gcc_assert (!lacc->grp_write);
+                 subtree_mark_written_and_enqueue (new_acc);
                  ret = true;
                }
 
@@ -2640,7 +2661,23 @@ propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
                ret |= propagate_subaccesses_across_link (new_acc, rchild);
            }
          else
-           lacc->grp_write = true;
+           {
+             if (rchild->grp_write && !lacc->grp_write)
+               {
+                 ret = true;
+                 subtree_mark_written_and_enqueue (lacc);
+               }
+           }
+         continue;
+       }
+
+      if (rchild->grp_unscalarizable_region)
+       {
+         if (rchild->grp_write && !lacc->grp_write)
+           {
+             ret = true;
+             subtree_mark_written_and_enqueue (lacc);
+           }
          continue;
        }
 
@@ -2648,36 +2685,17 @@ propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
       new_acc = create_artificial_child_access (lacc, rchild, norm_offset,
                                                lacc->grp_write
                                                || rchild->grp_write);
-      if (new_acc)
-       {
-         ret = true;
-         if (racc->first_child)
-           propagate_subaccesses_across_link (new_acc, rchild);
-       }
+      gcc_checking_assert (new_acc);
+      if (racc->first_child)
+       propagate_subaccesses_across_link (new_acc, rchild);
+
+      add_access_to_work_queue (lacc);
+      ret = true;
     }
 
   return ret;
 }
 
-/* Beginning with ACCESS, traverse its whole access subtree and mark all
-   sub-trees as written to.  If any of them has not been marked so previously
-   and has assignment links leading from it, re-enqueue it.  */
-
-static void
-subtree_mark_written_and_enqueue (struct access *access)
-{
-  if (access->grp_write)
-    return;
-  access->grp_write = true;
-  add_access_to_work_queue (access);
-
-  struct access *child;
-  for (child = access->first_child; child; child = child->next_sibling)
-    subtree_mark_written_and_enqueue (child);
-}
-
-
-
 /* Propagate all subaccesses across assignment links.  */
 
 static void