On Mon, Nov 24, 2025 at 10:24 PM Victor Do Nascimento
<[email protected]> wrote:
>
> Default types:
> --------------
>
> While the primary exit condition for loops is no longer tied to some
> upper limit in the number of executed iterations, similar limits are
> still required for vectorization. One example of this is with prolog
> peeling. The prolog will always have an IV exit associated with the
> misalignment of data accesses within the loop.
>
> Historically, the assumption held that the data-type that this counter
> should have could be derived from the type of the niters limit for the
> original loop, so we could get the type from `TREE_TYPE (niters)'.
>
> Moving forward, we provide a backup type to be used for iteration
> counters when the maximum number of iterations to be run is unknown.
>
> We take this to be `size_t', given its role in storing the maximum
`sizetype' (those need not necessarily be the same), the patch is OK.
> size of a theoretically possible object of any type (including array).
>
> Default return values:
> ----------------------
>
> To avoid having to gate all calls to functions that query a loop's
> niters value it is better to "teach" such functions how to handle
> uncounted loops and have them return a sensible value that can be
> handled upon a function's return.
>
> We therefore prevent functions operating on niters from segfaulting by
> adding a default `SCEV_NOT_KNOWN' return value when niters information
> absent.
>
> gcc/ChangeLog:
>
> * tree-vect-loop-manip.cc (vect_gen_prolog_loop_niters): Add
> type default of `size_t'.
> (vect_gen_vector_loop_niters): Likewise.
> (vect_do_peeling): Likewise.
> * tree-vect-loop.cc (vect_min_prec_for_max_niters): Likewise.
> * tree-vect-loop-manip.cc (vect_build_loop_niters): Gracefully
> handle uncounted loops.
> * tree-vect-loop.cc (loop_niters_no_overflow): Likewise.
> ---
> gcc/tree-vect-loop-manip.cc | 13 ++++++++++---
> gcc/tree-vect-loop.cc | 12 ++++++++++--
> 2 files changed, 20 insertions(+), 5 deletions(-)
>
> diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc
> index 85a733d6408..89532dbb9f2 100644
> --- a/gcc/tree-vect-loop-manip.cc
> +++ b/gcc/tree-vect-loop-manip.cc
> @@ -2511,7 +2511,10 @@ vect_gen_prolog_loop_niters (loop_vec_info loop_vinfo,
> {
> dr_vec_info *dr_info = LOOP_VINFO_UNALIGNED_DR (loop_vinfo);
> tree var;
> - tree niters_type = TREE_TYPE (LOOP_VINFO_NITERS (loop_vinfo));
> + tree niters_type
> + = LOOP_VINFO_NITERS_UNCOUNTED_P (loop_vinfo) ? sizetype
> + : TREE_TYPE
> (LOOP_VINFO_NITERS
> + (loop_vinfo));
> gimple_seq stmts = NULL, new_stmts = NULL;
> tree iters, iters_name;
> stmt_vec_info stmt_info = dr_info->stmt;
> @@ -2690,6 +2693,8 @@ vect_prepare_for_masked_peels (loop_vec_info loop_vinfo)
> tree
> vect_build_loop_niters (loop_vec_info loop_vinfo, bool *new_var_p)
> {
> + if (LOOP_VINFO_NITERS_UNCOUNTED_P (loop_vinfo))
> + return NULL_TREE;
> tree ni = unshare_expr (LOOP_VINFO_NITERS (loop_vinfo));
> if (TREE_CODE (ni) == INTEGER_CST)
> return ni;
> @@ -2791,7 +2796,8 @@ vect_gen_vector_loop_niters (loop_vec_info loop_vinfo,
> tree niters,
> bool niters_no_overflow)
> {
> tree ni_minus_gap, var;
> - tree niters_vector, step_vector, type = TREE_TYPE (niters);
> + tree niters_vector, step_vector;
> + tree type = niters ? TREE_TYPE (niters) : sizetype;
> poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
> edge pe = loop_preheader_edge (LOOP_VINFO_LOOP (loop_vinfo));
>
> @@ -3135,7 +3141,8 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters,
> tree nitersm1,
> tree *advance)
> {
> edge e, guard_e;
> - tree type = TREE_TYPE (niters), guard_cond;
> + tree type = niters ? TREE_TYPE (niters) : sizetype;
> + tree guard_cond;
> basic_block guard_bb, guard_to;
> profile_probability prob_prolog, prob_vector, prob_epilog;
> int estimated_vf;
> diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
> index 6e55252c270..ccd1132c89c 100644
> --- a/gcc/tree-vect-loop.cc
> +++ b/gcc/tree-vect-loop.cc
> @@ -941,7 +941,11 @@ vect_min_prec_for_max_niters (loop_vec_info loop_vinfo,
> unsigned int factor)
>
> /* Get the maximum number of iterations that is representable
> in the counter type. */
> - tree ni_type = TREE_TYPE (LOOP_VINFO_NITERSM1 (loop_vinfo));
> + tree ni_type;
> + if (!LOOP_VINFO_NITERS_UNCOUNTED_P (loop_vinfo))
> + ni_type = TREE_TYPE (LOOP_VINFO_NITERSM1 (loop_vinfo));
> + else
> + ni_type = sizetype;
> widest_int max_ni = wi::to_widest (TYPE_MAX_VALUE (ni_type)) + 1;
>
> /* Get a more refined estimate for the number of iterations. */
> @@ -10491,6 +10495,8 @@ vectorizable_live_operation (vec_info *vinfo,
> stmt_vec_info stmt_info,
> static bool
> loop_niters_no_overflow (loop_vec_info loop_vinfo)
> {
> + gcc_assert (!LOOP_VINFO_NITERS_UNCOUNTED_P (loop_vinfo));
> +
> /* Constant case. */
> if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo))
> {
> @@ -11053,6 +11059,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");
>
> @@ -11114,9 +11121,10 @@ vect_transform_loop (loop_vec_info loop_vinfo,
> gimple *loop_vectorized_call)
> tree niters = vect_build_loop_niters (loop_vinfo);
> LOOP_VINFO_NITERS_UNCHANGED (loop_vinfo) = niters;
> tree nitersm1 = unshare_expr (LOOP_VINFO_NITERSM1 (loop_vinfo));
> - bool niters_no_overflow = loop_niters_no_overflow (loop_vinfo);
> tree advance;
> drs_init_vec orig_drs_init;
> + bool niters_no_overflow = uncounted_p ? false /* Not known. */
> + : loop_niters_no_overflow
> (loop_vinfo);
>
> epilogue = vect_do_peeling (loop_vinfo, niters, nitersm1, &niters_vector,
> &step_vector, &niters_vector_mult_vf, th,
> --
> 2.43.0
>