When the latch execution count is the maximum value of its type then
the number of header executions wraps to zero.  This is a common cause
of wrong-code.  The following fixes one such issue in the generic
loop unroller infrastructure for example exercised by predictive
commoning.  There is no good way to improve the early out for
non-constant niter, so I only bother with constant niter now.

Bootstrapped and tested on x86_64-unkown-linux-gnu.

        PR tree-optimization/128615
        * tree-ssa-loop-manip.cc (determine_exit_conditions): Avoid
        wrapping to zero when computing the header execution count
        when determining an early out.

        * gcc.dg/torture/pr128615.c: New testcase.
---
 gcc/testsuite/gcc.dg/torture/pr128615.c | 23 +++++++++++++++++++++++
 gcc/tree-ssa-loop-manip.cc              |  8 ++++----
 2 files changed, 27 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr128615.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr128615.c 
b/gcc/testsuite/gcc.dg/torture/pr128615.c
new file mode 100644
index 00000000000..c56de96a47d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr128615.c
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+
+int b[1024], x[1024];
+
+__attribute__((noipa)) void
+f (int *__restrict q, const int *__restrict p)
+{
+  unsigned char i = 0;
+  do
+    *q++ = p[0] + p[1] + p[2] + p[3];
+  while (p++, i++ != 255);  /* 256 iterations */
+}
+
+int
+main (void)
+{
+  for (int k = 0; k < 1024; k++)
+    x[k] = -1;
+  f (x, b);
+  if (x[256] != -1)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/tree-ssa-loop-manip.cc b/gcc/tree-ssa-loop-manip.cc
index f1e381e7d17..ab799842540 100644
--- a/gcc/tree-ssa-loop-manip.cc
+++ b/gcc/tree-ssa-loop-manip.cc
@@ -1068,10 +1068,10 @@ determine_exit_conditions (class loop *loop, class 
tree_niter_desc *desc,
   if (integer_nonzerop (cond)
       && integer_zerop (desc->may_be_zero))
     {
-      /* Convert the latch count to an iteration count.  */
-      tree niter = fold_build2 (PLUS_EXPR, type, desc->niter,
-                               build_one_cst (type));
-      if (multiple_of_p (type, niter, build_int_cst (type, factor)))
+      /* When the iteration count is an exact multiple of factor we're done.  
*/
+      if (TREE_CODE (desc->niter) == INTEGER_CST
+         && wi::multiple_of_p (wi::to_widest (desc->niter) + 1,
+                               factor, UNSIGNED))
        return;
     }
 

base-commit: 1600ba65f603ec6e92583ba8aeba5c825cd7c887
-- 
2.51.0

Reply via email to