Changes on V1:
* Add more test case
* Add comment for exit-condition transform
* Removing duplicate setting on niter->control

This patch reset niter->control, niter->bound and niter->cmp in
number_of_iterations_until_wrap.

Bootstrap and test pass on ppc64 and x86, and pass the test cases
in PR.  Is this ok for trunk?

One thing, in this patch, the IVbase is still keep as biasing by 1 step.


BR.
Jiufu Guo

gcc/ChangeLog:

2021-09-02  Jiufu Guo  <guoji...@linux.ibm.com>

        PR tree-optimization/102087
        * tree-ssa-loop-niter.c (number_of_iterations_until_wrap):
        Update bound/cmp/control for niter.

gcc/testsuite/ChangeLog:

2021-09-02  Jiufu Guo  <guoji...@linux.ibm.com>

        PR tree-optimization/102087
        * gcc.dg/pr102087.c: New test.

---
 gcc/tree-ssa-loop-niter.c       | 16 ++++++++++++++-
 gcc/testsuite/gcc.dg/pr102087.c | 35 +++++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr102087.c

diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 7af92d1c893..75109407124 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -1482,7 +1482,7 @@ number_of_iterations_until_wrap (class loop *, tree type, 
affine_iv *iv0,
                                 affine_iv *iv1, class tree_niter_desc *niter)
 {
   tree niter_type = unsigned_type_for (type);
-  tree step, num, assumptions, may_be_zero;
+  tree step, num, assumptions, may_be_zero, span;
   wide_int high, low, max, min;
 
   may_be_zero = fold_build2 (LE_EXPR, boolean_type_node, iv1->base, iv0->base);
@@ -1557,6 +1557,20 @@ number_of_iterations_until_wrap (class loop *, tree 
type, affine_iv *iv0,
 
   niter->control.no_overflow = false;
 
+  /* Update bound and exit condition as:
+     bound = niter * STEP + (IVbase - STEP).
+     { IVbase - STEP, +, STEP } != bound
+     Here, biasing IVbase by 1 step makes 'bound' be the value before wrap.
+     */
+  niter->control.base = fold_build2 (MINUS_EXPR, niter_type,
+                                    niter->control.base, niter->control.step);
+  span = fold_build2 (MULT_EXPR, niter_type, niter->niter,
+                     fold_convert (niter_type, niter->control.step));
+  niter->bound = fold_build2 (PLUS_EXPR, niter_type, span,
+                             fold_convert (niter_type, niter->control.base));
+  niter->bound = fold_convert (type, niter->bound);
+  niter->cmp = NE_EXPR;
+
   return true;
 }
 
diff --git a/gcc/testsuite/gcc.dg/pr102087.c b/gcc/testsuite/gcc.dg/pr102087.c
new file mode 100644
index 00000000000..fc60cbda066
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102087.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+unsigned __attribute__ ((noinline))
+foo (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n)
+{
+  while (n < ++l)
+    *a++ = *b++ + 1;
+  return l;
+}
+
+volatile int a[1];
+unsigned b;
+int c;
+
+int
+check ()
+{
+  int d;
+  for (; b > 1; b++)
+    for (c = 0; c < 2; c++)
+      for (d = 0; d < 2; d++)
+       a[0];
+  return 0;
+}
+
+char **Gif_ClipImage_gfi_0;
+int Gif_ClipImage_y, Gif_ClipImage_shift;
+void
+Gif_ClipImage ()
+{
+  for (; Gif_ClipImage_y >= Gif_ClipImage_shift; Gif_ClipImage_y++)
+    Gif_ClipImage_gfi_0[Gif_ClipImage_shift]
+      = Gif_ClipImage_gfi_0[Gif_ClipImage_y];
+}
-- 
2.17.1

Reply via email to