aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2014-01-29 14:45:44 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2014-01-29 14:45:44 +0000
commit77574c353464b38f98b7d69a5fb555b6888701a3 (patch)
tree0b29ae9817e081fdd5d933b5bcbf8bebda1d3615 /gcc
parent15b25b242b7165045c40850b3759330c39ff1c02 (diff)
downloadgcc-77574c353464b38f98b7d69a5fb555b6888701a3.zip
gcc-77574c353464b38f98b7d69a5fb555b6888701a3.tar.gz
gcc-77574c353464b38f98b7d69a5fb555b6888701a3.tar.bz2
re PR middle-end/58742 (pointer arithmetic simplification)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/pr58742-1.c13
-rw-r--r--gcc/testsuite/gcc.dg/pr58742-2.c13
-rw-r--r--gcc/testsuite/gcc.dg/pr58742-3.c14
-rw-r--r--gcc/tree-ssa-forwprop.c99
6 files changed, 154 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fc31af0..c81432d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 15ea8c7..f330ee0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..94f5627
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr58742-1.c
@@ -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
index 0000000..e0011e9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr58742-2.c
@@ -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
index 0000000..f4e95e6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr58742-3.c
@@ -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" } } */
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 41285d3..ebdd8f5 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -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. */