Hi, PR 89546 is a nasty miscompilation bug that is in the compiler since r247604 (May 2017) but is surprisingly hard to trigger. Since that revision, SRA does not consider all aggregates that are assigned a value in a gimple assignment statement from another aggregate as automatically containing data. Instead, it records existence of such assignments and then propagates this information from RHSs to LHSs in a simple queue driven algorithm. That of course relies on the fact that whenever a part of a LHSs is marked as containing data, all relevant parts of that aggregate which are on the RHS of some other assignment are re-queued. Well, it turns out I forgot to add that to one spot where that has to be done.
Fixed with the patch below. Bootstrapped and tested on x86_64-linux. OK for trunk and gcc 8? Thanks, Martin 2019-03-14 Martin Jambor <mjam...@suse.cz> PR tree-optimization/89546 * tree-sra.c (propagate_subaccesses_across_link): Requeue new_acc if any propagation to its children took place. testsuite/ * gcc.dg/tree-ssa/pr89546.c: New test. --- gcc/testsuite/gcc.dg/tree-ssa/pr89546.c | 100 ++++++++++++++++++++++++ gcc/tree-sra.c | 8 +- 2 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr89546.c diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89546.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89546.c new file mode 100644 index 00000000000..c4645ae1858 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89546.c @@ -0,0 +1,100 @@ +/* { dg-do run } */ +/* { dg-options "-O" } */ + +struct I +{ + int i; +}; + +struct A +{ + struct I i1; + struct I i2; + struct I i3; +}; + +struct B +{ + struct I i0; + struct A a; +}; + +struct C +{ + struct I i00; + struct B b; +}; + +volatile int v; + +void __attribute__((noipa)) +consume_i (struct I i) +{ + v = i.i; +} + +void __attribute__((noipa)) +consume_a (struct A a) +{ + v = a.i1.i; +} + +void __attribute__((noipa)) +consume_b (struct B b) +{ + v = b.a.i1.i; +} + +void __attribute__((noipa)) +consume_c (struct C c) +{ + v = c.b.a.i1.i; +} + + + + +int __attribute__((noipa)) +foo (struct I input) +{ + struct I i1, i2, i3; + struct A a1, a2, a3; + struct B b1; + struct C c; + + i1 = input; + a1.i1 = i1; + b1.a = a1; + + i2.i = 1; + b1.i0 = i2; + + c.b = b1; + + a2 = c.b.a; + a3 = a2; + i3 = a3.i1; + + int t = c.b.i0.i; + a2.i3.i = 4; + consume_i (i1); + consume_i (i2); + consume_b (b1); + consume_a (a1); + consume_a (a2); + consume_a (a3); + consume_c (c); + + return i3.i + t; +} + +int +main (int argc, char *argv[]) +{ + struct I s; + s.i = 1234; + int i = foo (s); + if (i != 1235) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index ca3858d5fc7..fd51a3d0323 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -2752,8 +2752,12 @@ propagate_subaccesses_across_link (struct access *lacc, struct access *racc) rchild->grp_hint = 1; new_acc->grp_hint |= new_acc->grp_read; - if (rchild->first_child) - ret |= propagate_subaccesses_across_link (new_acc, rchild); + if (rchild->first_child + && propagate_subaccesses_across_link (new_acc, rchild)) + { + ret = 1; + add_access_to_work_queue (new_acc); + } } else { -- 2.21.0