On Mon, 10 Nov 2025, Victor Do Nascimento wrote:
> In `vect_do_peeling' and `vect_transform_loop', there are several bits
> of logic reliant on niters that need to be handled differently in the
> case of uncounted loops.
>
> Firstly When we peel the loop, adding a prolog, we subtract the
> prolog peeling factor from the original number of iterations for the
> main loop.
>
> Then, upon vectorization of the main loop, we need to update the
> iteration upper-bound to reflect the fact that each iteration now acts
> on VF elements, such that less iterations will be needed.
>
> Both of these updates become unnecessary when we don't have an IV
> counting exit. Therefore, it is sufficient to guard these
> manipulations behind a check for whether the loop we're dealing with
> is uncounted.
OK.
> gcc/ChangeLog:
>
> * tree-vect-loop-manip.cc (vect_do_peeling): Disable niters
> update.
> * tree-vect-loop.cc (vect_transform_loop): Likewise.
> ---
> gcc/tree-vect-loop-manip.cc | 53 ++++++++++++++++++++-----------------
> gcc/tree-vect-loop.cc | 21 +++++++++------
> 2 files changed, 42 insertions(+), 32 deletions(-)
>
> diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc
> index 928045540da..18a5059251b 100644
> --- a/gcc/tree-vect-loop-manip.cc
> +++ b/gcc/tree-vect-loop-manip.cc
> @@ -3152,6 +3152,7 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters,
> tree nitersm1,
> int estimated_vf;
> int prolog_peeling = 0;
> bool vect_epilogues = loop_vinfo->epilogue_vinfo != NULL;
> + bool uncounted_p = LOOP_VINFO_NITERS_UNCOUNTED_P (loop_vinfo);
>
> if (!vect_use_loop_mask_for_alignment_p (loop_vinfo))
> prolog_peeling = LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo);
> @@ -3545,36 +3546,40 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree
> niters, tree nitersm1,
> bb_before_epilog = loop_preheader_edge (epilog)->src;
> }
>
> - /* If loop is peeled for non-zero constant times, now niters refers to
> - orig_niters - prolog_peeling, it won't overflow even the orig_niters
> - overflows. */
> - niters_no_overflow |= (prolog_peeling > 0);
> - vect_gen_vector_loop_niters (loop_vinfo, niters,
> - niters_vector, step_vector,
> - niters_no_overflow);
> - if (!integer_onep (*step_vector))
> + if (!uncounted_p)
> {
> - /* On exit from the loop we will have an easy way of calcalating
> - NITERS_VECTOR / STEP * STEP. Install a dummy definition
> - until then. */
> - niters_vector_mult_vf = make_ssa_name (TREE_TYPE (*niters_vector));
> - SSA_NAME_DEF_STMT (niters_vector_mult_vf) = gimple_build_nop ();
> - *niters_vector_mult_vf_var = niters_vector_mult_vf;
> + /* If loop is peeled for non-zero constant times, now niters refers to
> + orig_niters - prolog_peeling, it won't overflow even the
> + orig_niters overflows. */
> + niters_no_overflow |= (prolog_peeling > 0);
> + vect_gen_vector_loop_niters (loop_vinfo, niters,
> + niters_vector, step_vector,
> + niters_no_overflow);
> + if (!integer_onep (*step_vector))
> + {
> + /* On exit from the loop we will have an easy way of calcalating
> + NITERS_VECTOR / STEP * STEP. Install a dummy definition
> + until then. */
> + niters_vector_mult_vf
> + = make_ssa_name (TREE_TYPE (*niters_vector));
> + SSA_NAME_DEF_STMT (niters_vector_mult_vf) = gimple_build_nop ();
> + *niters_vector_mult_vf_var = niters_vector_mult_vf;
> + }
> + else
> + vect_gen_vector_loop_niters_mult_vf (loop_vinfo, *niters_vector,
> + &niters_vector_mult_vf);
> + /* Update IVs of original loop as if they were advanced by
> + niters_vector_mult_vf steps. */
> + gcc_checking_assert (vect_can_advance_ivs_p (loop_vinfo));
> + update_e = skip_vector ? e : loop_preheader_edge (epilog);
> + if (LOOP_VINFO_EARLY_BREAKS (loop_vinfo))
> + update_e = single_succ_edge (LOOP_VINFO_IV_EXIT (loop_vinfo)->dest);
> }
> - else
> - vect_gen_vector_loop_niters_mult_vf (loop_vinfo, *niters_vector,
> - &niters_vector_mult_vf);
> - /* Update IVs of original loop as if they were advanced by
> - niters_vector_mult_vf steps. */
> - gcc_checking_assert (vect_can_advance_ivs_p (loop_vinfo));
> - update_e = skip_vector ? e : loop_preheader_edge (epilog);
> - if (LOOP_VINFO_EARLY_BREAKS (loop_vinfo))
> - update_e = single_succ_edge (LOOP_VINFO_IV_EXIT (loop_vinfo)->dest);
>
> /* If we have a peeled vector iteration, all exits are the same, leave
> it
> and so the main exit needs to be treated the same as the alternative
> exits in that we leave their updates to vectorizable_live_operations.
> - */
> + */
> if (!LOOP_VINFO_EARLY_BREAKS_VECT_PEELED (loop_vinfo))
> vect_update_ivs_after_vectorizer (loop_vinfo, niters_vector_mult_vf,
> update_e);
> diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
> index b17745cdaa1..901903cfbea 100644
> --- a/gcc/tree-vect-loop.cc
> +++ b/gcc/tree-vect-loop.cc
> @@ -11060,6 +11060,7 @@ vect_transform_loop (loop_vec_info loop_vinfo, gimple
> *loop_vectorized_call)
> bool check_profitability = false;
> unsigned int th;
> bool flat = maybe_flat_loop_profile (loop);
> + bool uncounted_p = LOOP_VINFO_NITERS_UNCOUNTED_P (loop_vinfo);
>
> DUMP_VECT_SCOPE ("vec_transform_loop");
>
> @@ -11144,7 +11145,7 @@ vect_transform_loop (loop_vec_info loop_vinfo, gimple
> *loop_vectorized_call)
> LOOP_VINFO_SCALAR_IV_EXIT (loop_vinfo)->dest->count = preheader->count;
> }
>
> - if (niters_vector == NULL_TREE)
> + if (niters_vector == NULL_TREE && !uncounted_p)
> {
> if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
> && !LOOP_VINFO_USING_PARTIAL_VECTORS_P (loop_vinfo)
> @@ -11267,13 +11268,17 @@ vect_transform_loop (loop_vec_info loop_vinfo,
> gimple *loop_vectorized_call)
> }
> }
>
> - /* The vectorization factor is always > 1, so if we use an IV increment of
> 1.
> - a zero NITERS becomes a nonzero NITERS_VECTOR. */
> - if (integer_onep (step_vector))
> - niters_no_overflow = true;
> - vect_set_loop_condition (loop, LOOP_VINFO_IV_EXIT (loop_vinfo), loop_vinfo,
> - niters_vector, step_vector, niters_vector_mult_vf,
> - !niters_no_overflow);
> + if (!uncounted_p)
> + {
> + /* The vectorization factor is always > 1, so if we use an IV
> increment of
> + 1. A zero NITERS becomes a nonzero NITERS_VECTOR. */
> + if (integer_onep (step_vector))
> + niters_no_overflow = true;
> +
> + vect_set_loop_condition (loop, LOOP_VINFO_IV_EXIT (loop_vinfo),
> + loop_vinfo, niters_vector, step_vector,
> + niters_vector_mult_vf, !niters_no_overflow);
> + }
>
> unsigned int assumed_vf = vect_vf_for_cost (loop_vinfo);
>
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)