https://gcc.gnu.org/g:a98b6cf01ba9fb69450a5e883c5d8e8600e2cc95
commit r16-5118-ga98b6cf01ba9fb69450a5e883c5d8e8600e2cc95 Author: Robin Dapp <[email protected]> Date: Fri Nov 7 15:54:52 2025 +0100 vect: Do not set range for step != 1 [PR121985]. 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. Thus, only set the range to TYPE_MAX / VF if step == 1. 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. Diff: --- .../gcc.target/riscv/rvv/autovec/pr121985.c | 17 +++++++++++ gcc/tree-vect-loop-manip.cc | 34 ++++++++++------------ 2 files changed, 32 insertions(+), 19 deletions(-) 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 000000000000..6e5cdd927b61 --- /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 6af07efe68ac..3e121a96ddf0 100644 --- a/gcc/tree-vect-loop-manip.cc +++ b/gcc/tree-vect-loop-manip.cc @@ -2776,7 +2776,14 @@ vect_gen_scalar_loop_niters (tree niters_prolog, int int_niters_prolog, In both cases, store niters_vector in *NITERS_VECTOR_PTR and add any new statements on the loop preheader edge. NITERS_NO_OVERFLOW - is true if NITERS doesn't overflow (i.e. if NITERS is always nonzero). */ + is true if NITERS doesn't overflow (i.e. if NITERS is always nonzero). + + Case (a) is used for LOOP_VINFO_USING_PARTIAL_VECTORS_P or if VF is + variable. As stated above, NITERS_VECTOR then equals the number + of scalar iterations and vect_set_loop_condition will handle the + step. As opposed to (b) we don't know anything about NITER_VECTOR's + range here. +*/ void vect_gen_vector_loop_niters (loop_vec_info loop_vinfo, tree niters, @@ -2850,29 +2857,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
