Message ID | 20220530132751.1752112-4-aldyh@redhat.com |
---|---|
State | New |
Headers | show |
Series | [1/5] Implement abstract vrange class. | expand |
Final patch committed. Re-tested on x86-64 Linux. On Mon, May 30, 2022 at 3:28 PM Aldy Hernandez <aldyh@redhat.com> wrote: > > This patch revamps the range allocator to handle generic vrange's. > I've cleaned it up somehow to make it obvious the various things you > can allocate with it. I've also moved away from overloads into > distinct names when appropriate. > > The various entry points are now: > > // Allocate a range of TYPE. > vrange *alloc_vrange (tree type); > // Allocate a memory block of BYTES. > void *alloc (unsigned bytes); > // Return a clone of SRC. > template <typename T> T *clone (const T &src); > > It is now possible to allocate a clone of an irange, or any future > range types: > > irange *i = allocator.clone <irange> (some_irange); > frange *f = allocator.clone <frange> (some_frange); > > You can actually do so without the <>, but I find it clearer to > specify the vrange type. > > So with it you can allocate a specific range type, or vrange, or a > block of memory. > > I have rewritten the C style casts to C++ casts, since casts tend to > be hints of problematic designs. With the C++ casts you can at least > grep for them easier. Speak of which, the next patch, which converts > ranger to vrange, will further clean this space by removing some > unnecessary casts. > > Tested on x86-64 Linux and ppc64le Linux. > > * gimple-range-cache.cc (sbr_vector::sbr_vector): Adjust for > vrange allocator. > (sbr_vector::grow): Same. > (sbr_vector::set_bb_range): Same. > (sbr_sparse_bitmap::sbr_sparse_bitmap): Same. > (sbr_sparse_bitmap::set_bb_range): Same. > (block_range_cache::~block_range_cache): Same. > (block_range_cache::set_bb_range): Same. > (ssa_global_cache::ssa_global_cache): Same. > (ssa_global_cache::~ssa_global_cache): Same. > (ssa_global_cache::set_global_range): Same. > * gimple-range-cache.h (block_range_cache): Same. > (ssa_global_cache): Same. > * gimple-range-edge.cc > (gimple_outgoing_range::calc_switch_ranges): Same. > * gimple-range-edge.h (gimple_outgoing_range): Same. > * gimple-range-side-effect.cc (side_effect_manager::get_nonzero): > Same. > (side_effect_manager::add_range): Same. > * gimple-range-side-effect.h (class side_effect_manager): Same. > * value-range.h (class irange_allocator): Rename to... > (class vrange_allocator): ...this. > (irange_allocator::irange_allocator): New. > (vrange_allocator::vrange_allocator): New. > (irange_allocator::~irange_allocator): New. > (vrange_allocator::~vrange_allocator): New. > (irange_allocator::get_memory): Rename to... > (vrange_allocator::alloc): ...this. > (vrange_allocator::alloc_vrange): Rename from... > (irange_allocator::allocate): ...this. > (vrange_allocator::alloc_irange): New. > --- > gcc/gimple-range-cache.cc | 55 +++++++++++----------- > gcc/gimple-range-cache.h | 4 +- > gcc/gimple-range-edge.cc | 4 +- > gcc/gimple-range-edge.h | 2 +- > gcc/gimple-range-side-effect.cc | 13 ++++-- > gcc/gimple-range-side-effect.h | 2 +- > gcc/value-range.h | 82 +++++++++++++++++++++------------ > 7 files changed, 96 insertions(+), 66 deletions(-) > > diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc > index c726393b380..9c541993fb6 100644 > --- a/gcc/gimple-range-cache.cc > +++ b/gcc/gimple-range-cache.cc > @@ -75,7 +75,7 @@ ssa_block_ranges::dump (FILE *f) > class sbr_vector : public ssa_block_ranges > { > public: > - sbr_vector (tree t, irange_allocator *allocator); > + sbr_vector (tree t, vrange_allocator *allocator); > > virtual bool set_bb_range (const_basic_block bb, const irange &r) override; > virtual bool get_bb_range (irange &r, const_basic_block bb) override; > @@ -86,20 +86,21 @@ protected: > int_range<2> m_varying; > int_range<2> m_undefined; > tree m_type; > - irange_allocator *m_irange_allocator; > + vrange_allocator *m_range_allocator; > void grow (); > }; > > > // Initialize a block cache for an ssa_name of type T. > > -sbr_vector::sbr_vector (tree t, irange_allocator *allocator) > +sbr_vector::sbr_vector (tree t, vrange_allocator *allocator) > { > gcc_checking_assert (TYPE_P (t)); > m_type = t; > - m_irange_allocator = allocator; > + m_range_allocator = allocator; > m_tab_size = last_basic_block_for_fn (cfun) + 1; > - m_tab = (irange **)allocator->get_memory (m_tab_size * sizeof (irange *)); > + m_tab = static_cast <irange **> > + (allocator->alloc (m_tab_size * sizeof (irange *))); > memset (m_tab, 0, m_tab_size * sizeof (irange *)); > > // Create the cached type range. > @@ -121,8 +122,8 @@ sbr_vector::grow () > int new_size = inc + curr_bb_size; > > // Allocate new memory, copy the old vector and clear the new space. > - irange **t = (irange **)m_irange_allocator->get_memory (new_size > - * sizeof (irange *)); > + irange **t = static_cast <irange **> > + (m_range_allocator->alloc (new_size * sizeof (irange *))); > memcpy (t, m_tab, m_tab_size * sizeof (irange *)); > memset (t + m_tab_size, 0, (new_size - m_tab_size) * sizeof (irange *)); > > @@ -143,7 +144,7 @@ sbr_vector::set_bb_range (const_basic_block bb, const irange &r) > else if (r.undefined_p ()) > m = &m_undefined; > else > - m = m_irange_allocator->allocate (r); > + m = m_range_allocator->clone (r); > m_tab[bb->index] = m; > return true; > } > @@ -191,14 +192,14 @@ sbr_vector::bb_range_p (const_basic_block bb) > class sbr_sparse_bitmap : public ssa_block_ranges > { > public: > - sbr_sparse_bitmap (tree t, irange_allocator *allocator, bitmap_obstack *bm); > + sbr_sparse_bitmap (tree t, vrange_allocator *allocator, bitmap_obstack *bm); > virtual bool set_bb_range (const_basic_block bb, const irange &r) override; > virtual bool get_bb_range (irange &r, const_basic_block bb) override; > virtual bool bb_range_p (const_basic_block bb) override; > private: > void bitmap_set_quad (bitmap head, int quad, int quad_value); > int bitmap_get_quad (const_bitmap head, int quad); > - irange_allocator *m_irange_allocator; > + vrange_allocator *m_range_allocator; > irange *m_range[SBR_NUM]; > bitmap_head bitvec; > tree m_type; > @@ -206,23 +207,25 @@ private: > > // Initialize a block cache for an ssa_name of type T. > > -sbr_sparse_bitmap::sbr_sparse_bitmap (tree t, irange_allocator *allocator, > - bitmap_obstack *bm) > +sbr_sparse_bitmap::sbr_sparse_bitmap (tree t, vrange_allocator *allocator, > + bitmap_obstack *bm) > { > gcc_checking_assert (TYPE_P (t)); > m_type = t; > bitmap_initialize (&bitvec, bm); > bitmap_tree_view (&bitvec); > - m_irange_allocator = allocator; > + m_range_allocator = allocator; > // Pre-cache varying. > - m_range[0] = m_irange_allocator->allocate (2); > + m_range[0] = static_cast <irange *> (m_range_allocator->alloc_vrange (t)); > m_range[0]->set_varying (t); > // Pre-cache zero and non-zero values for pointers. > if (POINTER_TYPE_P (t)) > { > - m_range[1] = m_irange_allocator->allocate (2); > + m_range[1] > + = static_cast <irange *> (m_range_allocator->alloc_vrange (t)); > m_range[1]->set_nonzero (t); > - m_range[2] = m_irange_allocator->allocate (2); > + m_range[2] > + = static_cast <irange *> (m_range_allocator->alloc_vrange (t)); > m_range[2]->set_zero (t); > } > else > @@ -267,7 +270,7 @@ sbr_sparse_bitmap::set_bb_range (const_basic_block bb, const irange &r) > if (!m_range[x] || r == *(m_range[x])) > { > if (!m_range[x]) > - m_range[x] = m_irange_allocator->allocate (r); > + m_range[x] = m_range_allocator->clone (r); > bitmap_set_quad (&bitvec, bb->index, x + 1); > return true; > } > @@ -312,14 +315,14 @@ block_range_cache::block_range_cache () > bitmap_obstack_initialize (&m_bitmaps); > m_ssa_ranges.create (0); > m_ssa_ranges.safe_grow_cleared (num_ssa_names); > - m_irange_allocator = new irange_allocator; > + m_range_allocator = new vrange_allocator; > } > > // Remove any m_block_caches which have been created. > > block_range_cache::~block_range_cache () > { > - delete m_irange_allocator; > + delete m_range_allocator; > // Release the vector itself. > m_ssa_ranges.release (); > bitmap_obstack_release (&m_bitmaps); > @@ -341,17 +344,17 @@ block_range_cache::set_bb_range (tree name, const_basic_block bb, > // Use sparse representation if there are too many basic blocks. > if (last_basic_block_for_fn (cfun) > param_evrp_sparse_threshold) > { > - void *r = m_irange_allocator->get_memory (sizeof (sbr_sparse_bitmap)); > + void *r = m_range_allocator->alloc (sizeof (sbr_sparse_bitmap)); > m_ssa_ranges[v] = new (r) sbr_sparse_bitmap (TREE_TYPE (name), > - m_irange_allocator, > + m_range_allocator, > &m_bitmaps); > } > else > { > // Otherwise use the default vector implemntation. > - void *r = m_irange_allocator->get_memory (sizeof (sbr_vector)); > + void *r = m_range_allocator->alloc (sizeof (sbr_vector)); > m_ssa_ranges[v] = new (r) sbr_vector (TREE_TYPE (name), > - m_irange_allocator); > + m_range_allocator); > } > } > return m_ssa_ranges[v]->set_bb_range (bb, r); > @@ -467,7 +470,7 @@ block_range_cache::dump (FILE *f, basic_block bb, bool print_varying) > ssa_global_cache::ssa_global_cache () > { > m_tab.create (0); > - m_irange_allocator = new irange_allocator; > + m_range_allocator = new vrange_allocator; > } > > // Deconstruct a global cache. > @@ -475,7 +478,7 @@ ssa_global_cache::ssa_global_cache () > ssa_global_cache::~ssa_global_cache () > { > m_tab.release (); > - delete m_irange_allocator; > + delete m_range_allocator; > } > > // Retrieve the global range of NAME from cache memory if it exists. > @@ -509,7 +512,7 @@ ssa_global_cache::set_global_range (tree name, const irange &r) > if (m && m->fits_p (r)) > *m = r; > else > - m_tab[v] = m_irange_allocator->allocate (r); > + m_tab[v] = m_range_allocator->clone (r); > return m != NULL; > } > > diff --git a/gcc/gimple-range-cache.h b/gcc/gimple-range-cache.h > index 555fe32513f..2472cd04f47 100644 > --- a/gcc/gimple-range-cache.h > +++ b/gcc/gimple-range-cache.h > @@ -44,7 +44,7 @@ private: > vec<class ssa_block_ranges *> m_ssa_ranges; > ssa_block_ranges &get_block_ranges (tree name); > ssa_block_ranges *query_block_ranges (tree name); > - irange_allocator *m_irange_allocator; > + vrange_allocator *m_range_allocator; > bitmap_obstack m_bitmaps; > }; > > @@ -64,7 +64,7 @@ public: > void dump (FILE *f = stderr); > private: > vec<irange *> m_tab; > - class irange_allocator *m_irange_allocator; > + vrange_allocator *m_range_allocator; > }; > > // This class provides all the caches a global ranger may need, and makes > diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc > index 5bbe23ae03d..5264e627c9a 100644 > --- a/gcc/gimple-range-edge.cc > +++ b/gcc/gimple-range-edge.cc > @@ -166,13 +166,13 @@ gimple_outgoing_range::calc_switch_ranges (gswitch *sw) > // If there was an existing range and it doesn't fit, we lose the memory. > // It'll get reclaimed when the obstack is freed. This seems less > // intrusive than allocating max ranges for each case. > - slot = m_range_allocator.allocate (case_range); > + slot = m_range_allocator.clone <irange> (case_range); > } > > irange *&slot = m_edge_table->get_or_insert (default_edge, &existed); > // This should be the first call into this switch. > gcc_checking_assert (!existed); > - irange *dr = m_range_allocator.allocate (default_range); > + irange *dr = m_range_allocator.clone <irange> (default_range); > slot = dr; > } > > diff --git a/gcc/gimple-range-edge.h b/gcc/gimple-range-edge.h > index c131b3309cc..ce383b0aa6f 100644 > --- a/gcc/gimple-range-edge.h > +++ b/gcc/gimple-range-edge.h > @@ -47,7 +47,7 @@ private: > > int m_max_edges; > hash_map<edge, irange *> *m_edge_table; > - irange_allocator m_range_allocator; > + vrange_allocator m_range_allocator; > }; > > // If there is a range control statement at the end of block BB, return it. > diff --git a/gcc/gimple-range-side-effect.cc b/gcc/gimple-range-side-effect.cc > index 2c8c77dc569..8d2ac35bc8d 100644 > --- a/gcc/gimple-range-side-effect.cc > +++ b/gcc/gimple-range-side-effect.cc > @@ -189,8 +189,10 @@ side_effect_manager::get_nonzero (tree name) > m_nonzero.safe_grow_cleared (num_ssa_names + 20); > if (!m_nonzero[v]) > { > - m_nonzero[v] = m_range_allocator.allocate (2); > - m_nonzero[v]->set_nonzero (TREE_TYPE (name)); > + tree type = TREE_TYPE (name); > + m_nonzero[v] > + = static_cast <irange *> (m_range_allocator.alloc_vrange (type)); > + m_nonzero[v]->set_nonzero (type); > } > return *(m_nonzero[v]); > } > @@ -259,14 +261,17 @@ side_effect_manager::add_range (tree name, basic_block bb, const irange &r) > if (ptr->range->fits_p (cur)) > *(ptr->range) = cur; > else > - ptr->range = m_range_allocator.allocate (cur); > + { > + vrange &v = cur; > + ptr->range = static_cast <irange *> (m_range_allocator.clone (v)); > + } > return; > } > > // Otherwise create a record. > bitmap_set_bit (m_on_exit[bb->index].m_names, SSA_NAME_VERSION (name)); > ptr = (exit_range *)obstack_alloc (&m_list_obstack, sizeof (exit_range)); > - ptr->range = m_range_allocator.allocate (r); > + ptr->range = m_range_allocator.clone (r); > ptr->name = name; > ptr->next = m_on_exit[bb->index].head; > m_on_exit[bb->index].head = ptr; > diff --git a/gcc/gimple-range-side-effect.h b/gcc/gimple-range-side-effect.h > index 848d94ba6d7..d76d6eb34f2 100644 > --- a/gcc/gimple-range-side-effect.h > +++ b/gcc/gimple-range-side-effect.h > @@ -76,7 +76,7 @@ private: > bitmap m_seen; > bitmap_obstack m_bitmaps; > struct obstack m_list_obstack; > - irange_allocator m_range_allocator; > + vrange_allocator m_range_allocator; > }; > > #endif // GCC_GIMPLE_RANGE_SIDE_H > diff --git a/gcc/value-range.h b/gcc/value-range.h > index d51998145da..a5da53f595e 100644 > --- a/gcc/value-range.h > +++ b/gcc/value-range.h > @@ -92,7 +92,7 @@ protected: > > class GTY((user)) irange : public vrange > { > - friend class irange_allocator; > + friend class vrange_allocator; > public: > // In-place setters. > virtual void set (tree, tree, value_range_kind = VR_RANGE) override; > @@ -892,56 +892,63 @@ vrp_val_min (const_tree type) > return NULL_TREE; > } > > -// This is the irange storage class. It is used to allocate the > -// minimum amount of storage needed for a given irange. Storage is > -// automatically freed at destruction of the storage class. > -// > -// It is meant for long term storage, as opposed to int_range_max > -// which is meant for intermediate temporary results on the stack. > -// > -// The newly allocated irange is initialized to the empty set > -// (undefined_p() is true). > +// This is the range storage class. It is used to allocate the > +// minimum amount of storage needed for a given range. Storage is > +// automatically freed at destruction of the class. > > -class irange_allocator > +class vrange_allocator > { > public: > - irange_allocator (); > - ~irange_allocator (); > - // Return a new range with NUM_PAIRS. > - irange *allocate (unsigned num_pairs); > - // Return a copy of SRC with the minimum amount of sub-ranges needed > - // to represent it. > - irange *allocate (const irange &src); > - void *get_memory (unsigned num_bytes); > + vrange_allocator (); > + ~vrange_allocator (); > + // Allocate a range of TYPE. > + vrange *alloc_vrange (tree type); > + // Allocate a memory block of BYTES. > + void *alloc (unsigned bytes); > + // Return a clone of SRC. > + template <typename T> T *clone (const T &src); > private: > - DISABLE_COPY_AND_ASSIGN (irange_allocator); > + irange *alloc_irange (unsigned pairs); > + DISABLE_COPY_AND_ASSIGN (vrange_allocator); > struct obstack m_obstack; > }; > > inline > -irange_allocator::irange_allocator () > +vrange_allocator::vrange_allocator () > { > obstack_init (&m_obstack); > } > > inline > -irange_allocator::~irange_allocator () > +vrange_allocator::~vrange_allocator () > { > obstack_free (&m_obstack, NULL); > } > > // Provide a hunk of memory from the obstack. > + > inline void * > -irange_allocator::get_memory (unsigned num_bytes) > +vrange_allocator::alloc (unsigned bytes) > { > - void *r = obstack_alloc (&m_obstack, num_bytes); > - return r; > + return obstack_alloc (&m_obstack, bytes); > +} > + > +// Return a new range to hold ranges of TYPE. The newly allocated > +// range is initialized to VR_UNDEFINED. > + > +inline vrange * > +vrange_allocator::alloc_vrange (tree type) > +{ > + if (irange::supports_type_p (type)) > + return alloc_irange (2); > + > + gcc_unreachable (); > } > > // Return a new range with NUM_PAIRS. > > inline irange * > -irange_allocator::allocate (unsigned num_pairs) > +vrange_allocator::alloc_irange (unsigned num_pairs) > { > // Never allocate 0 pairs. > // Don't allocate 1 either, or we get legacy value_range's. > @@ -951,17 +958,32 @@ irange_allocator::allocate (unsigned num_pairs) > size_t nbytes = sizeof (tree) * 2 * num_pairs; > > // Allocate the irange and required memory for the vector. > - void *r = obstack_alloc (&m_obstack, sizeof (irange)); > - tree *mem = (tree *) obstack_alloc (&m_obstack, nbytes); > + void *r = alloc (sizeof (irange)); > + tree *mem = static_cast <tree *> (alloc (nbytes)); > return new (r) irange (mem, num_pairs); > } > > +// Return a clone of an irange. > + > +template <> > inline irange * > -irange_allocator::allocate (const irange &src) > +vrange_allocator::clone <irange> (const irange &src) > { > - irange *r = allocate (src.num_pairs ()); > + irange *r = alloc_irange (src.num_pairs ()); > *r = src; > return r; > } > > +// Return a clone of a vrange. > + > +template <> > +inline vrange * > +vrange_allocator::clone <vrange> (const vrange &src) > +{ > + if (is_a <irange> (src)) > + return clone <irange> (as_a <irange> (src)); > + > + gcc_unreachable (); > +} > + > #endif // GCC_VALUE_RANGE_H > -- > 2.36.1 >
diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc index c726393b380..9c541993fb6 100644 --- a/gcc/gimple-range-cache.cc +++ b/gcc/gimple-range-cache.cc @@ -75,7 +75,7 @@ ssa_block_ranges::dump (FILE *f) class sbr_vector : public ssa_block_ranges { public: - sbr_vector (tree t, irange_allocator *allocator); + sbr_vector (tree t, vrange_allocator *allocator); virtual bool set_bb_range (const_basic_block bb, const irange &r) override; virtual bool get_bb_range (irange &r, const_basic_block bb) override; @@ -86,20 +86,21 @@ protected: int_range<2> m_varying; int_range<2> m_undefined; tree m_type; - irange_allocator *m_irange_allocator; + vrange_allocator *m_range_allocator; void grow (); }; // Initialize a block cache for an ssa_name of type T. -sbr_vector::sbr_vector (tree t, irange_allocator *allocator) +sbr_vector::sbr_vector (tree t, vrange_allocator *allocator) { gcc_checking_assert (TYPE_P (t)); m_type = t; - m_irange_allocator = allocator; + m_range_allocator = allocator; m_tab_size = last_basic_block_for_fn (cfun) + 1; - m_tab = (irange **)allocator->get_memory (m_tab_size * sizeof (irange *)); + m_tab = static_cast <irange **> + (allocator->alloc (m_tab_size * sizeof (irange *))); memset (m_tab, 0, m_tab_size * sizeof (irange *)); // Create the cached type range. @@ -121,8 +122,8 @@ sbr_vector::grow () int new_size = inc + curr_bb_size; // Allocate new memory, copy the old vector and clear the new space. - irange **t = (irange **)m_irange_allocator->get_memory (new_size - * sizeof (irange *)); + irange **t = static_cast <irange **> + (m_range_allocator->alloc (new_size * sizeof (irange *))); memcpy (t, m_tab, m_tab_size * sizeof (irange *)); memset (t + m_tab_size, 0, (new_size - m_tab_size) * sizeof (irange *)); @@ -143,7 +144,7 @@ sbr_vector::set_bb_range (const_basic_block bb, const irange &r) else if (r.undefined_p ()) m = &m_undefined; else - m = m_irange_allocator->allocate (r); + m = m_range_allocator->clone (r); m_tab[bb->index] = m; return true; } @@ -191,14 +192,14 @@ sbr_vector::bb_range_p (const_basic_block bb) class sbr_sparse_bitmap : public ssa_block_ranges { public: - sbr_sparse_bitmap (tree t, irange_allocator *allocator, bitmap_obstack *bm); + sbr_sparse_bitmap (tree t, vrange_allocator *allocator, bitmap_obstack *bm); virtual bool set_bb_range (const_basic_block bb, const irange &r) override; virtual bool get_bb_range (irange &r, const_basic_block bb) override; virtual bool bb_range_p (const_basic_block bb) override; private: void bitmap_set_quad (bitmap head, int quad, int quad_value); int bitmap_get_quad (const_bitmap head, int quad); - irange_allocator *m_irange_allocator; + vrange_allocator *m_range_allocator; irange *m_range[SBR_NUM]; bitmap_head bitvec; tree m_type; @@ -206,23 +207,25 @@ private: // Initialize a block cache for an ssa_name of type T. -sbr_sparse_bitmap::sbr_sparse_bitmap (tree t, irange_allocator *allocator, - bitmap_obstack *bm) +sbr_sparse_bitmap::sbr_sparse_bitmap (tree t, vrange_allocator *allocator, + bitmap_obstack *bm) { gcc_checking_assert (TYPE_P (t)); m_type = t; bitmap_initialize (&bitvec, bm); bitmap_tree_view (&bitvec); - m_irange_allocator = allocator; + m_range_allocator = allocator; // Pre-cache varying. - m_range[0] = m_irange_allocator->allocate (2); + m_range[0] = static_cast <irange *> (m_range_allocator->alloc_vrange (t)); m_range[0]->set_varying (t); // Pre-cache zero and non-zero values for pointers. if (POINTER_TYPE_P (t)) { - m_range[1] = m_irange_allocator->allocate (2); + m_range[1] + = static_cast <irange *> (m_range_allocator->alloc_vrange (t)); m_range[1]->set_nonzero (t); - m_range[2] = m_irange_allocator->allocate (2); + m_range[2] + = static_cast <irange *> (m_range_allocator->alloc_vrange (t)); m_range[2]->set_zero (t); } else @@ -267,7 +270,7 @@ sbr_sparse_bitmap::set_bb_range (const_basic_block bb, const irange &r) if (!m_range[x] || r == *(m_range[x])) { if (!m_range[x]) - m_range[x] = m_irange_allocator->allocate (r); + m_range[x] = m_range_allocator->clone (r); bitmap_set_quad (&bitvec, bb->index, x + 1); return true; } @@ -312,14 +315,14 @@ block_range_cache::block_range_cache () bitmap_obstack_initialize (&m_bitmaps); m_ssa_ranges.create (0); m_ssa_ranges.safe_grow_cleared (num_ssa_names); - m_irange_allocator = new irange_allocator; + m_range_allocator = new vrange_allocator; } // Remove any m_block_caches which have been created. block_range_cache::~block_range_cache () { - delete m_irange_allocator; + delete m_range_allocator; // Release the vector itself. m_ssa_ranges.release (); bitmap_obstack_release (&m_bitmaps); @@ -341,17 +344,17 @@ block_range_cache::set_bb_range (tree name, const_basic_block bb, // Use sparse representation if there are too many basic blocks. if (last_basic_block_for_fn (cfun) > param_evrp_sparse_threshold) { - void *r = m_irange_allocator->get_memory (sizeof (sbr_sparse_bitmap)); + void *r = m_range_allocator->alloc (sizeof (sbr_sparse_bitmap)); m_ssa_ranges[v] = new (r) sbr_sparse_bitmap (TREE_TYPE (name), - m_irange_allocator, + m_range_allocator, &m_bitmaps); } else { // Otherwise use the default vector implemntation. - void *r = m_irange_allocator->get_memory (sizeof (sbr_vector)); + void *r = m_range_allocator->alloc (sizeof (sbr_vector)); m_ssa_ranges[v] = new (r) sbr_vector (TREE_TYPE (name), - m_irange_allocator); + m_range_allocator); } } return m_ssa_ranges[v]->set_bb_range (bb, r); @@ -467,7 +470,7 @@ block_range_cache::dump (FILE *f, basic_block bb, bool print_varying) ssa_global_cache::ssa_global_cache () { m_tab.create (0); - m_irange_allocator = new irange_allocator; + m_range_allocator = new vrange_allocator; } // Deconstruct a global cache. @@ -475,7 +478,7 @@ ssa_global_cache::ssa_global_cache () ssa_global_cache::~ssa_global_cache () { m_tab.release (); - delete m_irange_allocator; + delete m_range_allocator; } // Retrieve the global range of NAME from cache memory if it exists. @@ -509,7 +512,7 @@ ssa_global_cache::set_global_range (tree name, const irange &r) if (m && m->fits_p (r)) *m = r; else - m_tab[v] = m_irange_allocator->allocate (r); + m_tab[v] = m_range_allocator->clone (r); return m != NULL; } diff --git a/gcc/gimple-range-cache.h b/gcc/gimple-range-cache.h index 555fe32513f..2472cd04f47 100644 --- a/gcc/gimple-range-cache.h +++ b/gcc/gimple-range-cache.h @@ -44,7 +44,7 @@ private: vec<class ssa_block_ranges *> m_ssa_ranges; ssa_block_ranges &get_block_ranges (tree name); ssa_block_ranges *query_block_ranges (tree name); - irange_allocator *m_irange_allocator; + vrange_allocator *m_range_allocator; bitmap_obstack m_bitmaps; }; @@ -64,7 +64,7 @@ public: void dump (FILE *f = stderr); private: vec<irange *> m_tab; - class irange_allocator *m_irange_allocator; + vrange_allocator *m_range_allocator; }; // This class provides all the caches a global ranger may need, and makes diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc index 5bbe23ae03d..5264e627c9a 100644 --- a/gcc/gimple-range-edge.cc +++ b/gcc/gimple-range-edge.cc @@ -166,13 +166,13 @@ gimple_outgoing_range::calc_switch_ranges (gswitch *sw) // If there was an existing range and it doesn't fit, we lose the memory. // It'll get reclaimed when the obstack is freed. This seems less // intrusive than allocating max ranges for each case. - slot = m_range_allocator.allocate (case_range); + slot = m_range_allocator.clone <irange> (case_range); } irange *&slot = m_edge_table->get_or_insert (default_edge, &existed); // This should be the first call into this switch. gcc_checking_assert (!existed); - irange *dr = m_range_allocator.allocate (default_range); + irange *dr = m_range_allocator.clone <irange> (default_range); slot = dr; } diff --git a/gcc/gimple-range-edge.h b/gcc/gimple-range-edge.h index c131b3309cc..ce383b0aa6f 100644 --- a/gcc/gimple-range-edge.h +++ b/gcc/gimple-range-edge.h @@ -47,7 +47,7 @@ private: int m_max_edges; hash_map<edge, irange *> *m_edge_table; - irange_allocator m_range_allocator; + vrange_allocator m_range_allocator; }; // If there is a range control statement at the end of block BB, return it. diff --git a/gcc/gimple-range-side-effect.cc b/gcc/gimple-range-side-effect.cc index 2c8c77dc569..8d2ac35bc8d 100644 --- a/gcc/gimple-range-side-effect.cc +++ b/gcc/gimple-range-side-effect.cc @@ -189,8 +189,10 @@ side_effect_manager::get_nonzero (tree name) m_nonzero.safe_grow_cleared (num_ssa_names + 20); if (!m_nonzero[v]) { - m_nonzero[v] = m_range_allocator.allocate (2); - m_nonzero[v]->set_nonzero (TREE_TYPE (name)); + tree type = TREE_TYPE (name); + m_nonzero[v] + = static_cast <irange *> (m_range_allocator.alloc_vrange (type)); + m_nonzero[v]->set_nonzero (type); } return *(m_nonzero[v]); } @@ -259,14 +261,17 @@ side_effect_manager::add_range (tree name, basic_block bb, const irange &r) if (ptr->range->fits_p (cur)) *(ptr->range) = cur; else - ptr->range = m_range_allocator.allocate (cur); + { + vrange &v = cur; + ptr->range = static_cast <irange *> (m_range_allocator.clone (v)); + } return; } // Otherwise create a record. bitmap_set_bit (m_on_exit[bb->index].m_names, SSA_NAME_VERSION (name)); ptr = (exit_range *)obstack_alloc (&m_list_obstack, sizeof (exit_range)); - ptr->range = m_range_allocator.allocate (r); + ptr->range = m_range_allocator.clone (r); ptr->name = name; ptr->next = m_on_exit[bb->index].head; m_on_exit[bb->index].head = ptr; diff --git a/gcc/gimple-range-side-effect.h b/gcc/gimple-range-side-effect.h index 848d94ba6d7..d76d6eb34f2 100644 --- a/gcc/gimple-range-side-effect.h +++ b/gcc/gimple-range-side-effect.h @@ -76,7 +76,7 @@ private: bitmap m_seen; bitmap_obstack m_bitmaps; struct obstack m_list_obstack; - irange_allocator m_range_allocator; + vrange_allocator m_range_allocator; }; #endif // GCC_GIMPLE_RANGE_SIDE_H diff --git a/gcc/value-range.h b/gcc/value-range.h index d51998145da..a5da53f595e 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -92,7 +92,7 @@ protected: class GTY((user)) irange : public vrange { - friend class irange_allocator; + friend class vrange_allocator; public: // In-place setters. virtual void set (tree, tree, value_range_kind = VR_RANGE) override; @@ -892,56 +892,63 @@ vrp_val_min (const_tree type) return NULL_TREE; } -// This is the irange storage class. It is used to allocate the -// minimum amount of storage needed for a given irange. Storage is -// automatically freed at destruction of the storage class. -// -// It is meant for long term storage, as opposed to int_range_max -// which is meant for intermediate temporary results on the stack. -// -// The newly allocated irange is initialized to the empty set -// (undefined_p() is true). +// This is the range storage class. It is used to allocate the +// minimum amount of storage needed for a given range. Storage is +// automatically freed at destruction of the class. -class irange_allocator +class vrange_allocator { public: - irange_allocator (); - ~irange_allocator (); - // Return a new range with NUM_PAIRS. - irange *allocate (unsigned num_pairs); - // Return a copy of SRC with the minimum amount of sub-ranges needed - // to represent it. - irange *allocate (const irange &src); - void *get_memory (unsigned num_bytes); + vrange_allocator (); + ~vrange_allocator (); + // Allocate a range of TYPE. + vrange *alloc_vrange (tree type); + // Allocate a memory block of BYTES. + void *alloc (unsigned bytes); + // Return a clone of SRC. + template <typename T> T *clone (const T &src); private: - DISABLE_COPY_AND_ASSIGN (irange_allocator); + irange *alloc_irange (unsigned pairs); + DISABLE_COPY_AND_ASSIGN (vrange_allocator); struct obstack m_obstack; }; inline -irange_allocator::irange_allocator () +vrange_allocator::vrange_allocator () { obstack_init (&m_obstack); } inline -irange_allocator::~irange_allocator () +vrange_allocator::~vrange_allocator () { obstack_free (&m_obstack, NULL); } // Provide a hunk of memory from the obstack. + inline void * -irange_allocator::get_memory (unsigned num_bytes) +vrange_allocator::alloc (unsigned bytes) { - void *r = obstack_alloc (&m_obstack, num_bytes); - return r; + return obstack_alloc (&m_obstack, bytes); +} + +// Return a new range to hold ranges of TYPE. The newly allocated +// range is initialized to VR_UNDEFINED. + +inline vrange * +vrange_allocator::alloc_vrange (tree type) +{ + if (irange::supports_type_p (type)) + return alloc_irange (2); + + gcc_unreachable (); } // Return a new range with NUM_PAIRS. inline irange * -irange_allocator::allocate (unsigned num_pairs) +vrange_allocator::alloc_irange (unsigned num_pairs) { // Never allocate 0 pairs. // Don't allocate 1 either, or we get legacy value_range's. @@ -951,17 +958,32 @@ irange_allocator::allocate (unsigned num_pairs) size_t nbytes = sizeof (tree) * 2 * num_pairs; // Allocate the irange and required memory for the vector. - void *r = obstack_alloc (&m_obstack, sizeof (irange)); - tree *mem = (tree *) obstack_alloc (&m_obstack, nbytes); + void *r = alloc (sizeof (irange)); + tree *mem = static_cast <tree *> (alloc (nbytes)); return new (r) irange (mem, num_pairs); } +// Return a clone of an irange. + +template <> inline irange * -irange_allocator::allocate (const irange &src) +vrange_allocator::clone <irange> (const irange &src) { - irange *r = allocate (src.num_pairs ()); + irange *r = alloc_irange (src.num_pairs ()); *r = src; return r; } +// Return a clone of a vrange. + +template <> +inline vrange * +vrange_allocator::clone <vrange> (const vrange &src) +{ + if (is_a <irange> (src)) + return clone <irange> (as_a <irange> (src)); + + gcc_unreachable (); +} + #endif // GCC_VALUE_RANGE_H