aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2014-01-28 14:53:52 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2014-01-28 14:53:52 +0000
commit07ec81f958b765032f234d08623b9a23c374a09e (patch)
treecbd321c0a8325f0dd1c5d1f02a29798d81d3d147 /gcc
parent5facb998d920cb29d4390c6ab04230b19aa0ff12 (diff)
downloadgcc-07ec81f958b765032f234d08623b9a23c374a09e.zip
gcc-07ec81f958b765032f234d08623b9a23c374a09e.tar.gz
gcc-07ec81f958b765032f234d08623b9a23c374a09e.tar.bz2
re PR middle-end/58742 (pointer arithmetic simplification)
2014-01-28 Richard Biener <rguenther@suse.de> PR tree-optimization/58742 * tree-ssa-forwprop.c (associate_plusminus): Handle pointer subtraction of the form (T)(P + A) - (T)P. From-SVN: r207194
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/tree-ssa-forwprop.c50
2 files changed, 56 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 364cc8a..0dc6d60 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2014-01-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58742
+ * tree-ssa-forwprop.c (associate_plusminus): Handle
+ pointer subtraction of the form (T)(P + A) - (T)P.
+
2014-01-28 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* config/arm/arm.c (arm_new_rtx_costs): Remove useless statement
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index ce9e426..6389811 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -2543,6 +2543,7 @@ associate_plusminus (gimple_stmt_iterator *gsi)
CST +- (CST +- A) -> CST +- A
CST +- (A +- CST) -> CST +- A
A + ~A -> -1
+ (T)(P + A) - (T)P -> (T)A
via commutating the addition and contracting operations to zero
by reassociation. */
@@ -2646,6 +2647,55 @@ associate_plusminus (gimple_stmt_iterator *gsi)
gimple_set_modified (stmt, true);
}
}
+ else if (CONVERT_EXPR_CODE_P (def_code) && code == MINUS_EXPR
+ && TREE_CODE (rhs2) == SSA_NAME)
+ {
+ /* (T)(ptr + adj) - (T)ptr -> (T)adj. */
+ gimple def_stmt2 = SSA_NAME_DEF_STMT (rhs2);
+ if (TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME
+ && is_gimple_assign (def_stmt2)
+ && can_propagate_from (def_stmt2)
+ && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt2))
+ && TREE_CODE (gimple_assign_rhs1 (def_stmt2)) == SSA_NAME)
+ {
+ /* Now we have (T)A - (T)ptr. */
+ tree ptr = gimple_assign_rhs1 (def_stmt2);
+ def_stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def_stmt));
+ if (is_gimple_assign (def_stmt2)
+ && gimple_assign_rhs_code (def_stmt2) == POINTER_PLUS_EXPR
+ && gimple_assign_rhs1 (def_stmt2) == ptr)
+ {
+ /* And finally (T)(ptr + X) - (T)ptr. */
+ tree adj = gimple_assign_rhs2 (def_stmt2);
+ /* If the conversion of the pointer adjustment to the
+ final type requires a sign- or zero-extension we
+ have to punt - it is not defined which one is
+ correct. */
+ if (TYPE_PRECISION (TREE_TYPE (rhs1))
+ <= TYPE_PRECISION (TREE_TYPE (adj))
+ || (TREE_CODE (adj) == INTEGER_CST
+ && tree_int_cst_sign_bit (adj) == 0))
+ {
+ if (useless_type_conversion_p (TREE_TYPE (rhs1),
+ TREE_TYPE (adj)))
+ {
+ code = TREE_CODE (adj);
+ rhs1 = adj;
+ }
+ else
+ {
+ code = NOP_EXPR;
+ rhs1 = adj;
+ }
+ rhs2 = NULL_TREE;
+ gimple_assign_set_rhs_with_ops (gsi, code, rhs1,
+ NULL_TREE);
+ gcc_assert (gsi_stmt (*gsi) == stmt);
+ gimple_set_modified (stmt, true);
+ }
+ }
+ }
+ }
}
}