tree-optimization/98117 - fix range set by vectorization on niter IVs
authorRichard Biener <rguenther@suse.de>
Mon, 7 Dec 2020 09:29:07 +0000 (10:29 +0100)
committerRichard Biener <rguenther@suse.de>
Mon, 7 Dec 2020 11:05:51 +0000 (12:05 +0100)
This avoids the degenerate case of a TYPE_MAX_VALUE latch iteration
count value causing wrong range info for the vector IV.  There's
still the case of VF == 1 where if we don't know whether we hit the
above case we cannot emit a range.

2020-12-07  Richard Biener  <rguenther@suse.de>

PR tree-optimization/98117
* tree-vect-loop-manip.c (vect_gen_vector_loop_niters):
Properly handle degenerate niter when setting the vector
loop IV range.

* gcc.dg/torture/pr98117.c: New testcase.

gcc/testsuite/gcc.dg/torture/pr98117.c [new file with mode: 0644]
gcc/tree-vect-loop-manip.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr98117.c b/gcc/testsuite/gcc.dg/torture/pr98117.c
new file mode 100644 (file)
index 0000000..f216025
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fno-tree-scev-cprop" } */
+
+unsigned char c;
+void __attribute__((noipa))
+e()
+{
+  do
+    {
+    }
+  while (++c);
+}
+int main()
+{
+  e();
+  if (c != 0)
+    __builtin_abort ();
+  return 0;
+}
index 3617918..2370b87 100644 (file)
@@ -2034,13 +2034,29 @@ vect_gen_vector_loop_niters (loop_vec_info loop_vinfo, tree niters,
       niters_vector = force_gimple_operand (niters_vector, &stmts, true, var);
       gsi_insert_seq_on_edge_immediate (pe, stmts);
       /* Peeling algorithm guarantees that vector loop bound is at least ONE,
-        we set range information to make niters analyzer's life easier.  */
+        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 >> log_vf.  */
       if (stmts != NULL && log_vf)
-       set_range_info (niters_vector, VR_RANGE,
-                       wi::to_wide (build_int_cst (type, 1)),
-                       wi::to_wide (fold_build2 (RSHIFT_EXPR, type,
-                                                 TYPE_MAX_VALUE (type),
-                                                 log_vf)));
+       {
+         if (niters_no_overflow)
+           set_range_info (niters_vector, VR_RANGE,
+                           wi::one (TYPE_PRECISION (type)),
+                           wi::rshift (wi::max_value (TYPE_PRECISION (type),
+                                                      TYPE_SIGN (type)),
+                                       exact_log2 (const_vf),
+                                       TYPE_SIGN (type)));
+         /* For VF == 1 the vector IV might also overflow so we cannot
+            assert a minimum value of 1.  */
+         else if (const_vf > 1)
+           set_range_info (niters_vector, VR_RANGE,
+                           wi::one (TYPE_PRECISION (type)),
+                           wi::rshift (wi::max_value (TYPE_PRECISION (type),
+                                                      TYPE_SIGN (type))
+                                       - (const_vf - 1),
+                                       exact_log2 (const_vf), TYPE_SIGN (type))
+                           + 1);
+       }
     }
   *niters_vector_ptr = niters_vector;
   *step_vector_ptr = step_vector;