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.

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

        PR tree-optimization/127588
        * tree-vect-loop-mainp.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.
---
 gcc/testsuite/gcc.dg/vect/vect-iv-15.c | 25 +++++++++++++++++++++++++
 gcc/tree-vect-loop-manip.cc            | 26 ++++++++++++++------------
 2 files changed, 39 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/vect/vect-iv-15.c

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 00000000000..912b18be75f
--- /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 b54353399d9..9d22d87705b 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)
-- 
2.51.0

Reply via email to