{
tree rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
+ /* If the rhs has side-effects we cannot propagate from it. */
+ if (TREE_SIDE_EFFECTS (rhs))
+ return false;
+
+ /* If the rhs is a load we cannot propagate from it. */
+ if (REFERENCE_CLASS_P (rhs))
+ return false;
+
/* We cannot propagate ssa names that occur in abnormal phi nodes. */
switch (TREE_CODE_LENGTH (TREE_CODE (rhs)))
{
/* Require that we got a boolean type out if we put one in. */
gcc_assert (TREE_CODE (TREE_TYPE (t)) == TREE_CODE (type));
- /* For (bool)x use x != 0. */
- if (TREE_CODE (t) == NOP_EXPR
- && TREE_TYPE (t) == boolean_type_node)
- {
- tree top0 = TREE_OPERAND (t, 0);
- t = build2 (NE_EXPR, type,
- top0, build_int_cst (TREE_TYPE (top0), 0));
- }
- /* For !x use x == 0. */
- else if (TREE_CODE (t) == TRUTH_NOT_EXPR)
- {
- tree top0 = TREE_OPERAND (t, 0);
- t = build2 (EQ_EXPR, type,
- top0, build_int_cst (TREE_TYPE (top0), 0));
- }
- /* For cmp ? 1 : 0 use cmp. */
- else if (TREE_CODE (t) == COND_EXPR
- && COMPARISON_CLASS_P (TREE_OPERAND (t, 0))
- && integer_onep (TREE_OPERAND (t, 1))
- && integer_zerop (TREE_OPERAND (t, 2)))
- {
- tree top0 = TREE_OPERAND (t, 0);
- t = build2 (TREE_CODE (top0), type,
- TREE_OPERAND (top0, 0), TREE_OPERAND (top0, 1));
- }
+ /* Canonicalize the combined condition for use in a COND_EXPR. */
+ t = canonicalize_cond_expr_cond (t);
/* Bail out if we required an invariant but didn't get one. */
- if (invariant_only
- && !is_gimple_min_invariant (t))
+ if (!t
+ || (invariant_only
+ && !is_gimple_min_invariant (t)))
return NULL_TREE;
- /* A valid conditional for a COND_EXPR is either a gimple value
- or a comparison with two gimple value operands. */
- if (is_gimple_val (t)
- || (COMPARISON_CLASS_P (t)
- && is_gimple_val (TREE_OPERAND (t, 0))
- && is_gimple_val (TREE_OPERAND (t, 1))))
- return t;
-
- return NULL_TREE;
+ return t;
}
/* Propagate from the ssa name definition statements of COND_EXPR
do {
tree tmp = NULL_TREE;
tree cond = COND_EXPR_COND (cond_expr);
- tree name, def_stmt, rhs;
- bool single_use_p;
+ tree name, def_stmt, rhs0 = NULL_TREE, rhs1 = NULL_TREE;
+ bool single_use0_p = false, single_use1_p = false;
/* We can do tree combining on SSA_NAME and comparison expressions. */
if (COMPARISON_CLASS_P (cond)
/* For comparisons use the first operand, that is likely to
simplify comparisons against constants. */
name = TREE_OPERAND (cond, 0);
- def_stmt = get_prop_source_stmt (name, false, &single_use_p);
+ def_stmt = get_prop_source_stmt (name, false, &single_use0_p);
if (def_stmt != NULL_TREE
&& can_propagate_from (def_stmt))
{
tree op1 = TREE_OPERAND (cond, 1);
- rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
+ rhs0 = GIMPLE_STMT_OPERAND (def_stmt, 1);
tmp = combine_cond_expr_cond (TREE_CODE (cond), boolean_type_node,
- fold_convert (TREE_TYPE (op1), rhs),
- op1, !single_use_p);
+ fold_convert (TREE_TYPE (op1), rhs0),
+ op1, !single_use0_p);
}
/* If that wasn't successful, try the second operand. */
if (tmp == NULL_TREE
{
tree op0 = TREE_OPERAND (cond, 0);
name = TREE_OPERAND (cond, 1);
- def_stmt = get_prop_source_stmt (name, false, &single_use_p);
+ def_stmt = get_prop_source_stmt (name, false, &single_use1_p);
if (def_stmt == NULL_TREE
|| !can_propagate_from (def_stmt))
return did_something;
- rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
+ rhs1 = GIMPLE_STMT_OPERAND (def_stmt, 1);
tmp = combine_cond_expr_cond (TREE_CODE (cond), boolean_type_node,
op0,
- fold_convert (TREE_TYPE (op0), rhs),
- !single_use_p);
+ fold_convert (TREE_TYPE (op0), rhs1),
+ !single_use1_p);
}
+ /* If that wasn't successful either, try both operands. */
+ if (tmp == NULL_TREE
+ && rhs0 != NULL_TREE
+ && rhs1 != NULL_TREE)
+ tmp = combine_cond_expr_cond (TREE_CODE (cond), boolean_type_node,
+ rhs0,
+ fold_convert (TREE_TYPE (rhs0), rhs1),
+ !(single_use0_p && single_use1_p));
}
else if (TREE_CODE (cond) == SSA_NAME)
{
|| !can_propagate_from (def_stmt))
return did_something;
- rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
- tmp = combine_cond_expr_cond (NE_EXPR, boolean_type_node, rhs,
- build_int_cst (TREE_TYPE (rhs), 0),
+ rhs0 = GIMPLE_STMT_OPERAND (def_stmt, 1);
+ tmp = combine_cond_expr_cond (NE_EXPR, boolean_type_node, rhs0,
+ build_int_cst (TREE_TYPE (rhs0), 0),
false);
}
did_something = forward_propagate_into_cond (stmt, stmt);
if (did_something == 2)
cfg_changed = true;
- fold_undefer_overflow_warnings (!TREE_NO_WARNING (stmt)
- && did_something, stmt,
+ fold_undefer_overflow_warnings (did_something, stmt,
WARN_STRICT_OVERFLOW_CONDITIONAL);
bsi_next (&bsi);
}