public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] PR91178, use tail-recursion for vn_reference_maybe_forwprop_address
@ 2019-07-31  8:03 Richard Biener
  0 siblings, 0 replies; only message in thread
From: Richard Biener @ 2019-07-31  8:03 UTC (permalink / raw)
  To: gcc-patches


Otherwise a sequence of _2 = _1 + 4; _3 = _2 + 4; ... can blow the
stack.

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

Richard.

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.

Index: gcc/tree-ssa-sccvn.c
===================================================================
--- gcc/tree-ssa-sccvn.c	(revision 273920)
+++ gcc/tree-ssa-sccvn.c	(working copy)
@@ -1249,113 +1250,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;
+      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)
+	{
+	  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)
+	    {
+	      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;
+	    }
+	  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;
 
-      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)
-	{
-	  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;
+	  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;
+      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);
 
-      off += wi::to_poly_offset (ptroff);
-      op->op0 = ptr;
+      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

Index: gcc/testsuite/gcc.dg/torture/pr91178-2.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr91178-2.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/torture/pr91178-2.c	(working copy)
@@ -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];
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2019-07-31  8:01 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-31  8:03 [PATCH] PR91178, use tail-recursion for vn_reference_maybe_forwprop_address Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).