From: Martin Jambor Date: Tue, 13 Jun 2017 11:40:24 +0000 (+0200) Subject: [PR80803 2/2] Diligent queuing in SRA grp_write prop X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=345683a95f5a9a2f6c319764da7e7491e765da86;p=gcc.git [PR80803 2/2] Diligent queuing in SRA grp_write prop 2017-06-13 Martin Jambor 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4dec155ad86..bf2efd50e64 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2017-06-13 Martin Jambor + + 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 * tree-sra.c (add_access_to_work_queue): Only enqueue accesses diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 71b89de0fbd..d9a9fb2fa65 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2017-06-13 Martin Jambor + + 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 * 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 00000000000..66834fb31fb --- /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 00000000000..399e2d19eb3 --- /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 05bc3d0e806..c9865c6eb31 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