https://gcc.gnu.org/g:0a970b2702183d290df044858fd4df13ef698924
commit r17-4648-g0a970b2702183d290df044858fd4df13ef698924 Author: Richard Biener <[email protected]> Date: Fri Sep 25 09:36:09 2026 +0200 tree-optimization/127588 - avoid UB in epilog IV init computation The following avoids UB when computing the start value of the epilog IV value which we compute as init + step * vect-niters where the step * vect-niters computation can overflow. PR tree-optimization/127588 * tree-vect-loop-manip.cc (vect_update_ivs_after_vectorizer): Use an unsigned type to compute the epilog start value. * gcc.dg/vect/vect-iv-15.c: New testcase. Diff: --- gcc/testsuite/gcc.dg/vect/vect-iv-15.c | 25 +++++++++++++++++++++++++ gcc/tree-vect-loop-manip.cc | 26 ++++++++++++++------------ 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/gcc/testsuite/gcc.dg/vect/vect-iv-15.c b/gcc/testsuite/gcc.dg/vect/vect-iv-15.c new file mode 100644 index 000000000000..912b18be75ff --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-iv-15.c @@ -0,0 +1,25 @@ +/* PR127588 */ +/* { dg-require-effective-target int32plus } */ + +#include "tree-vect.h" + +int s; + +__attribute__((noipa)) +void foo (int init) +{ + s = init; + do { + s += 1074790400; + } while (s <= 1073741823); +} + +int main () +{ + check_vect (); + + foo (-1264552634); + if (s != 1959818566) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc index b54353399d9e..9d22d87705ba 100644 --- a/gcc/tree-vect-loop-manip.cc +++ b/gcc/tree-vect-loop-manip.cc @@ -2612,7 +2612,7 @@ vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo, gsi_next (&gsi), gsi_next (&gsi1)) { tree init_expr; - tree step_expr, off; + tree step_expr; tree type; tree var, ni, ni_name; @@ -2648,17 +2648,19 @@ vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo, if (induction_type == vect_step_op_add) { - tree stype = TREE_TYPE (step_expr); - off = fold_build2 (MULT_EXPR, stype, - fold_convert (stype, niters), step_expr); - - if (POINTER_TYPE_P (type)) - ni = fold_build_pointer_plus (init_expr, off); - else - ni = fold_convert (type, - fold_build2 (PLUS_EXPR, stype, - fold_convert (stype, init_expr), - off)); + /* Use an unsigned type because we compute 'off' without + accounting for 'init_expr', thus the computation might + overflow. Note we can also have FP inductions. */ + tree ctype = (INTEGRAL_TYPE_P (TREE_TYPE (step_expr)) + ? unsigned_type_for (TREE_TYPE (step_expr)) + : TREE_TYPE (step_expr)); + tree off = fold_build2 (MULT_EXPR, ctype, + fold_convert (ctype, niters), + fold_convert (ctype, step_expr)); + ni = fold_convert (type, + fold_build2 (PLUS_EXPR, ctype, + fold_convert (ctype, init_expr), + off)); } /* Don't bother call vect_peel_nonlinear_iv_init. */ else if (induction_type == vect_step_op_neg)
