Add storage support for prange.

gcc/ChangeLog:

	* value-range-storage.cc (vrange_allocator::clone_varying): Add
	prange support.
	(vrange_allocator::clone_undefined): Same.
	(vrange_storage::alloc): Same.
	(vrange_storage::set_vrange): Same.
	(vrange_storage::get_vrange): Same.
	(vrange_storage::fits_p): Same.
	(vrange_storage::equal_p): Same.
	(prange_storage::alloc): New.
	(prange_storage::prange_storage): New.
	(prange_storage::set_prange): New.
	(prange_storage::get_prange): New.
	(prange_storage::equal_p): New.
	(prange_storage::fits_p): New.
	* value-range-storage.h (class prange_storage): Add prange support.
This commit is contained in:
Aldy Hernandez 2024-03-20 06:38:06 +01:00
parent a7f1285380
commit f859996a97
2 changed files with 150 additions and 0 deletions

View File

@ -118,6 +118,8 @@ vrange_allocator::clone_varying (tree type)
{
if (irange::supports_p (type))
return irange_storage::alloc (*m_alloc, int_range <1> (type));
if (prange::supports_p (type))
return prange_storage::alloc (*m_alloc, prange (type));
if (frange::supports_p (type))
return frange_storage::alloc (*m_alloc, frange (type));
return NULL;
@ -128,6 +130,8 @@ vrange_allocator::clone_undefined (tree type)
{
if (irange::supports_p (type))
return irange_storage::alloc (*m_alloc, int_range<1> ());
if (prange::supports_p (type))
return prange_storage::alloc (*m_alloc, prange ());
if (frange::supports_p (type))
return frange_storage::alloc (*m_alloc, frange ());
return NULL;
@ -141,6 +145,8 @@ vrange_storage::alloc (vrange_internal_alloc &allocator, const vrange &r)
{
if (is_a <irange> (r))
return irange_storage::alloc (allocator, as_a <irange> (r));
if (is_a <prange> (r))
return prange_storage::alloc (allocator, as_a <prange> (r));
if (is_a <frange> (r))
return frange_storage::alloc (allocator, as_a <frange> (r));
return NULL;
@ -157,6 +163,12 @@ vrange_storage::set_vrange (const vrange &r)
gcc_checking_assert (s->fits_p (as_a <irange> (r)));
s->set_irange (as_a <irange> (r));
}
else if (is_a <prange> (r))
{
prange_storage *s = static_cast <prange_storage *> (this);
gcc_checking_assert (s->fits_p (as_a <prange> (r)));
s->set_prange (as_a <prange> (r));
}
else if (is_a <frange> (r))
{
frange_storage *s = static_cast <frange_storage *> (this);
@ -190,6 +202,11 @@ vrange_storage::get_vrange (vrange &r, tree type) const
const irange_storage *s = static_cast <const irange_storage *> (this);
s->get_irange (as_a <irange> (r), type);
}
else if (is_a <prange> (r))
{
const prange_storage *s = static_cast <const prange_storage *> (this);
s->get_prange (as_a <prange> (r), type);
}
else if (is_a <frange> (r))
{
const frange_storage *s = static_cast <const frange_storage *> (this);
@ -209,6 +226,11 @@ vrange_storage::fits_p (const vrange &r) const
const irange_storage *s = static_cast <const irange_storage *> (this);
return s->fits_p (as_a <irange> (r));
}
if (is_a <prange> (r))
{
const prange_storage *s = static_cast <const prange_storage *> (this);
return s->fits_p (as_a <prange> (r));
}
if (is_a <frange> (r))
{
const frange_storage *s = static_cast <const frange_storage *> (this);
@ -230,6 +252,11 @@ vrange_storage::equal_p (const vrange &r) const
const irange_storage *s = static_cast <const irange_storage *> (this);
return s->equal_p (as_a <irange> (r));
}
if (is_a <prange> (r))
{
const prange_storage *s = static_cast <const prange_storage *> (this);
return s->equal_p (as_a <prange> (r));
}
if (is_a <frange> (r))
{
const frange_storage *s = static_cast <const frange_storage *> (this);
@ -559,6 +586,96 @@ frange_storage::fits_p (const frange &) const
return true;
}
//============================================================================
// prange_storage implementation
//============================================================================
prange_storage *
prange_storage::alloc (vrange_internal_alloc &allocator, const prange &r)
{
// Assume all pointers are the same size.
unsigned prec = TYPE_PRECISION (TREE_TYPE (null_pointer_node));
gcc_checking_assert (r.undefined_p () || TYPE_PRECISION (r.type ()) == prec);
typedef trailing_wide_ints<NINTS> twi;
size_t size = sizeof (prange_storage) + twi::extra_size (prec);
prange_storage *p = static_cast <prange_storage *> (allocator.alloc (size));
new (p) prange_storage (r);
return p;
}
// Initialize the storage with R.
prange_storage::prange_storage (const prange &r)
{
// It is the caller's responsibility to allocate enough space such
// that the precision fits.
unsigned prec = TYPE_PRECISION (TREE_TYPE (null_pointer_node));
m_trailing_ints.set_precision (prec);
set_prange (r);
}
void
prange_storage::set_prange (const prange &r)
{
if (r.undefined_p ())
m_kind = VR_UNDEFINED;
else if (r.varying_p ())
m_kind = VR_VARYING;
else
{
m_kind = VR_RANGE;
set_low (r.lower_bound ());
set_high (r.upper_bound ());
irange_bitmask bm = r.m_bitmask;
set_value (bm.value ());
set_mask (bm.mask ());
}
}
void
prange_storage::get_prange (prange &r, tree type) const
{
gcc_checking_assert (r.supports_type_p (type));
if (m_kind == VR_UNDEFINED)
r.set_undefined ();
else if (m_kind == VR_VARYING)
r.set_varying (type);
else
{
gcc_checking_assert (m_kind == VR_RANGE);
gcc_checking_assert (TYPE_PRECISION (type) == m_trailing_ints.get_precision ());
r.m_kind = VR_RANGE;
r.m_type = type;
r.m_min = get_low ();
r.m_max = get_high ();
r.m_bitmask = irange_bitmask (get_value (), get_mask ());
if (flag_checking)
r.verify_range ();
}
}
bool
prange_storage::equal_p (const prange &r) const
{
if (r.undefined_p ())
return m_kind == VR_UNDEFINED;
prange tmp;
get_prange (tmp, r.type ());
return tmp == r;
}
bool
prange_storage::fits_p (const prange &) const
{
// All pointers are the same size.
return true;
}
static vrange_allocator ggc_vrange_allocator (true);
vrange_storage *ggc_alloc_vrange_storage (tree type)

View File

@ -98,6 +98,39 @@ private:
irange_storage (const irange &r);
};
// Efficient memory storage for a prange.
class prange_storage : public vrange_storage
{
public:
static prange_storage *alloc (vrange_internal_alloc &, const prange &);
void set_prange (const prange &r);
void get_prange (prange &r, tree type) const;
bool equal_p (const prange &r) const;
bool fits_p (const prange &r) const;
void dump () const;
private:
DISABLE_COPY_AND_ASSIGN (prange_storage);
prange_storage (const prange &r);
enum value_range_kind m_kind : 3;
// We don't use TRAILING_WIDE_INT_ACCESSOR because the getters here
// must be const. Perhaps TRAILING_WIDE_INT_ACCESSOR could be made
// const and return wide_int instead of trailing_wide_int.
wide_int get_low () const { return m_trailing_ints[0]; }
wide_int get_high () const { return m_trailing_ints[1]; }
wide_int get_value () const { return m_trailing_ints[2]; }
wide_int get_mask () const { return m_trailing_ints[3]; }
template <typename T> void set_low (const T &x) { m_trailing_ints[0] = x; }
template <typename T> void set_high (const T &x) { m_trailing_ints[1] = x; }
template <typename T> void set_value (const T &x) { m_trailing_ints[2] = x; }
template <typename T> void set_mask (const T &x) { m_trailing_ints[3] = x; }
static const unsigned int NINTS = 4;
trailing_wide_ints<NINTS> m_trailing_ints;
};
// Efficient memory storage for an frange.
class frange_storage : public vrange_storage