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