aboutsummaryrefslogtreecommitdiff
path: root/gcc/vr-values.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/vr-values.c')
-rw-r--r--gcc/vr-values.c160
1 files changed, 89 insertions, 71 deletions
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index e117f66..c999ca8 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -117,14 +117,16 @@ vr_values::get_lattice_entry (const_tree var)
default definitions of PARM_DECLs. */
if (POINTER_TYPE_P (TREE_TYPE (sym))
&& (nonnull_arg_p (sym)
- || get_ptr_nonnull (var)))
+ || (get_global_range_query ()->range_of_expr (*vr,
+ const_cast <tree> (var))
+ && vr->nonzero_p ())))
{
vr->set_nonzero (TREE_TYPE (sym));
vr->equiv_clear ();
}
else if (INTEGRAL_TYPE_P (TREE_TYPE (sym)))
{
- get_range_info (var, *vr);
+ get_global_range_query ()->range_of_expr (*vr, const_cast <tree> (var));
if (vr->undefined_p ())
vr->set_varying (TREE_TYPE (sym));
}
@@ -178,11 +180,11 @@ bool
vr_values::range_of_expr (irange &r, tree expr, gimple *stmt)
{
if (!gimple_range_ssa_p (expr))
- return get_tree_range (r, expr);
+ return get_tree_range (r, expr, stmt);
if (const value_range *vr = get_value_range (expr, stmt))
{
- if (vr->undefined_p () || vr->varying_p () || vr->constant_p ())
+ if (vr->undefined_p () || vr->constant_p ())
r = *vr;
else
{
@@ -262,7 +264,7 @@ vr_values::update_value_range (const_tree var, value_range_equiv *new_vr)
if (INTEGRAL_TYPE_P (TREE_TYPE (var)))
{
value_range_equiv nr;
- get_range_info (var, nr);
+ get_global_range_query ()->range_of_expr (nr, const_cast <tree> (var));
if (!nr.undefined_p ())
new_vr->intersect (&nr);
}
@@ -336,16 +338,17 @@ gimple_assign_nonzero_p (gimple *stmt)
{
enum tree_code code = gimple_assign_rhs_code (stmt);
bool strict_overflow_p;
+ tree type = TREE_TYPE (gimple_assign_lhs (stmt));
switch (get_gimple_rhs_class (code))
{
case GIMPLE_UNARY_RHS:
return tree_unary_nonzero_warnv_p (gimple_assign_rhs_code (stmt),
- gimple_expr_type (stmt),
+ type,
gimple_assign_rhs1 (stmt),
&strict_overflow_p);
case GIMPLE_BINARY_RHS:
return tree_binary_nonzero_warnv_p (gimple_assign_rhs_code (stmt),
- gimple_expr_type (stmt),
+ type,
gimple_assign_rhs1 (stmt),
gimple_assign_rhs2 (stmt),
&strict_overflow_p);
@@ -427,7 +430,7 @@ vr_values::vrp_stmt_computes_nonzero (gimple *stmt)
&& !TYPE_OVERFLOW_WRAPS (TREE_TYPE (expr))))
{
const value_range_equiv *vr
- = get_value_range (TREE_OPERAND (base, 0));
+ = get_value_range (TREE_OPERAND (base, 0), stmt);
if (!range_includes_zero_p (vr))
return true;
}
@@ -484,7 +487,7 @@ vr_values::op_with_constant_singleton_value_range (tree op)
/* Return true if op is in a boolean [0, 1] value-range. */
bool
-simplify_using_ranges::op_with_boolean_value_range_p (tree op)
+simplify_using_ranges::op_with_boolean_value_range_p (tree op, gimple *s)
{
if (TYPE_PRECISION (TREE_TYPE (op)) == 1)
return true;
@@ -498,7 +501,7 @@ simplify_using_ranges::op_with_boolean_value_range_p (tree op)
/* ?? Errr, this should probably check for [0,0] and [1,1] as well
as [0,1]. */
- const value_range *vr = query->get_value_range (op);
+ const value_range *vr = query->get_value_range (op, s);
return *vr == value_range (build_zero_cst (TREE_TYPE (op)),
build_one_cst (TREE_TYPE (op)));
}
@@ -697,7 +700,7 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var,
build_int_cst (TREE_TYPE (max), 1));
/* Signal to compare_values_warnv this expr doesn't overflow. */
if (EXPR_P (max))
- TREE_NO_WARNING (max) = 1;
+ suppress_warning (max, OPT_Woverflow);
}
vr_p->update (min, max);
@@ -737,7 +740,7 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var,
build_int_cst (TREE_TYPE (min), 1));
/* Signal to compare_values_warnv this expr doesn't overflow. */
if (EXPR_P (min))
- TREE_NO_WARNING (min) = 1;
+ suppress_warning (min, OPT_Woverflow);
}
vr_p->update (min, max);
@@ -1023,7 +1026,7 @@ vr_values::extract_range_from_comparison (value_range_equiv *vr,
gimple *stmt)
{
enum tree_code code = gimple_assign_rhs_code (stmt);
- tree type = gimple_expr_type (stmt);
+ tree type = TREE_TYPE (gimple_assign_lhs (stmt));
tree op0 = gimple_assign_rhs1 (stmt);
tree op1 = gimple_assign_rhs2 (stmt);
bool sop;
@@ -1055,18 +1058,18 @@ vr_values::extract_range_from_comparison (value_range_equiv *vr,
static bool
check_for_binary_op_overflow (range_query *query,
enum tree_code subcode, tree type,
- tree op0, tree op1, bool *ovf)
+ tree op0, tree op1, bool *ovf, gimple *s = NULL)
{
value_range vr0, vr1;
if (TREE_CODE (op0) == SSA_NAME)
- vr0 = *query->get_value_range (op0);
+ vr0 = *query->get_value_range (op0, s);
else if (TREE_CODE (op0) == INTEGER_CST)
vr0.set (op0);
else
vr0.set_varying (TREE_TYPE (op0));
if (TREE_CODE (op1) == SSA_NAME)
- vr1 = *query->get_value_range (op1);
+ vr1 = *query->get_value_range (op1, s);
else if (TREE_CODE (op1) == INTEGER_CST)
vr1.set (op1);
else
@@ -1162,7 +1165,6 @@ bool
vr_values::extract_range_from_ubsan_builtin (value_range_equiv *vr, gimple *stmt)
{
gcc_assert (is_gimple_call (stmt));
- tree type = gimple_expr_type (stmt);
enum tree_code subcode = ERROR_MARK;
combined_fn cfn = gimple_call_combined_fn (stmt);
scalar_int_mode mode;
@@ -1188,7 +1190,8 @@ vr_values::extract_range_from_ubsan_builtin (value_range_equiv *vr, gimple *stmt
any overflow, we'll complain, but will actually do
wrapping operation. */
flag_wrapv = 1;
- extract_range_from_binary_expr (vr, subcode, type,
+ extract_range_from_binary_expr (vr, subcode,
+ TREE_TYPE (gimple_call_arg (stmt, 0)),
gimple_call_arg (stmt, 0),
gimple_call_arg (stmt, 1));
flag_wrapv = saved_flag_wrapv;
@@ -1215,7 +1218,6 @@ void
vr_values::extract_range_basic (value_range_equiv *vr, gimple *stmt)
{
bool sop;
- tree type = gimple_expr_type (stmt);
if (is_gimple_call (stmt))
{
@@ -1229,7 +1231,7 @@ vr_values::extract_range_basic (value_range_equiv *vr, gimple *stmt)
return;
break;
default:
- if (range_of_builtin_call (*this, *vr, as_a<gcall *> (stmt)))
+ if (fold_range (*vr, stmt, this))
{
/* The original code nuked equivalences every time a
range was found, so do the same here. */
@@ -1242,13 +1244,14 @@ vr_values::extract_range_basic (value_range_equiv *vr, gimple *stmt)
/* Handle extraction of the two results (result of arithmetics and
a flag whether arithmetics overflowed) from {ADD,SUB,MUL}_OVERFLOW
internal function. Similarly from ATOMIC_COMPARE_EXCHANGE. */
- else if (is_gimple_assign (stmt)
- && (gimple_assign_rhs_code (stmt) == REALPART_EXPR
- || gimple_assign_rhs_code (stmt) == IMAGPART_EXPR)
- && INTEGRAL_TYPE_P (type))
+ if (is_gimple_assign (stmt)
+ && (gimple_assign_rhs_code (stmt) == REALPART_EXPR
+ || gimple_assign_rhs_code (stmt) == IMAGPART_EXPR)
+ && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (stmt))))
{
enum tree_code code = gimple_assign_rhs_code (stmt);
tree op = gimple_assign_rhs1 (stmt);
+ tree type = TREE_TYPE (gimple_assign_lhs (stmt));
if (TREE_CODE (op) == code && TREE_CODE (TREE_OPERAND (op, 0)) == SSA_NAME)
{
gimple *g = SSA_NAME_DEF_STMT (TREE_OPERAND (op, 0));
@@ -1326,6 +1329,9 @@ vr_values::extract_range_basic (value_range_equiv *vr, gimple *stmt)
}
}
}
+ /* None of the below should need a 'type', but we are only called
+ for assignments and calls with a LHS. */
+ tree type = TREE_TYPE (gimple_get_lhs (stmt));
if (INTEGRAL_TYPE_P (type)
&& gimple_stmt_nonnegative_warnv_p (stmt, &sop))
set_value_range_to_nonnegative (vr, type);
@@ -1353,12 +1359,12 @@ vr_values::extract_range_from_assignment (value_range_equiv *vr, gassign *stmt)
extract_range_from_ssa_name (vr, gimple_assign_rhs1 (stmt));
else if (TREE_CODE_CLASS (code) == tcc_binary)
extract_range_from_binary_expr (vr, gimple_assign_rhs_code (stmt),
- gimple_expr_type (stmt),
+ TREE_TYPE (gimple_assign_lhs (stmt)),
gimple_assign_rhs1 (stmt),
gimple_assign_rhs2 (stmt));
else if (TREE_CODE_CLASS (code) == tcc_unary)
extract_range_from_unary_expr (vr, gimple_assign_rhs_code (stmt),
- gimple_expr_type (stmt),
+ TREE_TYPE (gimple_assign_lhs (stmt)),
gimple_assign_rhs1 (stmt));
else if (code == COND_EXPR)
extract_range_from_cond_expr (vr, stmt);
@@ -1650,6 +1656,9 @@ bounds_of_var_in_loop (tree *min, tree *max, range_query *query,
init = initial_condition_in_loop_num (chrec, loop->num);
step = evolution_part_in_loop_num (chrec, loop->num);
+ if (!init || !step)
+ return false;
+
/* If INIT is an SSA with a singleton range, set INIT to said
singleton, otherwise leave INIT alone. */
if (TREE_CODE (init) == SSA_NAME)
@@ -1816,7 +1825,7 @@ vr_values::adjust_range_with_scev (value_range_equiv *vr, class loop *loop,
/* Dump value ranges of all SSA_NAMEs to FILE. */
void
-vr_values::dump_all_value_ranges (FILE *file)
+vr_values::dump (FILE *file)
{
size_t i;
@@ -1975,10 +1984,11 @@ vr_values::vrp_visit_assignment_or_call (gimple *stmt, tree *output_p,
is varying or undefined. Uses TEM as storage for the alternate range. */
const value_range_equiv *
-simplify_using_ranges::get_vr_for_comparison (int i, value_range_equiv *tem)
+simplify_using_ranges::get_vr_for_comparison (int i, value_range_equiv *tem,
+ gimple *s)
{
/* Shallow-copy equiv bitmap. */
- const value_range_equiv *vr = query->get_value_range (ssa_name (i));
+ const value_range_equiv *vr = query->get_value_range (ssa_name (i), s);
/* If name N_i does not have a valid range, use N_i as its own
range. This allows us to compare against names that may
@@ -2000,10 +2010,11 @@ simplify_using_ranges::get_vr_for_comparison (int i, value_range_equiv *tem)
tree
simplify_using_ranges::compare_name_with_value
(enum tree_code comp, tree var, tree val,
- bool *strict_overflow_p, bool use_equiv_p)
+ bool *strict_overflow_p, bool use_equiv_p,
+ gimple *s)
{
/* Get the set of equivalences for VAR. */
- bitmap e = query->get_value_range (var)->equiv ();
+ bitmap e = query->get_value_range (var, s)->equiv ();
/* Start at -1. Set it to 0 if we do a comparison without relying
on overflow, or 1 if all comparisons rely on overflow. */
@@ -2012,7 +2023,7 @@ simplify_using_ranges::compare_name_with_value
/* Compare vars' value range with val. */
value_range_equiv tem_vr;
const value_range_equiv *equiv_vr
- = get_vr_for_comparison (SSA_NAME_VERSION (var), &tem_vr);
+ = get_vr_for_comparison (SSA_NAME_VERSION (var), &tem_vr, s);
bool sop = false;
tree retval = compare_range_with_value (comp, equiv_vr, val, &sop);
if (retval)
@@ -2039,7 +2050,7 @@ simplify_using_ranges::compare_name_with_value
&& prop_simulate_again_p (SSA_NAME_DEF_STMT (name)))
continue;
- equiv_vr = get_vr_for_comparison (i, &tem_vr);
+ equiv_vr = get_vr_for_comparison (i, &tem_vr, s);
sop = false;
tree t = compare_range_with_value (comp, equiv_vr, val, &sop);
if (t)
@@ -2079,12 +2090,12 @@ simplify_using_ranges::compare_name_with_value
tree
simplify_using_ranges::compare_names (enum tree_code comp, tree n1, tree n2,
- bool *strict_overflow_p)
+ bool *strict_overflow_p, gimple *s)
{
/* Compare the ranges of every name equivalent to N1 against the
ranges of every name equivalent to N2. */
- bitmap e1 = query->get_value_range (n1)->equiv ();
- bitmap e2 = query->get_value_range (n2)->equiv ();
+ bitmap e1 = query->get_value_range (n1, s)->equiv ();
+ bitmap e2 = query->get_value_range (n2, s)->equiv ();
/* Use the fake bitmaps if e1 or e2 are not available. */
static bitmap s_e1 = NULL, s_e2 = NULL;
@@ -2134,7 +2145,7 @@ simplify_using_ranges::compare_names (enum tree_code comp, tree n1, tree n2,
continue;
value_range_equiv tem_vr1;
- const value_range_equiv *vr1 = get_vr_for_comparison (i1, &tem_vr1);
+ const value_range_equiv *vr1 = get_vr_for_comparison (i1, &tem_vr1, s);
tree t = NULL_TREE, retval = NULL_TREE;
bitmap_iterator bi2;
@@ -2147,7 +2158,8 @@ simplify_using_ranges::compare_names (enum tree_code comp, tree n1, tree n2,
bool sop = false;
value_range_equiv tem_vr2;
- const value_range_equiv *vr2 = get_vr_for_comparison (i2, &tem_vr2);
+ const value_range_equiv *vr2 = get_vr_for_comparison (i2, &tem_vr2,
+ s);
t = compare_ranges (comp, vr1, vr2, &sop);
if (t)
@@ -2193,11 +2205,12 @@ simplify_using_ranges::compare_names (enum tree_code comp, tree n1, tree n2,
tree
simplify_using_ranges::vrp_evaluate_conditional_warnv_with_ops_using_ranges
- (enum tree_code code, tree op0, tree op1, bool * strict_overflow_p)
+ (enum tree_code code, tree op0, tree op1, bool * strict_overflow_p,
+ gimple *s)
{
const value_range_equiv *vr0, *vr1;
- vr0 = (TREE_CODE (op0) == SSA_NAME) ? query->get_value_range (op0) : NULL;
- vr1 = (TREE_CODE (op1) == SSA_NAME) ? query->get_value_range (op1) : NULL;
+ vr0 = (TREE_CODE (op0) == SSA_NAME) ? query->get_value_range (op0, s) : NULL;
+ vr1 = (TREE_CODE (op1) == SSA_NAME) ? query->get_value_range (op1, s) : NULL;
tree res = NULL_TREE;
if (vr0 && vr1)
@@ -2297,20 +2310,20 @@ simplify_using_ranges::vrp_evaluate_conditional_warnv_with_ops
}
if ((ret = vrp_evaluate_conditional_warnv_with_ops_using_ranges
- (code, op0, op1, strict_overflow_p)))
+ (code, op0, op1, strict_overflow_p, stmt)))
return ret;
if (only_ranges)
*only_ranges = false;
/* Do not use compare_names during propagation, it's quadratic. */
if (TREE_CODE (op0) == SSA_NAME && TREE_CODE (op1) == SSA_NAME
&& use_equiv_p)
- return compare_names (code, op0, op1, strict_overflow_p);
+ return compare_names (code, op0, op1, strict_overflow_p, stmt);
else if (TREE_CODE (op0) == SSA_NAME)
return compare_name_with_value (code, op0, op1,
- strict_overflow_p, use_equiv_p);
+ strict_overflow_p, use_equiv_p, stmt);
else if (TREE_CODE (op1) == SSA_NAME)
return compare_name_with_value (swap_tree_comparison (code), op1, op0,
- strict_overflow_p, use_equiv_p);
+ strict_overflow_p, use_equiv_p, stmt);
return NULL_TREE;
}
@@ -2924,11 +2937,11 @@ simplify_using_ranges::simplify_truth_ops_using_ranges
gcc_assert (rhs_code == EQ_EXPR || rhs_code == NE_EXPR);
op0 = gimple_assign_rhs1 (stmt);
- if (!op_with_boolean_value_range_p (op0))
+ if (!op_with_boolean_value_range_p (op0, stmt))
return false;
op1 = gimple_assign_rhs2 (stmt);
- if (!op_with_boolean_value_range_p (op1))
+ if (!op_with_boolean_value_range_p (op1, stmt))
return false;
/* Reduce number of cases to handle to NE_EXPR. As there is no
@@ -3126,12 +3139,12 @@ simplify_using_ranges::simplify_min_or_max_using_ranges
tree val;
val = (vrp_evaluate_conditional_warnv_with_ops_using_ranges
- (LE_EXPR, op0, op1, &sop));
+ (LE_EXPR, op0, op1, &sop, stmt));
if (!val)
{
sop = false;
val = (vrp_evaluate_conditional_warnv_with_ops_using_ranges
- (LT_EXPR, op0, op1, &sop));
+ (LT_EXPR, op0, op1, &sop, stmt));
}
if (val)
@@ -3350,7 +3363,7 @@ test_for_singularity (enum tree_code cond_code, tree op0,
max = fold_build2 (MINUS_EXPR, TREE_TYPE (op0), max, one);
/* Signal to compare_values_warnv this expr doesn't overflow. */
if (EXPR_P (max))
- TREE_NO_WARNING (max) = 1;
+ suppress_warning (max, OPT_Woverflow);
}
}
else if (cond_code == GE_EXPR || cond_code == GT_EXPR)
@@ -3364,7 +3377,7 @@ test_for_singularity (enum tree_code cond_code, tree op0,
min = fold_build2 (PLUS_EXPR, TREE_TYPE (op0), min, one);
/* Signal to compare_values_warnv this expr doesn't overflow. */
if (EXPR_P (min))
- TREE_NO_WARNING (min) = 1;
+ suppress_warning (min, OPT_Woverflow);
}
}
@@ -3447,11 +3460,6 @@ range_fits_type_p (const value_range *vr,
bool
simplify_using_ranges::fold_cond (gcond *cond)
{
- /* ?? vrp_folder::fold_predicate_in() is a superset of this. At
- some point we should merge all variants of this code. */
- edge taken_edge;
- vrp_visit_cond_stmt (cond, &taken_edge);
-
int_range_max r;
if (query->range_of_stmt (r, cond) && r.singleton_p ())
{
@@ -3462,17 +3470,13 @@ simplify_using_ranges::fold_cond (gcond *cond)
if (r.zero_p ())
{
- gcc_checking_assert (!taken_edge
- || taken_edge->flags & EDGE_FALSE_VALUE);
- if (dump_file && (dump_flags & TDF_DETAILS) && !taken_edge)
+ if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\nPredicate evaluates to: 0\n");
gimple_cond_make_false (cond);
}
else
{
- gcc_checking_assert (!taken_edge
- || taken_edge->flags & EDGE_TRUE_VALUE);
- if (dump_file && (dump_flags & TDF_DETAILS) && !taken_edge)
+ if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\nPredicate evaluates to: 1\n");
gimple_cond_make_true (cond);
}
@@ -3480,12 +3484,25 @@ simplify_using_ranges::fold_cond (gcond *cond)
return true;
}
+ /* ?? vrp_folder::fold_predicate_in() is a superset of this. At
+ some point we should merge all variants of this code. */
+ edge taken_edge;
+ vrp_visit_cond_stmt (cond, &taken_edge);
+
if (taken_edge)
{
if (taken_edge->flags & EDGE_TRUE_VALUE)
- gimple_cond_make_true (cond);
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "\nVRP Predicate evaluates to: 1\n");
+ gimple_cond_make_true (cond);
+ }
else if (taken_edge->flags & EDGE_FALSE_VALUE)
- gimple_cond_make_false (cond);
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "\nVRP Predicate evaluates to: 0\n");
+ gimple_cond_make_false (cond);
+ }
else
gcc_unreachable ();
update_stmt (cond);
@@ -3826,13 +3843,13 @@ simplify_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
|| SSA_NAME_OCCURS_IN_ABNORMAL_PHI (innerop))
return false;
- /* Get the value-range of the inner operand. Use get_range_info in
+ /* Get the value-range of the inner operand. Use global ranges in
case innerop was created during substitute-and-fold. */
wide_int imin, imax;
value_range vr;
if (!INTEGRAL_TYPE_P (TREE_TYPE (innerop)))
return false;
- get_range_info (innerop, vr);
+ get_range_query (cfun)->range_of_expr (vr, innerop, stmt);
if (vr.undefined_p () || vr.varying_p ())
return false;
innermin = widest_int::from (vr.lower_bound (), TYPE_SIGN (TREE_TYPE (innerop)));
@@ -3995,7 +4012,7 @@ simplify_using_ranges::simplify_internal_call_using_ranges
return false;
else
type = TREE_TYPE (TREE_TYPE (gimple_call_lhs (stmt)));
- if (!check_for_binary_op_overflow (query, subcode, type, op0, op1, &ovf)
+ if (!check_for_binary_op_overflow (query, subcode, type, op0, op1, &ovf, stmt)
|| (is_ubsan && ovf))
return false;
@@ -4052,9 +4069,10 @@ simplify_using_ranges::simplify_internal_call_using_ranges
two-values when it is true. Return false otherwise. */
bool
-simplify_using_ranges::two_valued_val_range_p (tree var, tree *a, tree *b)
+simplify_using_ranges::two_valued_val_range_p (tree var, tree *a, tree *b,
+ gimple *s)
{
- value_range vr = *query->get_value_range (var);
+ value_range vr = *query->get_value_range (var, s);
vr.normalize_symbolics ();
if (vr.varying_p () || vr.undefined_p ())
return false;
@@ -4128,7 +4146,7 @@ simplify_using_ranges::simplify (gimple_stmt_iterator *gsi)
tree cmp_var = NULL_TREE;
if (TREE_CODE (rhs2) == SSA_NAME
- && two_valued_val_range_p (rhs2, &val1, &val2))
+ && two_valued_val_range_p (rhs2, &val1, &val2, stmt))
{
/* Optimize RHS1 OP [VAL1, VAL2]. */
new_rhs1 = int_const_binop (rhs_code, rhs1, val1);
@@ -4136,7 +4154,7 @@ simplify_using_ranges::simplify (gimple_stmt_iterator *gsi)
cmp_var = rhs2;
}
else if (TREE_CODE (rhs1) == SSA_NAME
- && two_valued_val_range_p (rhs1, &val1, &val2))
+ && two_valued_val_range_p (rhs1, &val1, &val2, stmt))
{
/* Optimize [VAL1, VAL2] OP RHS2. */
new_rhs1 = int_const_binop (rhs_code, val1, rhs2);