From f76968e6d5ab3ca8bd5b64ba0143197c00f59943 Mon Sep 17 00:00:00 2001
From: Richard Guenther <rguenther@suse.de>
Date: Thu, 9 Apr 2009 08:05:43 +0000
Subject: [PATCH] tree-ssa-ccp.c (maybe_fold_stmt_addition): Move non-constant
 indices into an array reference if possible.

2009-04-09  Richard Guenther  <rguenther@suse.de>

	* tree-ssa-ccp.c (maybe_fold_stmt_addition): Move non-constant
	indices into an array reference if possible.
	* tree-ssa-forwprop.c (tree_ssa_forward_propagate_single_use_vars):
	Fold POINTER_PLUS_EXPR statements with invariant address.

	* gcc.dg/tree-ssa/ssa-ccp-25.c: New testcase.
	* gcc.dg/tree-ssa/ssa-ccp-26.c: Likewise.

From-SVN: r145799
---
 gcc/ChangeLog                              |  7 ++++
 gcc/testsuite/ChangeLog                    |  5 +++
 gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-25.c | 14 ++++++++
 gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-26.c | 11 ++++++
 gcc/tree-ssa-ccp.c                         | 39 ++++++++++++++++++++--
 gcc/tree-ssa-forwprop.c                    |  9 +++++
 6 files changed, 82 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-25.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-26.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 581337c9d392..f9ffe707a9b3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2009-04-09  Richard Guenther  <rguenther@suse.de>
+
+	* tree-ssa-ccp.c (maybe_fold_stmt_addition): Move non-constant
+	indices into an array reference if possible.
+	* tree-ssa-forwprop.c (tree_ssa_forward_propagate_single_use_vars):
+	Fold POINTER_PLUS_EXPR statements with invariant address.
+
 2009-04-09  Alan Modra  <amodra@bigpond.net.au>
 
 	PR target/39634
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 27343277a47c..e56170e1cd0c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-04-09  Richard Guenther  <rguenther@suse.de>
+
+	* gcc.dg/tree-ssa/ssa-ccp-25.c: New testcase.
+	* gcc.dg/tree-ssa/ssa-ccp-26.c: Likewise.
+
 2009-04-09  Joseph Myers  <joseph@codesourcery.com>
 
 	PR c/39613
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-25.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-25.c
new file mode 100644
index 000000000000..c6e76a2a3fd8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-25.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-ccp1 -fdump-tree-forwprop1" } */
+
+int a[256];
+int foo(int i)
+{
+  int *p = &a[0];
+  return *(p + i);
+}
+
+/* { dg-final { scan-tree-dump "&a\\\[D\\\." "ccp1" } } */
+/* { dg-final { scan-tree-dump "= a\\\[D\\\." "forwprop1" } } */
+/* { dg-final { cleanup-tree-dump "ccp1" } } */
+/* { dg-final { cleanup-tree-dump "forwprop1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-26.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-26.c
new file mode 100644
index 000000000000..542c42939607
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-26.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-forwprop1" } */
+
+int a[256];
+int foo(int i)
+{
+  return (a + 1)[i];
+}
+
+/* { dg-final { scan-tree-dump "= a\\\[D\\\." "forwprop1" } } */
+/* { dg-final { cleanup-tree-dump "forwprop1" } } */
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index a67850448a79..226fd3dbb27c 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -2114,14 +2114,47 @@ maybe_fold_stmt_addition (tree res_type, tree op0, tree op1)
   tree ptd_type;
   tree t;
 
-  /* It had better be a constant.  */
-  if (TREE_CODE (op1) != INTEGER_CST)
-    return NULL_TREE;
   /* The first operand should be an ADDR_EXPR.  */
   if (TREE_CODE (op0) != ADDR_EXPR)
     return NULL_TREE;
   op0 = TREE_OPERAND (op0, 0);
 
+  /* It had better be a constant.  */
+  if (TREE_CODE (op1) != INTEGER_CST)
+    {
+      /* Or op0 should now be A[0] and the non-constant offset defined
+	 via a multiplication by the array element size.  */
+      if (TREE_CODE (op0) == ARRAY_REF
+	  && integer_zerop (TREE_OPERAND (op0, 1))
+	  && TREE_CODE (op1) == SSA_NAME
+	  && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (op0)), 1))
+	{
+	  gimple offset_def = SSA_NAME_DEF_STMT (op1);
+	  if (!is_gimple_assign (offset_def))
+	    return NULL_TREE;
+
+	  if (gimple_assign_rhs_code (offset_def) == MULT_EXPR
+	      && TREE_CODE (gimple_assign_rhs2 (offset_def)) == INTEGER_CST
+	      && tree_int_cst_equal (gimple_assign_rhs2 (offset_def),
+				     TYPE_SIZE_UNIT (TREE_TYPE (op0))))
+	    return build1 (ADDR_EXPR, res_type,
+			   build4 (ARRAY_REF, TREE_TYPE (op0),
+				   TREE_OPERAND (op0, 0),
+				   gimple_assign_rhs1 (offset_def),
+				   TREE_OPERAND (op0, 2),
+				   TREE_OPERAND (op0, 3)));
+	  else if (integer_onep (TYPE_SIZE_UNIT (TREE_TYPE (op0)))
+		   && gimple_assign_rhs_code (offset_def) != MULT_EXPR)
+	    return build1 (ADDR_EXPR, res_type,
+			   build4 (ARRAY_REF, TREE_TYPE (op0),
+				   TREE_OPERAND (op0, 0),
+				   op1,
+				   TREE_OPERAND (op0, 2),
+				   TREE_OPERAND (op0, 3)));
+	}
+      return NULL_TREE;
+    }
+
   /* If the first operand is an ARRAY_REF, expand it so that we can fold
      the offset into it.  */
   while (TREE_CODE (op0) == ARRAY_REF)
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index ff6bda0b1de8..f75e0afa73ff 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -1256,6 +1256,15 @@ tree_ssa_forward_propagate_single_use_vars (void)
 		  else
 		    gsi_next (&gsi);
 		}
+	      else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR
+		       && is_gimple_min_invariant (rhs))
+		{
+		  /* Make sure to fold &a[0] + off_1 here.  */
+		  fold_stmt_inplace (stmt);
+		  update_stmt (stmt);
+		  if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
+		    gsi_next (&gsi);
+		}
 	      else if ((gimple_assign_rhs_code (stmt) == BIT_NOT_EXPR
 		        || gimple_assign_rhs_code (stmt) == NEGATE_EXPR)
 		       && TREE_CODE (rhs) == SSA_NAME)
-- 
GitLab