summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-forwprop.c
diff options
context:
space:
mode:
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2014-01-29 14:45:44 +0000
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2014-01-29 14:45:44 +0000
commitb904104cb8c81fcd196aa64cde69663157de4be0 (patch)
tree0b29ae9817e081fdd5d933b5bcbf8bebda1d3615 /gcc/tree-ssa-forwprop.c
parent3dbd6a28ad910ef80a90038f6f24c14727566fd7 (diff)
downloadgcc-b904104cb8c81fcd196aa64cde69663157de4be0.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@207239 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-forwprop.c')
-rw-r--r--gcc/tree-ssa-forwprop.c99
1 files changed, 98 insertions, 1 deletions
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 41285d3a19f..ebdd8f546f2 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. */