commit 9ad503e1d6a2edd8b74b1d8cc9a8d9d4ee31386e Author: Aldy Hernandez Date: Mon Jul 8 12:45:40 2019 +0200 Allow min/max in VR_VARYING and VR_UNDEFINED ranges. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b0d78ee6871..2cb308bb568 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,62 @@ +2019-07-01 Aldy Hernandez + + * gimple-ssa-evrp-analyze.c (record_ranges_from_phis): Skip PHIs + who's result are not valid for a value_range. + Set type for varying value_range. + * tree-ssa-threadedge.c (record_temporary_equivalences_from_phis): + Same. + * tree-ssanames.c (get_range_info): Same. + * tree-vrp.c (value_range_base::value_range_base): New constructor. + (value_range_base::check): Remove assert for empty min/max. + (value_range_base::equal_p): Allow comparison of typeless undefs. + (value_range_base::set_undefined): Add type. + (value_range::set_undefined): Same. + (value_range_base::set_varying): Same. + (value_range::set_varying): Same. + (value_range_base::type): Remove assert. + (value_range_base::dump): Display type for varying/undef. + (value_range_base::dump): Add argument-less overload. + (value_range::dump): Same. + (vrp_val_max): Add handle_pointers argument. + (vrp_val_min): Same. + (vrp_val_is_max): Same. + (vrp_val_is_min): Same. + (value_range_base::set_and_canonicalize): Adjust so type is + allowed for varying/undef. + (ranges_from_anti_range): Same. + (extract_range_from_muliplicative_op): Same. + (extract_range_from_binary_expr): Same. + (extract_range_from_unary_expr): Same. + (vrp_prop::vrp_initialize): Same. + (vrp_prop::visit_stmt): Same. + (value_range_base::union_helper): Same. + (value_range_base::normalize_symbolics): Same. + (determine_value_range_1): Same. + * tree-vrp.h (value_range_base): Add value_range_base(tree type) + constructor. + Add dump (), supports_type_p, + value_range_base_normalize_symbolics, set_varying, and + set_undefined. + (value_range): Add set_varying, set_undefined, and dump(). + (vrp_val_is_min): Add argument. + (vrp_val_is_max): Same. + (vrp_val_min): Same. + (vrp_val_max): Same. + (range_includes_zero_p): Adjust for varying/undef with types. + * vr-values.c (set_value_range_to_truthvalue): Adjust for + varying/undef with types. + (get_value_range): Same. + (vr_values::set_defs_to_varying): Same. + (vr_values::update_value_range): Same. + (extract_range_for_var_from_comparison_expr): Same. + (extract_range_from_binary_expr): Same. + (extract_range_from_cond_expr): Same. + (check_for_binary_op_overflow): Same. + (extract_range_basic): Same. + (extract_range_from_assignment): Same. + (extract_range_from_phi_node): Adjust for varying/undef with + types. + 2019-07-01 Aldy Hernandez * tree-vrp.c (intersect_ranges): If we know the intersection is diff --git a/gcc/gimple-ssa-evrp-analyze.c b/gcc/gimple-ssa-evrp-analyze.c index 4c68af847e1..467ca57061f 100644 --- a/gcc/gimple-ssa-evrp-analyze.c +++ b/gcc/gimple-ssa-evrp-analyze.c @@ -251,6 +251,11 @@ evrp_range_analyzer::record_ranges_from_phis (basic_block bb) if (virtual_operand_p (lhs)) continue; + /* Skips floats and other things we can't represent in a + range. */ + if (!value_range_base::supports_type_p (TREE_TYPE (lhs))) + continue; + value_range vr_result; bool interesting = stmt_interesting_for_vrp (phi); if (!has_unvisited_preds && interesting) diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c index 785227df690..781f802f365 100644 --- a/gcc/tree-ssa-threadedge.c +++ b/gcc/tree-ssa-threadedge.c @@ -183,7 +183,7 @@ record_temporary_equivalences_from_phis (edge e, else if (TREE_CODE (src) == INTEGER_CST) new_vr->set (src); else - new_vr->set_varying (); + new_vr->set_varying (TREE_TYPE (src)); /* This is a temporary range for DST, so push it. */ evrp_range_analyzer->push_value_range (dst, new_vr); diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index 8b80bce8945..343e98488a9 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -440,14 +440,16 @@ get_range_info (const_tree name, value_range_base &vr) wide_int wmin, wmax; enum value_range_kind kind = get_range_info (name, &wmin, &wmax); - if (kind == VR_VARYING || kind == VR_UNDEFINED) - min = max = NULL; + if (kind == VR_VARYING) + vr.set_varying (TREE_TYPE (name)); + else if (kind == VR_UNDEFINED) + vr.set_undefined (TREE_TYPE (name)); else { min = wide_int_to_tree (TREE_TYPE (name), wmin); max = wide_int_to_tree (TREE_TYPE (name), wmax); + vr.set (kind, min, max); } - vr.set (kind, min, max); return kind; } diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 594ee9adc17..c5a18686909 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -134,6 +134,11 @@ value_range::value_range (const value_range_base &other) set (other.kind (), other.min(), other.max (), NULL); } +value_range_base::value_range_base (tree type) +{ + set_varying (type); +} + /* Like set, but keep the equivalences in place. */ void @@ -190,7 +195,6 @@ value_range_base::check () } case VR_UNDEFINED: case VR_VARYING: - gcc_assert (!min () && !max ()); break; default: gcc_unreachable (); @@ -217,6 +221,10 @@ value_range::check () bool value_range_base::equal_p (const value_range_base &other) const { + /* Ignore types for undefined. All undefines are equal. */ + if (undefined_p ()) + return m_kind == other.m_kind; + return (m_kind == other.m_kind && vrp_operand_equal_p (m_min, other.m_min) && vrp_operand_equal_p (m_max, other.m_max)); @@ -259,27 +267,43 @@ value_range_base::constant_p () const } void -value_range_base::set_undefined () +value_range_base::set_undefined (tree type) { - set (VR_UNDEFINED, NULL, NULL); + m_kind = VR_UNDEFINED; + if (type) + { + m_min = vrp_val_min (type, true); + m_max = vrp_val_max (type, true); + } + else + m_min = m_max = NULL; } void -value_range::set_undefined () +value_range::set_undefined (tree type) { - set (VR_UNDEFINED, NULL, NULL, NULL); + value_range_base::set_undefined (type); + equiv_clear (); } void -value_range_base::set_varying () +value_range_base::set_varying (tree type) { - set (VR_VARYING, NULL, NULL); + m_kind = VR_VARYING; + if (type) + { + m_min = vrp_val_min (type, true); + m_max = vrp_val_max (type, true); + } + else + m_min = m_max = NULL; } void -value_range::set_varying () +value_range::set_varying (tree type) { - set (VR_VARYING, NULL, NULL, NULL); + value_range_base::set_varying (type); + equiv_clear (); } /* Return TRUE if it is possible that range contains VAL. */ @@ -338,21 +362,29 @@ value_range_base::singleton_p (tree *result) const tree value_range_base::type () const { - /* Types are only valid for VR_RANGE and VR_ANTI_RANGE, which are - known to have non-zero min/max. */ - gcc_assert (min ()); return TREE_TYPE (min ()); } void value_range_base::dump (FILE *file) const { + tree ttype; + if (m_min) + ttype = TREE_TYPE (m_min); + else + ttype = NULL; + if (undefined_p ()) - fprintf (file, "UNDEFINED"); + { + if (ttype) + { + print_generic_expr (file, ttype); + fprintf (file, " "); + } + fprintf (file, "UNDEFINED"); + } else if (m_kind == VR_RANGE || m_kind == VR_ANTI_RANGE) { - tree ttype = type (); - print_generic_expr (file, ttype); fprintf (file, " "); @@ -378,11 +410,24 @@ value_range_base::dump (FILE *file) const fprintf (file, "]"); } else if (varying_p ()) - fprintf (file, "VARYING"); + { + if (ttype) + { + print_generic_expr (file, ttype); + fprintf (file, " "); + } + fprintf (file, "VARYING"); + } else gcc_unreachable (); } +void +value_range_base::dump () const +{ + dump (stderr); +} + void value_range::dump (FILE *file) const { @@ -406,6 +451,12 @@ value_range::dump (FILE *file) const } } +void +value_range::dump () const +{ + dump (stderr); +} + void dump_value_range (FILE *file, const value_range *vr) { @@ -499,10 +550,18 @@ static assert_locus **asserts_for; /* Return the maximum value for TYPE. */ tree -vrp_val_max (const_tree type) +vrp_val_max (const_tree type, bool handle_pointers) { if (!INTEGRAL_TYPE_P (type)) - return NULL_TREE; + { + if (POINTER_TYPE_P (type) && handle_pointers) + { + wide_int max = wi::max_value (TYPE_PRECISION (type), + TYPE_SIGN (type)); + return wide_int_to_tree (const_cast (type), max); + } + return NULL_TREE; + } return TYPE_MAX_VALUE (type); } @@ -510,23 +569,22 @@ vrp_val_max (const_tree type) /* Return the minimum value for TYPE. */ tree -vrp_val_min (const_tree type) +vrp_val_min (const_tree type, bool handle_pointers) { if (!INTEGRAL_TYPE_P (type)) - return NULL_TREE; + { + if (POINTER_TYPE_P (type) && handle_pointers) + return build_zero_cst (const_cast (type)); + return NULL_TREE; + } return TYPE_MIN_VALUE (type); } -/* Return whether VAL is equal to the maximum value of its type. - We can't do a simple equality comparison with TYPE_MAX_VALUE because - C typedefs and Ada subtypes can produce types whose TYPE_MAX_VALUE - is not == to the integer constant with the same value in the type. */ - bool -vrp_val_is_max (const_tree val) +vrp_val_is_max (const_tree val, bool handle_pointers) { - tree type_max = vrp_val_max (TREE_TYPE (val)); + tree type_max = vrp_val_max (TREE_TYPE (val), handle_pointers); return (val == type_max || (type_max != NULL_TREE && operand_equal_p (val, type_max, 0))); @@ -535,9 +593,9 @@ vrp_val_is_max (const_tree val) /* Return whether VAL is equal to the minimum value of its type. */ bool -vrp_val_is_min (const_tree val) +vrp_val_is_min (const_tree val, bool handle_pointers) { - tree type_min = vrp_val_min (TREE_TYPE (val)); + tree type_min = vrp_val_min (TREE_TYPE (val), handle_pointers); return (val == type_min || (type_min != NULL_TREE && operand_equal_p (val, type_min, 0))); @@ -629,15 +687,20 @@ void value_range_base::set_and_canonicalize (enum value_range_kind kind, tree min, tree max) { - /* Use the canonical setters for VR_UNDEFINED and VR_VARYING. */ if (kind == VR_UNDEFINED) { - set_undefined (); + if (min) + set_undefined (TREE_TYPE (min)); + else + set_undefined (); return; } else if (kind == VR_VARYING) { - set_varying (); + if (min) + set_varying (TREE_TYPE (min)); + else + set_varying (); return; } @@ -660,7 +723,7 @@ value_range_base::set_and_canonicalize (enum value_range_kind kind, for VR_ANTI_RANGE empty range, so drop to varying as well. */ if (TYPE_PRECISION (TREE_TYPE (min)) == 1) { - set_varying (); + set_varying (TREE_TYPE (min)); return; } @@ -674,7 +737,7 @@ value_range_base::set_and_canonicalize (enum value_range_kind kind, to varying in this case. */ if (tree_int_cst_lt (max, min)) { - set_varying (); + set_varying (TREE_TYPE (min)); return; } @@ -696,7 +759,7 @@ value_range_base::set_and_canonicalize (enum value_range_kind kind, { /* We cannot deal with empty ranges, drop to varying. ??? This could be VR_UNDEFINED instead. */ - set_varying (); + set_varying (type); return; } else if (TYPE_PRECISION (TREE_TYPE (min)) == 1 @@ -1178,8 +1241,8 @@ ranges_from_anti_range (const value_range_base *ar, { tree type = ar->type (); - vr0->set_undefined (); - vr1->set_undefined (); + vr0->set_undefined (type); + vr1->set_undefined (type); /* As a future improvement, we could handle ~[0, A] as: [-INF, -1] U [A+1, +INF]. Not sure if this helps in practice, though. */ @@ -1202,7 +1265,7 @@ ranges_from_anti_range (const value_range_base *ar, if (vr0->undefined_p ()) { *vr0 = *vr1; - vr1->set_undefined (); + vr1->set_undefined (type); } return !vr0->undefined_p (); @@ -1240,7 +1303,8 @@ static void extract_range_from_multiplicative_op (value_range_base *vr, enum tree_code code, const value_range_base *vr0, - const value_range_base *vr1) + const value_range_base *vr1, + tree type) { gcc_assert (code == MULT_EXPR || code == TRUNC_DIV_EXPR @@ -1250,13 +1314,31 @@ extract_range_from_multiplicative_op (value_range_base *vr, || code == ROUND_DIV_EXPR || code == RSHIFT_EXPR || code == LSHIFT_EXPR); - gcc_assert (vr0->kind () == VR_RANGE - && vr0->kind () == vr1->kind ()); + if (!range_int_cst_p (vr1)) + { + vr->set_varying (type); + return; + } + + /* Even if vr0 is VARYING or otherwise not usable, we can derive + useful ranges just from the shift count. E.g. + x >> 63 for signed 64-bit x is always [-1, 0]. */ + value_range_base tem = vr0->normalize_symbolics (type); + tree vr0_min, vr0_max; + if (tem.kind () == VR_RANGE) + { + vr0_min = tem.min (); + vr0_max = tem.max (); + } + else + { + vr0_min = vrp_val_min (type); + vr0_max = vrp_val_max (type); + } - tree type = vr0->type (); wide_int res_lb, res_ub; - wide_int vr0_lb = wi::to_wide (vr0->min ()); - wide_int vr0_ub = wi::to_wide (vr0->max ()); + wide_int vr0_lb = wi::to_wide (vr0_min); + wide_int vr0_ub = wi::to_wide (vr0_max); wide_int vr1_lb = wi::to_wide (vr1->min ()); wide_int vr1_ub = wi::to_wide (vr1->max ()); bool overflow_undefined = TYPE_OVERFLOW_UNDEFINED (type); @@ -1270,7 +1352,7 @@ extract_range_from_multiplicative_op (value_range_base *vr, wide_int_to_tree (type, res_lb), wide_int_to_tree (type, res_ub)); else - vr->set_varying (); + vr->set_varying (type); } /* If BOUND will include a symbolic bound, adjust it accordingly, @@ -1479,7 +1561,7 @@ extract_range_from_binary_expr (value_range_base *vr, if (!INTEGRAL_TYPE_P (expr_type) && !POINTER_TYPE_P (expr_type)) { - vr->set_varying (); + vr->set_varying (expr_type); return; } @@ -1503,14 +1585,14 @@ extract_range_from_binary_expr (value_range_base *vr, && code != BIT_IOR_EXPR && code != BIT_XOR_EXPR) { - vr->set_varying (); + vr->set_varying (expr_type); return; } /* If both ranges are UNDEFINED, so is the result. */ if (vr0.undefined_p () && vr1.undefined_p ()) { - vr->set_undefined (); + vr->set_undefined (expr_type); return; } /* If one of the ranges is UNDEFINED drop it to VARYING for the following @@ -1518,9 +1600,9 @@ extract_range_from_binary_expr (value_range_base *vr, have UNDEFINED result for all or some value-ranges of the not UNDEFINED operand. */ else if (vr0.undefined_p ()) - vr0.set_varying (); + vr0.set_varying (expr_type); else if (vr1.undefined_p ()) - vr1.set_varying (); + vr1.set_varying (expr_type); /* We get imprecise results from ranges_from_anti_range when code is EXACT_DIV_EXPR. We could mask out bits in the resulting @@ -1592,7 +1674,7 @@ extract_range_from_binary_expr (value_range_base *vr, || vr0.symbolic_p () || vr1.symbolic_p ())) { - vr->set_varying (); + vr->set_varying (expr_type); return; } @@ -1610,7 +1692,7 @@ extract_range_from_binary_expr (value_range_base *vr, else if (vr0.zero_p () && vr1.zero_p ()) vr->set_zero (expr_type); else - vr->set_varying (); + vr->set_varying (expr_type); } else if (code == POINTER_PLUS_EXPR) { @@ -1639,7 +1721,7 @@ extract_range_from_binary_expr (value_range_base *vr, else if (vr0.zero_p () && vr1.zero_p ()) vr->set_zero (expr_type); else - vr->set_varying (); + vr->set_varying (expr_type); } else if (code == BIT_AND_EXPR) { @@ -1650,10 +1732,10 @@ extract_range_from_binary_expr (value_range_base *vr, else if (vr0.zero_p () || vr1.zero_p ()) vr->set_zero (expr_type); else - vr->set_varying (); + vr->set_varying (expr_type); } else - vr->set_varying (); + vr->set_varying (expr_type); return; } @@ -1720,7 +1802,7 @@ extract_range_from_binary_expr (value_range_base *vr, if (((bool)min_ovf && sym_min_op0 != sym_min_op1) || ((bool)max_ovf && sym_max_op0 != sym_max_op1)) { - vr->set_varying (); + vr->set_varying (expr_type); return; } @@ -1731,7 +1813,7 @@ extract_range_from_binary_expr (value_range_base *vr, wmin, wmax, min_ovf, max_ovf); if (type == VR_VARYING) { - vr->set_varying (); + vr->set_varying (expr_type); return; } @@ -1757,7 +1839,7 @@ extract_range_from_binary_expr (value_range_base *vr, a single range or anti-range as the above is [-INF+1, +INF(OVF)] intersected with ~[5, 5] but one could use a scheme similar to equivalences for this. */ - vr->set_varying (); + vr->set_varying (expr_type); return; } } @@ -1774,7 +1856,7 @@ extract_range_from_binary_expr (value_range_base *vr, vr->set (VR_RANGE, wide_int_to_tree (expr_type, wmin), wide_int_to_tree (expr_type, wmax)); else - vr->set_varying (); + vr->set_varying (expr_type); return; } else if (code == MULT_EXPR) @@ -1782,10 +1864,10 @@ extract_range_from_binary_expr (value_range_base *vr, if (!range_int_cst_p (&vr0) || !range_int_cst_p (&vr1)) { - vr->set_varying (); + vr->set_varying (expr_type); return; } - extract_range_from_multiplicative_op (vr, code, &vr0, &vr1); + extract_range_from_multiplicative_op (vr, code, &vr0, &vr1, expr_type); return; } else if (code == RSHIFT_EXPR @@ -1800,13 +1882,8 @@ extract_range_from_binary_expr (value_range_base *vr, { if (code == RSHIFT_EXPR) { - /* Even if vr0 is VARYING or otherwise not usable, we can derive - useful ranges just from the shift count. E.g. - x >> 63 for signed 64-bit x is always [-1, 0]. */ - if (vr0.kind () != VR_RANGE || vr0.symbolic_p ()) - vr0.set (VR_RANGE, vrp_val_min (expr_type), - vrp_val_max (expr_type)); - extract_range_from_multiplicative_op (vr, code, &vr0, &vr1); + extract_range_from_multiplicative_op (vr, code, &vr0, &vr1, + expr_type); return; } else if (code == LSHIFT_EXPR @@ -1827,7 +1904,7 @@ extract_range_from_binary_expr (value_range_base *vr, } } } - vr->set_varying (); + vr->set_varying (expr_type); return; } else if (code == TRUNC_DIV_EXPR @@ -1843,7 +1920,7 @@ extract_range_from_binary_expr (value_range_base *vr, /* Special case explicit division by zero as undefined. */ if (vr1.zero_p ()) { - vr->set_undefined (); + vr->set_undefined (expr_type); return; } @@ -1864,7 +1941,7 @@ extract_range_from_binary_expr (value_range_base *vr, TYPE_OVERFLOW_UNDEFINED (expr_type), extra_range_p, extra_min, extra_max)) { - vr->set_varying (); + vr->set_varying (expr_type); return; } vr->set (VR_RANGE, wide_int_to_tree (expr_type, wmin), @@ -1882,7 +1959,7 @@ extract_range_from_binary_expr (value_range_base *vr, { if (vr1.zero_p ()) { - vr->set_undefined (); + vr->set_undefined (expr_type); return; } wide_int wmin, wmax, tmp; @@ -1923,7 +2000,7 @@ extract_range_from_binary_expr (value_range_base *vr, vr->set (VR_RANGE, min, max); } else - vr->set_varying (); + vr->set_varying (expr_type); return; } else if (code == BIT_IOR_EXPR) @@ -1941,7 +2018,7 @@ extract_range_from_binary_expr (value_range_base *vr, vr->set (VR_RANGE, min, max); } else - vr->set_varying (); + vr->set_varying (expr_type); return; } else if (code == BIT_XOR_EXPR) @@ -1957,7 +2034,7 @@ extract_range_from_binary_expr (value_range_base *vr, vr->set (VR_RANGE, min, max); } else - vr->set_varying (); + vr->set_varying (expr_type); return; } } @@ -1971,7 +2048,7 @@ extract_range_from_binary_expr (value_range_base *vr, || max == NULL_TREE || TREE_OVERFLOW_P (max)) { - vr->set_varying (); + vr->set_varying (expr_type); return; } @@ -1980,7 +2057,7 @@ extract_range_from_binary_expr (value_range_base *vr, Note that we do accept [-INF, -INF] and [+INF, +INF]. */ if (vrp_val_is_min (min) && vrp_val_is_max (max)) { - vr->set_varying (); + vr->set_varying (expr_type); return; } @@ -1990,7 +2067,7 @@ extract_range_from_binary_expr (value_range_base *vr, /* If the new range has its limits swapped around (MIN > MAX), then the operation caused one of them to wrap around, mark the new range VARYING. */ - vr->set_varying (); + vr->set_varying (expr_type); } else vr->set (type, min, max); @@ -2016,14 +2093,14 @@ extract_range_from_unary_expr (value_range_base *vr, || !(INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))) { - vr->set_varying (); + vr->set_varying (type); return; } /* If VR0 is UNDEFINED, so is the result. */ if (vr0.undefined_p ()) { - vr->set_undefined (); + vr->set_undefined (type); return; } @@ -2088,7 +2165,7 @@ extract_range_from_unary_expr (value_range_base *vr, else if (vr0.zero_p ()) vr->set_zero (type); else - vr->set_varying (); + vr->set_varying (type); return; } @@ -2123,7 +2200,7 @@ extract_range_from_unary_expr (value_range_base *vr, vr->set_and_canonicalize (VR_RANGE, min, max); } else - vr->set_varying (); + vr->set_varying (outer_type); return; } else if (code == ABS_EXPR) @@ -2136,7 +2213,7 @@ extract_range_from_unary_expr (value_range_base *vr, vr->set (VR_RANGE, wide_int_to_tree (type, wmin), wide_int_to_tree (type, wmax)); else - vr->set_varying (); + vr->set_varying (type); return; } else if (code == ABSU_EXPR) @@ -2151,7 +2228,7 @@ extract_range_from_unary_expr (value_range_base *vr, } /* For unhandled operations fall back to varying. */ - vr->set_varying (); + vr->set_varying (type); return; } @@ -5147,7 +5224,7 @@ vrp_prop::vrp_initialize () if (!stmt_interesting_for_vrp (phi)) { tree lhs = PHI_RESULT (phi); - get_value_range (lhs)->set_varying (); + get_value_range (lhs)->set_varying (TREE_TYPE (lhs)); prop_set_simulate_again (phi, false); } else @@ -5342,7 +5419,7 @@ vrp_prop::visit_stmt (gimple *stmt, edge *taken_edge_p, tree *output_p) use_operand_p use_p; enum ssa_prop_result res = SSA_PROP_VARYING; - get_value_range (lhs)->set_varying (); + get_value_range (lhs)->set_varying (TREE_TYPE (lhs)); FOR_EACH_IMM_USE_FAST (use_p, iter, lhs) { @@ -6132,7 +6209,12 @@ value_range_base::union_helper (const value_range_base *vr0, /* Work on a temporary so we can still use vr0 when union returns varying. */ value_range_base tem; - tem.set_and_canonicalize (vr0type, vr0min, vr0max); + if (vr0type == VR_UNDEFINED) + tem.set_undefined (TREE_TYPE (vr0->min ())); + else if (vr0type == VR_VARYING) + tem.set_varying (TREE_TYPE (vr0->min ())); + else + tem.set_and_canonicalize (vr0type, vr0min, vr0max); /* Failed to find an efficient meet. Before giving up and setting the result to VARYING, see if we can at least derive a useful @@ -6212,6 +6294,49 @@ value_range::union_ (const value_range *other) } } +/* Normalize symbolics into constants. */ + +value_range_base +value_range_base::normalize_symbolics (tree ttype) const +{ + if (varying_p () || undefined_p ()) + return *this; + bool min_symbolic = !is_gimple_min_invariant (min ()); + bool max_symbolic = !is_gimple_min_invariant (max ()); + if (!min_symbolic && !max_symbolic) + return *this; + + // [SYM, SYM] -> VARYING + if (min_symbolic && max_symbolic) + return value_range_base (ttype); + if (kind () == VR_RANGE) + { + // [SYM, NUM] -> [-MIN, NUM] + if (min_symbolic) + return value_range_base (VR_RANGE, vrp_val_min (ttype), max ()); + // [NUM, SYM] -> [NUM, +MAX] + return value_range_base (VR_RANGE, min (), vrp_val_max (ttype)); + } + gcc_assert (kind () == VR_ANTI_RANGE); + // ~[SYM, NUM] -> [NUM + 1, +MAX] + if (min_symbolic) + { + if (!vrp_val_is_max (max ())) + { + tree n = wide_int_to_tree (ttype, wi::to_wide (max ()) + 1); + return value_range_base (VR_RANGE, n, vrp_val_max (ttype)); + } + return value_range_base (ttype); + } + // ~[NUM, SYM] -> [-MIN, NUM - 1] + if (!vrp_val_is_min (min ())) + { + tree n = wide_int_to_tree (ttype, wi::to_wide (min ()) - 1); + return value_range_base (VR_RANGE, vrp_val_min (ttype), n); + } + return value_range_base (ttype); +} + /* Visit all arguments for PHI node PHI that flow through executable edges. If a valid value range can be derived from all the incoming value ranges, set a new range for the LHS of PHI. */ @@ -6885,7 +7010,7 @@ determine_value_range_1 (value_range_base *vr, tree expr) vr->set (kind, wide_int_to_tree (TREE_TYPE (expr), min), wide_int_to_tree (TREE_TYPE (expr), max)); else - vr->set_varying (); + vr->set_varying (TREE_TYPE (expr)); } } diff --git a/gcc/tree-vrp.h b/gcc/tree-vrp.h index 4ec974f5fdb..b1ddf484aa7 100644 --- a/gcc/tree-vrp.h +++ b/gcc/tree-vrp.h @@ -43,6 +43,7 @@ class GTY((for_user)) value_range_base public: value_range_base (); value_range_base (value_range_kind, tree, tree); + value_range_base (tree type); void set (value_range_kind, tree, tree); void set (tree); @@ -58,8 +59,8 @@ public: bool constant_p () const; bool undefined_p () const; bool varying_p () const; - void set_varying (); - void set_undefined (); + void set_varying (tree = NULL); + void set_undefined (tree = NULL); void union_ (const value_range_base *); void intersect (const value_range_base *); @@ -76,6 +77,10 @@ public: bool nonzero_p () const; bool singleton_p (tree *result = NULL) const; void dump (FILE *) const; + void dump () const; + + static bool supports_type_p (tree); + value_range_base normalize_symbolics (tree) const; protected: void check (); @@ -133,8 +138,8 @@ class GTY((user)) value_range : public value_range_base bool equal_p (const value_range &, bool ignore_equivs) const; /* Types of value ranges. */ - void set_undefined (); - void set_varying (); + void set_undefined (tree = NULL); + void set_varying (tree = NULL); /* Equivalence bitmap methods. */ bitmap equiv () const; @@ -145,6 +150,7 @@ class GTY((user)) value_range : public value_range_base void deep_copy (const value_range *); void set_and_canonicalize (enum value_range_kind, tree, tree, bitmap = NULL); void dump (FILE *) const; + void dump () const; private: /* Deep-copies bitmap argument. */ @@ -254,6 +260,17 @@ struct assert_info tree expr; }; +// Return true if TYPE is a valid type for value_range to operate on. +// Otherwise return FALSE. + +inline bool +value_range_base::supports_type_p (tree type) +{ + if (type && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))) + return type; + return NULL; +} + extern void register_edge_assert_for (tree, edge, enum tree_code, tree, tree, vec &); extern bool stmt_interesting_for_vrp (gimple *); @@ -267,11 +284,11 @@ extern bool range_int_cst_singleton_p (const value_range_base *); extern int compare_values (tree, tree); extern int compare_values_warnv (tree, tree, bool *); extern int operand_less_p (tree, tree); -extern bool vrp_val_is_min (const_tree); -extern bool vrp_val_is_max (const_tree); +extern bool vrp_val_is_min (const_tree, bool handle_pointers = false); +extern bool vrp_val_is_max (const_tree, bool handle_pointers = false); -extern tree vrp_val_min (const_tree); -extern tree vrp_val_max (const_tree); +extern tree vrp_val_min (const_tree, bool handle_pointers = false); +extern tree vrp_val_max (const_tree, bool handle_pointers = false); extern void extract_range_from_unary_expr (value_range_base *vr, enum tree_code code, diff --git a/gcc/vr-values.c b/gcc/vr-values.c index 3f20c1a6fe8..f0efb6eca3d 100644 --- a/gcc/vr-values.c +++ b/gcc/vr-values.c @@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see #include "attribs.h" #include "vr-values.h" #include "cfghooks.h" +#include "wide-int-range.h" /* Set value range VR to a non-negative range of type TYPE. */ @@ -64,7 +65,7 @@ static inline void set_value_range_to_truthvalue (value_range *vr, tree type) { if (TYPE_PRECISION (type) == 1) - vr->set_varying (); + vr->set_varying (type); else vr->update (VR_RANGE, build_int_cst (type, 0), build_int_cst (type, 1)); } @@ -126,10 +127,10 @@ vr_values::get_value_range (const_tree var) { get_range_info (var, *vr); if (vr->undefined_p ()) - vr->set_varying (); + vr->set_varying (TREE_TYPE (sym)); } else - vr->set_varying (); + vr->set_varying (TREE_TYPE (sym)); } else if (TREE_CODE (sym) == RESULT_DECL && DECL_BY_REFERENCE (sym)) @@ -198,13 +199,13 @@ vr_values::update_value_range (const_tree var, value_range *new_vr) called, if we are anyway, keep it VARYING. */ if (old_vr->varying_p ()) { - new_vr->set_varying (); + new_vr->set_varying (new_vr->type ()); is_new = false; } else if (new_vr->undefined_p ()) { - old_vr->set_varying (); - new_vr->set_varying (); + old_vr->set_varying (TREE_TYPE (var)); + new_vr->set_varying (TREE_TYPE (var)); return true; } else @@ -435,7 +436,7 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var, if ((POINTER_TYPE_P (type) && cond_code != NE_EXPR && cond_code != EQ_EXPR) || limit == var) { - vr_p->set_varying (); + vr_p->set_varying (type); return; } @@ -595,7 +596,7 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var, all should be optimized away above us. */ if (cond_code == LT_EXPR && compare_values (max, min) == 0) - vr_p->set_varying (); + vr_p->set_varying (TREE_TYPE (min)); else { /* For LT_EXPR, we create the range [MIN, MAX - 1]. */ @@ -635,7 +636,7 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var, all should be optimized away above us. */ if (cond_code == GT_EXPR && compare_values (min, max) == 0) - vr_p->set_varying (); + vr_p->set_varying (TREE_TYPE (min)); else { /* For GT_EXPR, we create the range [MIN + 1, MAX]. */ @@ -743,14 +744,14 @@ vr_values::extract_range_from_binary_expr (value_range *vr, else if (is_gimple_min_invariant (op0)) vr0.set (op0); else - vr0.set_varying (); + vr0.set_varying (TREE_TYPE (op0)); if (TREE_CODE (op1) == SSA_NAME) vr1 = *(get_value_range (op1)); else if (is_gimple_min_invariant (op1)) vr1.set (op1); else - vr1.set_varying (); + vr1.set_varying (TREE_TYPE (op1)); /* If one argument is varying, we can sometimes still deduce a range for the output: any + [3, +INF] is in [MIN+3, +INF]. */ @@ -891,7 +892,7 @@ vr_values::extract_range_from_unary_expr (value_range *vr, enum tree_code code, else if (is_gimple_min_invariant (op0)) vr0.set (op0); else - vr0.set_varying (); + vr0.set_varying (type); ::extract_range_from_unary_expr (vr, code, type, &vr0, TREE_TYPE (op0)); } @@ -913,7 +914,7 @@ vr_values::extract_range_from_cond_expr (value_range *vr, gassign *stmt) else if (is_gimple_min_invariant (op0)) tem0.set (op0); else - tem0.set_varying (); + tem0.set_varying (TREE_TYPE (op0)); tree op1 = gimple_assign_rhs3 (stmt); value_range tem1; @@ -923,7 +924,7 @@ vr_values::extract_range_from_cond_expr (value_range *vr, gassign *stmt) else if (is_gimple_min_invariant (op1)) tem1.set (op1); else - tem1.set_varying (); + tem1.set_varying (TREE_TYPE (op1)); /* The resulting value range is the union of the operand ranges */ vr->deep_copy (vr0); @@ -975,14 +976,14 @@ vr_values::check_for_binary_op_overflow (enum tree_code subcode, tree type, else if (TREE_CODE (op0) == INTEGER_CST) vr0.set (op0); else - vr0.set_varying (); + vr0.set_varying (TREE_TYPE (op0)); if (TREE_CODE (op1) == SSA_NAME) vr1 = *get_value_range (op1); else if (TREE_CODE (op1) == INTEGER_CST) vr1.set (op1); else - vr1.set_varying (); + vr1.set_varying (TREE_TYPE (op1)); tree vr0min = vr0.min (), vr0max = vr0.max (); tree vr1min = vr1.min (), vr1max = vr1.max (); @@ -1310,7 +1311,7 @@ vr_values::extract_range_basic (value_range *vr, gimple *stmt) if (vr->kind () == VR_RANGE && (vr->min () == vr->max () || operand_equal_p (vr->min (), vr->max (), 0))) - vr->set_varying (); + vr->set_varying (vr->type ()); return; } } @@ -1366,7 +1367,7 @@ vr_values::extract_range_basic (value_range *vr, gimple *stmt) vr->set (build_int_cst (type, ovf)); else if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type)) - vr->set_varying (); + vr->set_varying (type); else vr->set (VR_RANGE, build_int_cst (type, 0), build_int_cst (type, 1)); @@ -1411,7 +1412,7 @@ vr_values::extract_range_basic (value_range *vr, gimple *stmt) vr->equiv_clear (); } else - vr->set_varying (); + vr->set_varying (type); } @@ -1447,7 +1448,7 @@ vr_values::extract_range_from_assignment (value_range *vr, gassign *stmt) && is_gimple_min_invariant (gimple_assign_rhs1 (stmt))) vr->set (gimple_assign_rhs1 (stmt)); else - vr->set_varying (); + vr->set_varying (TREE_TYPE (gimple_assign_lhs (stmt))); if (vr->varying_p ()) extract_range_basic (vr, stmt); @@ -2856,7 +2857,7 @@ vr_values::extract_range_from_phi_node (gphi *phi, value_range *vr_result) vr_arg_tem.set (vr_arg_->kind (), vr_arg_->min (), vr_arg_->max (), NULL); if (vr_arg_tem.symbolic_p ()) - vr_arg_tem.set_varying (); + vr_arg_tem.set_varying (TREE_TYPE (arg)); } else vr_arg = vr_arg_; @@ -2978,7 +2979,7 @@ vr_values::extract_range_from_phi_node (gphi *phi, value_range *vr_result) goto update_range; varying: - vr_result->set_varying (); + vr_result->set_varying (TREE_TYPE (lhs)); scev_check: /* If this is a loop PHI node SCEV may known more about its value-range. @@ -2999,7 +3000,7 @@ infinite_check: || compare_values (vr_result->min (), vr_result->max ()) > 0)) ; else - vr_result->set_varying (); + vr_result->set_varying (TREE_TYPE (lhs)); /* If the new range is different than the previous value, keep iterating. */