https://gcc.gnu.org/g:f864411bb9dd5113735c3d5d46de4b0ea454ab0a
commit r16-6124-gf864411bb9dd5113735c3d5d46de4b0ea454ab0a Author: Victor Do Nascimento <[email protected]> Date: Mon Sep 22 17:52:11 2025 +0100 vect: Add default types & retvals for uncounted loops Detecting uncounted loops: -------------------------- Given that scalar evolution analysis of uncounted loops sets `loop_vec_info->num_iters' to `chrec_dont_know', we use this as the criterion for probing whether a loop is uncounted or not. Consequently, we introduce a new access function on `loop_vec_info' to conveniently test whether a loop in question is uncounted or not, in the form of `LOOP_VINFO_NITERS_UNCOUNTED_P(L)'. 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 `sizetype', given its role in storing the maximum 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_build_loop_niters): Gracefully handle uncounted loops. (vect_gen_prolog_loop_niters): Add type default of `sizetype'. (vect_gen_vector_loop_niters): Likewise. (vect_do_peeling): Likewise. * tree-vect-loop.cc (vect_min_prec_for_max_niters): Likewise. (loop_niters_no_overflow): Likewise. * tree-vectorizer.h (LOOP_VINFO_NITERS_UNCOUNTED_P): New. Diff: --- gcc/tree-vect-loop-manip.cc | 13 ++++++++++--- gcc/tree-vect-loop.cc | 12 ++++++++++-- gcc/tree-vectorizer.h | 2 ++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc index c6d8b05b617f..bf60628a2896 100644 --- a/gcc/tree-vect-loop-manip.cc +++ b/gcc/tree-vect-loop-manip.cc @@ -2550,7 +2550,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; @@ -2729,6 +2732,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; @@ -2830,7 +2835,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)); @@ -3174,7 +3180,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 f9dd88ed8246..eb89d8e6ebe8 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -923,7 +923,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. */ @@ -10399,6 +10403,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)) { @@ -11056,6 +11062,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"); @@ -11117,9 +11124,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, diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 563a69ffd93b..5b68c3b46fe0 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -1263,6 +1263,8 @@ public: #define LOOP_VINFO_NBBS(L) (L)->nbbs #define LOOP_VINFO_NITERSM1(L) (L)->num_itersm1 #define LOOP_VINFO_NITERS(L) (L)->num_iters +#define LOOP_VINFO_NITERS_UNCOUNTED_P(L) (LOOP_VINFO_NITERS (L) \ + == chrec_dont_know) /* Since LOOP_VINFO_NITERS and LOOP_VINFO_NITERSM1 can change after prologue peeling retain total unchanged scalar loop iterations for cost model. */
