diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 95d1d0ac008167b47ed006f36fb128114be0eef6..b5f7b08f0a89161e0ddc4a1eb7a9edd61bb2d665 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2017-01-13 Richard Sandiford <richard.sandiford@arm.com> + + * hash-table.h (hash_table::too_empty_p): New function. + (hash_table::expand): Use it. + (hash_table::traverse): Likewise. + (hash_table::empty_slot): Use sizeof (value_type) instead of + sizeof (PTR) to convert bytes to elements. Shrink the table + if the current size is excessive for the current number of + elements. + 2017-01-13 Richard Sandiford <richard.sandiford@arm.com> * ira-costs.c (record_reg_classes): Break from the inner loop diff --git a/gcc/hash-table.h b/gcc/hash-table.h index 0bee093a6451259720757b7a5fde7aaf89eff790..0f7e21a2cc5e4c22e0f608c8f2ba932d69e5fae2 100644 --- a/gcc/hash-table.h +++ b/gcc/hash-table.h @@ -503,6 +503,7 @@ private: value_type *alloc_entries (size_t n CXX_MEM_STAT_INFO) const; value_type *find_empty_slot_for_expand (hashval_t); + bool too_empty_p (unsigned int); void expand (); static bool is_deleted (value_type &v) { @@ -691,6 +692,15 @@ hash_table<Descriptor, Allocator>::find_empty_slot_for_expand (hashval_t hash) } } +/* Return true if the current table is excessively big for ELTS elements. */ + +template<typename Descriptor, template<typename Type> class Allocator> +inline bool +hash_table<Descriptor, Allocator>::too_empty_p (unsigned int elts) +{ + return elts * 8 < m_size && m_size > 32; +} + /* The following function changes size of memory allocated for the entries and repeatedly inserts the table elements. The occupancy of the table after the call will be about 50%. Naturally the hash @@ -712,7 +722,7 @@ hash_table<Descriptor, Allocator>::expand () too full or too empty. */ unsigned int nindex; size_t nsize; - if (elts * 2 > osize || (elts * 8 < osize && osize > 32)) + if (elts * 2 > osize || too_empty_p (elts)) { nindex = hash_table_higher_prime_index (elts * 2); nsize = prime_tab[nindex].prime; @@ -764,6 +774,7 @@ void hash_table<Descriptor, Allocator>::empty_slow () { size_t size = m_size; + size_t nsize = size; value_type *entries = m_entries; int i; @@ -772,9 +783,14 @@ hash_table<Descriptor, Allocator>::empty_slow () Descriptor::remove (entries[i]); /* Instead of clearing megabyte, downsize the table. */ - if (size > 1024*1024 / sizeof (PTR)) + if (size > 1024*1024 / sizeof (value_type)) + nsize = 1024 / sizeof (value_type); + else if (too_empty_p (m_n_elements)) + nsize = m_n_elements * 2; + + if (nsize != size) { - int nindex = hash_table_higher_prime_index (1024 / sizeof (PTR)); + int nindex = hash_table_higher_prime_index (nsize); int nsize = prime_tab[nindex].prime; if (!m_ggc) @@ -965,8 +981,7 @@ template <typename Argument, void hash_table<Descriptor, Allocator>::traverse (Argument argument) { - size_t size = m_size; - if (elements () * 8 < size && size > 32) + if (too_empty_p (elements ())) expand (); traverse_noresize <Argument, Callback> (argument);