return (ret ? fold (ret) : expr);
}
+/* Expand definitions of ssa names in EXPR as long as they are simple
+ enough, and return the new expression. */
+
+static tree
+expand_simple_operations (tree expr)
+{
+ unsigned i, n;
+ tree ret = NULL_TREE, e, ee, stmt;
+ enum tree_code code = TREE_CODE (expr);
+
+ if (is_gimple_min_invariant (expr))
+ return expr;
+
+ if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
+ {
+ n = TREE_CODE_LENGTH (code);
+ for (i = 0; i < n; i++)
+ {
+ e = TREE_OPERAND (expr, i);
+ ee = expand_simple_operations (e);
+ if (e == ee)
+ continue;
+
+ if (!ret)
+ ret = copy_node (expr);
+
+ TREE_OPERAND (ret, i) = ee;
+ }
+
+ return (ret ? fold (ret) : expr);
+ }
+
+ if (TREE_CODE (expr) != SSA_NAME)
+ return expr;
+
+ stmt = SSA_NAME_DEF_STMT (expr);
+ if (TREE_CODE (stmt) != MODIFY_EXPR)
+ return expr;
+
+ e = TREE_OPERAND (stmt, 1);
+ if (/* Casts are simple. */
+ TREE_CODE (e) != NOP_EXPR
+ && TREE_CODE (e) != CONVERT_EXPR
+ /* Copies are simple. */
+ && TREE_CODE (e) != SSA_NAME
+ /* Assignments of invariants are simple. */
+ && !is_gimple_min_invariant (e)
+ /* And increments and decrements by a constant are simple. */
+ && !((TREE_CODE (e) == PLUS_EXPR
+ || TREE_CODE (e) == MINUS_EXPR)
+ && is_gimple_min_invariant (TREE_OPERAND (e, 1))))
+ return expr;
+
+ return expand_simple_operations (e);
+}
+
/* Tries to simplify EXPR using the condition COND. Returns the simplified
- expression (or EXPR unchanged, if no simplification was possible).*/
+ expression (or EXPR unchanged, if no simplification was possible). */
static tree
-tree_simplify_using_condition (tree cond, tree expr)
+tree_simplify_using_condition_1 (tree cond, tree expr)
{
bool changed;
- tree e, e0, e1, e2, notcond;
+ tree e, te, e0, e1, e2, notcond;
enum tree_code code = TREE_CODE (expr);
if (code == INTEGER_CST)
{
changed = false;
- e0 = tree_simplify_using_condition (cond, TREE_OPERAND (expr, 0));
+ e0 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 0));
if (TREE_OPERAND (expr, 0) != e0)
changed = true;
- e1 = tree_simplify_using_condition (cond, TREE_OPERAND (expr, 1));
+ e1 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 1));
if (TREE_OPERAND (expr, 1) != e1)
changed = true;
if (code == COND_EXPR)
{
- e2 = tree_simplify_using_condition (cond, TREE_OPERAND (expr, 2));
+ e2 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 2));
if (TREE_OPERAND (expr, 2) != e2)
changed = true;
}
return boolean_true_node;
}
+ te = expand_simple_operations (expr);
+
/* Check whether COND ==> EXPR. */
notcond = invert_truthvalue (cond);
- e = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
- notcond, expr);
+ e = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, notcond, te);
if (nonzero_p (e))
return e;
/* Check whether COND ==> not EXPR. */
- e = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
- cond, expr);
+ e = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, cond, te);
if (zero_p (e))
return e;
return expr;
}
+/* Tries to simplify EXPR using the condition COND. Returns the simplified
+ expression (or EXPR unchanged, if no simplification was possible).
+ Wrapper around tree_simplify_using_condition_1 that ensures that chains
+ of simple operations in definitions of ssa names in COND are expanded,
+ so that things like casts or incrementing the value of the bound before
+ the loop do not cause us to fail. */
+
+static tree
+tree_simplify_using_condition (tree cond, tree expr)
+{
+ cond = expand_simple_operations (cond);
+
+ return tree_simplify_using_condition_1 (cond, expr);
+}
+
/* Tries to simplify EXPR using the conditions on entry to LOOP.
Record the conditions used for simplification to CONDS_USED.
Returns the simplified expression (or EXPR unchanged, if no
&& !POINTER_TYPE_P (type))
return false;
- if (!simple_iv (loop, stmt, op0, &base0, &step0))
+ if (!simple_iv (loop, stmt, op0, &base0, &step0, false))
return false;
- if (!simple_iv (loop, stmt, op1, &base1, &step1))
+ if (!simple_iv (loop, stmt, op1, &base1, &step1, false))
return false;
niter->niter = NULL_TREE;
chain_of_csts_start (struct loop *loop, tree x)
{
tree stmt = SSA_NAME_DEF_STMT (x);
+ tree use;
basic_block bb = bb_for_stmt (stmt);
- use_optype uses;
if (!bb
|| !flow_bb_inside_loop_p (loop, bb))
if (TREE_CODE (stmt) != MODIFY_EXPR)
return NULL_TREE;
- get_stmt_operands (stmt);
- if (NUM_VUSES (STMT_VUSE_OPS (stmt)) > 0)
- return NULL_TREE;
- if (NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt)) > 0)
+ if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
return NULL_TREE;
- if (NUM_V_MUST_DEFS (STMT_V_MUST_DEF_OPS (stmt)) > 0)
+ if (SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF) == NULL_DEF_OPERAND_P)
return NULL_TREE;
- if (NUM_DEFS (STMT_DEF_OPS (stmt)) > 1)
- return NULL_TREE;
- uses = STMT_USE_OPS (stmt);
- if (NUM_USES (uses) != 1)
+
+ use = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_USE);
+ if (use == NULL_USE_OPERAND_P)
return NULL_TREE;
- return chain_of_csts_start (loop, USE_OP (uses, 0));
+ return chain_of_csts_start (loop, use);
}
/* Determines whether the expression X is derived from a result of a phi node
get_val_for (tree x, tree base)
{
tree stmt, nx, val;
- use_optype uses;
use_operand_p op;
+ ssa_op_iter iter;
if (!x)
return base;
if (TREE_CODE (stmt) == PHI_NODE)
return base;
- uses = STMT_USE_OPS (stmt);
- op = USE_OP_PTR (uses, 0);
-
- nx = USE_FROM_PTR (op);
- val = get_val_for (nx, base);
- SET_USE (op, val);
- val = fold (TREE_OPERAND (stmt, 1));
- SET_USE (op, nx);
+ FOR_EACH_SSA_USE_OPERAND (op, stmt, iter, SSA_OP_USE)
+ {
+ nx = USE_FROM_PTR (op);
+ val = get_val_for (nx, base);
+ SET_USE (op, val);
+ val = fold (TREE_OPERAND (stmt, 1));
+ SET_USE (op, nx);
+ /* only iterate loop once. */
+ return val;
+ }
- return val;
+ /* Should never reach here. */
+ gcc_unreachable();
}
/* Tries to count the number of iterations of LOOP till it exits by EXIT