Currently multi-ranges calculate the undefined and varying bits on the fly, whereas legacy uses the m_kind field. Since we will always have space in the irange class for a kind field, might as well keep it in sync as ranges are created, thus speeding up lookups.
This patch, along with an upcoming ones for num_pairs(), speeds up EVRP by 8.47%, VRP proper by 1.84% and overall compilation by 0.24%. FWIW, since evrp is such a fast pass, and is hard to measure clock-wise, we've been using callgrind to estimate improvements. This has coincided more or less with -ftime-report numbers (albeit having to run -ftime-report half a dozen times and use the average). OK? gcc/ChangeLog: * value-range.cc (irange::operator=): Set m_kind. (irange::copy_to_legacy): Handle varying and undefined sources as a legacy copy since they can be easily copied. (irange::irange_set): Set m_kind. (irange::irange_set_anti_range): Same. (irange::set): Rename normalize_min_max to normalize_kind. (irange::verify_range): Adjust for multi-ranges having the m_kind field set. (irange::irange_union): Set m_kind. (irange::irange_intersect): Same. (irange::invert): Same. * value-range.h (irange::kind): Always return m_kind. (irange::varying_p): Rename to... (irange::irange_varying_p): ...this. (irange::undefined_p): Only look at m_kind. (irange::irange): Always set VR_UNDEFINED if applicable. (irange::set_undefined): Always set VR_UNDEFINED. (irange::set_varying): Always set m_kind to VR_VARYING. (irange::normalize_min_max): Rename to... (irange::normalize_kind): ...this. --- gcc/value-range.cc | 69 +++++++++++++++++++++++++++------------------- gcc/value-range.h | 66 ++++++++++++++++---------------------------- 2 files changed, 63 insertions(+), 72 deletions(-) diff --git a/gcc/value-range.cc b/gcc/value-range.cc index f5ef4808530..369eeabd7d5 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -59,6 +59,7 @@ irange::operator= (const irange &src) m_base[x - 1] = src.m_base[src.m_num_ranges * 2 - 1]; m_num_ranges = lim; + m_kind = src.m_kind; return *this; } @@ -106,8 +107,8 @@ void irange::copy_to_legacy (const irange &src) { gcc_checking_assert (legacy_mode_p ()); - // Copy legacy to legacy. - if (src.legacy_mode_p ()) + // Handle legacy to legacy and other things that are easy to copy. + if (src.legacy_mode_p () || src.varying_p () || src.undefined_p ()) { m_num_ranges = src.m_num_ranges; m_base[0] = src.m_base[0]; @@ -116,11 +117,7 @@ irange::copy_to_legacy (const irange &src) return; } // Copy multi-range to legacy. - if (src.undefined_p ()) - set_undefined (); - else if (src.varying_p ()) - set_varying (src.type ()); - else if (src.maybe_anti_range ()) + if (src.maybe_anti_range ()) { int_range<3> r (src); r.invert (); @@ -180,6 +177,9 @@ irange::irange_set (tree min, tree max) m_base[0] = min; m_base[1] = max; m_num_ranges = 1; + m_kind = VR_RANGE; + normalize_kind (); + if (flag_checking) verify_range (); } @@ -247,6 +247,10 @@ irange::irange_set_anti_range (tree min, tree max) m_base[m_num_ranges * 2 + 1] = type_range.tree_upper_bound (0); ++m_num_ranges; } + + m_kind = VR_RANGE; + normalize_kind (); + if (flag_checking) verify_range (); } @@ -353,7 +357,7 @@ irange::set (tree min, tree max, value_range_kind kind) m_base[0] = min; m_base[1] = max; m_num_ranges = 1; - normalize_min_max (); + normalize_kind (); if (flag_checking) verify_range (); } @@ -363,9 +367,22 @@ irange::set (tree min, tree max, value_range_kind kind) void irange::verify_range () { + if (m_kind == VR_UNDEFINED) + { + gcc_assert (m_num_ranges == 0); + return; + } + gcc_assert (m_num_ranges != 0); + + if (m_kind == VR_VARYING) + { + gcc_assert (m_num_ranges == 1); + gcc_assert (irange_varying_p ()); + return; + } if (!legacy_mode_p ()) { - gcc_checking_assert (m_kind == VR_RANGE); + gcc_assert (!irange_varying_p ()); for (unsigned i = 0; i < m_num_ranges; ++i) { tree lb = tree_lower_bound (i); @@ -375,28 +392,11 @@ irange::verify_range () } return; } - - switch (m_kind) + if (m_kind == VR_RANGE || m_kind == VR_ANTI_RANGE) { - case VR_UNDEFINED: - gcc_assert (m_num_ranges == 0); - break; - - case VR_VARYING: gcc_assert (m_num_ranges == 1); - break; - - case VR_ANTI_RANGE: - case VR_RANGE: - { - gcc_assert (m_num_ranges == 1); - int cmp = compare_values (tree_lower_bound (0), tree_upper_bound (0)); - gcc_assert (cmp == 0 || cmp == -1 || cmp == -2); - return; - } - - default: - gcc_unreachable (); + int cmp = compare_values (tree_lower_bound (0), tree_upper_bound (0)); + gcc_assert (cmp == 0 || cmp == -1 || cmp == -2); } } @@ -1667,6 +1667,9 @@ irange::irange_union (const irange &r) m_base[j] = res [j]; m_num_ranges = i / 2; + m_kind = VR_RANGE; + normalize_kind (); + if (flag_checking) verify_range (); } @@ -1758,6 +1761,10 @@ irange::irange_intersect (const irange &r) // At the exit of this loop, it is one of 2 things: // ran out of r1, or r2, but either means we are done. m_num_ranges = bld_pair; + + m_kind = VR_RANGE; + normalize_kind (); + if (flag_checking) verify_range (); } @@ -1890,6 +1897,10 @@ irange::invert () } m_num_ranges = nitems / 2; + // We disallow undefined or varying coming in, so the result can + // only be a VR_RANGE. + gcc_checking_assert (m_kind == VR_RANGE); + if (flag_checking) verify_range (); } diff --git a/gcc/value-range.h b/gcc/value-range.h index bb27e706207..bfba1a3469e 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -111,7 +111,7 @@ protected: void irange_set (tree, tree); void irange_set_anti_range (tree, tree); - void normalize_min_max (); + void normalize_kind (); bool legacy_mode_p () const; bool legacy_equal_p (const irange &) const; @@ -128,6 +128,7 @@ protected: private: void irange_set_1bit_anti_range (tree, tree); + bool irange_varying_p () const; unsigned char m_num_ranges; unsigned char m_max_ranges; @@ -198,16 +199,7 @@ extern bool vrp_operand_equal_p (const_tree, const_tree); inline value_range_kind irange::kind () const { - if (legacy_mode_p ()) - return m_kind; - - if (undefined_p ()) - return VR_UNDEFINED; - - if (varying_p ()) - return VR_VARYING; - - return VR_RANGE; + return m_kind; } // Number of sub-ranges in a range. @@ -271,17 +263,18 @@ irange::max () const } inline bool -irange::varying_p () const +irange::irange_varying_p () const { - if (legacy_mode_p ()) - return m_kind == VR_VARYING; - if (m_num_ranges != 1) return false; tree l = m_base[0]; tree u = m_base[1]; tree t = TREE_TYPE (l); + + if (m_kind == VR_VARYING && t == error_mark_node) + return true; + unsigned prec = TYPE_PRECISION (t); signop sign = TYPE_SIGN (t); if (INTEGRAL_TYPE_P (t)) @@ -291,22 +284,17 @@ irange::varying_p () const return (wi::to_wide (l) == 0 && wi::to_wide (u) == wi::max_value (prec, sign)); return true; +} +inline bool +irange::varying_p () const +{ + return m_kind == VR_VARYING; } inline bool irange::undefined_p () const { - if (!legacy_mode_p ()) - return m_num_ranges == 0; - - if (CHECKING_P && legacy_mode_p ()) - { - if (m_kind == VR_UNDEFINED) - gcc_checking_assert (m_num_ranges == 0); - else - gcc_checking_assert (m_num_ranges != 0); - } return m_kind == VR_UNDEFINED; } @@ -389,10 +377,7 @@ irange::irange (tree *base, unsigned nranges) m_base = base; m_num_ranges = 0; m_max_ranges = nranges; - if (legacy_mode_p ()) - m_kind = VR_UNDEFINED; - else - m_kind = VR_RANGE; + m_kind = VR_UNDEFINED; } // Constructors for int_range<>. @@ -459,18 +444,16 @@ irange::set (tree val) inline void irange::set_undefined () { + m_kind = VR_UNDEFINED; m_num_ranges = 0; - if (legacy_mode_p ()) - m_kind = VR_UNDEFINED; } inline void irange::set_varying (tree type) { - if (legacy_mode_p ()) - m_kind = VR_VARYING; - + m_kind = VR_VARYING; m_num_ranges = 1; + if (INTEGRAL_TYPE_P (type)) { wide_int min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type)); @@ -574,17 +557,14 @@ irange::set_zero (tree type) // Normalize a range to VARYING or UNDEFINED if possible. inline void -irange::normalize_min_max () -{ - gcc_checking_assert (legacy_mode_p ()); - gcc_checking_assert (!undefined_p ()); - unsigned prec = TYPE_PRECISION (type ()); - signop sign = TYPE_SIGN (type ()); - if (wi::eq_p (wi::to_wide (min ()), wi::min_value (prec, sign)) - && wi::eq_p (wi::to_wide (max ()), wi::max_value (prec, sign))) +irange::normalize_kind () +{ + if (m_num_ranges == 0) + m_kind = VR_UNDEFINED; + else if (irange_varying_p ()) { if (m_kind == VR_RANGE) - set_varying (type ()); + m_kind = VR_VARYING; else if (m_kind == VR_ANTI_RANGE) set_undefined (); else -- 2.30.2