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);