diff options
author | Aldy Hernandez <aldyh@redhat.com> | 2022-07-01 13:20:42 +0200 |
---|---|---|
committer | Aldy Hernandez <aldyh@redhat.com> | 2022-07-04 11:34:20 +0200 |
commit | 4e82205b68024f5c1a9006fe2b62e1a0fa7f1245 (patch) | |
tree | 77cebaa3afd64005e885a7660996b11fa753eda8 /gcc/value-range.h | |
parent | d2a898666609452ef79a14feae1cadc3538e4b45 (diff) | |
download | gcc-4e82205b68024f5c1a9006fe2b62e1a0fa7f1245.zip gcc-4e82205b68024f5c1a9006fe2b62e1a0fa7f1245.tar.gz gcc-4e82205b68024f5c1a9006fe2b62e1a0fa7f1245.tar.bz2 |
Integrate nonzero bits with irange.
The nonzero bits and integer ranges compliment each other quite well,
and it only makes sense to make the mask a first class citizen in the
irange. We do a half assed job of keeping ranges and nonzero bits
somewhat in sync in SSA_NAME_RANGE_INFO, and the goal has always
been to integrate them properly. This patch does that, in preparation
for streaming out full-resolution iranges between passes (think
SSA_NAME_RANGE_INFO).
Having nonzero bits in the irange allows us to get better results from
things like irange::contains_p() and keeping them in the irange allows
us to propagate the bits throughout with the ranger. This patch
provides the bare infrastructure, without any optimizations to
range-ops, etc. Those will come as follow-ups.
A few notes:
Legacy SSA_NAME_RANGE_INFO updates the nonzero bits every time a range
is set. Here instead, we don't update the nonzero bits on a new
range, but calculate it on the fly when irange::get_nonzero_bits() is
called. The goal is to only store nonzero bits that provide
meaningful information that can't be gleaned from the range itself.
But you can always call get_nonzero_bits() and get the full
information.
Nonzero bits are not supported in legacy mode. The mask may be set
as a consequence of propagation or reading global ranges, but no
one from legacy land should be querying irange::get_nonzero_bits. There
is an assert enforcing this. However, legacy/global set_nonzero_bits()
continue to work as before. There is no change to legacy behavior.
There is virtually no performance change with this patch, as there are
no consumers. The next patch I post will be the SSA_NAME_RANGE_INFO
conversion to the new world, in which I will discuss performance
proper. Hint: I'll be chewing up the time budget we gained with the
vrange conversion.
Tested and benchmarked on x86-64 Linux.
gcc/ChangeLog:
* value-range-storage.cc (irange_storage_slot::set_irange): Set
nonzero bits in irange.
(irange_storage_slot::get_irange): Get nonzero bits from irange.
* value-range.cc (irange::operator=): Set nonzero bits.
(irange::irange_set): Same.
(irange::irange_set_anti_range): Same.
(irange::set): Same.
(irange::verify_range): Same.
(irange::legacy_equal_p): Check nonzero bits.
(irange::equal_p): Same.
(irange::contains_p): Handle nonzero bits.
(irange::irange_union): Same.
(irange::irange_intersect): Same.
(irange::dump): Same.
(irange::set_nonzero_bits): New.
(irange::get_nonzero_bits): New.
(irange::intersect_nonzero_bits): New.
(irange::union_nonzero_bits): New.
(irange::dump_bitmasks): New.
* value-range.h (class irange): Add m_nonzero_mask.
(gt_ggc_mx): Handle nonzero bits.
(gt_pch_nx): Same.
(irange::set_undefined): Set nonzero bits.
(irange::set_varying): Same.
(irange::normalize_kind): Call set_undefined.
Diffstat (limited to 'gcc/value-range.h')
-rw-r--r-- | gcc/value-range.h | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/gcc/value-range.h b/gcc/value-range.h index fd67031..2e48d92 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -109,6 +109,7 @@ protected: class GTY((user)) irange : public vrange { friend class vrange_allocator; + friend class irange_storage_slot; // For legacy_mode_p checks. public: // In-place setters. virtual void set (tree, tree, value_range_kind = VR_RANGE) override; @@ -149,6 +150,10 @@ public: virtual bool fits_p (const vrange &r) const override; virtual void dump (FILE * = stderr) const override; + // Nonzero masks. + wide_int get_nonzero_bits () const; + void set_nonzero_bits (const wide_int_ref &bits); + // Deprecated legacy public methods. tree min () const; // DEPRECATED tree max () const; // DEPRECATED @@ -196,10 +201,15 @@ private: void irange_set_1bit_anti_range (tree, tree); bool varying_compatible_p () const; + void set_nonzero_bits (tree bits) { m_nonzero_mask = bits; } + bool intersect_nonzero_bits (const irange &r); + bool union_nonzero_bits (const irange &r); + void dump_bitmasks (FILE *) const; bool intersect (const wide_int& lb, const wide_int& ub); unsigned char m_num_ranges; unsigned char m_max_ranges; + tree m_nonzero_mask; tree *m_base; }; @@ -608,6 +618,8 @@ gt_ggc_mx (irange *x) gt_ggc_mx (x->m_base[i * 2]); gt_ggc_mx (x->m_base[i * 2 + 1]); } + if (x->m_nonzero_mask) + gt_ggc_mx (x->m_nonzero_mask); } inline void @@ -618,6 +630,8 @@ gt_pch_nx (irange *x) gt_pch_nx (x->m_base[i * 2]); gt_pch_nx (x->m_base[i * 2 + 1]); } + if (x->m_nonzero_mask) + gt_pch_nx (x->m_nonzero_mask); } inline void @@ -628,6 +642,8 @@ gt_pch_nx (irange *x, gt_pointer_operator op, void *cookie) op (&x->m_base[i * 2], NULL, cookie); op (&x->m_base[i * 2 + 1], NULL, cookie); } + if (x->m_nonzero_mask) + op (&x->m_nonzero_mask, NULL, cookie); } template<unsigned N> @@ -722,6 +738,7 @@ irange::set_undefined () { m_kind = VR_UNDEFINED; m_num_ranges = 0; + m_nonzero_mask = NULL; } inline void @@ -729,6 +746,7 @@ irange::set_varying (tree type) { m_kind = VR_VARYING; m_num_ranges = 1; + m_nonzero_mask = NULL; if (INTEGRAL_TYPE_P (type)) { @@ -843,7 +861,7 @@ inline void irange::normalize_kind () { if (m_num_ranges == 0) - m_kind = VR_UNDEFINED; + set_undefined (); else if (varying_compatible_p ()) { if (m_kind == VR_RANGE) |