tree-ssa-loop-ivopts.c (ivopts_data): New field name_expansion_cache.
authorBin Cheng <bin.cheng@arm.com>
Fri, 15 Aug 2014 02:42:33 +0000 (02:42 +0000)
committerBin Cheng <amker@gcc.gnu.org>
Fri, 15 Aug 2014 02:42:33 +0000 (02:42 +0000)
* tree-ssa-loop-ivopts.c (ivopts_data): New field
name_expansion_cache.
(tree_ssa_iv_optimize_init): Initialize name_expansion_cache.
(tree_ssa_iv_optimize_finalize): Free name_expansion_cache.
(strip_wrap_conserving_type_conversions, expr_equal_p): Delete.
(difference_cannot_overflow_p): New parameter.  Use affine
expansion for equality check.
(iv_elimination_compare_lt): Pass new argument.

testsuite/ChangeLog
* gcc.dg/tree-ssa/ivopts-lt-2.c: New test.

From-SVN: r213997

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/ivopts-lt-2.c [new file with mode: 0644]
gcc/tree-ssa-loop-ivopts.c

index 88196b2..f1b1733 100644 (file)
@@ -1,3 +1,14 @@
+2014-08-15  Bin Cheng  <bin.cheng@arm.com>
+
+       * tree-ssa-loop-ivopts.c (ivopts_data): New field
+       name_expansion_cache.
+       (tree_ssa_iv_optimize_init): Initialize name_expansion_cache.
+       (tree_ssa_iv_optimize_finalize): Free name_expansion_cache.
+       (strip_wrap_conserving_type_conversions, expr_equal_p): Delete.
+       (difference_cannot_overflow_p): New parameter.  Use affine
+       expansion for equality check.
+       (iv_elimination_compare_lt): Pass new argument.
+
 2014-08-14  DJ Delorie  <dj@redhat.com>
 
        * config/rl78/rl78-expand.md (umulqihi3): Disable for G10.
index 73a6ab8..a552147 100644 (file)
@@ -1,3 +1,7 @@
+2014-08-15  Bin Cheng  <bin.cheng@arm.com>
+
+       * gcc.dg/tree-ssa/ivopts-lt-2.c: New test.
+
 2014-08-14  Jan Hubicka  <hubicka@ucw.cz>
 
        PR tree-optimization/62091
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopts-lt-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopts-lt-2.c
new file mode 100644 (file)
index 0000000..177e068
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ivopts" } */
+
+void
+f1 (int *p, unsigned int i)
+{
+  p += i;
+  do
+    {
+      *p = 0;
+      p += 1;
+      i++;
+    }
+  while (i < 100);
+}
+
+/* { dg-final { scan-tree-dump-times "PHI" 1 "ivopts" } } */
+/* { dg-final { scan-tree-dump-times "PHI <p_" 1 "ivopts"} } */
+/* { dg-final { scan-tree-dump-times "p_\[0-9\]* <" 1 "ivopts" } } */
+/* { dg-final { cleanup-tree-dump "ivopts" } } */
index 98b60ab..8f5ecbc 100644 (file)
@@ -323,6 +323,9 @@ struct ivopts_data
   /* A bitmap of important candidates.  */
   bitmap important_candidates;
 
+  /* Cache used by tree_to_aff_combination_expand.  */
+  hash_map<tree, name_expansion *> *name_expansion_cache;
+
   /* The maximum invariant id.  */
   unsigned max_inv_id;
 
@@ -876,6 +879,7 @@ tree_ssa_iv_optimize_init (struct ivopts_data *data)
   data->iv_candidates.create (20);
   data->inv_expr_tab = new hash_table<iv_inv_expr_hasher> (10);
   data->inv_expr_id = 0;
+  data->name_expansion_cache = NULL;
   decl_rtl_to_reset.create (20);
 }
 
@@ -4462,75 +4466,20 @@ iv_elimination_compare (struct ivopts_data *data, struct iv_use *use)
   return (exit->flags & EDGE_TRUE_VALUE ? EQ_EXPR : NE_EXPR);
 }
 
-static tree
-strip_wrap_conserving_type_conversions (tree exp)
-{
-  while (tree_ssa_useless_type_conversion (exp)
-        && (nowrap_type_p (TREE_TYPE (exp))
-            == nowrap_type_p (TREE_TYPE (TREE_OPERAND (exp, 0)))))
-    exp = TREE_OPERAND (exp, 0);
-  return exp;
-}
-
-/* Walk the SSA form and check whether E == WHAT.  Fairly simplistic, we
-   check for an exact match.  */
-
-static bool
-expr_equal_p (tree e, tree what)
-{
-  gimple stmt;
-  enum tree_code code;
-
-  e = strip_wrap_conserving_type_conversions (e);
-  what = strip_wrap_conserving_type_conversions (what);
-
-  code = TREE_CODE (what);
-  if (TREE_TYPE (e) != TREE_TYPE (what))
-    return false;
-
-  if (operand_equal_p (e, what, 0))
-    return true;
-
-  if (TREE_CODE (e) != SSA_NAME)
-    return false;
-
-  stmt = SSA_NAME_DEF_STMT (e);
-  if (gimple_code (stmt) != GIMPLE_ASSIGN
-      || gimple_assign_rhs_code (stmt) != code)
-    return false;
-
-  switch (get_gimple_rhs_class (code))
-    {
-    case GIMPLE_BINARY_RHS:
-      if (!expr_equal_p (gimple_assign_rhs2 (stmt), TREE_OPERAND (what, 1)))
-       return false;
-      /* Fallthru.  */
-
-    case GIMPLE_UNARY_RHS:
-    case GIMPLE_SINGLE_RHS:
-      return expr_equal_p (gimple_assign_rhs1 (stmt), TREE_OPERAND (what, 0));
-    default:
-      return false;
-    }
-}
-
 /* Returns true if we can prove that BASE - OFFSET does not overflow.  For now,
    we only detect the situation that BASE = SOMETHING + OFFSET, where the
    calculation is performed in non-wrapping type.
 
    TODO: More generally, we could test for the situation that
         BASE = SOMETHING + OFFSET' and OFFSET is between OFFSET' and zero.
-        This would require knowing the sign of OFFSET.
-
-        Also, we only look for the first addition in the computation of BASE.
-        More complex analysis would be better, but introducing it just for
-        this optimization seems like an overkill.  */
+        This would require knowing the sign of OFFSET.  */
 
 static bool
-difference_cannot_overflow_p (tree base, tree offset)
+difference_cannot_overflow_p (struct ivopts_data *data, tree base, tree offset)
 {
   enum tree_code code;
   tree e1, e2;
+  aff_tree aff_e1, aff_e2, aff_offset;
 
   if (!nowrap_type_p (TREE_TYPE (base)))
     return false;
@@ -4560,13 +4509,27 @@ difference_cannot_overflow_p (tree base, tree offset)
       e2 = TREE_OPERAND (base, 1);
     }
 
-  /* TODO: deeper inspection may be necessary to prove the equality.  */
+  /* Use affine expansion as deeper inspection to prove the equality.  */
+  tree_to_aff_combination_expand (e2, TREE_TYPE (e2),
+                                 &aff_e2, &data->name_expansion_cache);
+  tree_to_aff_combination_expand (offset, TREE_TYPE (offset),
+                                 &aff_offset, &data->name_expansion_cache);
+  aff_combination_scale (&aff_offset, -1);
   switch (code)
     {
     case PLUS_EXPR:
-      return expr_equal_p (e1, offset) || expr_equal_p (e2, offset);
+      aff_combination_add (&aff_e2, &aff_offset);
+      if (aff_combination_zero_p (&aff_e2))
+       return true;
+
+      tree_to_aff_combination_expand (e1, TREE_TYPE (e1),
+                                     &aff_e1, &data->name_expansion_cache);
+      aff_combination_add (&aff_e1, &aff_offset);
+      return aff_combination_zero_p (&aff_e1);
+
     case POINTER_PLUS_EXPR:
-      return expr_equal_p (e2, offset);
+      aff_combination_add (&aff_e2, &aff_offset);
+      return aff_combination_zero_p (&aff_e2);
 
     default:
       return false;
@@ -4690,7 +4653,7 @@ iv_elimination_compare_lt (struct ivopts_data *data,
   offset = fold_build2 (MULT_EXPR, TREE_TYPE (cand->iv->step),
                        cand->iv->step,
                        fold_convert (TREE_TYPE (cand->iv->step), a));
-  if (!difference_cannot_overflow_p (cand->iv->base, offset))
+  if (!difference_cannot_overflow_p (data, cand->iv->base, offset))
     return false;
 
   /* Determine the new comparison operator.  */
@@ -6815,6 +6778,7 @@ tree_ssa_iv_optimize_finalize (struct ivopts_data *data)
   data->iv_candidates.release ();
   delete data->inv_expr_tab;
   data->inv_expr_tab = NULL;
+  free_affine_expand_cache (&data->name_expansion_cache);
 }
 
 /* Returns true if the loop body BODY includes any function calls.  */