else if (get_alias_set (TREE_TYPE (type_d)) !=
get_alias_set (TREE_TYPE (type_o)))
return false;
+
+ /* Also verify flow-sensitive information is compatible. */
+ if (SSA_NAME_PTR_INFO (orig) && SSA_NAME_PTR_INFO (dest))
+ {
+ struct ptr_info_def *orig_ptr_info = SSA_NAME_PTR_INFO (orig);
+ struct ptr_info_def *dest_ptr_info = SSA_NAME_PTR_INFO (dest);
+
+ if (orig_ptr_info->name_mem_tag
+ && dest_ptr_info->name_mem_tag
+ && orig_ptr_info->pt_vars
+ && dest_ptr_info->pt_vars
+ && !bitmap_intersect_p (dest_ptr_info->pt_vars,
+ orig_ptr_info->pt_vars))
+ return false;
+ }
}
/* If the destination is a SSA_NAME for a virtual operand, then we have
if (TREE_CODE (stmt) == PHI_NODE)
return !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (stmt));
- if (TREE_CODE (stmt) != MODIFY_EXPR)
+ if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
return false;
- lhs = TREE_OPERAND (stmt, 0);
- rhs = TREE_OPERAND (stmt, 1);
+ lhs = GIMPLE_STMT_OPERAND (stmt, 0);
+ rhs = GIMPLE_STMT_OPERAND (stmt, 1);
ann = stmt_ann (stmt);
/* If the statement has volatile operands, it won't generate a
/* Otherwise, the only statements that generate useful copies are
assignments whose RHS is just an SSA name that doesn't flow
through abnormal edges. */
- return TREE_CODE (rhs) == SSA_NAME && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs);
+ return (do_store_copy_prop
+ && TREE_CODE (lhs) == SSA_NAME)
+ || (TREE_CODE (rhs) == SSA_NAME
+ && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs));
}
tree lhs, rhs;
prop_value_t *rhs_val;
- lhs = TREE_OPERAND (stmt, 0);
- rhs = TREE_OPERAND (stmt, 1);
+ lhs = GIMPLE_STMT_OPERAND (stmt, 0);
+ rhs = GIMPLE_STMT_OPERAND (stmt, 1);
gcc_assert (TREE_CODE (rhs) == SSA_NAME);
if (!may_propagate_copy (lhs, rhs))
return SSA_PROP_VARYING;
- /* Avoid copy propagation from an inner into an outer loop.
- Otherwise, this may move loop variant variables outside of
- their loops and prevent coalescing opportunities. If the
- value was loop invariant, it will be hoisted by LICM and
- exposed for copy propagation. */
- if (loop_depth_of_name (rhs) > loop_depth_of_name (lhs))
- return SSA_PROP_VARYING;
-
/* Notice that in the case of assignments, we make the LHS be a
copy of RHS's value, not of RHS itself. This avoids keeping
unnecessary copy-of chains (assignments cannot be in a cycle
static enum ssa_prop_result
copy_prop_visit_stmt (tree stmt, edge *taken_edge_p, tree *result_p)
{
- stmt_ann_t ann;
enum ssa_prop_result retval;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\n");
}
- ann = stmt_ann (stmt);
-
- if (TREE_CODE (stmt) == MODIFY_EXPR
- && TREE_CODE (TREE_OPERAND (stmt, 1)) == SSA_NAME
+ if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
+ && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == SSA_NAME
&& (do_store_copy_prop
- || TREE_CODE (TREE_OPERAND (stmt, 0)) == SSA_NAME))
+ || TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == SSA_NAME))
{
/* If the statement is a copy assignment, evaluate its RHS to
see if the lattice value of its output has changed. */
retval = copy_prop_visit_assignment (stmt, result_p);
}
+ else if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
+ && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == SSA_NAME
+ && do_store_copy_prop
+ && stmt_makes_single_load (stmt))
+ {
+ /* If the statement is a copy assignment with a memory load
+ on the RHS, see if we know the value of this load and
+ update the lattice accordingly. */
+ prop_value_t *val = get_value_loaded_by (stmt, copy_of);
+ if (val
+ && val->mem_ref
+ && is_gimple_reg (val->value)
+ && operand_equal_p (val->mem_ref, GIMPLE_STMT_OPERAND (stmt, 1), 0))
+ {
+ bool changed;
+ changed = set_copy_of_val (GIMPLE_STMT_OPERAND (stmt, 0),
+ val->value, val->mem_ref);
+ if (changed)
+ {
+ *result_p = GIMPLE_STMT_OPERAND (stmt, 0);
+ retval = SSA_PROP_INTERESTING;
+ }
+ else
+ retval = SSA_PROP_NOT_INTERESTING;
+ }
+ else
+ retval = SSA_PROP_VARYING;
+ }
else if (TREE_CODE (stmt) == COND_EXPR)
{
/* See if we can determine which edge goes out of a conditional
{
basic_block bb;
- copy_of = XNEWVEC (prop_value_t, num_ssa_names);
- memset (copy_of, 0, num_ssa_names * sizeof (*copy_of));
+ copy_of = XCNEWVEC (prop_value_t, num_ssa_names);
- cached_last_copy_of = XNEWVEC (tree, num_ssa_names);
- memset (cached_last_copy_of, 0, num_ssa_names * sizeof (*cached_last_copy_of));
+ cached_last_copy_of = XCNEWVEC (tree, num_ssa_names);
FOR_EACH_BB (bb)
{
block_stmt_iterator si;
- tree phi;
+ tree phi, def;
+ int depth = bb->loop_depth;
for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
{
tree stmt = bsi_stmt (si);
+ ssa_op_iter iter;
/* The only statements that we care about are those that may
generate useful copies. We also need to mark conditional
jumps so that their outgoing edges are added to the work
- lists of the propagator. */
+ lists of the propagator.
+
+ Avoid copy propagation from an inner into an outer loop.
+ Otherwise, this may move loop variant variables outside of
+ their loops and prevent coalescing opportunities. If the
+ value was loop invariant, it will be hoisted by LICM and
+ exposed for copy propagation. */
if (stmt_ends_bb_p (stmt))
DONT_SIMULATE_AGAIN (stmt) = false;
- else if (stmt_may_generate_copy (stmt))
+ else if (stmt_may_generate_copy (stmt)
+ && loop_depth_of_name (GIMPLE_STMT_OPERAND (stmt, 1)) <= depth)
DONT_SIMULATE_AGAIN (stmt) = false;
else
- {
- tree def;
- ssa_op_iter iter;
-
- /* No need to simulate this statement anymore. */
- DONT_SIMULATE_AGAIN (stmt) = true;
-
- /* Mark all the outputs of this statement as not being
- the copy of anything. */
- FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
- set_copy_of_val (def, def, NULL_TREE);
- }
+ DONT_SIMULATE_AGAIN (stmt) = true;
+
+ /* Mark all the outputs of this statement as not being
+ the copy of anything. */
+ FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
+ if (DONT_SIMULATE_AGAIN (stmt))
+ set_copy_of_val (def, def, NULL_TREE);
+ else
+ cached_last_copy_of[SSA_NAME_VERSION (def)] = def;
}
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
- DONT_SIMULATE_AGAIN (phi) = false;
+ {
+ def = PHI_RESULT (phi);
+ if (!do_store_copy_prop && !is_gimple_reg (def))
+ DONT_SIMULATE_AGAIN (phi) = true;
+ else
+ DONT_SIMULATE_AGAIN (phi) = false;
+
+ if (DONT_SIMULATE_AGAIN (phi))
+ set_copy_of_val (def, def, NULL_TREE);
+ else
+ cached_last_copy_of[SSA_NAME_VERSION (def)] = def;
+ }
}
}
/* Set the final copy-of value for each variable by traversing the
copy-of chains. */
- tmp = XNEWVEC (prop_value_t, num_ssa_names);
- memset (tmp, 0, num_ssa_names * sizeof (*tmp));
+ tmp = XCNEWVEC (prop_value_t, num_ssa_names);
for (i = 1; i < num_ssa_names; i++)
{
tree var = ssa_name (i);