[PR 80898] Propagate grp_write from disqualified SRA candidates
authorMartin Jambor <mjambor@suse.cz>
Thu, 1 Jun 2017 12:14:29 +0000 (14:14 +0200)
committerMartin Jambor <jamborm@gcc.gnu.org>
Thu, 1 Jun 2017 12:14:29 +0000 (14:14 +0200)
2017-06-01  Martin Jambor  <mjambor@suse.cz>

PR tree-optimization/80898
* tree-sra.c (process_subtree_disqualification): Removed.
(disqualify_candidate): Do not acll
process_subtree_disqualification.
(subtree_mark_written_and_enqueue): New function.
(propagate_all_subaccesses): Set grp_write of LHS subtree if the
RHS has been disqualified and re-queue LHS if necessary.  Apart
from that, ignore disqualified RHS.

testsuite/
* gcc.dg/tree-ssa/pr80898.c: New test.
* gcc.dg/tree-ssa/pr80898-2.c: Likewise.

From-SVN: r248790

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

index 9cfcfad9090f1279c0babd9aa582667d242ef5e1..81d8337e05040ce1bb93b4cd9f28945d918d5ed8 100644 (file)
@@ -1,3 +1,14 @@
+2017-06-01  Martin Jambor  <mjambor@suse.cz>
+
+       PR tree-optimization/80898
+       * tree-sra.c (process_subtree_disqualification): Removed.
+       (disqualify_candidate): Do not acll
+       process_subtree_disqualification.
+       (subtree_mark_written_and_enqueue): New function.
+       (propagate_all_subaccesses): Set grp_write of LHS subtree if the
+       RHS has been disqualified and re-queue LHS if necessary.  Apart
+       from that, ignore disqualified RHS.
+
 2017-06-01  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
 
        * config/s390/s390.c (s390_emit_epilogue): Disable early return
index a1212f24b6b5b9ca05e637c9e60472dd8ed8a799..e398b31644a176b49fee1b83f9470c860e2f7a36 100644 (file)
@@ -1,3 +1,9 @@
+2017-06-01  Martin Jambor  <mjambor@suse.cz>
+
+       PR tree-optimization/80898
+       * gcc.dg/tree-ssa/pr80898.c: New test.
+       * gcc.dg/tree-ssa/pr80898-2.c: Likewise.
+
 2017-06-01  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/80896
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr80898-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr80898-2.c
new file mode 100644 (file)
index 0000000..cb4799c
--- /dev/null
@@ -0,0 +1,71 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+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;
+  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;
+
+      m = u.s1;
+      m.s0.c = 0;
+      l = m.s0;
+      gs = l;
+    }
+
+  gu = u;
+  check_outcome ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr80898.c b/gcc/testsuite/gcc.dg/tree-ssa/pr80898.c
new file mode 100644 (file)
index 0000000..ed88f2c
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+struct S0 {
+  int f0 : 24;
+  int f1;
+  int f74;
+} a, *c = &a;
+struct S0 fn1() {
+  struct S0 b = {4, 3};
+  return b;
+}
+
+int main() {
+  *c = fn1();
+
+  if (a.f1 != 3)
+    __builtin_abort ();
+  return 0;
+}
index 6a8a0a4a4273328e0ee3dbd998d6d0b454ef5115..f25818f44814f043e647a8c96372139fd0987588 100644 (file)
@@ -694,21 +694,9 @@ static bool constant_decl_p (tree decl)
   return VAR_P (decl) && DECL_IN_CONSTANT_POOL (decl);
 }
 
-
-/* Mark LHS of assign links out of ACCESS and its children as written to.  */
-
-static void
-process_subtree_disqualification (struct access *access)
-{
-  struct access *child;
-  for (struct assign_link *link = access->first_link; link; link = link->next)
-    link->lacc->grp_write = true;
-  for (child = access->first_child; child; child = child->next_sibling)
-    process_subtree_disqualification (child);
-}
-
 /* Remove DECL from candidates for SRA and write REASON to the dump file if
    there is one.  */
+
 static void
 disqualify_candidate (tree decl, const char *reason)
 {
@@ -723,13 +711,6 @@ disqualify_candidate (tree decl, const char *reason)
       print_generic_expr (dump_file, decl);
       fprintf (dump_file, " - %s\n", reason);
     }
-
-  struct access *access = get_first_repr_for_decl (decl);
-  while (access)
-    {
-      process_subtree_disqualification (access);
-      access = access->next_grp;
-    }
 }
 
 /* Return true iff the type contains a field or an element which does not allow
@@ -2679,6 +2660,26 @@ propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
   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;
+  if (access->first_link)
+    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
@@ -2698,7 +2699,20 @@ propagate_all_subaccesses (void)
          if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
            continue;
          lacc = lacc->group_representative;
-         if (propagate_subaccesses_across_link (lacc, racc))
+
+         bool reque_parents = false;
+         if (!bitmap_bit_p (candidate_bitmap, DECL_UID (racc->base)))
+           {
+             if (!lacc->grp_write)
+               {
+                 subtree_mark_written_and_enqueue (lacc);
+                 reque_parents = true;
+               }
+           }
+         else if (propagate_subaccesses_across_link (lacc, racc))
+           reque_parents = true;
+
+         if (reque_parents)
            do
              {
                if (lacc->first_link)