]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-ssa-loop-niter.c (tree_simplify_using_condition_1): New parameter.
authorBin Cheng <bin.cheng@arm.com>
Thu, 17 Sep 2015 03:08:41 +0000 (03:08 +0000)
committerBin Cheng <amker@gcc.gnu.org>
Thu, 17 Sep 2015 03:08:41 +0000 (03:08 +0000)
* tree-ssa-loop-niter.c (tree_simplify_using_condition_1): New
parameter.
(tree_simplify_using_condition): Ditto.
(simplify_using_initial_conditions): Ditto.
(loop_exits_before_overflow): Pass new argument to function
simplify_using_initial_conditions.  Remove case for type conversions
simplification.
* tree-ssa-loop-niter.h (simplify_using_initial_conditions): New
parameter.
* tree-scalar-evolution.c (simple_iv): Simplify type conversions
in iv base using loop initial conditions.

gcc/testsuite/ChangeLog
* gcc.dg/tree-ssa/loop-bound-2.c: New test.
* gcc.dg/tree-ssa/loop-bound-4.c: New test.
* gcc.dg/tree-ssa/loop-bound-6.c: New test.

From-SVN: r227843

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/loop-bound-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/loop-bound-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/loop-bound-6.c [new file with mode: 0644]
gcc/tree-scalar-evolution.c
gcc/tree-ssa-loop-niter.c
gcc/tree-ssa-loop-niter.h

index 376b642e8f9c2e1ae71157c03d97c4e4b2598297..435e2791524c1e85a795a63c1d72b0df5bc44d94 100644 (file)
@@ -1,3 +1,17 @@
+2015-09-17  Bin Cheng  <bin.cheng@arm.com>
+
+       * tree-ssa-loop-niter.c (tree_simplify_using_condition_1): New
+       parameter.
+       (tree_simplify_using_condition): Ditto.
+       (simplify_using_initial_conditions): Ditto.
+       (loop_exits_before_overflow): Pass new argument to function
+       simplify_using_initial_conditions.  Remove case for type conversions
+       simplification.
+       * tree-ssa-loop-niter.h (simplify_using_initial_conditions): New
+       parameter.
+       * tree-scalar-evolution.c (simple_iv): Simplify type conversions
+       in iv base using loop initial conditions.
+
 2015-09-16  Jeff Law  <law@redhat.com>
 
        PR tree-optimization/47679
index 14ca461665188a8c2577dc26f34e14f8a2bc5ca8..bea92585038d0cd314a02940c09a05b7016fe952 100644 (file)
@@ -1,3 +1,9 @@
+2015-09-17  Bin Cheng  <bin.cheng@arm.com>
+
+       * gcc.dg/tree-ssa/loop-bound-2.c: New test.
+       * gcc.dg/tree-ssa/loop-bound-4.c: New test.
+       * gcc.dg/tree-ssa/loop-bound-6.c: New test.
+
 2015-09-16  John Marino  <gnugcc@marino.st>
 
        * gfortran.dg/read_dir.f90: XFAIL this testcase on DragonFly.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-bound-2.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-bound-2.c
new file mode 100644 (file)
index 0000000..802dd29
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ivopts-details" } */
+
+int *a;
+
+int
+foo (signed char s, signed char l)
+{
+  signed char i;
+  int sum = 0;
+
+  for (i = s; i < l; i++)
+    {
+      sum += a[i];
+    }
+
+  return sum;
+}
+
+/* Check loop niter bound information.  */
+/* { dg-final { scan-tree-dump "bounded by 254" "ivopts" } } */
+/* { dg-final { scan-tree-dump-not "bounded by 255" "ivopts" } } */
+/* { dg-final { scan-tree-dump-not "zero if " "ivopts" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-bound-4.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-bound-4.c
new file mode 100644 (file)
index 0000000..b9d7d41
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ivopts-details" } */
+
+int *a;
+
+int
+foo (signed char s, signed char l)
+{
+  signed char i;
+  int sum = 0;
+
+  for (i = s; i > l; i--)
+    {
+      sum += a[i];
+    }
+
+  return sum;
+}
+
+/* Check loop niter bound information.  */
+/* { dg-final { scan-tree-dump "bounded by 254" "ivopts" } } */
+/* { dg-final { scan-tree-dump-not "bounded by 255" "ivopts" } } */
+/* { dg-final { scan-tree-dump-not "zero if " "ivopts" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-bound-6.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-bound-6.c
new file mode 100644 (file)
index 0000000..8319434
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ivopts-details" } */
+
+int *a;
+
+int
+foo (signed char s)
+{
+  signed char i;
+  int sum = 0;
+
+  for (i = s; i > 0; i--)
+    {
+      sum += a[i];
+    }
+
+  return sum;
+}
+
+/* Check loop niter bound information.  */
+/* { dg-final { scan-tree-dump "bounded by 126" "ivopts" } } */
+/* { dg-final { scan-tree-dump-not "bounded by 127" "ivopts" } } */
+/* { dg-final { scan-tree-dump-not "zero if " "ivopts" } } */
index 54fe223cf0de78442001b2221cdd1ead87f59014..328846b898c1690e17c468399856e3214dd453bc 100644 (file)
@@ -3234,8 +3234,10 @@ bool
 simple_iv (struct loop *wrto_loop, struct loop *use_loop, tree op,
           affine_iv *iv, bool allow_nonconstant_step)
 {
-  tree type, ev;
-  bool folded_casts;
+  enum tree_code code;
+  tree type, ev, base, e, stop;
+  wide_int extreme;
+  bool folded_casts, overflow;
 
   iv->base = NULL_TREE;
   iv->step = NULL_TREE;
@@ -3276,6 +3278,82 @@ simple_iv (struct loop *wrto_loop, struct loop *use_loop, tree op,
   iv->no_overflow = (!folded_casts && ANY_INTEGRAL_TYPE_P (type)
                     && TYPE_OVERFLOW_UNDEFINED (type));
 
+  /* Try to simplify iv base:
+
+       (signed T) ((unsigned T)base + step) ;; TREE_TYPE (base) == signed T
+        == (signed T)(unsigned T)base + step
+        == base + step
+
+     If we can prove operation (base + step) doesn't overflow or underflow.
+     Specifically, we try to prove below conditions are satisfied:
+
+            base <= UPPER_BOUND (type) - step  ;;step > 0
+            base >= LOWER_BOUND (type) - step  ;;step < 0
+
+     This is done by proving the reverse conditions are false using loop's
+     initial conditions.
+
+     The is necessary to make loop niter, or iv overflow analysis easier
+     for below example:
+
+       int foo (int *a, signed char s, signed char l)
+        {
+          signed char i;
+          for (i = s; i < l; i++)
+            a[i] = 0;
+          return 0;
+         }
+
+     Note variable I is firstly converted to type unsigned char, incremented,
+     then converted back to type signed char.  */
+
+  if (wrto_loop->num != use_loop->num)
+    return true;
+
+  if (!CONVERT_EXPR_P (iv->base) || TREE_CODE (iv->step) != INTEGER_CST)
+    return true;
+
+  type = TREE_TYPE (iv->base);
+  e = TREE_OPERAND (iv->base, 0);
+  if (TREE_CODE (e) != PLUS_EXPR
+      || TREE_CODE (TREE_OPERAND (e, 1)) != INTEGER_CST
+      || !tree_int_cst_equal (iv->step,
+                             fold_convert (type, TREE_OPERAND (e, 1))))
+    return true;
+  e = TREE_OPERAND (e, 0);
+  if (!CONVERT_EXPR_P (e))
+    return true;
+  base = TREE_OPERAND (e, 0);
+  if (!useless_type_conversion_p (type, TREE_TYPE (base)))
+    return true;
+
+  if (tree_int_cst_sign_bit (iv->step))
+    {
+      code = LT_EXPR;
+      extreme = wi::min_value (type);
+    }
+  else
+    {
+      code = GT_EXPR;
+      extreme = wi::max_value (type);
+    }
+  overflow = false;
+  extreme = wi::sub (extreme, iv->step, TYPE_SIGN (type), &overflow);
+  if (overflow)
+    return true;
+  e = fold_build2 (code, boolean_type_node, base,
+                  wide_int_to_tree (type, extreme));
+  stop = (TREE_CODE (base) == SSA_NAME) ? base : NULL;
+  e = simplify_using_initial_conditions (use_loop, e, stop);
+  if (!integer_zerop (e))
+    return true;
+
+  if (POINTER_TYPE_P (TREE_TYPE (base)))
+    code = POINTER_PLUS_EXPR;
+  else
+    code = PLUS_EXPR;
+
+  iv->base = fold_build2 (code, TREE_TYPE (base), base, iv->step);
   return true;
 }
 
index 39d68072240309b4603c2c05e3afc9a860a60c47..0309f4adff668d23b7dbcc719fb86ea0ee3c6714 100644 (file)
@@ -1926,7 +1926,7 @@ expand_simple_operations (tree expr, tree stop)
    expression (or EXPR unchanged, if no simplification was possible).  */
 
 static tree
-tree_simplify_using_condition_1 (tree cond, tree expr)
+tree_simplify_using_condition_1 (tree cond, tree expr, tree stop)
 {
   bool changed;
   tree e, te, e0, e1, e2, notcond;
@@ -1941,17 +1941,17 @@ tree_simplify_using_condition_1 (tree cond, tree expr)
     {
       changed = false;
 
-      e0 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 0));
+      e0 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 0), stop);
       if (TREE_OPERAND (expr, 0) != e0)
        changed = true;
 
-      e1 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 1));
+      e1 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 1), stop);
       if (TREE_OPERAND (expr, 1) != e1)
        changed = true;
 
       if (code == COND_EXPR)
        {
-         e2 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 2));
+         e2 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 2), stop);
          if (TREE_OPERAND (expr, 2) != e2)
            changed = true;
        }
@@ -2014,7 +2014,7 @@ tree_simplify_using_condition_1 (tree cond, tree expr)
        return boolean_true_node;
     }
 
-  te = expand_simple_operations (expr);
+  te = expand_simple_operations (expr, stop);
 
   /* Check whether COND ==> EXPR.  */
   notcond = invert_truthvalue (cond);
@@ -2038,19 +2038,19 @@ tree_simplify_using_condition_1 (tree cond, tree expr)
    the loop do not cause us to fail.  */
 
 static tree
-tree_simplify_using_condition (tree cond, tree expr)
+tree_simplify_using_condition (tree cond, tree expr, tree stop)
 {
-  cond = expand_simple_operations (cond);
+  cond = expand_simple_operations (cond, stop);
 
-  return tree_simplify_using_condition_1 (cond, expr);
+  return tree_simplify_using_condition_1 (cond, expr, stop);
 }
 
 /* Tries to simplify EXPR using the conditions on entry to LOOP.
    Returns the simplified expression (or EXPR unchanged, if no
-   simplification was possible).*/
+   simplification was possible).  */
 
-static tree
-simplify_using_initial_conditions (struct loop *loop, tree expr)
+tree
+simplify_using_initial_conditions (struct loop *loop, tree expr, tree stop)
 {
   edge e;
   basic_block bb;
@@ -2082,7 +2082,7 @@ simplify_using_initial_conditions (struct loop *loop, tree expr)
                          gimple_cond_rhs (stmt));
       if (e->flags & EDGE_FALSE_VALUE)
        cond = invert_truthvalue (cond);
-      expr = tree_simplify_using_condition (cond, expr);
+      expr = tree_simplify_using_condition (cond, expr, stop);
       /* Break if EXPR is simplified to const values.  */
       if (expr && (integer_zerop (expr) || integer_nonzerop (expr)))
        break;
@@ -4114,137 +4114,68 @@ loop_exits_before_overflow (tree base, tree step,
      help of analyzed loop control IV.  This is done only for IVs with
      constant step because otherwise we don't have the information.  */
   if (TREE_CODE (step) == INTEGER_CST)
-    for (civ = loop->control_ivs; civ; civ = civ->next)
-      {
-       enum tree_code code;
-       tree stepped, extreme, civ_type = TREE_TYPE (civ->step);
-
-       /* Have to consider type difference because operand_equal_p ignores
-          that for constants.  */
-       if (TYPE_UNSIGNED (type) != TYPE_UNSIGNED (civ_type)
-           || element_precision (type) != element_precision (civ_type))
-         continue;
-
-       /* Only consider control IV with same step.  */
-       if (!operand_equal_p (step, civ->step, 0))
-         continue;
-
-       /* Done proving if this is a no-overflow control IV.  */
-       if (operand_equal_p (base, civ->base, 0))
-         return true;
-
-       /* If this is a before stepping control IV, in other words, we have
-
-            {civ_base, step} = {base + step, step}
-
-          Because civ {base + step, step} doesn't overflow during loop
-          iterations, {base, step} will not overflow if we can prove the
-          operation "base + step" does not overflow.  Specifically, we try
-          to prove below conditions are satisfied:
-
-            base <= UPPER_BOUND (type) - step  ;;step > 0
-            base >= LOWER_BOUND (type) - step  ;;step < 0
-
-          by proving the reverse conditions are false using loop's initial
-          condition.  */
-       if (POINTER_TYPE_P (TREE_TYPE (base)))
-         code = POINTER_PLUS_EXPR;
-       else
-         code = PLUS_EXPR;
+    {
+      tree stop = (TREE_CODE (base) == SSA_NAME) ? base : NULL;
 
-       stepped = fold_build2 (code, TREE_TYPE (base), base, step);
-       if (operand_equal_p (stepped, civ->base, 0))
-         {
-           if (tree_int_cst_sign_bit (step))
-             {
-               code = LT_EXPR;
-               extreme = lower_bound_in_type (type, type);
-             }
-           else
-             {
-               code = GT_EXPR;
-               extreme = upper_bound_in_type (type, type);
-             }
-           extreme = fold_build2 (MINUS_EXPR, type, extreme, step);
-           e = fold_build2 (code, boolean_type_node, base, extreme);
-           e = simplify_using_initial_conditions (loop, e);
-           if (integer_zerop (e))
-             return true;
+      for (civ = loop->control_ivs; civ; civ = civ->next)
+       {
+         enum tree_code code;
+         tree stepped, extreme, civ_type = TREE_TYPE (civ->step);
 
+         /* Have to consider type difference because operand_equal_p ignores
+            that for constants.  */
+         if (TYPE_UNSIGNED (type) != TYPE_UNSIGNED (civ_type)
+             || element_precision (type) != element_precision (civ_type))
            continue;
-         }
-
-       /* Similar to above, only in this case we have:
-
-            {civ_base, step} = {(signed T)((unsigned T)base + step), step}
-            && TREE_TYPE (civ_base) = signed T.
-
-          We prove that below condition is satisfied:
-
-            (signed T)((unsigned T)base + step)
-              == (signed T)(unsigned T)base + step
-              == base + step
 
-          because of exact the same reason as above.  This also proves
-          there is no overflow in the operation "base + step", thus the
-          induction variable {base, step} during loop iterations.
+         /* Only consider control IV with same step.  */
+         if (!operand_equal_p (step, civ->step, 0))
+           continue;
 
-          This is necessary to handle cases as below:
+         /* Done proving if this is a no-overflow control IV.  */
+         if (operand_equal_p (base, civ->base, 0))
+           return true;
 
-            int foo (int *a, signed char s, signed char l)
-              {
-                signed char i;
-                for (i = s; i < l; i++)
-                  a[i] = 0;
-                return 0;
-              }
+         /* If this is a before stepping control IV, in other words, we have
 
-          The variable I is firstly converted to type unsigned char,
-          incremented, then converted back to type signed char.  */
-       if (!CONVERT_EXPR_P (civ->base) || TREE_TYPE (civ->base) != type)
-         continue;
-       e = TREE_OPERAND (civ->base, 0);
-       if (TREE_CODE (e) != PLUS_EXPR
-           || TREE_CODE (TREE_OPERAND (e, 1)) != INTEGER_CST
-           || !operand_equal_p (step,
-                                fold_convert (type,
-                                              TREE_OPERAND (e, 1)), 0))
-         continue;
-       e = TREE_OPERAND (e, 0);
-       if (!CONVERT_EXPR_P (e) || !operand_equal_p (e, unsigned_base, 0))
-         continue;
-       e = TREE_OPERAND (e, 0);
-       /* It may still be possible to prove no overflow even if condition
-          "operand_equal_p (e, base, 0)" isn't satisfied here, like below
-          example:
+              {civ_base, step} = {base + step, step}
 
-            e             : ssa_var                 ; unsigned long type
-            base          : (int) ssa_var
-            unsigned_base : (unsigned int) ssa_var
+            Because civ {base + step, step} doesn't overflow during loop
+            iterations, {base, step} will not overflow if we can prove the
+            operation "base + step" does not overflow.  Specifically, we try
+            to prove below conditions are satisfied:
 
-          Unfortunately this is a rare case observed during GCC profiled
-          bootstrap.  See PR66638 for more information.
+              base <= UPPER_BOUND (type) - step  ;;step > 0
+              base >= LOWER_BOUND (type) - step  ;;step < 0
 
-          For now, we just skip the possibility.  */
-       if (!operand_equal_p (e, base, 0))
-         continue;
+            by proving the reverse conditions are false using loop's initial
+            condition.  */
+         if (POINTER_TYPE_P (TREE_TYPE (base)))
+           code = POINTER_PLUS_EXPR;
+         else
+           code = PLUS_EXPR;
 
-       if (tree_int_cst_sign_bit (step))
-         {
-           code = LT_EXPR;
-           extreme = lower_bound_in_type (type, type);
-         }
-       else
-         {
-           code = GT_EXPR;
-           extreme = upper_bound_in_type (type, type);
-         }
-       extreme = fold_build2 (MINUS_EXPR, type, extreme, step);
-       e = fold_build2 (code, boolean_type_node, base, extreme);
-       e = simplify_using_initial_conditions (loop, e);
-       if (integer_zerop (e))
-         return true;
-      }
+         stepped = fold_build2 (code, TREE_TYPE (base), base, step);
+         if (operand_equal_p (stepped, civ->base, 0))
+           {
+             if (tree_int_cst_sign_bit (step))
+               {
+                 code = LT_EXPR;
+                 extreme = lower_bound_in_type (type, type);
+               }
+             else
+               {
+                 code = GT_EXPR;
+                 extreme = upper_bound_in_type (type, type);
+               }
+             extreme = fold_build2 (MINUS_EXPR, type, extreme, step);
+             e = fold_build2 (code, boolean_type_node, base, extreme);
+             e = simplify_using_initial_conditions (loop, e, stop);
+             if (integer_zerop (e))
+               return true;
+           }
+        }
+    }
 
   return false;
 }
index 8d4f799c090fd50900ec203a09c61bef8922f352..1442fe965d2a350cdd13f26e56e24c1173ba441b 100644 (file)
@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_TREE_SSA_LOOP_NITER_H
 
 extern tree expand_simple_operations (tree, tree = NULL);
+extern tree simplify_using_initial_conditions (struct loop *,
+                                              tree, tree = NULL);
 extern bool loop_only_exit_p (const struct loop *, const_edge);
 extern bool number_of_iterations_exit (struct loop *, edge,
                                       struct tree_niter_desc *niter, bool,