/* SSA Jump Threading
- Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
Contributed by Jeff Law <law@redhat.com>
This file is part of GCC.
lhs_of_dominating_assert (tree op, basic_block bb, tree stmt)
{
imm_use_iterator imm_iter;
- use_operand_p imm_use;
+ tree use_stmt;
+ use_operand_p use_p;
- FOR_EACH_IMM_USE_SAFE (imm_use, imm_iter, op)
+ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, op)
{
- tree use_stmt = USE_STMT (imm_use);
-
+ use_stmt = USE_STMT (use_p);
if (use_stmt != stmt
- && TREE_CODE (use_stmt) == MODIFY_EXPR
- && TREE_CODE (TREE_OPERAND (use_stmt, 1)) == ASSERT_EXPR
- && TREE_OPERAND (TREE_OPERAND (use_stmt, 1), 0) == op
+ && TREE_CODE (use_stmt) == GIMPLE_MODIFY_STMT
+ && TREE_CODE (GIMPLE_STMT_OPERAND (use_stmt, 1)) == ASSERT_EXPR
+ && TREE_OPERAND (GIMPLE_STMT_OPERAND (use_stmt, 1), 0) == op
&& dominated_by_p (CDI_DOMINATORS, bb, bb_for_stmt (use_stmt)))
- op = TREE_OPERAND (use_stmt, 0);
+ {
+ return GIMPLE_STMT_OPERAND (use_stmt, 0);
+ }
}
return op;
}
dest = VEC_pop (tree, *stack);
- /* A NULL value indicates we should stop unwinding, oherwise
+ /* A NULL value indicates we should stop unwinding, otherwise
pop off the next entry as they're recorded in pairs. */
if (dest == NULL)
break;
if (IS_EMPTY_STMT (stmt) || TREE_CODE (stmt) == LABEL_EXPR)
continue;
- /* Safely handle threading across loop backedges. Only allowing
- a conditional at the target of the backedge is over conservative,
- but still allows us to capture the majority of the cases where
- we can thread across a loop backedge. */
- if ((e->flags & EDGE_DFS_BACK) != 0
- && TREE_CODE (stmt) != COND_EXPR
- && TREE_CODE (stmt) != SWITCH_EXPR)
- return NULL;
-
/* If the statement has volatile operands, then we assume we
can not thread through this block. This is overly
conservative in some ways. */
if (stmt_count > max_stmt_count)
return NULL;
- /* If this is not a MODIFY_EXPR which sets an SSA_NAME to a new
+ /* If this is not a GIMPLE_MODIFY_STMT which sets an SSA_NAME to a new
value, then do not try to simplify this statement as it will
not simplify in any way that is helpful for jump threading. */
- if (TREE_CODE (stmt) != MODIFY_EXPR
- || TREE_CODE (TREE_OPERAND (stmt, 0)) != SSA_NAME)
+ if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT
+ || TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) != SSA_NAME)
continue;
/* At this point we have a statement which assigns an RHS to an
Handle simple copy operations as well as implied copies from
ASSERT_EXPRs. */
- if (TREE_CODE (TREE_OPERAND (stmt, 1)) == SSA_NAME)
- cached_lhs = TREE_OPERAND (stmt, 1);
- else if (TREE_CODE (TREE_OPERAND (stmt, 1)) == ASSERT_EXPR)
- cached_lhs = TREE_OPERAND (TREE_OPERAND (stmt, 1), 0);
+ if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == SSA_NAME)
+ cached_lhs = GIMPLE_STMT_OPERAND (stmt, 1);
+ else if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == ASSERT_EXPR)
+ cached_lhs = TREE_OPERAND (GIMPLE_STMT_OPERAND (stmt, 1), 0);
else
{
/* A statement that is not a trivial copy or ASSERT_EXPR.
here, because fold expects all the operands of an expression
to be folded before the expression itself is folded, but we
can't just substitute the folded condition here. */
- if (TREE_CODE (TREE_OPERAND (stmt, 1)) == COND_EXPR)
+ if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == COND_EXPR)
{
- tree cond = COND_EXPR_COND (TREE_OPERAND (stmt, 1));
+ tree cond = COND_EXPR_COND (GIMPLE_STMT_OPERAND (stmt, 1));
cond = fold (cond);
if (cond == boolean_true_node)
- pre_fold_expr = COND_EXPR_THEN (TREE_OPERAND (stmt, 1));
+ pre_fold_expr = COND_EXPR_THEN (GIMPLE_STMT_OPERAND (stmt, 1));
else if (cond == boolean_false_node)
- pre_fold_expr = COND_EXPR_ELSE (TREE_OPERAND (stmt, 1));
+ pre_fold_expr = COND_EXPR_ELSE (GIMPLE_STMT_OPERAND (stmt, 1));
else
- pre_fold_expr = TREE_OPERAND (stmt, 1);
+ pre_fold_expr = GIMPLE_STMT_OPERAND (stmt, 1);
}
else
- pre_fold_expr = TREE_OPERAND (stmt, 1);
+ pre_fold_expr = GIMPLE_STMT_OPERAND (stmt, 1);
if (pre_fold_expr)
{
if (cached_lhs
&& (TREE_CODE (cached_lhs) == SSA_NAME
|| is_gimple_min_invariant (cached_lhs)))
- record_temporary_equivalence (TREE_OPERAND (stmt, 0),
+ record_temporary_equivalence (GIMPLE_STMT_OPERAND (stmt, 0),
cached_lhs,
stack);
}
/* We absolutely do not care about any type conversions
we only care about a zero/nonzero value. */
+ fold_defer_overflow_warnings ();
+
cached_lhs = fold (COND_EXPR_COND (dummy_cond));
while (TREE_CODE (cached_lhs) == NOP_EXPR
|| TREE_CODE (cached_lhs) == CONVERT_EXPR
|| TREE_CODE (cached_lhs) == NON_LVALUE_EXPR)
cached_lhs = TREE_OPERAND (cached_lhs, 0);
-
+
+ fold_undefer_overflow_warnings (is_gimple_min_invariant (cached_lhs),
+ stmt, WARN_STRICT_OVERFLOW_CONDITIONAL);
+
/* If we have not simplified the condition down to an invariant,
then use the pass specific callback to simplify the condition. */
if (! is_gimple_min_invariant (cached_lhs))
{
cached_lhs = cond;
- /* Get the variable's current value from the equivalency chains. */
- while (cached_lhs
- && TREE_CODE (cached_lhs) == SSA_NAME
- && SSA_NAME_VALUE (cached_lhs))
+ /* Get the variable's current value from the equivalency chains.
+
+ It is possible to get loops in the SSA_NAME_VALUE chains
+ (consider threading the backedge of a loop where we have
+ a loop invariant SSA_NAME used in the condition. */
+ if (cached_lhs
+ && TREE_CODE (cached_lhs) == SSA_NAME
+ && SSA_NAME_VALUE (cached_lhs))
cached_lhs = SSA_NAME_VALUE (cached_lhs);
/* If we're dominated by a suitable ASSERT_EXPR, then
{
tree stmt;
+ /* If E is a backedge, then we want to verify that the COND_EXPR,
+ SWITCH_EXPR or GOTO_EXPR at the end of e->dest is not affected
+ by any statements in e->dest. If it is affected, then it is not
+ safe to thread this edge. */
+ if (e->flags & EDGE_DFS_BACK)
+ {
+ ssa_op_iter iter;
+ use_operand_p use_p;
+ tree last = bsi_stmt (bsi_last (e->dest));
+
+ FOR_EACH_SSA_USE_OPERAND (use_p, last, iter, SSA_OP_USE | SSA_OP_VUSE)
+ {
+ tree use = USE_FROM_PTR (use_p);
+
+ if (TREE_CODE (use) == SSA_NAME
+ && TREE_CODE (SSA_NAME_DEF_STMT (use)) != PHI_NODE
+ && bb_for_stmt (SSA_NAME_DEF_STMT (use)) == e->dest)
+ goto fail;
+ }
+ }
+
stmt_count = 0;
/* PHIs create temporary equivalences. */