The following avoids different avail answers depending on how the iteration progressed.
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed. PR tree-optimization/113707 * tree-ssa-sccvn.cc (rpo_elim::eliminate_avail): After checking the avail set treat out-of-region defines as available. * gcc.dg/torture/pr113707-1.c: New testcase. * gcc.dg/torture/pr113707-2.c: Likewise. --- gcc/testsuite/gcc.dg/torture/pr113707-1.c | 45 +++++++++++++++++++++++ gcc/testsuite/gcc.dg/torture/pr113707-2.c | 26 +++++++++++++ gcc/tree-ssa-sccvn.cc | 5 +++ 3 files changed, 76 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/torture/pr113707-1.c create mode 100644 gcc/testsuite/gcc.dg/torture/pr113707-2.c diff --git a/gcc/testsuite/gcc.dg/torture/pr113707-1.c b/gcc/testsuite/gcc.dg/torture/pr113707-1.c new file mode 100644 index 00000000000..c1a50b31025 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr113707-1.c @@ -0,0 +1,45 @@ +/* { dg-do compile } */ + +int printf(const char *, ...); +struct a { + int b; +} n; +int a, c, d, e, f = 1, g, h, j = 1, k, l, m, o; +int main() { + struct a p; + int i; + p.b = 1; + if (!j) + goto q; + p.b = i = 0; + for (; i < 1; i++) + if (k) + while (m) + r: + q: + if (p.b) + g = 1; + while (1) { + i = 0; + for (; i < 5; i++) + ; + if (l) { + while (h) + ; + if (o) { + d = 0; + for (; d < 8; d++) + ; + } + } + for (; e; e--) + while (a) + p = n; + if (c) + goto r; + printf("0"); + if (f) + break; + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr113707-2.c b/gcc/testsuite/gcc.dg/torture/pr113707-2.c new file mode 100644 index 00000000000..957e6f1b534 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr113707-2.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ + +int a, b, c, d, e, f, g, h, j, k, l; +void n() { + while (c) + if (1) { + for (h = 5; h; h--) { + int m = e % 2; + d = ~g || h ^ m / -1; + if (h > 5) + e = k; + } + return; + } +} +int main() { + if (a) + for (int i = 0; i < 2; i++) { + for (f = 1; f < 6; f++) + for (c = 7; c >= 0; c--) + if (l) + b = 0; + n(); + } + return 0; +} diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc index bbcf86588f9..8792cd07901 100644 --- a/gcc/tree-ssa-sccvn.cc +++ b/gcc/tree-ssa-sccvn.cc @@ -7776,6 +7776,11 @@ rpo_elim::eliminate_avail (basic_block bb, tree op) av = av->next; } while (av); + /* While we prefer avail we have to fallback to using the value + directly if defined outside of the region when none of the + available defs suit. */ + if (!valnum_info->visited) + return valnum; } else if (valnum != VN_TOP) /* valnum is is_gimple_min_invariant. */ -- 2.35.3