aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-forwprop.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2013-10-15 10:20:58 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2013-10-15 10:20:58 +0000
commit5de989edfb971e43d009307fc273f0d561f1c50f (patch)
treeedaf637c89b4570769ea55aee074b8bc953501bb /gcc/tree-ssa-forwprop.c
parent7457605705ec616086ecf5834325964703631155 (diff)
downloadgcc-5de989edfb971e43d009307fc273f0d561f1c50f.zip
gcc-5de989edfb971e43d009307fc273f0d561f1c50f.tar.gz
gcc-5de989edfb971e43d009307fc273f0d561f1c50f.tar.bz2
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
Diffstat (limited to 'gcc/tree-ssa-forwprop.c')
-rw-r--r--gcc/tree-ssa-forwprop.c76
1 files changed, 45 insertions, 31 deletions
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 8807db1..65f7ee1 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -161,7 +161,7 @@ along with GCC; see the file COPYING3. If not see
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. */
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 = gimple_assign_rhs1 (use_stmt);
- /* Trivial cases. The use statement could be a trivial copy or a
- useless conversion. Recurse to the uses of the lhs as copyprop does
- not copy through different variant pointers and FRE does not catch
- all useless conversions. Treat the case of a single-use name and
+ /* Do not perform copy-propagation but recurse through copy chains. */
+ if (TREE_CODE (lhs) == SSA_NAME
+ && rhs_code == SSA_NAME)
+ 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. */
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
- do the propagation to the current statement. In particular
- we can end up with a conversion needed for a non-invariant
- address which we cannot do in a single statement. */
- if (!single_use_p
- || (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (def_rhs))
- && (!is_gimple_min_invariant (def_rhs)
- || (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
- && POINTER_TYPE_P (TREE_TYPE (def_rhs))
- && (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));
- if (useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (def_rhs)))
- gimple_assign_set_rhs_code (use_stmt, TREE_CODE (def_rhs));
- else
- gimple_assign_set_rhs_code (use_stmt, NOP_EXPR);
- return true;
+ /* If there is a point in a conversion chain where the types match
+ so we can remove a conversion re-materialize the address here
+ and stop. */
+ if (single_use_p
+ && useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (def_rhs)))
+ {
+ gimple_assign_set_rhs1 (use_stmt, unshare_expr (def_rhs));
+ gimple_assign_set_rhs_code (use_stmt, TREE_CODE (def_rhs));
+ return true;
+ }
+
+ /* Else recurse if the conversion preserves the address value. */
+ if ((INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+ || POINTER_TYPE_P (TREE_TYPE (lhs)))
+ && (TYPE_PRECISION (TREE_TYPE (lhs))
+ >= TYPE_PRECISION (TREE_TYPE (def_rhs))))
+ 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. */
if (TREE_CODE (lhs) == SSA_NAME
&& 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
bother to replace into the current use but just pretend we did. */
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;
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.
Often this will allow for removal of an ADDR_EXPR and INDIRECT_REF
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. */
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;
gimple use_stmt;
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)
{
@@ -3336,7 +3350,7 @@ ssa_forward_propagate_and_combine (void)
|| !DECL_P (base)
|| decl_address_invariant_p (base))
&& !stmt_references_abnormal_ssa_name (stmt)
- && forward_propagate_addr_expr (lhs, rhs))
+ && forward_propagate_addr_expr (lhs, rhs, true))
{
release_defs (stmt);
gsi_remove (&gsi, true);
@@ -3360,7 +3374,7 @@ ssa_forward_propagate_and_combine (void)
TREE_TYPE (TREE_TYPE (rhs)),
rhs,
fold_convert (ptr_type_node,
- off)))))
+ off))), true))
{
release_defs (stmt);
gsi_remove (&gsi, true);