On 4/26/21 10:16 AM, Aldy Hernandez wrote:
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?
Guess we should have done this earlier.. varying_p is very heavily
used. I assume this also passes regressions and bootstrap :-)?
// 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;
+}
I find the routine irange_varying_p() name to be a bit confusing...
since varying_p is also an irange routine.. Maybe call it something
like varying_p_compatible () or something along those lines?
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
I see that normalize_kind will turn a varying ANTI_RANGE to UNDEFINED.
If you go into irange::set (tree min, tree max, value_range_kind kind)
I see:
// Anti-ranges that can be represented as ranges should be so.
if (kind == VR_ANTI_RANGE)
{
/* For -fstrict-enums we may receive out-of-range ranges so consider
values < -INF and values > INF as -INF/INF as well. */
bool is_min = vrp_val_is_min (min);
bool is_max = vrp_val_is_max (max);
tree type = TREE_TYPE (min);
if (is_min && is_max)
{
/* We cannot deal with empty ranges, drop to varying.
??? This could be VR_UNDEFINED instead. */
set_varying (type);
return;
}
should that be set_undefined? or is that a different can of worms
related to strict-enum?
Assuming bootstrap and regression tests, OK
Andrew