re PR middle-end/58742 (pointer arithmetic simplification)
authorRichard Biener <rguenther@suse.de>
Wed, 29 Jan 2014 14:45:44 +0000 (14:45 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 29 Jan 2014 14:45:44 +0000 (14:45 +0000)
2014-01-29  Richard Biener  <rguenther@suse.de>

PR tree-optimization/58742
* tree-ssa-forwprop.c (associate_pointerplus): Rename to
associate_pointerplus_align.
(associate_pointerplus_diff): New function.
(associate_pointerplus): Likewise.  Call associate_pointerplus_align
and associate_pointerplus_diff.

* gcc.dg/pr58742-1.c: New testcase.
* gcc.dg/pr58742-2.c: Likewise.
* gcc.dg/pr58742-3.c: Likewise.

From-SVN: r207239

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr58742-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr58742-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr58742-3.c [new file with mode: 0644]
gcc/tree-ssa-forwprop.c

index fc31af0..c81432d 100644 (file)
@@ -1,5 +1,14 @@
 2014-01-29  Richard Biener  <rguenther@suse.de>
 
+       PR tree-optimization/58742
+       * tree-ssa-forwprop.c (associate_pointerplus): Rename to
+       associate_pointerplus_align.
+       (associate_pointerplus_diff): New function.
+       (associate_pointerplus): Likewise.  Call associate_pointerplus_align
+       and associate_pointerplus_diff.
+
+2014-01-29  Richard Biener  <rguenther@suse.de>
+
        * lto-streamer.h (LTO_major_version): Bump to 3.
        (LTO_minor_version): Reset to 0.
 
index 15ea8c7..f330ee0 100644 (file)
@@ -1,3 +1,10 @@
+2014-01-29  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/58742
+       * gcc.dg/pr58742-1.c: New testcase.
+       * gcc.dg/pr58742-2.c: Likewise.
+       * gcc.dg/pr58742-3.c: Likewise.
+
 2014-01-29  Renlin Li  <Renlin.Li@arm.com>
 
        * gcc.target/arm/ftest-armv7ve-arm.c: New.
diff --git a/gcc/testsuite/gcc.dg/pr58742-1.c b/gcc/testsuite/gcc.dg/pr58742-1.c
new file mode 100644 (file)
index 0000000..94f5627
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-cddce1" } */
+
+int *
+fx (int *b, int *e)
+{
+  __SIZE_TYPE__ p = e - b;
+  /* The first forwprop pass should optimize this to return e;  */
+  return b + p;
+}
+
+/* { dg-final { scan-tree-dump "return e" "cddce1" } } */
+/* { dg-final { cleanup-tree-dump "cddce1" } } */
diff --git a/gcc/testsuite/gcc.dg/pr58742-2.c b/gcc/testsuite/gcc.dg/pr58742-2.c
new file mode 100644 (file)
index 0000000..e0011e9
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-cddce1" } */
+
+__SIZE_TYPE__
+fx (char *a, __SIZE_TYPE__ sz)
+{
+  char *b = a + sz;
+  /* The first forwprop pass should optimize this to return sz;  */
+  return b - a;
+}
+
+/* { dg-final { scan-tree-dump "return sz" "cddce1" } } */
+/* { dg-final { cleanup-tree-dump "cddce1" } } */
diff --git a/gcc/testsuite/gcc.dg/pr58742-3.c b/gcc/testsuite/gcc.dg/pr58742-3.c
new file mode 100644 (file)
index 0000000..f4e95e6
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-cddce1" } */
+
+int *
+fx (int *a, int sz)
+{
+  int *b = a + sz;
+  b = b - sz;
+  /* forwprop together with FRE should optimize this to return a;  */
+  return b;
+}
+
+/* { dg-final { scan-tree-dump "return a" "cddce1" } } */
+/* { dg-final { cleanup-tree-dump "cddce1" } } */
index 41285d3..ebdd8f5 100644 (file)
@@ -2802,7 +2802,7 @@ out:
    true if anything changed, false otherwise.  */
 
 static bool
-associate_pointerplus (gimple_stmt_iterator *gsi)
+associate_pointerplus_align (gimple_stmt_iterator *gsi)
 {
   gimple stmt = gsi_stmt (*gsi);
   gimple def_stmt;
@@ -2850,6 +2850,103 @@ associate_pointerplus (gimple_stmt_iterator *gsi)
   return true;
 }
 
+/* Associate operands of a POINTER_PLUS_EXPR assignmen at *GSI.  Returns
+   true if anything changed, false otherwise.  */
+
+static bool
+associate_pointerplus_diff (gimple_stmt_iterator *gsi)
+{
+  gimple stmt = gsi_stmt (*gsi);
+  gimple def_stmt;
+  tree ptr1, rhs;
+
+  /* Pattern match
+       tem1 = (long) ptr1;
+       tem2 = (long) ptr2;
+       tem3 = tem2 - tem1;
+       tem4 = (unsigned long) tem3;
+       tem5 = ptr1 + tem4;
+     and produce
+       tem5 = ptr2;  */
+  ptr1 = gimple_assign_rhs1 (stmt);
+  rhs = gimple_assign_rhs2 (stmt);
+  if (TREE_CODE (rhs) != SSA_NAME)
+    return false;
+  gimple minus = SSA_NAME_DEF_STMT (rhs);
+  /* Conditionally look through a sign-changing conversion.  */
+  if (is_gimple_assign (minus)
+      && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (minus))
+      && (TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (minus)))
+         == TYPE_PRECISION (TREE_TYPE (rhs)))
+      && TREE_CODE (gimple_assign_rhs1 (minus)) == SSA_NAME)
+    minus = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (minus));
+  if (!is_gimple_assign (minus))
+    return false;
+  if (gimple_assign_rhs_code (minus) != MINUS_EXPR)
+    return false;
+  rhs = gimple_assign_rhs2 (minus);
+  if (TREE_CODE (rhs) != SSA_NAME)
+    return false;
+  def_stmt = SSA_NAME_DEF_STMT (rhs);
+  if (!is_gimple_assign (def_stmt)
+      || ! CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt))
+      || gimple_assign_rhs1 (def_stmt) != ptr1)
+    return false;
+  rhs = gimple_assign_rhs1 (minus);
+  if (TREE_CODE (rhs) != SSA_NAME)
+    return false;
+  def_stmt = SSA_NAME_DEF_STMT (rhs);
+  if (!is_gimple_assign (def_stmt)
+      || ! CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
+    return false;
+  rhs = gimple_assign_rhs1 (def_stmt);
+  if (! useless_type_conversion_p (TREE_TYPE (ptr1), TREE_TYPE (rhs)))
+    return false;
+
+  gimple_assign_set_rhs_with_ops (gsi, TREE_CODE (rhs), rhs, NULL_TREE);
+  update_stmt (stmt);
+
+  return true;
+}
+
+/* Associate operands of a POINTER_PLUS_EXPR assignmen at *GSI.  Returns
+   true if anything changed, false otherwise.  */
+
+static bool
+associate_pointerplus (gimple_stmt_iterator *gsi)
+{
+  gimple stmt = gsi_stmt (*gsi);
+  gimple def_stmt;
+  tree ptr, off1, off2;
+
+  if (associate_pointerplus_align (gsi)
+      || associate_pointerplus_diff (gsi))
+    return true;
+
+  /* Associate (p +p off1) +p off2 as (p +p (off1 + off2)).  */
+  ptr = gimple_assign_rhs1 (stmt);
+  off1 = gimple_assign_rhs2 (stmt);
+  if (TREE_CODE (ptr) != SSA_NAME)
+    return false;
+  def_stmt = SSA_NAME_DEF_STMT (ptr);
+  if (!is_gimple_assign (def_stmt)
+      || gimple_assign_rhs_code (def_stmt) != POINTER_PLUS_EXPR)
+    return false;
+  ptr = gimple_assign_rhs1 (def_stmt);
+  off2 = gimple_assign_rhs2 (def_stmt);
+  if (!types_compatible_p (TREE_TYPE (off1), TREE_TYPE (off2)))
+    return false;
+
+  tree off = make_ssa_name (TREE_TYPE (off1), NULL);
+  gimple ostmt = gimple_build_assign_with_ops (PLUS_EXPR, off, off1, off2);
+  gsi_insert_before (gsi, ostmt, GSI_SAME_STMT);
+
+  gimple_assign_set_rhs_with_ops (gsi, POINTER_PLUS_EXPR, ptr, off);
+  update_stmt (stmt);
+
+  return true;
+}
+
 /* Combine two conversions in a row for the second conversion at *GSI.
    Returns 1 if there were any changes made, 2 if cfg-cleanup needs to
    run.  Else it returns 0.  */