aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2017-06-13 13:40:24 +0200
committerMartin Jambor <jamborm@gcc.gnu.org>2017-06-13 13:40:24 +0200
commit345683a95f5a9a2f6c319764da7e7491e765da86 (patch)
treeccaa86c7ea9c58ffef3b5ae4b86a308be277d376
parent35a952ba70028b50fbd2fd19f7dc91f2da45371e (diff)
downloadgcc-345683a95f5a9a2f6c319764da7e7491e765da86.zip
gcc-345683a95f5a9a2f6c319764da7e7491e765da86.tar.gz
gcc-345683a95f5a9a2f6c319764da7e7491e765da86.tar.bz2
[PR80803 2/2] Diligent queuing in SRA grp_write prop
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
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr80803.c72
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr81063.c28
-rw-r--r--gcc/tree-sra.c100
5 files changed, 174 insertions, 41 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4dec155..bf2efd5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,13 @@
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
that have a first_link.
(sort_and_splice_var_accesses): Do not check first_link before
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 71b89de..d9a9fb2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..66834fb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr80803.c
@@ -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
index 0000000..399e2d1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr81063.c
@@ -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;
+}
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 05bc3d0..c9865c6 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -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