Hi, The if-conversion patch for PR77848 missed a case where an outer loop should not be versioned for vectorization; this was caught by an assert in tests recorded in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78413. This patch fixes the problem by ensuring that both inner and outer loop latches have a single predecessor before versioning an outer loop.
Bootstrapped and tested on powerpc64le-unknown-linux-gnu with no regressions. Is this ok for trunk? Thanks, Bill [gcc] 2016-11-18 Bill Schmidt <wschm...@linux.vnet.ibm.com> PR tree-optimization/78413 * tree-if-conv.c (versionable_outer_loop_p): Require that both inner and outer loop latches have single predecessors. [gcc/testsuite] 2016-11-18 Bill Schmidt <wschm...@linux.vnet.ibm.com> PR tree-optimization/78413 * gcc.dg/tree-ssa/pr78413.c: New test. Index: gcc/testsuite/gcc.dg/tree-ssa/pr78413.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/pr78413.c (revision 0) +++ gcc/testsuite/gcc.dg/tree-ssa/pr78413.c (working copy) @@ -0,0 +1,35 @@ +/* PR78413. These previously failed in tree if-conversion due to a loop + latch with multiple predecessors that the code did not anticipate. */ +/* { dg-do compile } */ +/* { dg-options "-O3 -ffast-math" } */ + +extern long long int llrint(double x); +int a; +double b; +__attribute__((cold)) void decode_init() { + int c, d = 0; + for (; d < 12; d++) { + if (d) + b = 0; + c = 0; + for (; c < 6; c++) + a = b ? llrint(b) : 0; + } +} + +struct S { + _Bool bo; +}; +int a, bb, c, d; +void fn1() { + do + do + do { + struct S *e = (struct S *)1; + do + bb = a / (e->bo ? 2 : 1); + while (bb); + } while (0); + while (d); + while (c); +} Index: gcc/tree-if-conv.c =================================================================== --- gcc/tree-if-conv.c (revision 242551) +++ gcc/tree-if-conv.c (working copy) @@ -2575,6 +2575,8 @@ version_loop_for_if_conversion (struct loop *loop) - The loop has a single exit. - The loop header has a single successor, which is the inner loop header. + - Each of the inner and outer loop latches have a single + predecessor. - The loop exit block has a single predecessor, which is the inner loop's exit block. */ @@ -2586,7 +2588,9 @@ versionable_outer_loop_p (struct loop *loop) || loop->inner->next || !single_exit (loop) || !single_succ_p (loop->header) - || single_succ (loop->header) != loop->inner->header) + || single_succ (loop->header) != loop->inner->header + || !single_pred_p (loop->latch) + || !single_pred_p (loop->inner->latch)) return false; basic_block outer_exit = single_pred (loop->latch);