When transform
  {iv0.base, iv0.step} LT/LE {iv1.base, iv1.step}
to
  {iv0.base, iv0.step - iv1.step} LT/LE {iv1.base, 0}

There would be error if 'iv0.step - iv1.step' in negative,
for which means run until wrap/overflow.

For example:
   {1, +, 1} <= {4, +, 3} => {1, +, -2} <= {4, +, 0}

This patch avoid this kind transform.

Bootstrap and regtest pass on ppc64le.
Is this ok for trunk?

BR.
Jiufu

gcc/ChangeLog:

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

        PR tree-optimization/102131
        * tree-ssa-loop-niter.c (number_of_iterations_cond):
        Avoid transform until wrap condition

gcc/testsuite/ChangeLog:

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

        PR tree-optimization/102131
        * gcc.dg/pr102131.c: New test.

---
 gcc/tree-ssa-loop-niter.c       | 18 +++++++++
 gcc/testsuite/gcc.dg/pr102131.c | 69 +++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/pr102131.c

diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 7af92d1c893..52ce517af89 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -1866,6 +1866,24 @@ number_of_iterations_cond (class loop *loop,
              || !iv0->no_overflow || !iv1->no_overflow))
        return false;
 
+      /* GT/GE has been transformed to LT/LE already.
+       cmp_code could be LT, LE or NE
+
+       For LE/LT transform
+       {iv0.base, iv0.step} LT/LE {iv1.base, iv1.step}
+       to
+       {iv0.base, iv0.step - iv1.step} LT/LE {iv1.base, 0}
+       Negative iv0.step - iv1.step means decreasing until wrap,
+       then the transform is not accurate.
+
+       For example:
+       {1, +, 1} <= {4, +, 3}
+       is not same with
+       {1, +, -2} <= {4, +, 0}
+       */
+      if ((code == LE_EXPR || code == LT_EXPR) && tree_int_cst_sign_bit (step))
+       return false;
+
       iv0->step = step;
       if (!POINTER_TYPE_P (type))
        iv0->no_overflow = false;
diff --git a/gcc/testsuite/gcc.dg/pr102131.c b/gcc/testsuite/gcc.dg/pr102131.c
new file mode 100644
index 00000000000..0fcfaa132da
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102131.c
@@ -0,0 +1,69 @@
+/* { dg-do run } */
+
+unsigned int a;
+int
+fun1 ()
+{
+  unsigned b = 0;
+  int c = 1;
+  for (; b < 3; b++)
+    {
+      while (c < b)
+       __builtin_abort ();
+      for (a = 0; a < 3; a++)
+       c++;
+    }
+  return 0;
+}
+
+unsigned b;
+int
+fun2 ()
+{
+  unsigned c = 0;
+  for (a = 0; a < 2; a++)
+    for (b = 0; b < 2; b++)
+      if (++c < a)
+       __builtin_abort ();
+  return 0;
+}
+
+int
+fun3 (void)
+{
+  unsigned a, b, c = 0;
+  for (a = 0; a < 10; a++)
+    {
+      for (b = 0; b < 2; b++)
+       {
+         c++;
+         if (c < a)
+           {
+             __builtin_abort ();
+           }
+       }
+    }
+  return 0;
+}
+
+int
+fun4 ()
+{
+  unsigned i;
+  for (i = 0; i < 3; ++i)
+    {
+      if (i > i * 2)
+       __builtin_abort ();
+    }
+  return 0;
+}
+
+int
+main ()
+{
+  fun1 ();
+  fun2 ();
+  fun3 ();
+  fun4 ();
+  return 0;
+}
-- 
2.17.1

Reply via email to