re PR tree-optimization/91137 (Wrong code with -O3)
authorBin Cheng <bin.cheng@linux.alibaba.com>
Thu, 18 Jul 2019 08:38:09 +0000 (08:38 +0000)
committerBin Cheng <amker@gcc.gnu.org>
Thu, 18 Jul 2019 08:38:09 +0000 (08:38 +0000)
        PR tree-optimization/91137
        * tree-ssa-loop-ivopts.c (struct ivopts_data): New field.
        (tree_ssa_iv_optimize_init, alloc_iv, tree_ssa_iv_optimize_finalize):
        Init, use and fini the above new field.
        (determine_base_object_1): New function.
        (determine_base_object): Reimplement using walk_tree.

gcc/testsuite
        PR tree-optimization/91137
        * gcc.c-torture/execute/pr91137.c: New test.

From-SVN: r273570

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr91137.c [new file with mode: 0644]
gcc/tree-ssa-loop-ivopts.c

index b545a034e57db48c68935ea0568704643561b5d2..e7ba87ac2e3e4366d45bb42c53513c41aaf2546a 100644 (file)
@@ -1,3 +1,12 @@
+2019-07-18  Bin Cheng  <bin.linux@linux.alibaba.com>
+
+       PR tree-optimization/91137
+       * tree-ssa-loop-ivopts.c (struct ivopts_data): New field.
+       (tree_ssa_iv_optimize_init, alloc_iv, tree_ssa_iv_optimize_finalize):
+       Init, use and fini the above new field.
+       (determine_base_object_1): New function.
+       (determine_base_object): Reimplement using walk_tree.
+
 2019-07-18  Richard Sandiford  <richard.sandiford@arm.com>
 
        * basic-block.h (CLEANUP_FORCE_FAST_DCE): New macro.
index f9f17893295d26ebdbfa7f368dcb2e78b66576c0..0bbbd8ad1b7e2b81815d78fec2f6a0d108dbc5fe 100644 (file)
@@ -1,3 +1,8 @@
+2019-07-18  Bin Cheng  <bin.linux@linux.alibaba.com>
+
+       PR tree-optimization/91137
+       * gcc.c-torture/execute/pr91137.c: New test.
+
 2019-07-18  Richard Sandiford  <richard.sandiford@arm.com>
 
        * c-c++-common/pr53633-2.c: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr91137.c b/gcc/testsuite/gcc.c-torture/execute/pr91137.c
new file mode 100644 (file)
index 0000000..aa6bb6c
--- /dev/null
@@ -0,0 +1,34 @@
+long long a;
+unsigned b;
+int c[70];
+int d[70][70];
+int e;
+
+__attribute__ ((noinline)) void f(long long *g, int p2) {
+  *g = p2;
+}
+
+__attribute__ ((noinline)) void fn2() {
+  for (int j = 0; j < 70; j++) {
+    for (int i = 0; i < 70; i++) {
+      if (b)
+        c[i] = 0;
+      for (int l = 0; l < 70; l++)
+        d[i][1] = d[l][i];
+    }
+    for (int k = 0; k < 70; k++)
+      e = c[0];
+  }
+}
+
+int main() {
+  b = 5;
+  for (int j = 0; j < 70; ++j)
+    c[j] = 2075593088;
+  fn2();
+  f(&a, e);
+  if (a)
+    __builtin_abort();
+  return 0;
+}
+
index fd5e99b3886e98588b5eb97149a531a0ef73c534..43ba4295d5721ef81fb9b117e4e4bec79837b5b9 100644 (file)
@@ -591,6 +591,9 @@ struct ivopts_data
   /* The common candidates.  */
   vec<iv_common_cand *> iv_common_cands;
 
+  /* Hash map recording base object information of tree exp.  */
+  hash_map<tree, tree> *base_object_map;
+
   /* The maximum invariant variable id.  */
   unsigned max_inv_var_id;
 
@@ -1043,61 +1046,68 @@ tree_ssa_iv_optimize_init (struct ivopts_data *data)
   data->vcands.create (20);
   data->inv_expr_tab = new hash_table<iv_inv_expr_hasher> (10);
   data->name_expansion_cache = NULL;
+  data->base_object_map = NULL;
   data->iv_common_cand_tab = new hash_table<iv_common_cand_hasher> (10);
   data->iv_common_cands.create (20);
   decl_rtl_to_reset.create (20);
   gcc_obstack_init (&data->iv_obstack);
 }
 
-/* Returns a memory object to that EXPR points.  In case we are able to
-   determine that it does not point to any such object, NULL is returned.  */
+/* walk_tree callback for determine_base_object.  */
 
 static tree
-determine_base_object (tree expr)
+determine_base_object_1 (tree *tp, int *walk_subtrees, void *wdata)
 {
-  enum tree_code code = TREE_CODE (expr);
-  tree base, obj;
-
-  /* If this is a pointer casted to any type, we need to determine
-     the base object for the pointer; so handle conversions before
-     throwing away non-pointer expressions.  */
-  if (CONVERT_EXPR_P (expr))
-    return determine_base_object (TREE_OPERAND (expr, 0));
-
-  if (!POINTER_TYPE_P (TREE_TYPE (expr)))
-    return NULL_TREE;
-
-  switch (code)
+  tree_code code = TREE_CODE (*tp);
+  tree obj = NULL_TREE;
+  if (code == ADDR_EXPR)
     {
-    case INTEGER_CST:
-      return NULL_TREE;
-
-    case ADDR_EXPR:
-      obj = TREE_OPERAND (expr, 0);
-      base = get_base_address (obj);
-
+      tree base = get_base_address (TREE_OPERAND (*tp, 0));
       if (!base)
-       return expr;
-
-      if (TREE_CODE (base) == MEM_REF)
-       return determine_base_object (TREE_OPERAND (base, 0));
+       obj = *tp;
+      else if (TREE_CODE (base) != MEM_REF)
+       obj = fold_convert (ptr_type_node, build_fold_addr_expr (base));
+    }
+  else if (code == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (*tp)))
+       obj = fold_convert (ptr_type_node, *tp);
 
-      return fold_convert (ptr_type_node,
-                          build_fold_addr_expr (base));
+  if (!obj)
+    {
+      if (!EXPR_P (*tp))
+       *walk_subtrees = 0;
 
-    case POINTER_PLUS_EXPR:
-      return determine_base_object (TREE_OPERAND (expr, 0));
+      return NULL_TREE;
+    }
+  /* Record special node for multiple base objects and stop.  */
+  if (*static_cast<tree *> (wdata))
+    {
+      *static_cast<tree *> (wdata) = integer_zero_node;
+      return integer_zero_node;
+    }
+  /* Record the base object and continue looking.  */
+  *static_cast<tree *> (wdata) = obj;
+  return NULL_TREE;
+}
 
-    case PLUS_EXPR:
-    case MINUS_EXPR:
-      /* Pointer addition is done solely using POINTER_PLUS_EXPR.  */
-      gcc_unreachable ();
+/* Returns a memory object to that EXPR points with caching.  Return NULL if we
+   are able to determine that it does not point to any such object; specially
+   return integer_zero_node if EXPR contains multiple base objects.  */
 
-    default:
-      if (POLY_INT_CST_P (expr))
-       return NULL_TREE;
-      return fold_convert (ptr_type_node, expr);
+static tree
+determine_base_object (struct ivopts_data *data, tree expr)
+{
+  tree *slot, obj = NULL_TREE;
+  if (data->base_object_map)
+    {
+      if ((slot = data->base_object_map->get(expr)) != NULL)
+       return *slot;
     }
+  else
+    data->base_object_map = new hash_map<tree, tree>;
+
+  (void) walk_tree_without_duplicates (&expr, determine_base_object_1, &obj);
+  data->base_object_map->put (expr, obj);
+  return obj;
 }
 
 /* Return true if address expression with non-DECL_P operand appears
@@ -1155,7 +1165,7 @@ alloc_iv (struct ivopts_data *data, tree base, tree step,
     }
 
   iv->base = base;
-  iv->base_object = determine_base_object (base);
+  iv->base_object = determine_base_object (data, base);
   iv->step = step;
   iv->biv_p = false;
   iv->nonlin_use = NULL;
@@ -7527,6 +7537,8 @@ tree_ssa_iv_optimize_finalize (struct ivopts_data *data)
   delete data->inv_expr_tab;
   data->inv_expr_tab = NULL;
   free_affine_expand_cache (&data->name_expansion_cache);
+  if (data->base_object_map)
+    delete data->base_object_map;
   delete data->iv_common_cand_tab;
   data->iv_common_cand_tab = NULL;
   data->iv_common_cands.release ();