Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.
Richard. 2018-09-19 Richard Biener <rguent...@suse.de> PR tree-optimization/87349 PR tree-optimization/87342 * tree-ssa-sccvn.c (do_rpo_vn): Iterate max_rpo computation. * gcc.dg/torture/pr87349-1.c: New testcase. * gcc.dg/torture/pr87349-2.c: Likewise. * gcc.dg/torture/pr87342.c: Likewise. Index: gcc/tree-ssa-sccvn.c =================================================================== --- gcc/tree-ssa-sccvn.c (revision 264390) +++ gcc/tree-ssa-sccvn.c (working copy) @@ -6374,6 +6374,7 @@ do_rpo_vn (function *fn, edge entry, bit vn_valueize = rpo_vn_valueize; /* Initialize the unwind state and edge/BB executable state. */ + bool need_max_rpo_iterate = false; for (int i = 0; i < n; ++i) { basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[i]); @@ -6388,11 +6389,14 @@ do_rpo_vn (function *fn, edge entry, bit if (e->flags & EDGE_DFS_BACK) has_backedges = true; e->flags &= ~EDGE_EXECUTABLE; - if (e == entry) + if (iterate || e == entry) continue; if (bb_to_rpo[e->src->index] > i) - rpo_state[i].max_rpo = MAX (rpo_state[i].max_rpo, - bb_to_rpo[e->src->index]); + { + rpo_state[i].max_rpo = MAX (rpo_state[i].max_rpo, + bb_to_rpo[e->src->index]); + need_max_rpo_iterate = true; + } else rpo_state[i].max_rpo = MAX (rpo_state[i].max_rpo, @@ -6403,6 +6407,35 @@ do_rpo_vn (function *fn, edge entry, bit entry->flags |= EDGE_EXECUTABLE; entry->dest->flags |= BB_EXECUTABLE; + /* When there are irreducible regions the simplistic max_rpo computation + above for the case of backedges doesn't work and we need to iterate + until there are no more changes. */ + unsigned nit = 0; + while (need_max_rpo_iterate) + { + nit++; + need_max_rpo_iterate = false; + for (int i = 0; i < n; ++i) + { + basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[i]); + edge e; + edge_iterator ei; + FOR_EACH_EDGE (e, ei, bb->preds) + { + if (e == entry) + continue; + int max_rpo = MAX (rpo_state[i].max_rpo, + rpo_state[bb_to_rpo[e->src->index]].max_rpo); + if (rpo_state[i].max_rpo != max_rpo) + { + rpo_state[i].max_rpo = max_rpo; + need_max_rpo_iterate = true; + } + } + } + } + statistics_histogram_event (cfun, "RPO max_rpo iterations", nit); + /* As heuristic to improve compile-time we handle only the N innermost loops and the outermost one optimistically. */ if (iterate) Index: gcc/testsuite/gcc.dg/torture/pr87349-1.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr87349-1.c (nonexistent) +++ gcc/testsuite/gcc.dg/torture/pr87349-1.c (working copy) @@ -0,0 +1,33 @@ +/* { dg-do compile } */ + +void +h1 (int *fh, int pw) +{ + *fh = 0; + if (*fh != 0) + for (;;) + { + fh = &pw; + + if (pw == 0) + { + } + else + while (pw < 1) + { + if (pw == 0) + { +ut: + ; + } + + ++pw; + } + + if (pw == 0) + goto ut; + } + + goto ut; +} + Index: gcc/testsuite/gcc.dg/torture/pr87349-2.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr87349-2.c (nonexistent) +++ gcc/testsuite/gcc.dg/torture/pr87349-2.c (working copy) @@ -0,0 +1,33 @@ +/* { dg-do compile } */ + +void +h1 (int *fh, int pw) +{ + *fh = 0; + if (*fh != 0) + for (;;) + { + fh = &pw; + + if (pw == 0) + { + } + else + while (pw < 1) + { + if (pw == 0) + { +ut: + ; + } + + ++pw; + } + + if (pw == *fh) + goto ut; + } + + goto ut; +} + Index: gcc/testsuite/gcc.dg/torture/pr87342.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr87342.c (nonexistent) +++ gcc/testsuite/gcc.dg/torture/pr87342.c (working copy) @@ -0,0 +1,44 @@ +/* { dg-do compile } */ + +int ix; + +void +o6 (int rh) +{ + if (rh == 0) + { + ix = 0; + while (ix < 1) + { + } + + for (;;) + if (ix == 0) + while (rh < 1) + { + if (rh == 0) + { + __builtin_unreachable (); + +kp: + if (ix == 0) + { +hk: + ix = 0; + } + } + + while (rh < 1) + if (ix == 0) + goto kp; + + while (rh < 1) + { + } + } + else + goto kp; + } + + goto hk; +}