{
tree src = PHI_ARG_DEF_FROM_EDGE (phi, e);
tree dst = PHI_RESULT (phi);
+
+ /* If the desired argument is not the same as this PHI's result
+ and it is set by a PHI in this block, then we can not thread
+ through this block. */
+ if (src != dst
+ && TREE_CODE (src) == SSA_NAME
+ && TREE_CODE (SSA_NAME_DEF_STMT (src)) == PHI_NODE
+ && bb_for_stmt (SSA_NAME_DEF_STMT (src)) == e->dest)
+ return;
+
record_const_or_copy (dst, src);
register_new_def (dst, &block_defs_stack);
}
if (SSA_NAME_VAR (cached_lhs) != SSA_NAME_VAR (lhs))
break;
- /* If CACHED_LHS does not represent the current value of the undering
+ /* If CACHED_LHS does not represent the current value of the underlying
variable in CACHED_LHS/LHS, then we can not ignore this statement. */
if (var_ann (SSA_NAME_VAR (lhs))->current_def != cached_lhs)
break;
|| TREE_CODE (stmt) == SWITCH_EXPR))
{
tree cond, cached_lhs;
- edge e1;
- edge_iterator ei;
-
- /* Do not forward entry edges into the loop. In the case loop
- has multiple entry edges we may end up in constructing irreducible
- region.
- ??? We may consider forwarding the edges in the case all incoming
- edges forward to the same destination block. */
- if (!e->flags & EDGE_DFS_BACK)
- {
- FOR_EACH_EDGE (e1, ei, e->dest->preds)
- if (e1->flags & EDGE_DFS_BACK)
- break;
- if (e1)
- return;
- }
/* Now temporarily cprop the operands and try to find the resulting
expression in the hash tables. */
otherwise look it up in the hash tables. */
cached_lhs = local_fold (COND_EXPR_COND (dummy_cond));
if (! is_gimple_min_invariant (cached_lhs))
- cached_lhs = lookup_avail_expr (dummy_cond, false);
- if (!cached_lhs || ! is_gimple_min_invariant (cached_lhs))
{
- cached_lhs = simplify_cond_and_lookup_avail_expr (dummy_cond,
- NULL,
- false);
+ cached_lhs = lookup_avail_expr (dummy_cond, false);
+ if (!cached_lhs || ! is_gimple_min_invariant (cached_lhs))
+ cached_lhs = simplify_cond_and_lookup_avail_expr (dummy_cond,
+ NULL,
+ false);
}
}
/* We can have conditionals which just test the state of a
{
tree last;
- /* If we are at a leaf node in the dominator graph, see if we can thread
+ /* If we are at a leaf node in the dominator tree, see if we can thread
the edge from BB through its successor.
Do this before we remove entries from our equivalence tables. */
{
tree t = PHI_ARG_DEF (phi, i);
- if (TREE_CODE (t) == SSA_NAME || is_gimple_min_invariant (t))
- {
- /* Ignore alternatives which are the same as our LHS. */
- if (operand_equal_p (lhs, t, 0))
- continue;
-
- /* If we have not processed an alternative yet, then set
- RHS to this alternative. */
- if (rhs == NULL)
- rhs = t;
- /* If we have processed an alternative (stored in RHS), then
- see if it is equal to this one. If it isn't, then stop
- the search. */
- else if (! operand_equal_p (rhs, t, 0))
- break;
- }
- else
+ /* Ignore alternatives which are the same as our LHS. Since
+ LHS is a PHI_RESULT, it is known to be a SSA_NAME, so we
+ can simply compare pointers. */
+ if (lhs == t)
+ continue;
+
+ /* If we have not processed an alternative yet, then set
+ RHS to this alternative. */
+ if (rhs == NULL)
+ rhs = t;
+ /* If we have processed an alternative (stored in RHS), then
+ see if it is equal to this one. If it isn't, then stop
+ the search. */
+ else if (! operand_equal_for_phi_arg_p (rhs, t))
break;
}
FOR_EACH_EDGE (e, ei, bb->succs)
{
tree phi;
- int phi_num_args;
- int hint;
+ int indx;
/* If this is an abnormal edge, then we do not want to copy propagate
into the PHI alternative associated with this edge. */
if (! phi)
continue;
- /* There is no guarantee that for any two PHI nodes in a block that
- the phi alternative associated with a particular edge will be
- at the same index in the phi alternative array.
-
- However, it is very likely they will be the same. So we keep
- track of the index of the alternative where we found the edge in
- the previous phi node and check that index first in the next
- phi node. If that hint fails, then we actually search all
- the entries. */
- phi_num_args = PHI_NUM_ARGS (phi);
- hint = phi_num_args;
+ indx = e->dest_idx;
for ( ; phi; phi = PHI_CHAIN (phi))
{
- int i;
tree new;
use_operand_p orig_p;
tree orig;
- /* If the hint is valid (!= phi_num_args), see if it points
- us to the desired phi alternative. */
- if (hint != phi_num_args && PHI_ARG_EDGE (phi, hint) == e)
- ;
- else
- {
- /* The hint was either invalid or did not point to the
- correct phi alternative. Search all the alternatives
- for the correct one. Update the hint. */
- for (i = 0; i < phi_num_args; i++)
- if (PHI_ARG_EDGE (phi, i) == e)
- break;
- hint = i;
- }
-
- /* If we did not find the proper alternative, then something is
- horribly wrong. */
- gcc_assert (hint != phi_num_args);
-
/* The alternative may be associated with a constant, so verify
it is an SSA_NAME before doing anything with it. */
- orig_p = PHI_ARG_DEF_PTR (phi, hint);
+ orig_p = PHI_ARG_DEF_PTR (phi, indx);
orig = USE_FROM_PTR (orig_p);
if (TREE_CODE (orig) != SSA_NAME)
continue;
/* If the alternative is known to have a nonzero value, record
that fact in the PHI node itself for future use. */
if (bitmap_bit_p (nonzero_vars, SSA_NAME_VERSION (orig)))
- PHI_ARG_NONZERO (phi, hint) = true;
+ PHI_ARG_NONZERO (phi, indx) = true;
/* If we have *ORIG_P in our constant/copy table, then replace
ORIG_P with its value in our constant/copy table. */
}
}
- if (is_gimple_min_invariant (op0)
- && (TREE_CODE (op1) == SSA_NAME
- || is_gimple_min_invariant (op1)))
+ else if (is_gimple_min_invariant (op0)
+ && (TREE_CODE (op1) == SSA_NAME
+ || is_gimple_min_invariant (op1)))
{
tree inverted = invert_truthvalue (cond);
struct edge_info *edge_info;
}
}
- if (TREE_CODE (op0) == SSA_NAME
- && (is_gimple_min_invariant (op1)
- || TREE_CODE (op1) == SSA_NAME))
+ else if (TREE_CODE (op0) == SSA_NAME
+ && (is_gimple_min_invariant (op1)
+ || TREE_CODE (op1) == SSA_NAME))
{
tree inverted = invert_truthvalue (cond);
struct edge_info *edge_info;