Commit 5de989ed by Richard Biener Committed by Richard Biener

tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Restructure forwarding…

tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Restructure forwarding through conversions and copies to avoid performing...

2013-10-15  Richard Biener  <rguenther@suse.de>

	* tree-ssa-forwprop.c (forward_propagate_addr_expr_1):
	Restructure forwarding through conversions and copies to
	avoid performing copy-propagation the wrong way.  Adjust
	recursion invocations.
	(forward_propagate_addr_expr): Add argument stating if we
	are recursing from a single-use.
	(ssa_forward_propagate_and_combine): Adjust.

From-SVN: r203591
parent 74576057
2013-10-15 Richard Biener <rguenther@suse.de>
* tree-ssa-forwprop.c (forward_propagate_addr_expr_1):
Restructure forwarding through conversions and copies to
avoid performing copy-propagation the wrong way. Adjust
recursion invocations.
(forward_propagate_addr_expr): Add argument stating if we
are recursing from a single-use.
(ssa_forward_propagate_and_combine): Adjust.
2013-10-14 David Malcolm <dmalcolm@redhat.com> 2013-10-14 David Malcolm <dmalcolm@redhat.com>
* dumpfile.h (gcc::dump_manager): New class, to hold state * dumpfile.h (gcc::dump_manager): New class, to hold state
......
...@@ -161,7 +161,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -161,7 +161,7 @@ along with GCC; see the file COPYING3. If not see
This will (of course) be extended as other needs arise. */ This will (of course) be extended as other needs arise. */
static bool forward_propagate_addr_expr (tree name, tree rhs); static bool forward_propagate_addr_expr (tree, tree, bool);
/* Set to true if we delete dead edges during the optimization. */ /* Set to true if we delete dead edges during the optimization. */
static bool cfg_changed; static bool cfg_changed;
...@@ -714,36 +714,45 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, ...@@ -714,36 +714,45 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
rhs_code = gimple_assign_rhs_code (use_stmt); rhs_code = gimple_assign_rhs_code (use_stmt);
rhs = gimple_assign_rhs1 (use_stmt); rhs = gimple_assign_rhs1 (use_stmt);
/* Trivial cases. The use statement could be a trivial copy or a /* Do not perform copy-propagation but recurse through copy chains. */
useless conversion. Recurse to the uses of the lhs as copyprop does if (TREE_CODE (lhs) == SSA_NAME
not copy through different variant pointers and FRE does not catch && rhs_code == SSA_NAME)
all useless conversions. Treat the case of a single-use name and return forward_propagate_addr_expr (lhs, def_rhs, single_use_p);
/* The use statement could be a conversion. Recurse to the uses of the
lhs as copyprop does not copy through pointer to integer to pointer
conversions and FRE does not catch all cases either.
Treat the case of a single-use name and
a conversion to def_rhs type separate, though. */ a conversion to def_rhs type separate, though. */
if (TREE_CODE (lhs) == SSA_NAME if (TREE_CODE (lhs) == SSA_NAME
&& ((rhs_code == SSA_NAME && rhs == name) && CONVERT_EXPR_CODE_P (rhs_code))
|| CONVERT_EXPR_CODE_P (rhs_code)))
{ {
/* Only recurse if we don't deal with a single use or we cannot /* If there is a point in a conversion chain where the types match
do the propagation to the current statement. In particular so we can remove a conversion re-materialize the address here
we can end up with a conversion needed for a non-invariant and stop. */
address which we cannot do in a single statement. */ if (single_use_p
if (!single_use_p && useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (def_rhs)))
|| (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (def_rhs)) {
&& (!is_gimple_min_invariant (def_rhs) gimple_assign_set_rhs1 (use_stmt, unshare_expr (def_rhs));
|| (INTEGRAL_TYPE_P (TREE_TYPE (lhs)) gimple_assign_set_rhs_code (use_stmt, TREE_CODE (def_rhs));
&& POINTER_TYPE_P (TREE_TYPE (def_rhs)) return true;
&& (TYPE_PRECISION (TREE_TYPE (lhs)) }
> TYPE_PRECISION (TREE_TYPE (def_rhs)))))))
return forward_propagate_addr_expr (lhs, def_rhs); /* Else recurse if the conversion preserves the address value. */
if ((INTEGRAL_TYPE_P (TREE_TYPE (lhs))
gimple_assign_set_rhs1 (use_stmt, unshare_expr (def_rhs)); || POINTER_TYPE_P (TREE_TYPE (lhs)))
if (useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (def_rhs))) && (TYPE_PRECISION (TREE_TYPE (lhs))
gimple_assign_set_rhs_code (use_stmt, TREE_CODE (def_rhs)); >= TYPE_PRECISION (TREE_TYPE (def_rhs))))
else return forward_propagate_addr_expr (lhs, def_rhs, single_use_p);
gimple_assign_set_rhs_code (use_stmt, NOP_EXPR);
return true; return false;
} }
/* If this isn't a conversion chain from this on we only can propagate
into compatible pointer contexts. */
if (!types_compatible_p (TREE_TYPE (name), TREE_TYPE (def_rhs)))
return false;
/* Propagate through constant pointer adjustments. */ /* Propagate through constant pointer adjustments. */
if (TREE_CODE (lhs) == SSA_NAME if (TREE_CODE (lhs) == SSA_NAME
&& rhs_code == POINTER_PLUS_EXPR && rhs_code == POINTER_PLUS_EXPR
...@@ -768,7 +777,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, ...@@ -768,7 +777,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
/* Recurse. If we could propagate into all uses of lhs do not /* Recurse. If we could propagate into all uses of lhs do not
bother to replace into the current use but just pretend we did. */ bother to replace into the current use but just pretend we did. */
if (TREE_CODE (new_def_rhs) == ADDR_EXPR if (TREE_CODE (new_def_rhs) == ADDR_EXPR
&& forward_propagate_addr_expr (lhs, new_def_rhs)) && forward_propagate_addr_expr (lhs, new_def_rhs, single_use_p))
return true; return true;
if (useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_def_rhs))) if (useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_def_rhs)))
...@@ -996,15 +1005,20 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, ...@@ -996,15 +1005,20 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
Try to forward propagate the ADDR_EXPR into all uses of the SSA_NAME. Try to forward propagate the ADDR_EXPR into all uses of the SSA_NAME.
Often this will allow for removal of an ADDR_EXPR and INDIRECT_REF Often this will allow for removal of an ADDR_EXPR and INDIRECT_REF
node or for recovery of array indexing from pointer arithmetic. node or for recovery of array indexing from pointer arithmetic.
PARENT_SINGLE_USE_P tells if, when in a recursive invocation, NAME was
the single use in the previous invocation. Pass true when calling
this as toplevel.
Returns true, if all uses have been propagated into. */ Returns true, if all uses have been propagated into. */
static bool static bool
forward_propagate_addr_expr (tree name, tree rhs) forward_propagate_addr_expr (tree name, tree rhs, bool parent_single_use_p)
{ {
imm_use_iterator iter; imm_use_iterator iter;
gimple use_stmt; gimple use_stmt;
bool all = true; bool all = true;
bool single_use_p = has_single_use (name); bool single_use_p = parent_single_use_p && has_single_use (name);
FOR_EACH_IMM_USE_STMT (use_stmt, iter, name) FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
{ {
...@@ -3336,7 +3350,7 @@ ssa_forward_propagate_and_combine (void) ...@@ -3336,7 +3350,7 @@ ssa_forward_propagate_and_combine (void)
|| !DECL_P (base) || !DECL_P (base)
|| decl_address_invariant_p (base)) || decl_address_invariant_p (base))
&& !stmt_references_abnormal_ssa_name (stmt) && !stmt_references_abnormal_ssa_name (stmt)
&& forward_propagate_addr_expr (lhs, rhs)) && forward_propagate_addr_expr (lhs, rhs, true))
{ {
release_defs (stmt); release_defs (stmt);
gsi_remove (&gsi, true); gsi_remove (&gsi, true);
...@@ -3360,7 +3374,7 @@ ssa_forward_propagate_and_combine (void) ...@@ -3360,7 +3374,7 @@ ssa_forward_propagate_and_combine (void)
TREE_TYPE (TREE_TYPE (rhs)), TREE_TYPE (TREE_TYPE (rhs)),
rhs, rhs,
fold_convert (ptr_type_node, fold_convert (ptr_type_node,
off))))) off))), true))
{ {
release_defs (stmt); release_defs (stmt);
gsi_remove (&gsi, true); gsi_remove (&gsi, true);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment