Hi All, The vectorizer at the moment uses a num_bb check to check for control flow. This rejects a number of loops with no reason. Instead this patch changes it to check the destination of the exits instead. This also allows early break to work by also dropping the single_exit check. Bootstrapped Regtested on aarch64-none-linux-gnu and no issues. Ok for master? Thanks, Tamar gcc/ChangeLog: * tree-vect-loop-manip.cc (slpeel_can_duplicate_loop_p): * tree-vect-loop.cc (vect_analyze_loop_form): --- inline copy of patch -- diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc index 9c1405d79fd8fe8689007df3b7605b7a3d3ecdd7..466cf4c47154099a33dc63e22d74eef42d282444 100644 --- a/gcc/tree-vect-loop-manip.cc +++ b/gcc/tree-vect-loop-manip.cc @@ -1937,12 +1937,10 @@ slpeel_can_duplicate_loop_p (const class loop *loop, const_edge exit_e, edge entry_e = loop_preheader_edge (loop); gcond *orig_cond = get_loop_exit_condition (exit_e); gimple_stmt_iterator loop_exit_gsi = gsi_last_bb (exit_e->src); - unsigned int num_bb = loop->inner? 5 : 2; /* All loops have an outer scope; the only case loop->outer is NULL is for the function itself. */ if (!loop_outer (loop) - || loop->num_nodes != num_bb || !empty_block_p (loop->latch) || !exit_e /* Verify that new loop exit condition can be trivially modified. */ diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index ddb6cad60f2f2cfdc96732f3f256d86e315d7357..27ab6abfa854f14f8a4cf3d9fcb1ac1c203a4198 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -1727,6 +1727,17 @@ vect_analyze_loop_form (class loop *loop, vect_loop_form_info *info) "using as main loop exit: %d -> %d [AUX: %p]\n", exit_e->src->index, exit_e->dest->index, exit_e->aux); + /* Check if we have any control flow that doesn't leave the loop. */ + class loop *v_loop = loop->inner ? loop->inner : loop; + basic_block *bbs= get_loop_body (v_loop); + for (unsigned i = 0; i < v_loop->num_nodes; i++) + if (!empty_block_p (bbs[i]) + && !loop_exits_from_bb_p (v_loop, bbs[i]) + && bbs[i]->loop_father == v_loop) + return opt_result::failure_at (vect_location, + "not vectorized:" + " unsupported control flow in loop.\n"); + /* Different restrictions apply when we are considering an inner-most loop, vs. an outer (nested) loop. (FORNOW. May want to relax some of these restrictions in the future). */ @@ -1746,11 +1757,6 @@ vect_analyze_loop_form (class loop *loop, vect_loop_form_info *info) | (exit-bb) */ - if (loop->num_nodes != 2) - return opt_result::failure_at (vect_location, - "not vectorized:" - " control flow in loop.\n"); - if (empty_block_p (loop->header)) return opt_result::failure_at (vect_location, "not vectorized: empty loop.\n"); @@ -1782,11 +1788,6 @@ vect_analyze_loop_form (class loop *loop, vect_loop_form_info *info) "not vectorized:" " multiple nested loops.\n"); - if (loop->num_nodes != 5) - return opt_result::failure_at (vect_location, - "not vectorized:" - " control flow in loop.\n"); - entryedge = loop_preheader_edge (innerloop); if (entryedge->src != loop->header || !single_exit (innerloop) @@ -1823,9 +1824,6 @@ vect_analyze_loop_form (class loop *loop, vect_loop_form_info *info) info->inner_loop_cond = inner.conds[0]; } - if (!single_exit (loop)) - return opt_result::failure_at (vect_location, - "not vectorized: multiple exits.\n"); if (EDGE_COUNT (loop->header->preds) != 2) return opt_result::failure_at (vect_location, "not vectorized:" --