On Mon, 10 Nov 2025, Victor Do Nascimento wrote:

> At present we reject uncounted loops outright when doing initial loop
> analysis in `vect_analyze_loop_form'.
> 
> We have the following gating condition that causes rejection of a
> given loop:
> 
>  if (integer_zerop (info->assumptions)
>       || !info->number_of_iterations
>       || chrec_contains_undetermined (info->number_of_iterations))
> 
> We can do away with this check altogether, but not without problems,
> allowing many malformed loops through which ought to be rejected as
> early as possible.
> 
> We observe that a common thread running through these malformed loops
> is the absence of any scalar evolution between iterations.
> 
> We have therefore adjusted the analysis replacing the checks on
> `niters' for a test for the presence of scalar evolution in the loop,
> which can be detected via the presence of phi nodes in the loop.
> 
> - Detecting uncounted loops going forward:
> 
> Given that scalar evolution analysis of uncounted loops sets
> `loop_vec_info->num_iters' to `SCEV_NOT_KNOWN', 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)'.
> 
> gcc/ChangeLog:
> 
>       * tree-vect-loop.cc (vect_analyze_loop_form): Relax niters
>       condition.
>       * tree-vectorizer.h (LOOP_VINFO_NITERS_UNCOUNTED_P): New.
> ---
>  gcc/tree-vect-loop.cc | 21 ++++++++++++++-------
>  gcc/tree-vectorizer.h |  2 ++
>  2 files changed, 16 insertions(+), 7 deletions(-)
> 
> diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
> index 576a69c82d2..b317386dc18 100644
> --- a/gcc/tree-vect-loop.cc
> +++ b/gcc/tree-vect-loop.cc
> @@ -1470,6 +1470,20 @@ vect_analyze_loop_form (class loop *loop, gimple 
> *loop_vectorized_call,
>                                      "not vectorized:"
>                                      " unsupported control flow in loop.\n");
>        }
> +
> +  /* Check if we have any control flow that doesn't leave the loop.  */
> +  bool has_phi = false;
> +  for (unsigned i = 0; i < loop->num_nodes; i++)
> +    if (!gimple_seq_empty_p (phi_nodes (bbs[i])))
> +      {
> +     has_phi = true;
> +     break;
> +      }
> +  if (!has_phi)
> +    return opt_result::failure_at (vect_location,
> +                                "not vectorized:"
> +                                " no scalar evolution detected in loop.\n");
> +
>    free (bbs);
>  
>    /* Different restrictions apply when we are considering an inner-most loop,
> @@ -1594,13 +1608,6 @@ vect_analyze_loop_form (class loop *loop, gimple 
> *loop_vectorized_call,
>       std::swap (info->conds[0], info->conds[i]);
>      }
>  
> -  if (integer_zerop (info->assumptions)
> -      || !info->number_of_iterations
> -      || chrec_contains_undetermined (info->number_of_iterations))
> -    return opt_result::failure_at
> -      (info->conds[0],
> -       "not vectorized: number of iterations cannot be computed.\n");
> -
>    if (integer_zerop (info->number_of_iterations))

I think the checks on assumptions this last one should be in a

   if (! chrec_contains_undetermined (info->number_of_iterations))

section.  When the IV is counted and we have to assume 'false' we do
not want to vectorize this - I don't think we want to fall back to
treating the loop as uncounted in this case.  So, can you
refactor this to simply early exit from the function for 
chrec_contains_undetermined (info->number_of_iterations), eliding
the following checks that only make sense for counted loops?

It might be helpful to dump that the loop is considered uncounted
in this case.

>      return opt_result::failure_at
>        (info->conds[0],
> diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
> index b7f3297a16b..bbc2e0df01d 100644
> --- a/gcc/tree-vectorizer.h
> +++ b/gcc/tree-vectorizer.h
> @@ -1259,6 +1259,8 @@ public:
>  /* Since LOOP_VINFO_NITERS and LOOP_VINFO_NITERSM1 can change after
>     prologue peeling retain total unchanged scalar loop iterations for
>     cost model.  */
> +#define LOOP_VINFO_NITERS_UNCOUNTED_P(L)   (TREE_CODE (LOOP_VINFO_NITERS 
> (L)) \
> +                                         == SCEV_NOT_KNOWN)

LOOP_VINFO_NITERS (L) == chrec_dont_know is cheaper.

Otherwise looks OK to me, but nothing to push early.

Thanks,
Richard.

>  #define LOOP_VINFO_NITERS_UNCHANGED(L)     (L)->num_iters_unchanged
>  #define LOOP_VINFO_NITERS_ASSUMPTIONS(L)   (L)->num_iters_assumptions
>  #define LOOP_VINFO_COST_MODEL_THRESHOLD(L) (L)->th
> 

-- 
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)

Reply via email to