diff options
author | Aldy Hernandez <aldyh@gcc.gnu.org> | 2019-08-19 15:59:47 +0000 |
---|---|---|
committer | Aldy Hernandez <aldyh@gcc.gnu.org> | 2019-08-19 15:59:47 +0000 |
commit | 09febaec27709d1a05ff422ba1bb29fd3150d643 (patch) | |
tree | 71b474ef626789d4f9b9ae355931d4fa095e6217 | |
parent | d99d7058288b6c38a0e5fe13ed2f5c3a2f2efeb5 (diff) | |
download | gcc-09febaec27709d1a05ff422ba1bb29fd3150d643.zip gcc-09febaec27709d1a05ff422ba1bb29fd3150d643.tar.gz gcc-09febaec27709d1a05ff422ba1bb29fd3150d643.tar.bz2 |
typeless undefine
From-SVN: r274674
-rw-r--r-- | gcc/grange.cc | 8 | ||||
-rw-r--r-- | gcc/range-op.cc | 49 | ||||
-rw-r--r-- | gcc/range.cc | 71 | ||||
-rw-r--r-- | gcc/range.h | 39 | ||||
-rw-r--r-- | gcc/ssa-range-cache.cc | 14 | ||||
-rw-r--r-- | gcc/ssa-range-gori.cc | 10 | ||||
-rw-r--r-- | gcc/ssa-range.cc | 12 | ||||
-rw-r--r-- | gcc/tree-ssanames.c | 2 | ||||
-rw-r--r-- | gcc/tree-vrp.c | 99 | ||||
-rw-r--r-- | gcc/tree-vrp.h | 23 | ||||
-rw-r--r-- | gcc/vr-values.c | 4 |
11 files changed, 175 insertions, 156 deletions
diff --git a/gcc/grange.cc b/gcc/grange.cc index 3180235..fb9b019 100644 --- a/gcc/grange.cc +++ b/gcc/grange.cc @@ -279,7 +279,7 @@ grange_op::fold (irange &res, const irange &orig_r1) const if (lhs ()) r2.set_varying (TREE_TYPE (lhs ())); else - r2.set_undefined (r1.type ()); + r2.set_undefined (); return fold (res, r1, r2); } @@ -327,7 +327,7 @@ grange_op::calc_op1_irange (irange &r, const irange &lhs_range) const tree type = TREE_TYPE (operand1 ()); if (lhs_range.undefined_p ()) { - r.set_undefined (type); + r.set_undefined (); return true; } // Unary operations require the type of the first operand in the second range @@ -352,7 +352,7 @@ grange_op::calc_op1_irange (irange &r, const irange &lhs_range, // An empty range is viral, so return an empty range. if (op2_range.undefined_p () || lhs_range.undefined_p ()) { - r.set_undefined (type); + r.set_undefined (); return true; } return handler ()->op1_range (r, type, lhs_range, op2_range); @@ -370,7 +370,7 @@ grange_op::calc_op2_irange (irange &r, const irange &lhs_range, // An empty range is viral, so return an empty range. if (op1_range.undefined_p () || lhs_range.undefined_p ()) { - r.set_undefined (type); + r.set_undefined (); return true; } return handler ()->op2_range (r, type, lhs_range, op1_range); diff --git a/gcc/range-op.cc b/gcc/range-op.cc index ad5443b..0d36e38 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -69,7 +69,7 @@ range_operator::fold_range (irange &r, tree type, const irange &lh, bool res = false; // Clear and set result type. - r.set_undefined (type); + r.set_undefined (); if (lh.undefined_p () || rh.undefined_p ()) return true; @@ -132,11 +132,11 @@ min_limit (const_tree type) // undefined and return true. inline bool -empty_range_check (irange &r, const irange &op1, const irange & op2, tree type) +empty_range_check (irange &r, const irange &op1, const irange & op2) { if (op1.undefined_p () || op2.undefined_p ()) { - r.set_undefined (type); + r.set_undefined (); return true; } else @@ -309,7 +309,7 @@ get_bool_state (irange &r, const irange &lhs, tree val_type) /* If there is no result, then this is unexectuable, so no range. */ if (lhs.undefined_p ()) { - r.set_undefined (val_type); + r.set_undefined (); return BRS_EMPTY; } @@ -345,7 +345,7 @@ bool operator_equal::fold_range (irange &r, tree type, const irange &op1, const irange &op2) const { - if (empty_range_check (r, op1, op2, type)) + if (empty_range_check (r, op1, op2)) return true; /* We can be sure the values are always equal or not if both ranges @@ -425,7 +425,7 @@ bool operator_not_equal::fold_range (irange &r, tree type, const irange &op1, const irange &op2) const { - if (empty_range_check (r, op1, op2, type)) + if (empty_range_check (r, op1, op2)) return true; /* We can be sure the values are always equal or not if both ranges @@ -497,7 +497,7 @@ build_lt (irange &r, tree type, const wide_int &val) /* If val - 1 underflows, check is X < MIN, which is an empty range. */ if (ov) - r.set_undefined (type); + r.set_undefined (); else r = irange (type, min_limit (type), lim); } @@ -517,7 +517,7 @@ build_gt (irange &r, tree type, const wide_int &val) wide_int lim = wi::add (val, 1, TYPE_SIGN (type), &ov); /* If val + 1 overflows, check is for X > MAX , which is an empty range. */ if (ov) - r.set_undefined (type); + r.set_undefined (); else r = irange (type, lim, max_limit (type)); } @@ -545,7 +545,7 @@ public: bool operator_lt::fold_range (irange &r, tree type, const irange &op1, const irange &op2) const { - if (empty_range_check (r, op1, op2, type)) + if (empty_range_check (r, op1, op2)) return true; signop sign = TYPE_SIGN (op1.type ()); @@ -616,7 +616,7 @@ public: bool operator_le::fold_range (irange &r, tree type, const irange &op1, const irange &op2) const { - if (empty_range_check (r, op1, op2, type)) + if (empty_range_check (r, op1, op2)) return true; signop sign = TYPE_SIGN (op1.type ()); @@ -687,7 +687,7 @@ public: bool operator_gt::fold_range (irange &r, tree type, const irange &op1, const irange &op2) const { - if (empty_range_check (r, op1, op2, type)) + if (empty_range_check (r, op1, op2)) return true; signop sign = TYPE_SIGN (op1.type ()); @@ -759,7 +759,7 @@ public: bool operator_ge::fold_range (irange &r, tree type, const irange &op1, const irange &op2) const { - if (empty_range_check (r, op1, op2, type)) + if (empty_range_check (r, op1, op2)) return true; signop sign = TYPE_SIGN (op1.type ()); @@ -1195,9 +1195,10 @@ public: r = (type_of(rh)) lh. */ bool -operator_cast::fold_range (irange &r, tree type, const irange &lh, const irange &rh) const +operator_cast::fold_range (irange &r, tree type ATTRIBUTE_UNUSED, + const irange &lh, const irange &rh) const { - if (empty_range_check (r, lh, rh, type)) + if (empty_range_check (r, lh, rh)) return true; if (lh.type () != rh.type ()) @@ -1309,7 +1310,7 @@ bool operator_logical_and::fold_range (irange &r, tree type, const irange &lh, const irange &rh) const { - if (empty_range_check (r, lh, rh, type)) + if (empty_range_check (r, lh, rh)) return true; // 0 && anything is 0 @@ -1400,7 +1401,7 @@ operator_bitwise_and::wi_fold (irange &r, tree type, // For AND, calculate each subrange separately, and then union // the results. irange tmp; - tmp.set_undefined (type); + tmp.set_undefined (); accumulate_range (tmp, type, new_lb, new_ub); r.union_ (tmp); return true; @@ -1441,10 +1442,10 @@ public: bool -operator_logical_or::fold_range (irange &r, tree type, const irange &lh, - const irange &rh) const +operator_logical_or::fold_range (irange &r, tree type ATTRIBUTE_UNUSED, + const irange &lh, const irange &rh) const { - if (empty_range_check (r, lh, rh, type)) + if (empty_range_check (r, lh, rh)) return true; r = range_union (lh, rh); @@ -1632,7 +1633,7 @@ bool operator_logical_not::fold_range (irange &r, tree type, const irange &lh, const irange &rh ATTRIBUTE_UNUSED) const { - if (empty_range_check (r, lh, rh, type)) + if (empty_range_check (r, lh, rh)) return true; if (lh.varying_p () || lh.undefined_p ()) @@ -1668,7 +1669,7 @@ bool operator_bitwise_not::fold_range (irange &r, tree type, const irange &lh, const irange &rh) const { - if (empty_range_check (r, lh, rh, type)) + if (empty_range_check (r, lh, rh)) return true; // ~X is simply -1 - X. @@ -1777,7 +1778,7 @@ bool operator_abs::op1_range (irange &r, tree type, const irange &lhs, const irange &op2) const { - if (empty_range_check (r, lhs, op2, type)) + if (empty_range_check (r, lhs, op2)) return true; if (TYPE_UNSIGNED (type)) { @@ -1859,7 +1860,7 @@ bool operator_negate::fold_range (irange &r, tree type, const irange &lh, const irange &rh) const { - if (empty_range_check (r, lh, rh, type)) + if (empty_range_check (r, lh, rh)) return true; // -X is simply 0 - X. return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, range_zero (type), @@ -1879,7 +1880,7 @@ bool operator_addr_expr::fold_range (irange &r, tree type, const irange &lh, const irange &rh) const { - if (empty_range_check (r, lh, rh, type)) + if (empty_range_check (r, lh, rh)) return true; // Return a non-null pointer of the LHS type (passed in op2) diff --git a/gcc/range.cc b/gcc/range.cc index 0867cff..1f27eda 100644 --- a/gcc/range.cc +++ b/gcc/range.cc @@ -127,7 +127,7 @@ range_negatives (tree type) signop sign = TYPE_SIGN (type); irange r; if (sign == UNSIGNED) - r.set_undefined (type); + r.set_undefined (); else r = irange (type, wi::min_value (prec, sign), wi::minus_one (prec)); return r; @@ -370,7 +370,7 @@ range_tests () r0 = range_zero (boolean_type_node); ASSERT_TRUE (r0 == irange (build_zero_cst (boolean_type_node), build_zero_cst (boolean_type_node))); - r0.invert(); + r0.invert (); ASSERT_TRUE (r0 == irange (build_one_cst (boolean_type_node), build_one_cst (boolean_type_node))); @@ -611,14 +611,14 @@ range_tests () // Test irange_storage. r0 = irange (INT (5), INT (10)); - irange_storage *stow = irange_storage::alloc (r0); + irange_storage *stow = irange_storage::alloc (r0, integer_type_node); r1 = irange (integer_type_node, stow); ASSERT_TRUE (r0 == r1); // Test irange_storage with signed 1-bit fields. tree s1bit_type = make_signed_type (1); r0 = irange (build_int_cst (s1bit_type, -1), build_int_cst (s1bit_type, 0)); - stow = irange_storage::alloc (r0); + stow = irange_storage::alloc (r0, s1bit_type); r1 = irange (s1bit_type, stow); ASSERT_TRUE (r0 == r1); @@ -667,7 +667,7 @@ irange::init (tree type, const wide_int &lbound, const wide_int &ubound, { if (rt == VR_UNDEFINED) { - set_undefined (type); + set_undefined (); return; } if (rt == VR_VARYING) @@ -1025,8 +1025,6 @@ irange::canonicalize () void irange::union_ (const irange &r) { - gcc_checking_assert (range_compatible_p (m_type, r.m_type)); - if (undefined_p ()) { *this = r; @@ -1035,6 +1033,8 @@ irange::union_ (const irange &r) else if (r.undefined_p ()) return; + gcc_checking_assert (range_compatible_p (m_type, r.m_type)); + // Do not worry about merging and such by reserving twice as many // pairs as needed, and then simply sort the 2 ranges into this // intermediate form. @@ -1141,8 +1141,10 @@ irange::union_ (const irange &r) void irange::intersect (const wide_int &x, const wide_int &y) { - unsigned pos = 0; + if (undefined_p ()) + return; + unsigned pos = 0; for (unsigned i = 0; i < m_nitems; i += 2) { signop sign = TYPE_SIGN (m_type); @@ -1169,13 +1171,16 @@ irange::intersect (const wide_int &x, const wide_int &y) void irange::intersect (const irange &r) { - gcc_checking_assert (range_compatible_p (m_type, r.m_type)); irange orig_range (*this); // Intersection with an empty range is an empty range. - set_undefined (); if (orig_range.undefined_p () || r.undefined_p ()) - return; + { + set_undefined (); + return; + } + + gcc_checking_assert (range_compatible_p (m_type, r.m_type)); // The general algorithm is as follows. // @@ -1188,6 +1193,7 @@ irange::intersect (const irange &r) // Step 2: [10,20][30,40][50,60] ^ [38,51] => [38,40] // Step 3: [10,20][30,40][50,60] ^ [55,70] => [55,60] // Final: [15,20] U [38,40] U [55,60] => [15,20][38,40][55,60] + set_undefined (); for (unsigned i = 0; i < r.m_nitems; i += 2) { irange tmp (orig_range); @@ -1203,6 +1209,9 @@ irange::intersect (const irange &r) void irange::invert () { + if (undefined_p ()) + return; + // We always need one more set of bounds to represent an inverse, so // if we're at the limit, we can't properly represent things. // @@ -1228,13 +1237,6 @@ irange::invert () return; } - // The inverse of the empty set is the entire domain. - if (undefined_p ()) - { - set_varying (m_type); - return; - } - // The algorithm is as follows. To calculate INVERT ([a,b][c,d]), we // generate [-MIN, a-1][b+1, c-1][d+1, MAX]. // @@ -1301,6 +1303,13 @@ irange::invert () void irange::dump (pretty_printer *buffer) const { + if (undefined_p ()) + { + pp_string (buffer, "[]"); + pp_flush (buffer); + return; + } + wide_int min = wi::min_value (TYPE_PRECISION (m_type), TYPE_SIGN (m_type)); wide_int max = wi::max_value (TYPE_PRECISION (m_type), TYPE_SIGN (m_type)); if (POINTER_TYPE_P (m_type) && nonzero_p ()) @@ -1343,8 +1352,6 @@ irange::dump (pretty_printer *buffer) const else pp_character (buffer, ']'); } - if (undefined_p ()) - pp_string (buffer, "[]"); pp_character (buffer, ' '); dump_generic_node (buffer, m_type, 0, TDF_NONE, false); @@ -1377,9 +1384,14 @@ irange::dump () const // Initialize the current irange_storage to the irange in IR. void -irange_storage::set (const irange &ir) +irange_storage::set (const irange &ir, tree type) { - unsigned precision = TYPE_PRECISION (ir.type ()); + if (type) + gcc_checking_assert (ir.undefined_p () + || types_compatible_p (type, ir.type ())); + else + type = ir.type (); + unsigned precision = TYPE_PRECISION (type); trailing_bounds.set_precision (precision); unsigned i; for (i = 0; i < ir.num_pairs () * 2; ++i) @@ -1387,7 +1399,7 @@ irange_storage::set (const irange &ir) // Clear the remaining empty ranges. for (; i < irange::m_max_pairs * 2; i += 2) - set_empty_pair (i, i + 1, ir.type ()); + set_empty_pair (i, i + 1, type); } // Update a previously initialized irange_storage to NEW_RANGE, iff the @@ -1395,11 +1407,11 @@ irange_storage::set (const irange &ir) // the new range. Return TRUE if update was successful. bool -irange_storage::update (const irange &new_range) +irange_storage::update (const irange &new_range, tree type) { - if (trailing_bounds.get_precision () == TYPE_PRECISION (new_range.type ())) + if (trailing_bounds.get_precision () == TYPE_PRECISION (type)) { - set (new_range); + set (new_range, type); return true; } return false; @@ -1432,7 +1444,7 @@ irange_to_value_range (const irange &r) } if (r.undefined_p ()) { - vr.set_undefined (r.type ()); + vr.set_undefined (); return vr; } tree type = r.type (); @@ -1485,13 +1497,12 @@ irange_to_value_range (const irange &r) static irange value_range_to_irange (const value_range_base &vr) { - tree type = vr.type (); if (vr.varying_p ()) - return irange (type); + return irange (vr.type ()); if (vr.undefined_p ()) { irange r; - r.set_undefined (type); + r.set_undefined (); return r; } return irange (vr.kind (), vr.min (), vr.max ()); diff --git a/gcc/range.h b/gcc/range.h index 0a1bf2c..8c8dd07 100644 --- a/gcc/range.h +++ b/gcc/range.h @@ -74,14 +74,14 @@ class irange static bool supports_p (tree expr); void set_varying (tree); - void set_undefined (tree = NULL); + void set_undefined (); unsigned num_pairs () const; wide_int lower_bound (unsigned pair = 0) const; wide_int upper_bound () const; wide_int upper_bound (unsigned pair) const; - tree type () const { return m_type; } + tree type () const; void cast (tree type); @@ -164,11 +164,17 @@ irange::num_pairs () const return m_nitems / 2; } +inline tree +irange::type () const +{ + gcc_checking_assert (!undefined_p ()); + return m_type; +} + inline void -irange::set_undefined (tree type) +irange::set_undefined () { - if (type) - m_type = type; + m_type = NULL; m_nitems = 0; } @@ -181,6 +187,8 @@ irange::undefined_p () const inline bool irange::zero_p () const { + if (m_nitems != 2) + return false; wide_int z = wi::zero (TYPE_PRECISION (m_type)); return (m_nitems == 2 && m_bounds[0] == z && m_bounds[1] == z); } @@ -188,6 +196,8 @@ irange::zero_p () const inline bool irange::nonzero_p () const { + if (undefined_p ()) + return false; unsigned prec = TYPE_PRECISION (m_type); return *this == irange (VR_ANTI_RANGE, m_type, wi::zero (prec), wi::zero (prec)); @@ -213,7 +223,7 @@ irange::varying_p () const // To store an irange class X into an irange_storage use: // // irange X = ...; -// irange_storage *stow = irange_storage::alloc (X); +// irange_storage *stow = irange_storage::alloc (X, range_type); // // To convert it back into an irange use: // @@ -231,12 +241,12 @@ class GTY((variable_size)) irange_storage friend class irange; public: - static irange_storage *alloc (const irange &); - bool update (const irange &); + static irange_storage *alloc (const irange &, tree type); + bool update (const irange &, tree type); private: static size_t size (unsigned precision); - void set (const irange &); + void set (const irange &, tree type); bool empty_pair_p (unsigned, unsigned, tree) const; void set_empty_pair (unsigned, unsigned, tree); void set_nonzero_bits (const wide_int &); @@ -276,12 +286,17 @@ irange_storage::size (unsigned precision) // initialize it to IR. inline irange_storage * -irange_storage::alloc (const irange &ir) +irange_storage::alloc (const irange &ir, tree type) { - unsigned precision = TYPE_PRECISION (ir.m_type); + if (type) + gcc_checking_assert (ir.undefined_p () + || types_compatible_p (type, ir.type ())); + else + type = ir.type (); + unsigned precision = TYPE_PRECISION (type); irange_storage *stow = static_cast<irange_storage *> (ggc_internal_alloc (size (precision))); - stow->set (ir); + stow->set (ir, type); stow->set_nonzero_bits (wi::shwi (-1, precision)); return stow; } diff --git a/gcc/ssa-range-cache.cc b/gcc/ssa-range-cache.cc index 1cc17a6..43be4bd 100644 --- a/gcc/ssa-range-cache.cc +++ b/gcc/ssa-range-cache.cc @@ -168,7 +168,7 @@ ssa_block_ranges::ssa_block_ranges (tree t) // Create the cached type range. tr.set_varying (t); - m_type_range = irange_storage::alloc (tr); + m_type_range = irange_storage::alloc (tr, t); m_tab[ENTRY_BLOCK_PTR_FOR_FN (cfun)->index] = m_type_range; } @@ -188,10 +188,10 @@ ssa_block_ranges::set_bb_range (const basic_block bb, const irange &r) irange_storage *m = m_tab[bb->index]; // If there is already range memory for this block, reuse it. - if (m && m != m_type_range && m->update (r)) + if (m && m != m_type_range && m->update (r, m_type)) ; else - m = irange_storage::alloc (r); + m = irange_storage::alloc (r, m_type); m_tab[bb->index] = m; } @@ -429,11 +429,11 @@ ssa_global_cache::set_global_range (tree name, const irange& r) m_tab.safe_grow_cleared (num_ssa_names + 1); irange_storage *m = m_tab[v]; - if (m && m->update (r)) + if (m && m->update (r, TREE_TYPE (name))) ; else { - m = irange_storage::alloc (r); + m = irange_storage::alloc (r, TREE_TYPE (name)); m_tab[SSA_NAME_VERSION (name)] = m; } } @@ -631,7 +631,7 @@ if (DEBUG_CACHE) fprintf (dump_file, "FWD visiting block %d\n", bb->index); gcc_assert (m_on_entry.get_bb_range (current_range, name, bb)); // Calculate the "new" range on entry by unioning the pred edges.. - new_range.set_undefined (TREE_TYPE (name)); + new_range.set_undefined (); FOR_EACH_EDGE (e, ei, bb->preds) { gcc_assert (edge_range (e_range, e, name)); @@ -678,7 +678,7 @@ gori_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb) // the range_on_entry cache for. m_workback.truncate (0); m_workback.quick_push (bb); - undefined.set_undefined (TREE_TYPE (name)); + undefined.set_undefined (); m_on_entry.set_bb_range (name, bb, undefined); gcc_checking_assert (m_update_list.length () == 0); diff --git a/gcc/ssa-range-gori.cc b/gcc/ssa-range-gori.cc index f5fdaf0..fc13d2a 100644 --- a/gcc/ssa-range-gori.cc +++ b/gcc/ssa-range-gori.cc @@ -738,7 +738,7 @@ gori_compute::compute_operand_range_op (irange &r, grange_op *stmt, // Empty ranges are viral as they are on a path which isn't executable. if (lhs.undefined_p ()) { - r.set_undefined (TREE_TYPE (name)); + r.set_undefined (); return true; } @@ -1165,9 +1165,11 @@ gori_compute::range_from_import (irange &r, tree name, irange &import_range) bool res; tree import = terminal_name (name); - gcc_checking_assert (import && - useless_type_conversion_p (TREE_TYPE (import), - import_range.type ())); + gcc_checking_assert + (import + && (import_range.undefined_p () + || useless_type_conversion_p (TREE_TYPE (import), + import_range.type ()))); // Only handling range_ops until we find a cond-expr that matters. // We process this specially so we can handle self-referencing chains. ie: diff --git a/gcc/ssa-range.cc b/gcc/ssa-range.cc index 481a45f..3e1ce85 100644 --- a/gcc/ssa-range.cc +++ b/gcc/ssa-range.cc @@ -227,7 +227,7 @@ switch_edge_manager::calc_single_range (irange &r, gswitch *sw, edge e) if (e != gimple_switch_default_edge (cfun, sw)) { - r.set_undefined (type); + r.set_undefined (); // Loop through all the switches edges, ignoring the default edge. // unioning the ranges together. for (x = 1; x < lim; x++) @@ -387,7 +387,7 @@ ssa_ranger::range_on_edge (irange &r, edge e, tree name) gcc_checking_assert (valid_ssa_p (name)); range_on_exit (r, e->src, name); - gcc_checking_assert (r.type() == TREE_TYPE (name)); + gcc_checking_assert (r.undefined_p () || r.type() == TREE_TYPE (name)); // Check to see if NAME is defined on edge e. if (outgoing_edge_range_p (edge_range, e, name, &r)) @@ -432,6 +432,8 @@ ssa_ranger::range_of_stmt (irange &r, gimple *s, tree name) } if (res) { + if (r.undefined_p ()) + return true; if (name && TREE_TYPE (name) != r.type ()) r.cast (TREE_TYPE (name)); return true; @@ -474,7 +476,7 @@ ssa_ranger::range_on_entry (irange &r, basic_block bb, tree name) gcc_checking_assert (irange::supports_type_p (type)); // Start with an empty range. - r.set_undefined (type); + r.set_undefined (); gcc_checking_assert (bb != ENTRY_BLOCK_PTR_FOR_FN (cfun)); @@ -507,7 +509,7 @@ ssa_ranger::range_on_exit (irange &r, basic_block bb, tree name) range_on_entry (r, bb, name); else gcc_assert (range_of_expr (r, name, s)); - gcc_checking_assert (r.type() == TREE_TYPE (name)); + gcc_checking_assert (r.undefined_p () || r.type() == TREE_TYPE (name)); } // Calculate a range for range_op statement S given RANGE1 and RANGE2 and @@ -660,7 +662,7 @@ ssa_ranger::range_of_phi (irange &r, gphi *phi, tree name, return false; // And start with an empty range, unioning in each argument's range. - r.set_undefined (type); + r.set_undefined (); for (x = 0; x < gimple_phi_num_args (phi); x++) { irange arg_range; diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index 343e984..3911db9 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -443,7 +443,7 @@ get_range_info (const_tree name, value_range_base &vr) if (kind == VR_VARYING) vr.set_varying (TREE_TYPE (name)); else if (kind == VR_UNDEFINED) - vr.set_undefined (TREE_TYPE (name)); + vr.set_undefined (); else { min = wide_int_to_tree (TREE_TYPE (name), wmin); diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 33ef25e..d47712f 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -298,32 +298,16 @@ value_range_base::constant_p () const } void -value_range_base::set_undefined (tree type) +value_range_base::set_undefined () { m_kind = VR_UNDEFINED; - if (type) - { - if (supports_type_p (type)) - { - m_min = vrp_val_min (type, true); - m_max = vrp_val_max (type, true); - } - else - { - /* This is a temporary kludge for ipa-cp which is building - undefined/varying of floats. ?? */ - m_min = m_max = build1 (NOP_EXPR, type, type); - } - } - else - m_min = m_max = NULL; + m_min = m_max = NULL; } void -value_range::set_undefined (tree type) +value_range::set_undefined () { - value_range_base::set_undefined (type); - equiv_clear (); + set (VR_UNDEFINED, NULL, NULL, NULL); } void @@ -421,25 +405,19 @@ value_range_base::singleton_p (tree *result) const tree value_range_base::type () const { - gcc_assert (m_min || undefined_p ()); + gcc_assert (m_min); return TREE_TYPE (min ()); } void value_range_base::dump (FILE *file) const { - tree ttype; - if (undefined_p () && !m_min) - ttype = void_type_node; - else ttype = TREE_TYPE (m_min); - if (undefined_p ()) - { - print_generic_expr (file, ttype); - fprintf (file, " UNDEFINED"); - } + fprintf (file, "UNDEFINED"); else if (m_kind == VR_RANGE || m_kind == VR_ANTI_RANGE) { + tree ttype = type (); + print_generic_expr (file, ttype); fprintf (file, " "); @@ -737,10 +715,7 @@ value_range_base::set (enum value_range_kind kind, tree min, tree max) { if (kind == VR_UNDEFINED) { - if (min) - set_undefined (TREE_TYPE (min)); - else - set_undefined (); + set_undefined (); return; } else if (kind == VR_VARYING) @@ -863,7 +838,7 @@ value_range_base::set (enum value_range_kind kind, tree min, tree max) if (kind == VR_RANGE) set_varying (type); else if (kind == VR_ANTI_RANGE) - set_undefined (type); + set_undefined (); else gcc_unreachable (); return; @@ -1323,8 +1298,8 @@ ranges_from_anti_range (const value_range_base *ar, tree type = ar->type (); - vr0->set_undefined (type); - vr1->set_undefined (type); + vr0->set_undefined (); + vr1->set_undefined (); /* As a future improvement, we could handle ~[0, A] as: [-INF, -1] U [A+1, +INF]. Not sure if this helps in practice, though. */ @@ -1347,7 +1322,7 @@ ranges_from_anti_range (const value_range_base *ar, if (vr0->undefined_p ()) { *vr0 = *vr1; - vr1->set_undefined (type); + vr1->set_undefined (); } return !vr0->undefined_p (); @@ -1608,7 +1583,7 @@ extract_range_from_binary_expr (value_range_base *vr, /* If both ranges are UNDEFINED, so is the result. */ if (vr0.undefined_p () && vr1.undefined_p ()) { - vr->set_undefined (expr_type); + vr->set_undefined (); return; } /* If one of the ranges is UNDEFINED drop it to VARYING for the following @@ -1921,7 +1896,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 (expr_type); + vr->set_undefined (); return; } @@ -1960,7 +1935,7 @@ extract_range_from_binary_expr (value_range_base *vr, { if (vr1.zero_p ()) { - vr->set_undefined (expr_type); + vr->set_undefined (); return; } wide_int wmin, wmax, tmp; @@ -2101,7 +2076,7 @@ extract_range_from_unary_expr (value_range_base *vr, /* If VR0 is UNDEFINED, so is the result. */ if (vr0.undefined_p ()) { - vr->set_undefined (type); + vr->set_undefined (); return; } @@ -2421,7 +2396,7 @@ range_ops_fold_binary_expr (value_range_base *vr, value_range_base vr0 = *vr0_, vr1 = *vr1_; if (vr0.undefined_p () && vr1.undefined_p ()) { - vr->set_undefined (expr_type); + vr->set_undefined (); return; } if (vr0.undefined_p ()) @@ -2473,7 +2448,7 @@ range_ops_fold_unary_expr (value_range_base *vr, } if (vr0->undefined_p ()) { - vr->set_undefined (expr_type); + vr->set_undefined (); return; } @@ -2535,8 +2510,10 @@ range_fold_binary_expr (value_range_base *vr, const value_range_base *vr1) { if (!value_range_base::supports_type_p (expr_type) - || !value_range_base::supports_type_p (vr0->type ()) - || !value_range_base::supports_type_p (vr1->type ())) + || (!vr0->undefined_p () + && !value_range_base::supports_type_p (vr0->type ())) + || (!vr1->undefined_p () + && !value_range_base::supports_type_p (vr1->type ()))) { *vr = value_range (expr_type); return; @@ -2562,10 +2539,11 @@ void range_fold_unary_expr (value_range_base *vr, enum tree_code code, tree expr_type, - const value_range_base *vr0) + const value_range_base *vr0, + tree vr0_type) { if (!value_range_base::supports_type_p (expr_type) - || !value_range_base::supports_type_p (vr0->type ())) + || !value_range_base::supports_type_p (vr0_type)) { *vr = value_range (expr_type); return; @@ -2575,7 +2553,7 @@ range_fold_unary_expr (value_range_base *vr, if (flag_ranges_mode & RANGES_VRP) { value_range_base old; - extract_range_from_unary_expr (&old, code, expr_type, vr0, vr0->type ()); + extract_range_from_unary_expr (&old, code, expr_type, vr0, vr0_type); if (flag_ranges_mode & RANGES_CHECKING) { value_range_base vr1 (expr_type); @@ -6464,7 +6442,7 @@ value_range_base::intersect_helper (const value_range_base *vr0, fall back to vr0 when this turns things to varying. */ value_range_base tem; if (vr0type == VR_UNDEFINED) - tem.set_undefined (TREE_TYPE (vr0->min ())); + tem.set_undefined (); else if (vr0type == VR_VARYING) tem.set_varying (TREE_TYPE (vr0->min ())); else @@ -6574,7 +6552,7 @@ 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; if (vr0type == VR_UNDEFINED) - tem.set_undefined (TREE_TYPE (vr0->min ())); + tem.set_undefined (); else if (vr0type == VR_VARYING) tem.set_varying (vr0->type ()); else @@ -6815,9 +6793,9 @@ void value_range_base::invert () { if (undefined_p ()) - set_varying (type ()); - else if (varying_p ()) - set_undefined (type ()); + return; + if (varying_p ()) + set_undefined (); else if (m_kind == VR_RANGE) m_kind = VR_ANTI_RANGE; else if (m_kind == VR_ANTI_RANGE) @@ -6826,6 +6804,19 @@ value_range_base::invert () gcc_unreachable (); } +value_range_storage * +value_range_storage::alloc (const value_range_base &r, tree type) +{ + if (type) + gcc_checking_assert (r.undefined_p () + || types_compatible_p (type, r.type ())); + else + type = r.type (); + value_range_storage *p = ggc_alloc<value_range_storage> (); + p->set (r, type); + return p; +} + void value_range_base::union_ (const value_range_base &r) { diff --git a/gcc/tree-vrp.h b/gcc/tree-vrp.h index ba60f47..562928a 100644 --- a/gcc/tree-vrp.h +++ b/gcc/tree-vrp.h @@ -57,7 +57,7 @@ public: bool undefined_p () const; bool varying_p () const; void set_varying (tree type); - void set_undefined (tree = NULL); + void set_undefined (); void union_ (const value_range_base *); void intersect (const value_range_base *); @@ -148,7 +148,7 @@ 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 (tree = NULL); + void set_undefined (); void set_varying (tree); /* Equivalence bitmap methods. */ @@ -175,19 +175,14 @@ class value_range_storage { friend class value_range_base; public: - static value_range_storage *alloc (const value_range_base &r) + static value_range_storage *alloc (const value_range_base &r, tree type); + bool update (const value_range_base &r, tree type) { - value_range_storage *p = ggc_alloc<value_range_storage> (); - p->set (r); - return p; - } - bool update (const value_range_base &r) - { - set (r); + set (r, type); return true; } private: - void set (const value_range_base &r) + void set (const value_range_base &r, tree type ATTRIBUTE_UNUSED) { m_vr = r; } @@ -372,17 +367,19 @@ void range_fold_binary_expr (value_range_base *, enum tree_code, tree, const value_range_base *, const value_range_base *); void range_fold_unary_expr (value_range_base *, enum tree_code, tree, - const value_range_base *); + const value_range_base *, tree); /* Return TRUE if *VR includes the value zero. */ inline bool range_includes_zero_p (const value_range_base *vr) { - /* UNDEFINED may not have a type in uninitialized ranges. */ if (vr->undefined_p ()) return false; + if (vr->varying_p ()) + return true; + return vr->may_contain_p (build_zero_cst (vr->type ())); } diff --git a/gcc/vr-values.c b/gcc/vr-values.c index 8e48178..c37c007 100644 --- a/gcc/vr-values.c +++ b/gcc/vr-values.c @@ -187,7 +187,7 @@ vr_values::get_lattice_entry (const_tree var) return vr; } - vr->set_undefined (TREE_TYPE (var)); + vr->set_undefined (); /* If VAR is a default definition of a parameter, the variable can take any value in VAR's type. */ @@ -1032,7 +1032,7 @@ vr_values::extract_range_from_unary_expr (value_range *vr, enum tree_code code, else vr0.set_varying (type); - range_fold_unary_expr (vr, code, type, &vr0); + range_fold_unary_expr (vr, code, type, &vr0, TREE_TYPE (op0)); } |