stmt = gsi_stmt (si);
+ if (is_gimple_debug (stmt))
+ continue;
+
/* See if we can derive an assertion for any of STMT's operands. */
FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_USE)
{
based on undefined signed overflow, issue a warning if
appropriate. */
-tree
+static tree
vrp_evaluate_conditional (enum tree_code code, tree op0, tree op1, gimple stmt)
{
bool sop;
value range information we have for op0. */
if (min && max)
{
- if (compare_values (vr->min, min) == -1)
- min = min;
- else
+ if (compare_values (vr->min, min) == 1)
min = vr->min;
- if (compare_values (vr->max, max) == 1)
- max = max;
- else
+ if (compare_values (vr->max, max) == -1)
max = vr->max;
/* If the new min/max values have converged to a single value,
/* Simplify STMT using ranges if possible. */
-bool
+static bool
simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
{
gimple stmt = gsi_stmt (*gsi);
return false;
}
+/* If the statement pointed by SI has a predicate whose value can be
+ computed using the value range information computed by VRP, compute
+ its value and return true. Otherwise, return false. */
+
+static bool
+fold_predicate_in (gimple_stmt_iterator *si)
+{
+ bool assignment_p = false;
+ tree val;
+ gimple stmt = gsi_stmt (*si);
+
+ if (is_gimple_assign (stmt)
+ && TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_comparison)
+ {
+ assignment_p = true;
+ val = vrp_evaluate_conditional (gimple_assign_rhs_code (stmt),
+ gimple_assign_rhs1 (stmt),
+ gimple_assign_rhs2 (stmt),
+ stmt);
+ }
+ else if (gimple_code (stmt) == GIMPLE_COND)
+ val = vrp_evaluate_conditional (gimple_cond_code (stmt),
+ gimple_cond_lhs (stmt),
+ gimple_cond_rhs (stmt),
+ stmt);
+ else
+ return false;
+
+ if (val)
+ {
+ if (assignment_p)
+ val = fold_convert (gimple_expr_type (stmt), val);
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "Folding predicate ");
+ print_gimple_expr (dump_file, stmt, 0, 0);
+ fprintf (dump_file, " to ");
+ print_generic_expr (dump_file, val, 0);
+ fprintf (dump_file, "\n");
+ }
+
+ if (is_gimple_assign (stmt))
+ gimple_assign_set_rhs_from_tree (si, val);
+ else
+ {
+ gcc_assert (gimple_code (stmt) == GIMPLE_COND);
+ if (integer_zerop (val))
+ gimple_cond_make_false (stmt);
+ else if (integer_onep (val))
+ gimple_cond_make_true (stmt);
+ else
+ gcc_unreachable ();
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+/* Callback for substitute_and_fold folding the stmt at *SI. */
+
+static bool
+vrp_fold_stmt (gimple_stmt_iterator *si)
+{
+ if (fold_predicate_in (si))
+ return true;
+
+ return simplify_stmt_using_ranges (si);
+}
+
/* Stack of dest,src equivalency pairs that need to be restored after
each attempt to thread a block's incoming edge to an outgoing edge.
}
/* We may have ended with ranges that have exactly one value. Those
- values can be substituted as any other copy/const propagated
+ values can be substituted as any other const propagated
value using substitute_and_fold. */
single_val_range = XCNEWVEC (prop_value_t, num_ssa_names);
for (i = 0; i < num_ssa_names; i++)
if (vr_value[i]
&& vr_value[i]->type == VR_RANGE
- && vr_value[i]->min == vr_value[i]->max)
+ && vr_value[i]->min == vr_value[i]->max
+ && is_gimple_min_invariant (vr_value[i]->min))
{
single_val_range[i].value = vr_value[i]->min;
do_value_subst_p = true;
single_val_range = NULL;
}
- substitute_and_fold (single_val_range, true);
+ substitute_and_fold (single_val_range, vrp_fold_stmt);
if (warn_array_bounds)
check_all_array_refs ();