> -----Original Message-----
> From: Robin Dapp <[email protected]>
> Sent: 07 November 2025 17:31
> To: gcc-patches <[email protected]>
> Cc: Robin Dapp <[email protected]>; Tamar Christina
> <[email protected]>
> Subject: [PATCH] vect: Do not set range for step != 1 [PR121985].
>
> Hi,
>
> In PR120922 we first disabled setting a range on niters_vector for
> partial vectorization and later introduced a ceiling division instead.
>
> In PR121985 we ran into this again where a bogus range caused wrong code
> later. On top I saw several instances of this issue on a local branch
> that enables more VLS length-controlled loops.
>
> I believe we must not set niter_vector's range to TYPE_MAX / VF, no
> matter the rounding due to the way niters_vector is used. It's not
> really identical to the number of vector iterations but the actual
> number the loop will iterate is niters_vector / step where step = VF
> for partial vectors.
If VF is known, I think it's ceil (ni_minus_gap / VF) because the last
iteration is
partial.
The intention was that for most masked loops if VF is constant than we
can determine a maximum to the amount the loop would iterate.
PR120922 should have adjusted niters_vector instead.
I think
if (vf.is_constant (&const_vf)
&& !LOOP_VINFO_USING_PARTIAL_VECTORS_P (loop_vinfo))
Should handle when
if (vf.is_constant (&const_vf)
&& LOOP_VINFO_USING_PARTIAL_VECTORS_P (loop_vinfo)
&& niters_no_overflow
Since the max latch iteration count is known then and the bounds would be
correctly set then.
>
> Thus, only set the range to TYPE_MAX / VF if step == 1.
So I do think the && integer_onep (step_vector) change is correct.
But the ceil division should be moved up since we can still set range for
partial vectors.
Thanks,
Tamar
>
> Bootstrapped and regtested on x86 and power10, regtested on aarch64 and
> riscv64.
>
> Regards
> Robin
>
> gcc/ChangeLog:
>
> PR middle-end/121985
>
> * tree-vect-loop-manip.cc (vect_gen_vector_loop_niters): Only
> set niter_vector's range if step == 1.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.target/riscv/rvv/autovec/pr121985.c: New test.
> ---
> .../gcc.target/riscv/rvv/autovec/pr121985.c | 17 +++++++++++++
> gcc/tree-vect-loop-manip.cc | 25 ++++++-------------
> 2 files changed, 24 insertions(+), 18 deletions(-)
> create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/pr121985.c
>
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr121985.c
> b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr121985.c
> new file mode 100644
> index 00000000000..6e5cdd927b6
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr121985.c
> @@ -0,0 +1,17 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=rv64gcv_zvl512b -mabi=lp64d -mrvv-max-
> lmul=m8" } */
> +
> +unsigned short a=3;
> +char f=1;
> +
> +int main()
> +{
> + for (char var=f; var<6; var++)
> + a *= 5;
> +
> + return a;
> +}
> +
> +/* We would set a wrong niter range that would cause us to extract the
> wrong
> + element. */
> +/* { dg-final { scan-assembler-not "vslidedown.vi.*,0" } } */
> diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc
> index 6af07efe68a..87ad7ee5bca 100644
> --- a/gcc/tree-vect-loop-manip.cc
> +++ b/gcc/tree-vect-loop-manip.cc
> @@ -2850,29 +2850,18 @@ vect_gen_vector_loop_niters (loop_vec_info
> loop_vinfo, tree niters,
> we set range information to make niters analyzer's life easier.
> Note the number of latch iteration value can be TYPE_MAX_VALUE so
> we have to represent the vector niter TYPE_MAX_VALUE + 1 / vf. */
> - if (stmts != NULL && const_vf > 0 && !LOOP_VINFO_EPILOGUE_P
> (loop_vinfo))
> + if (stmts != NULL
> + && integer_onep (step_vector))
> {
> - if (niters_no_overflow
> - && LOOP_VINFO_USING_PARTIAL_VECTORS_P (loop_vinfo))
> - {
> - int_range<1> vr (type,
> - wi::one (TYPE_PRECISION (type)),
> - wi::div_ceil (wi::max_value
> - (TYPE_PRECISION
> (type),
> - TYPE_SIGN (type)),
> - const_vf,
> - TYPE_SIGN (type)));
> - set_range_info (niters_vector, vr);
> - }
> - else if (niters_no_overflow)
> + if (niters_no_overflow)
> {
> int_range<1> vr (type,
> wi::one (TYPE_PRECISION (type)),
> wi::div_trunc (wi::max_value
> - (TYPE_PRECISION
> (type),
> - TYPE_SIGN (type)),
> - const_vf,
> - TYPE_SIGN (type)));
> + (TYPE_PRECISION (type),
> + TYPE_SIGN (type)),
> + const_vf,
> + TYPE_SIGN (type)));
> set_range_info (niters_vector, vr);
> }
> /* For VF == 1 the vector IV might also overflow so we cannot
> --
> 2.51.0
>