[PATCH][mem-ref2] More forwrpop
Richard Guenther
rguenther@suse.de
Thu Jun 17 16:08:00 GMT 2010
Also forward-propagate into plain MEM_REFs. We can propagate
non-invariant addresses there.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.
Richard.
2010-06-17 Richard Guenther <rguenther@suse.de>
* tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Also
forward-propagate into plain MEM_REFs.
Index: mem-ref2/gcc/tree-ssa-forwprop.c
===================================================================
*** mem-ref2.orig/gcc/tree-ssa-forwprop.c 2010-06-17 15:18:39.000000000 +0200
--- mem-ref2/gcc/tree-ssa-forwprop.c 2010-06-17 15:53:09.000000000 +0200
*************** forward_propagate_addr_expr_1 (tree name
*** 820,825 ****
--- 820,826 ----
{
tree def_rhs_base;
HOST_WIDE_INT def_rhs_offset;
+ /* If the address is invariant we can always fold it. */
if ((def_rhs_base = get_addr_base_and_unit_offset (TREE_OPERAND (def_rhs, 0),
&def_rhs_offset)))
{
*************** forward_propagate_addr_expr_1 (tree name
*** 837,848 ****
TREE_OPERAND (lhs, 0) = new_ptr;
TREE_OPERAND (lhs, 1)
= double_int_to_tree (TREE_TYPE (TREE_OPERAND (lhs, 1)), off);
- fold_stmt_inplace (use_stmt);
tidy_after_forward_propagate_addr (use_stmt);
/* Continue propagating into the RHS if this was not the only use. */
if (single_use_p)
return true;
}
else
/* We can have a struct assignment dereferencing our name twice.
Note that we didn't propagate into the lhs to not falsely
--- 838,884 ----
TREE_OPERAND (lhs, 0) = new_ptr;
TREE_OPERAND (lhs, 1)
= double_int_to_tree (TREE_TYPE (TREE_OPERAND (lhs, 1)), off);
tidy_after_forward_propagate_addr (use_stmt);
/* Continue propagating into the RHS if this was not the only use. */
if (single_use_p)
return true;
}
+ /* If the LHS is a plain dereference and the value type is the same as
+ that of the pointed-to type of the address we can put the
+ dereferenced address on the LHS preserving the original alias-type. */
+ else if (gimple_assign_lhs (use_stmt) == lhs
+ && useless_type_conversion_p
+ (TREE_TYPE (TREE_OPERAND (def_rhs, 0)),
+ TREE_TYPE (gimple_assign_rhs1 (use_stmt))))
+ {
+ tree *def_rhs_basep = &TREE_OPERAND (def_rhs, 0);
+ tree new_offset, new_base, saved;
+ while (handled_component_p (*def_rhs_basep))
+ def_rhs_basep = &TREE_OPERAND (*def_rhs_basep, 0);
+ saved = *def_rhs_basep;
+ if (TREE_CODE (*def_rhs_basep) == MEM_REF)
+ {
+ new_base = TREE_OPERAND (*def_rhs_basep, 0);
+ new_offset
+ = int_const_binop (PLUS_EXPR, TREE_OPERAND (lhs, 1),
+ TREE_OPERAND (*def_rhs_basep, 1), 0);
+ }
+ else
+ {
+ new_base = build_fold_addr_expr (*def_rhs_basep);
+ new_offset = TREE_OPERAND (lhs, 1);
+ }
+ *def_rhs_basep = build2 (MEM_REF, TREE_TYPE (*def_rhs_basep),
+ new_base, new_offset);
+ gimple_assign_set_lhs (use_stmt,
+ unshare_expr (TREE_OPERAND (def_rhs, 0)));
+ *def_rhs_basep = saved;
+ tidy_after_forward_propagate_addr (use_stmt);
+ /* Continue propagating into the RHS if this was not the
+ only use. */
+ if (single_use_p)
+ return true;
+ }
else
/* We can have a struct assignment dereferencing our name twice.
Note that we didn't propagate into the lhs to not falsely
*************** forward_propagate_addr_expr_1 (tree name
*** 885,890 ****
--- 921,960 ----
fold_stmt_inplace (use_stmt);
tidy_after_forward_propagate_addr (use_stmt);
return res;
+ }
+ /* If the LHS is a plain dereference and the value type is the same as
+ that of the pointed-to type of the address we can put the
+ dereferenced address on the LHS preserving the original alias-type. */
+ else if (gimple_assign_rhs1 (use_stmt) == rhs
+ && useless_type_conversion_p
+ (TREE_TYPE (gimple_assign_lhs (use_stmt)),
+ TREE_TYPE (TREE_OPERAND (def_rhs, 0))))
+ {
+ tree *def_rhs_basep = &TREE_OPERAND (def_rhs, 0);
+ tree new_offset, new_base, saved;
+ while (handled_component_p (*def_rhs_basep))
+ def_rhs_basep = &TREE_OPERAND (*def_rhs_basep, 0);
+ saved = *def_rhs_basep;
+ if (TREE_CODE (*def_rhs_basep) == MEM_REF)
+ {
+ new_base = TREE_OPERAND (*def_rhs_basep, 0);
+ new_offset
+ = int_const_binop (PLUS_EXPR, TREE_OPERAND (rhs, 1),
+ TREE_OPERAND (*def_rhs_basep, 1), 0);
+ }
+ else
+ {
+ new_base = build_fold_addr_expr (*def_rhs_basep);
+ new_offset = TREE_OPERAND (rhs, 1);
+ }
+ *def_rhs_basep = build2 (MEM_REF, TREE_TYPE (*def_rhs_basep),
+ new_base, new_offset);
+ gimple_assign_set_rhs1 (use_stmt,
+ unshare_expr (TREE_OPERAND (def_rhs, 0)));
+ *def_rhs_basep = saved;
+ fold_stmt_inplace (use_stmt);
+ tidy_after_forward_propagate_addr (use_stmt);
+ return res;
}
}
More information about the Gcc-patches
mailing list