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


Reply via email to