Hi folks!
In implementing prange (pointer ranges), I have found a 1.74% slowdown
in VRP, even without any code path actually using the code. I have
tracked this down to irange::get_bitmask() being compiled differently
with and without the bare bones patch. With the patch,
irange::get_bitmask() has a lot of code inlined into it, particularly
get_bitmask_from_range() and consequently the wide_int_storage code.
I don't know whether this is expected behavior, and if it is, how to
mitigate it. I have tried declaring get_bitmask_from_range() inline,
but that didn't help. OTOH, using __attribute__((always_inline))
helps a bit, but not entirely. What does help is inlining
irange::get_bitmask() entirely, but that seems like a big hammer.
The overall slowdown in compilation is 0.26%, because VRP is a
relatively fast pass, but a measurable pass slowdown is something we'd
like to avoid.
What's the recommended approach here?
For the curious, I am attaching before and after copies of
value-range.s. I am also attaching the two patches needed to
reproduce the problem on mainline. The first patch is merely setup.
It is the second patch that exhibits the problem. Notice there are no
uses of prange yet.
Thanks.
Aldy
From ee63833c5f56064ef47c2bb9debd485f77d00171 Mon Sep 17 00:00:00 2001
From: Aldy Hernandez
Date: Tue, 19 Mar 2024 18:04:55 +0100
Subject: [PATCH] Move get_bitmask_from_range out of irange class.
---
gcc/value-range.cc | 52 +++---
gcc/value-range.h | 1 -
2 files changed, 26 insertions(+), 27 deletions(-)
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 70375f7abf9..0f81ce32615 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -31,6 +31,30 @@ along with GCC; see the file COPYING3. If not see
#include "fold-const.h"
#include "gimple-range.h"
+// Return the bitmask inherent in a range.
+
+static irange_bitmask
+get_bitmask_from_range (tree type,
+ const wide_int &min, const wide_int &max)
+{
+ unsigned prec = TYPE_PRECISION (type);
+
+ // All the bits of a singleton are known.
+ if (min == max)
+{
+ wide_int mask = wi::zero (prec);
+ wide_int value = min;
+ return irange_bitmask (value, mask);
+}
+
+ wide_int xorv = min ^ max;
+
+ if (xorv != 0)
+xorv = wi::mask (prec - wi::clz (xorv), false, prec);
+
+ return irange_bitmask (wi::zero (prec), min | xorv);
+}
+
void
irange::accept (const vrange_visitor &v) const
{
@@ -1832,31 +1856,6 @@ irange::invert ()
verify_range ();
}
-// Return the bitmask inherent in the range.
-
-irange_bitmask
-irange::get_bitmask_from_range () const
-{
- unsigned prec = TYPE_PRECISION (type ());
- wide_int min = lower_bound ();
- wide_int max = upper_bound ();
-
- // All the bits of a singleton are known.
- if (min == max)
-{
- wide_int mask = wi::zero (prec);
- wide_int value = lower_bound ();
- return irange_bitmask (value, mask);
-}
-
- wide_int xorv = min ^ max;
-
- if (xorv != 0)
-xorv = wi::mask (prec - wi::clz (xorv), false, prec);
-
- return irange_bitmask (wi::zero (prec), min | xorv);
-}
-
// Remove trailing ranges that this bitmask indicates can't exist.
void
@@ -1978,7 +1977,8 @@ irange::get_bitmask () const
// in the mask.
//
// See also the note in irange_bitmask::intersect.
- irange_bitmask bm = get_bitmask_from_range ();
+ irange_bitmask bm
+= get_bitmask_from_range (type (), lower_bound (), upper_bound ());
if (!m_bitmask.unknown_p ())
bm.intersect (m_bitmask);
return bm;
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 9531df56988..dc5b153a83e 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -351,7 +351,6 @@ private:
bool varying_compatible_p () const;
bool intersect_bitmask (const irange &r);
bool union_bitmask (const irange &r);
- irange_bitmask get_bitmask_from_range () const;
bool set_range_from_bitmask ();
bool intersect (const wide_int& lb, const wide_int& ub);
--
2.44.0
From 03c70de43177a97ec5e9c243aafc798c1f37e6d8 Mon Sep 17 00:00:00 2001
From: Aldy Hernandez
Date: Wed, 20 Mar 2024 06:25:52 +0100
Subject: [PATCH] Implement minimum prange class exhibiting VRP slowdown.
---
gcc/value-range-pretty-print.cc | 25 +++
gcc/value-range-pretty-print.h | 1 +
gcc/value-range.cc | 274
gcc/value-range.h | 196 +++
4 files changed, 496 insertions(+)
diff --git a/gcc/value-range-pretty-print.cc b/gcc/value-range-pretty-print.cc
index c75cbea3955..154253e047f 100644
--- a/gcc/value-range-pretty-print.cc
+++ b/gcc/value-range-pretty-print.cc
@@ -113,6 +113,31 @@ vrange_printer::print_irange_bitmasks (const irange &r) const
pp_string (pp, p);
}
+void
+vrange_printer::visit (const prange &r) const
+{
+ pp_string (pp, "[prange] ");
+ if (r.undefined_p ())
+{
+ pp_string (pp, "UNDEFINED");
+ return;
+}
+ dump_generic_node (pp, r.type (), 0