re PR tree-optimization/91178 (Infinite recursion in split_constant_offset in slp...
authorRichard Biener <rguenther@suse.de>
Wed, 31 Jul 2019 09:46:18 +0000 (09:46 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 31 Jul 2019 09:46:18 +0000 (09:46 +0000)
2019-07-31  Richard Biener  <rguenther@suse.de>

PR tree-optimization/91178
* tree-ssa-sccvn.c (vn_reference_maybe_forwprop_address):
Use tail-recursion.

* gcc.dg/torture/pr91178-2.c: New testcase.

From-SVN: r273928

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr91178-2.c [new file with mode: 0644]
gcc/tree-ssa-sccvn.c

index c0b86881f4afc49d6dab7837068687c3f7ab124c..c7b99f2ef26655e9473897fae8733e22b475ea14 100644 (file)
@@ -1,3 +1,9 @@
+2019-07-31  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/91178
+       * tree-ssa-sccvn.c (vn_reference_maybe_forwprop_address):
+       Use tail-recursion.
+
 2019-07-31  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/91201
index e09f3bf4e50093fbf0c85abc30ac9f56ad64aef5..44166d1385eff280e33c47636818fbb57e548a6e 100644 (file)
@@ -1,3 +1,8 @@
+2019-07-31  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/91178
+       * gcc.dg/torture/pr91178-2.c: New testcase.
+
 2019-07-31  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/91201
diff --git a/gcc/testsuite/gcc.dg/torture/pr91178-2.c b/gcc/testsuite/gcc.dg/torture/pr91178-2.c
new file mode 100644 (file)
index 0000000..0ebb470
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+
+int a[100][70304];
+int b[100];
+void c()
+{
+  for (int d = 2; d < 4; d++)
+    for (int e = 2; e <= 50; e++)
+      for (int f = 32; f <= 38; f++)
+       b[d + f] -= a[e][5];
+}
index 23f7400f2e9201929093750e04b60d1597297e88..eb7e4be09e699783173f37b0504dbc733a05ea9c 100644 (file)
@@ -1249,113 +1249,123 @@ static bool
 vn_reference_maybe_forwprop_address (vec<vn_reference_op_s> *ops,
                                     unsigned int *i_p)
 {
-  unsigned int i = *i_p;
-  vn_reference_op_t op = &(*ops)[i];
-  vn_reference_op_t mem_op = &(*ops)[i - 1];
-  gimple *def_stmt;
-  enum tree_code code;
-  poly_offset_int off;
-
-  def_stmt = SSA_NAME_DEF_STMT (op->op0);
-  if (!is_gimple_assign (def_stmt))
-    return false;
-
-  code = gimple_assign_rhs_code (def_stmt);
-  if (code != ADDR_EXPR
-      && code != POINTER_PLUS_EXPR)
-    return false;
-
-  off = poly_offset_int::from (wi::to_poly_wide (mem_op->op0), SIGNED);
+  bool changed = false;
+  vn_reference_op_t op;
 
-  /* The only thing we have to do is from &OBJ.foo.bar add the offset
-     from .foo.bar to the preceding MEM_REF offset and replace the
-     address with &OBJ.  */
-  if (code == ADDR_EXPR)
+  do
     {
-      tree addr, addr_base;
-      poly_int64 addr_offset;
-
-      addr = gimple_assign_rhs1 (def_stmt);
-      addr_base = get_addr_base_and_unit_offset (TREE_OPERAND (addr, 0),
-                                                &addr_offset);
-      /* If that didn't work because the address isn't invariant propagate
-         the reference tree from the address operation in case the current
-        dereference isn't offsetted.  */
-      if (!addr_base
-         && *i_p == ops->length () - 1
-         && known_eq (off, 0)
-         /* This makes us disable this transform for PRE where the
-            reference ops might be also used for code insertion which
-            is invalid.  */
-         && default_vn_walk_kind == VN_WALKREWRITE)
+      unsigned int i = *i_p;
+      op = &(*ops)[i];
+      vn_reference_op_t mem_op = &(*ops)[i - 1];
+      gimple *def_stmt;
+      enum tree_code code;
+      poly_offset_int off;
+
+      def_stmt = SSA_NAME_DEF_STMT (op->op0);
+      if (!is_gimple_assign (def_stmt))
+       return changed;
+
+      code = gimple_assign_rhs_code (def_stmt);
+      if (code != ADDR_EXPR
+         && code != POINTER_PLUS_EXPR)
+       return changed;
+
+      off = poly_offset_int::from (wi::to_poly_wide (mem_op->op0), SIGNED);
+
+      /* The only thing we have to do is from &OBJ.foo.bar add the offset
+        from .foo.bar to the preceding MEM_REF offset and replace the
+        address with &OBJ.  */
+      if (code == ADDR_EXPR)
        {
-         auto_vec<vn_reference_op_s, 32> tem;
-         copy_reference_ops_from_ref (TREE_OPERAND (addr, 0), &tem);
-         /* Make sure to preserve TBAA info.  The only objects not
-            wrapped in MEM_REFs that can have their address taken are
-            STRING_CSTs.  */
-         if (tem.length () >= 2
-             && tem[tem.length () - 2].opcode == MEM_REF)
+         tree addr, addr_base;
+         poly_int64 addr_offset;
+
+         addr = gimple_assign_rhs1 (def_stmt);
+         addr_base = get_addr_base_and_unit_offset (TREE_OPERAND (addr, 0),
+                                                    &addr_offset);
+         /* If that didn't work because the address isn't invariant propagate
+            the reference tree from the address operation in case the current
+            dereference isn't offsetted.  */
+         if (!addr_base
+             && *i_p == ops->length () - 1
+             && known_eq (off, 0)
+             /* This makes us disable this transform for PRE where the
+                reference ops might be also used for code insertion which
+                is invalid.  */
+             && default_vn_walk_kind == VN_WALKREWRITE)
            {
-             vn_reference_op_t new_mem_op = &tem[tem.length () - 2];
-             new_mem_op->op0
-               = wide_int_to_tree (TREE_TYPE (mem_op->op0),
-                                   wi::to_poly_wide (new_mem_op->op0));
+             auto_vec<vn_reference_op_s, 32> tem;
+             copy_reference_ops_from_ref (TREE_OPERAND (addr, 0), &tem);
+             /* Make sure to preserve TBAA info.  The only objects not
+                wrapped in MEM_REFs that can have their address taken are
+                STRING_CSTs.  */
+             if (tem.length () >= 2
+                 && tem[tem.length () - 2].opcode == MEM_REF)
+               {
+                 vn_reference_op_t new_mem_op = &tem[tem.length () - 2];
+                 new_mem_op->op0
+                     = wide_int_to_tree (TREE_TYPE (mem_op->op0),
+                                         wi::to_poly_wide (new_mem_op->op0));
+               }
+             else
+               gcc_assert (tem.last ().opcode == STRING_CST);
+             ops->pop ();
+             ops->pop ();
+             ops->safe_splice (tem);
+             --*i_p;
+             return true;
            }
-         else
-           gcc_assert (tem.last ().opcode == STRING_CST);
-         ops->pop ();
-         ops->pop ();
-         ops->safe_splice (tem);
-         --*i_p;
-         return true;
+         if (!addr_base
+             || TREE_CODE (addr_base) != MEM_REF
+             || (TREE_CODE (TREE_OPERAND (addr_base, 0)) == SSA_NAME
+                 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND (addr_base,
+                                                                   0))))
+           return changed;
+
+         off += addr_offset;
+         off += mem_ref_offset (addr_base);
+         op->op0 = TREE_OPERAND (addr_base, 0);
+       }
+      else
+       {
+         tree ptr, ptroff;
+         ptr = gimple_assign_rhs1 (def_stmt);
+         ptroff = gimple_assign_rhs2 (def_stmt);
+         if (TREE_CODE (ptr) != SSA_NAME
+             || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr)
+             /* Make sure to not endlessly recurse.
+                See gcc.dg/tree-ssa/20040408-1.c for an example.  Can easily
+                happen when we value-number a PHI to its backedge value.  */
+             || SSA_VAL (ptr) == op->op0
+             || !poly_int_tree_p (ptroff))
+           return changed;
+
+         off += wi::to_poly_offset (ptroff);
+         op->op0 = ptr;
        }
-      if (!addr_base
-         || TREE_CODE (addr_base) != MEM_REF
-         || (TREE_CODE (TREE_OPERAND (addr_base, 0)) == SSA_NAME
-             && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND (addr_base, 0))))
-       return false;
-
-      off += addr_offset;
-      off += mem_ref_offset (addr_base);
-      op->op0 = TREE_OPERAND (addr_base, 0);
-    }
-  else
-    {
-      tree ptr, ptroff;
-      ptr = gimple_assign_rhs1 (def_stmt);
-      ptroff = gimple_assign_rhs2 (def_stmt);
-      if (TREE_CODE (ptr) != SSA_NAME
-         || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr)
-         /* Make sure to not endlessly recurse.
-            See gcc.dg/tree-ssa/20040408-1.c for an example.  Can easily
-            happen when we value-number a PHI to its backedge value.  */
-         || SSA_VAL (ptr) == op->op0
-         || !poly_int_tree_p (ptroff))
-       return false;
 
-      off += wi::to_poly_offset (ptroff);
-      op->op0 = ptr;
+      mem_op->op0 = wide_int_to_tree (TREE_TYPE (mem_op->op0), off);
+      if (tree_fits_shwi_p (mem_op->op0))
+       mem_op->off = tree_to_shwi (mem_op->op0);
+      else
+       mem_op->off = -1;
+      /* ???  Can end up with endless recursion here!?
+        gcc.c-torture/execute/strcmp-1.c  */
+      if (TREE_CODE (op->op0) == SSA_NAME)
+       op->op0 = SSA_VAL (op->op0);
+      if (TREE_CODE (op->op0) != SSA_NAME)
+       op->opcode = TREE_CODE (op->op0);
+
+      changed = true;
     }
+  /* Tail-recurse.  */
+  while (TREE_CODE (op->op0) == SSA_NAME);
 
-  mem_op->op0 = wide_int_to_tree (TREE_TYPE (mem_op->op0), off);
-  if (tree_fits_shwi_p (mem_op->op0))
-    mem_op->off = tree_to_shwi (mem_op->op0);
-  else
-    mem_op->off = -1;
-  /* ???  Can end up with endless recursion here!?
-     gcc.c-torture/execute/strcmp-1.c  */
-  if (TREE_CODE (op->op0) == SSA_NAME)
-    op->op0 = SSA_VAL (op->op0);
-  if (TREE_CODE (op->op0) != SSA_NAME)
-    op->opcode = TREE_CODE (op->op0);
-
-  /* And recurse.  */
-  if (TREE_CODE (op->op0) == SSA_NAME)
-    vn_reference_maybe_forwprop_address (ops, i_p);
-  else if (TREE_CODE (op->op0) == ADDR_EXPR)
+  /* Fold a remaining *&.  */
+  if (TREE_CODE (op->op0) == ADDR_EXPR)
     vn_reference_fold_indirect (ops, i_p);
-  return true;
+
+  return changed;
 }
 
 /* Optimize the reference REF to a constant if possible or return