mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
7457605705
commit
5de989edfb
|
|
@ -1,3 +1,13 @@
|
||||||
|
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
|
||||||
|
|
||||||
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,
|
||||||
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);
|
|
||||||
|
|
||||||
gimple_assign_set_rhs1 (use_stmt, unshare_expr (def_rhs));
|
/* Else recurse if the conversion preserves the address value. */
|
||||||
if (useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (def_rhs)))
|
if ((INTEGRAL_TYPE_P (TREE_TYPE (lhs))
|
||||||
gimple_assign_set_rhs_code (use_stmt, TREE_CODE (def_rhs));
|
|| POINTER_TYPE_P (TREE_TYPE (lhs)))
|
||||||
else
|
&& (TYPE_PRECISION (TREE_TYPE (lhs))
|
||||||
gimple_assign_set_rhs_code (use_stmt, NOP_EXPR);
|
>= TYPE_PRECISION (TREE_TYPE (def_rhs))))
|
||||||
return true;
|
return forward_propagate_addr_expr (lhs, def_rhs, single_use_p);
|
||||||
|
|
||||||
|
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,
|
||||||
/* 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,
|
||||||
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)
|
||||||
|| !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)
|
||||||
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);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue