On Mon, 6 Nov 2023, Tamar Christina wrote:
> 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?
I think this can go in independently, one comment below ...
> 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)
That looks a bit complicated. Better matching the comment would be
if (EDGE_COUNT (bbs[i]->succs) != 1
&& (EDGE_COUNT (bbs[i]->succs) != 2
|| !loop_exits_from_bb_p (bb[i]->loop_father, bb[i])))
I'd say OK with that change, and independently if the removed
single_exit test below isn't harmful (I suppose it is).
Btw, for the outer loop case we still have the single_exit tests
but you already said you're not supporting multi-exits there yet.
Thanks,
Richard.
> + 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:"