diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/tree-ssa-forwprop.c | 50 |
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); + } + } + } + } } } |