On Fri, Jun 20, 2014 at 12:52 PM,  <tsaund...@mozilla.com> wrote:
> From: Trevor Saunders <tsaund...@mozilla.com>
>
> Hi,
>
> this patch allows you to define the type the hash table stores as elements
> instead of the type elements point at by having your hash descriptor define 
> the
> type store_values_directly.  It turns out trying to implement both cases with
> the same code is really confusing, so I ended up providing one partial
> specialization for each case.  Its a lot of coppying, but I'm hoping the next
> patch will get rid of many direct users of hash_table, and the rest can all 
> get
> converted to tell the hash table the type entries should have at which point
> the dupplication can be removed.
>
> bootstrapped + regtested without regression on x86_64-unknown-linux-gnu, ok?

Ok.  I hope that de-duplication works out.

Thanks,
Richard.

> Trev
>
> gcc/
>
>         * hash-table.h: Add a template arg to choose between storing values
>         and storing pointers to values, and then provide partial
>         specializations for both.
>         * tree-browser.c (tree_upper_hasher): Provide the type the hash table
>         should store, not the type values should point to.
>         * tree-into-ssa.c (var_info_hasher): Likewise.
>         * tree-ssa-dom.c (expr_elt_hasher): Likewise.
>         * tree-complex.c: Adjust.
>         * tree-hasher.h (int_tree_hasher): store int_tree_map in the hash
>         table instead of int_tree_map *.
>         * tree-parloops.c: Adjust.
>         * tree-ssa-reassoc.c (ocount_hasher): Don't lie to hash_map about what
>         type is being stored.
>         * tree-vectorizer.c: Adjust.
>
> diff --git a/gcc/hash-table.h b/gcc/hash-table.h
> index 41cc19e..22af12f 100644
> --- a/gcc/hash-table.h
> +++ b/gcc/hash-table.h
> @@ -272,19 +272,18 @@ typed_noop_remove <Type>::remove (Type *p 
> ATTRIBUTE_UNUSED)
>  template <typename Type>
>  struct pointer_hash : typed_noop_remove <Type>
>  {
> -  typedef Type value_type;
> -  typedef Type compare_type;
> +  typedef Type *value_type;
> +  typedef Type *compare_type;
> +  typedef int store_values_directly;
>
> -  static inline hashval_t
> -  hash (const value_type *);
> +  static inline hashval_t hash (const value_type &);
>
> -  static inline int
> -  equal (const value_type *existing, const compare_type *candidate);
> +  static inline bool equal (const value_type &existing, const compare_type 
> &candidate);
>  };
>
>  template <typename Type>
>  inline hashval_t
> -pointer_hash <Type>::hash (const value_type *candidate)
> +pointer_hash <Type>::hash (const value_type &candidate)
>  {
>    /* This is a really poor hash function, but it is what the current code 
> uses,
>       so I am reusing it to avoid an additional axis in testing.  */
> @@ -292,9 +291,9 @@ pointer_hash <Type>::hash (const value_type *candidate)
>  }
>
>  template <typename Type>
> -inline int
> -pointer_hash <Type>::equal (const value_type *existing,
> -                          const compare_type *candidate)
> +inline bool
> +pointer_hash <Type>::equal (const value_type &existing,
> +                          const compare_type &candidate)
>  {
>    return existing == candidate;
>  }
> @@ -319,10 +318,147 @@ extern unsigned int hash_table_higher_prime_index 
> (unsigned long n);
>  extern hashval_t hash_table_mod1 (hashval_t hash, unsigned int index);
>  extern hashval_t hash_table_mod2 (hashval_t hash, unsigned int index);
>
> +/* The below is some template meta programming to decide if we should use the
> +   hash table partial specialization that directly stores value_type instead 
> of
> +   pointers to value_type.  If the Descriptor type defines the type
> +   Descriptor::store_values_directly then values are stored directly 
> otherwise
> +   pointers to them are stored.  */
> +template<typename T> struct notype { typedef void type; };
> +
> +template<typename T, typename = void>
> +struct storage_tester
> +{
> +  static const bool value = false;
> +};
> +
> +template<typename T>
> +struct storage_tester<T, typename notype<typename
> +                                        T::store_values_directly>::type>
> +{
> +  static const bool value = true;
> +};
> +
> + template<typename Traits>
> + struct has_is_deleted
> +{
> +  template<typename U, bool (*)(U &)> struct helper {};
> +  template<typename U> static char test (helper<U, U::is_deleted> *);
> +  template<typename U> static int test (...);
> +  static const bool value = sizeof (test<Traits> (0)) == sizeof (char);
> +};
> +
> +template<typename Type, typename Traits, bool = 
> has_is_deleted<Traits>::value>
> +struct is_deleted_helper
> +{
> +  static inline bool
> +  call (Type &v)
> +  {
> +    return Traits::is_deleted (v);
> +  }
> +};
> +
> +template<typename Type, typename Traits>
> +struct is_deleted_helper<Type *, Traits, false>
> +{
> +  static inline bool
> +  call (Type *v)
> +  {
> +    return v == HTAB_DELETED_ENTRY;
> +  }
> +};
> +
> + template<typename Traits>
> + struct has_is_empty
> +{
> +  template<typename U, bool (*)(U &)> struct helper {};
> +  template<typename U> static char test (helper<U, U::is_empty> *);
> +  template<typename U> static int test (...);
> +  static const bool value = sizeof (test<Traits> (0)) == sizeof (char);
> +};
> +
> +template<typename Type, typename Traits, bool = 
> has_is_deleted<Traits>::value>
> +struct is_empty_helper
> +{
> +  static inline bool
> +  call (Type &v)
> +  {
> +    return Traits::is_empty (v);
> +  }
> +};
> +
> +template<typename Type, typename Traits>
> +struct is_empty_helper<Type *, Traits, false>
> +{
> +  static inline bool
> +  call (Type *v)
> +  {
> +    return v == HTAB_EMPTY_ENTRY;
> +  }
> +};
> +
> + template<typename Traits>
> + struct has_mark_deleted
> +{
> +  template<typename U, void (*)(U &)> struct helper {};
> +  template<typename U> static char test (helper<U, U::mark_deleted> *);
> +  template<typename U> static int test (...);
> +  static const bool value = sizeof (test<Traits> (0)) == sizeof (char);
> +};
> +
> +template<typename Type, typename Traits, bool = 
> has_is_deleted<Traits>::value>
> +struct mark_deleted_helper
> +{
> +  static inline void
> +  call (Type &v)
> +  {
> +    Traits::mark_deleted (v);
> +  }
> +};
> +
> +template<typename Type, typename Traits>
> +struct mark_deleted_helper<Type *, Traits, false>
> +{
> +  static inline void
> +  call (Type *&v)
> +  {
> +    v = static_cast<Type *> (HTAB_DELETED_ENTRY);
> +  }
> +};
> +
> + template<typename Traits>
> + struct has_mark_empty
> +{
> +  template<typename U, void (*)(U &)> struct helper {};
> +  template<typename U> static char test (helper<U, U::mark_empty> *);
> +  template<typename U> static int test (...);
> +  static const bool value = sizeof (test<Traits> (0)) == sizeof (char);
> +};
> +
> +template<typename Type, typename Traits, bool = 
> has_is_deleted<Traits>::value>
> +struct mark_empty_helper
> +{
> +  static inline void
> +  call (Type &v)
> +  {
> +    Traits::mark_empty (v);
> +  }
> +};
> +
> +template<typename Type, typename Traits>
> +struct mark_empty_helper<Type *, Traits, false>
> +{
> +  static inline void
> +  call (Type *&v)
> +  {
> +    v = static_cast<Type *> (HTAB_EMPTY_ENTRY);
> +  }
> +};
>
>  /* User-facing hash table type.
>
> -   The table stores elements of type Descriptor::value_type.
> +   The table stores elements of type Descriptor::value_type, or pointers to
> +   objects of type value_type if the descriptor does not define the type
> +   store_values_directly.
>
>     It hashes values with the hash member function.
>       The table currently works with relatively weak hash functions.
> @@ -340,11 +476,21 @@ extern hashval_t hash_table_mod2 (hashval_t hash, 
> unsigned int index);
>     Specify the template Allocator to allocate and free memory.
>       The default is xcallocator.
>
> +     Storage is an implementation detail and should not be used outside the
> +     hash table code.
> +
>  */
>  template <typename Descriptor,
> -        template<typename Type> class Allocator= xcallocator>
> +        template<typename Type> class Allocator= xcallocator,
> +        bool Storage = storage_tester<Descriptor>::value>
>  class hash_table
>  {
> +};
> +
> +template <typename Descriptor,
> +        template<typename Type> class Allocator>
> +class hash_table<Descriptor, Allocator, false>
> +{
>    typedef typename Descriptor::value_type value_type;
>    typedef typename Descriptor::compare_type compare_type;
>
> @@ -428,7 +574,7 @@ public:
>      iterator (value_type **slot, value_type **limit) :
>        m_slot (slot), m_limit (limit) {}
>
> -    inline value_type &operator * () { return **m_slot; }
> +    inline value_type *operator * () { return *m_slot; }
>      void slide ();
>      inline iterator &operator ++ ();
>      bool operator != (const iterator &other) const
> @@ -485,7 +631,7 @@ private:
>  };
>
>  template<typename Descriptor, template<typename Type> class Allocator>
> -hash_table<Descriptor, Allocator>::hash_table (size_t size) :
> +hash_table<Descriptor, Allocator, false>::hash_table (size_t size) :
>    m_n_elements (0), m_n_deleted (0), m_searches (0), m_collisions (0)
>  {
>    unsigned int size_prime_index;
> @@ -500,7 +646,7 @@ hash_table<Descriptor, Allocator>::hash_table (size_t 
> size) :
>  }
>
>  template<typename Descriptor, template<typename Type> class Allocator>
> -hash_table<Descriptor, Allocator>::~hash_table ()
> +hash_table<Descriptor, Allocator, false>::~hash_table ()
>  {
>    for (size_t i = m_size - 1; i < m_size; i--)
>      if (m_entries[i] != HTAB_EMPTY_ENTRY && m_entries[i] != 
> HTAB_DELETED_ENTRY)
> @@ -518,7 +664,8 @@ hash_table<Descriptor, Allocator>::~hash_table ()
>
>  template<typename Descriptor, template<typename Type> class Allocator>
>  typename Descriptor::value_type **
> -hash_table<Descriptor, Allocator>::find_empty_slot_for_expand (hashval_t 
> hash)
> +hash_table<Descriptor, Allocator, false>
> +::find_empty_slot_for_expand (hashval_t hash)
>  {
>    hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
>    size_t size = m_size;
> @@ -554,7 +701,7 @@ hash_table<Descriptor, 
> Allocator>::find_empty_slot_for_expand (hashval_t hash)
>
>           template<typename Descriptor, template<typename Type> class 
> Allocator>
>  void
> -hash_table<Descriptor, Allocator>::expand ()
> +hash_table<Descriptor, Allocator, false>::expand ()
>  {
>    value_type **oentries = m_entries;
>    unsigned int oindex = m_size_prime_index;
> @@ -606,7 +753,7 @@ hash_table<Descriptor, Allocator>::expand ()
>
>  template<typename Descriptor, template<typename Type> class Allocator>
>  void
> -hash_table<Descriptor, Allocator>::empty ()
> +hash_table<Descriptor, Allocator, false>::empty ()
>  {
>    size_t size = m_size;
>    value_type **entries = m_entries;
> @@ -639,7 +786,7 @@ hash_table<Descriptor, Allocator>::empty ()
>
>  template<typename Descriptor, template<typename Type> class Allocator>
>  void
> -hash_table<Descriptor, Allocator>::clear_slot (value_type **slot)
> +hash_table<Descriptor, Allocator, false>::clear_slot (value_type **slot)
>  {
>    if (slot < m_entries || slot >= m_entries + size ()
>        || *slot == HTAB_EMPTY_ENTRY || *slot == HTAB_DELETED_ENTRY)
> @@ -657,7 +804,7 @@ hash_table<Descriptor, Allocator>::clear_slot (value_type 
> **slot)
>
>  template<typename Descriptor, template<typename Type> class Allocator>
>  typename Descriptor::value_type *
> -hash_table<Descriptor, Allocator>
> +hash_table<Descriptor, Allocator, false>
>  ::find_with_hash (const compare_type *comparable, hashval_t hash)
>  {
>    m_searches++;
> @@ -695,7 +842,7 @@ hash_table<Descriptor, Allocator>
>
>  template<typename Descriptor, template<typename Type> class Allocator>
>  typename Descriptor::value_type **
> -hash_table<Descriptor, Allocator>
> +hash_table<Descriptor, Allocator, false>
>  ::find_slot_with_hash (const compare_type *comparable, hashval_t hash,
>                        enum insert_option insert)
>  {
> @@ -756,7 +903,7 @@ hash_table<Descriptor, Allocator>
>
>  template<typename Descriptor, template<typename Type> class Allocator>
>  void
> -hash_table<Descriptor, Allocator>
> +hash_table<Descriptor, Allocator, false>
>  ::remove_elt_with_hash (const compare_type *comparable, hashval_t hash)
>  {
>    value_type **slot = find_slot_with_hash (comparable, hash, NO_INSERT);
> @@ -773,12 +920,11 @@ hash_table<Descriptor, Allocator>
>     each live entry.  If CALLBACK returns false, the iteration stops.
>     ARGUMENT is passed as CALLBACK's second argument. */
>
> -template<typename Descriptor,
> -         template<typename Type> class Allocator>
> +template<typename Descriptor, template<typename Type> class Allocator>
>  template<typename Argument,
>           int (*Callback) (typename Descriptor::value_type **slot, Argument 
> argument)>
>  void
> -hash_table<Descriptor, Allocator>::traverse_noresize (Argument argument)
> +hash_table<Descriptor, Allocator, false>::traverse_noresize (Argument 
> argument)
>  {
>    value_type **slot = m_entries;
>    value_type **limit = slot + size ();
> @@ -803,7 +949,7 @@ template <typename Argument,
>           int (*Callback) (typename Descriptor::value_type **slot,
>                            Argument argument)>
>  void
> -hash_table<Descriptor, Allocator>::traverse (Argument argument)
> +hash_table<Descriptor, Allocator, false>::traverse (Argument argument)
>  {
>    size_t size = m_size;
>    if (elements () * 8 < size && size > 32)
> @@ -816,7 +962,7 @@ hash_table<Descriptor, Allocator>::traverse (Argument 
> argument)
>
>  template<typename Descriptor, template<typename Type> class Allocator>
>  void
> -hash_table<Descriptor, Allocator>::iterator::slide ()
> +hash_table<Descriptor, Allocator, false>::iterator::slide ()
>  {
>    for ( ; m_slot < m_limit; ++m_slot )
>      {
> @@ -831,8 +977,527 @@ hash_table<Descriptor, Allocator>::iterator::slide ()
>  /* Bump the iterator.  */
>
>  template<typename Descriptor, template<typename Type> class Allocator>
> -inline typename hash_table<Descriptor, Allocator>::iterator &
> -hash_table<Descriptor, Allocator>::iterator::operator ++ ()
> +inline typename hash_table<Descriptor, Allocator, false>::iterator &
> +hash_table<Descriptor, Allocator, false>::iterator::operator ++ ()
> +{
> +  ++m_slot;
> +  slide ();
> +  return *this;
> +}
> +
> +/* A partial specialization used when values should be stored directly.  */
> +
> +template <typename Descriptor,
> +        template<typename Type> class Allocator>
> +class hash_table<Descriptor, Allocator, true>
> +{
> +  typedef typename Descriptor::value_type value_type;
> +  typedef typename Descriptor::compare_type compare_type;
> +
> +public:
> +  hash_table (size_t);
> +  ~hash_table ();
> +
> +  /* Current size (in entries) of the hash table.  */
> +  size_t size () const { return m_size; }
> +
> +  /* Return the current number of elements in this hash table. */
> +  size_t elements () const { return m_n_elements - m_n_deleted; }
> +
> +  /* Return the current number of elements in this hash table. */
> +  size_t elements_with_deleted () const { return m_n_elements; }
> +
> +  /* This function clears all entries in the given hash table.  */
> +  void empty ();
> +
> +  /* This function clears a specified SLOT in a hash table.  It is
> +     useful when you've already done the lookup and don't want to do it
> +     again. */
> +
> +  void clear_slot (value_type *);
> +
> +  /* This function searches for a hash table entry equal to the given
> +     COMPARABLE element starting with the given HASH value.  It cannot
> +     be used to insert or delete an element. */
> +  value_type &find_with_hash (const compare_type &, hashval_t);
> +
> +/* Like find_slot_with_hash, but compute the hash value from the element.  */
> +  value_type &find (const value_type &value)
> +    {
> +      return find_with_hash (value, Descriptor::hash (value));
> +    }
> +
> +  value_type *find_slot (const value_type &value, insert_option insert)
> +    {
> +      return find_slot_with_hash (value, Descriptor::hash (value), insert);
> +    }
> +
> +  /* This function searches for a hash table slot containing an entry
> +     equal to the given COMPARABLE element and starting with the given
> +     HASH.  To delete an entry, call this with insert=NO_INSERT, then
> +     call clear_slot on the slot returned (possibly after doing some
> +     checks).  To insert an entry, call this with insert=INSERT, then
> +     write the value you want into the returned slot.  When inserting an
> +     entry, NULL may be returned if memory allocation fails. */
> +  value_type *find_slot_with_hash (const compare_type &comparable,
> +                                   hashval_t hash, enum insert_option 
> insert);
> +
> +  /* This function deletes an element with the given COMPARABLE value
> +     from hash table starting with the given HASH.  If there is no
> +     matching element in the hash table, this function does nothing. */
> +  void remove_elt_with_hash (const compare_type &, hashval_t);
> +
> +/* Like remove_elt_with_hash, but compute the hash value from the element.  
> */
> +  void remove_elt (const value_type &value)
> +    {
> +      remove_elt_with_hash (value, Descriptor::hash (value));
> +    }
> +
> +  /* This function scans over the entire hash table calling CALLBACK for
> +     each live entry.  If CALLBACK returns false, the iteration stops.
> +     ARGUMENT is passed as CALLBACK's second argument. */
> +  template <typename Argument,
> +           int (*Callback) (value_type *slot, Argument argument)>
> +  void traverse_noresize (Argument argument);
> +
> +  /* Like traverse_noresize, but does resize the table when it is too empty
> +     to improve effectivity of subsequent calls.  */
> +  template <typename Argument,
> +           int (*Callback) (value_type *slot, Argument argument)>
> +  void traverse (Argument argument);
> +
> +  class iterator
> +  {
> +  public:
> +    iterator () : m_slot (NULL), m_limit (NULL) {}
> +
> +    iterator (value_type *slot, value_type *limit) :
> +      m_slot (slot), m_limit (limit) {}
> +
> +    inline value_type &operator * () { return *m_slot; }
> +    void slide ();
> +    inline iterator &operator ++ ();
> +    bool operator != (const iterator &other) const
> +      {
> +       return m_slot != other.m_slot || m_limit != other.m_limit;
> +      }
> +
> +  private:
> +    value_type *m_slot;
> +    value_type *m_limit;
> +  };
> +
> +  iterator begin () const
> +    {
> +      iterator iter (m_entries, m_entries + m_size);
> +      iter.slide ();
> +      return iter;
> +    }
> +
> +  iterator end () const { return iterator (); }
> +
> +  double collisions () const
> +    {
> +      return m_searches ? static_cast <double> (m_collisions) / m_searches : 
> 0;
> +    }
> +
> +private:
> +
> +  value_type *find_empty_slot_for_expand (hashval_t);
> +  void expand ();
> +  static bool is_deleted (value_type &v)
> +    {
> +      return is_deleted_helper<value_type, Descriptor>::call (v);
> +    }
> +  static bool is_empty (value_type &v)
> +    {
> +      return is_empty_helper<value_type, Descriptor>::call (v);
> +    }
> +
> +  static void mark_deleted (value_type &v)
> +    {
> +      return mark_deleted_helper<value_type, Descriptor>::call (v);
> +    }
> +
> +  static void mark_empty (value_type &v)
> +    {
> +      return mark_empty_helper<value_type, Descriptor>::call (v);
> +    }
> +
> +  /* Table itself.  */
> +  typename Descriptor::value_type *m_entries;
> +
> +  size_t m_size;
> +
> +  /* Current number of elements including also deleted elements.  */
> +  size_t m_n_elements;
> +
> +  /* Current number of deleted elements in the table.  */
> +  size_t m_n_deleted;
> +
> +  /* The following member is used for debugging. Its value is number
> +     of all calls of `htab_find_slot' for the hash table. */
> +  unsigned int m_searches;
> +
> +  /* The following member is used for debugging.  Its value is number
> +     of collisions fixed for time of work with the hash table. */
> +  unsigned int m_collisions;
> +
> +  /* Current size (in entries) of the hash table, as an index into the
> +     table of primes.  */
> +  unsigned int m_size_prime_index;
> +};
> +
> +template<typename Descriptor, template<typename Type> class Allocator>
> +hash_table<Descriptor, Allocator, true>::hash_table (size_t size) :
> +  m_n_elements (0), m_n_deleted (0), m_searches (0), m_collisions (0)
> +{
> +  unsigned int size_prime_index;
> +
> +  size_prime_index = hash_table_higher_prime_index (size);
> +  size = prime_tab[size_prime_index].prime;
> +
> +  m_entries = Allocator <value_type> ::data_alloc (size);
> +  gcc_assert (m_entries != NULL);
> +  m_size = size;
> +  m_size_prime_index = size_prime_index;
> +}
> +
> +template<typename Descriptor, template<typename Type> class Allocator>
> +hash_table<Descriptor, Allocator, true>::~hash_table ()
> +{
> +  for (size_t i = m_size - 1; i < m_size; i--)
> +    if (!is_empty (m_entries[i]) && !is_deleted (m_entries[i]))
> +      Descriptor::remove (m_entries[i]);
> +
> +  Allocator <value_type> ::data_free (m_entries);
> +}
> +
> +/* Similar to find_slot, but without several unwanted side effects:
> +    - Does not call equal when it finds an existing entry.
> +    - Does not change the count of elements/searches/collisions in the
> +      hash table.
> +   This function also assumes there are no deleted entries in the table.
> +   HASH is the hash value for the element to be inserted.  */
> +
> +template<typename Descriptor, template<typename Type> class Allocator>
> +typename Descriptor::value_type *
> +hash_table<Descriptor, Allocator, true>
> +::find_empty_slot_for_expand (hashval_t hash)
> +{
> +  hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
> +  size_t size = m_size;
> +  value_type *slot = m_entries + index;
> +  hashval_t hash2;
> +
> +  if (is_empty (*slot))
> +    return slot;
> +  else if (is_deleted (*slot))
> +    abort ();
> +
> +  hash2 = hash_table_mod2 (hash, m_size_prime_index);
> +  for (;;)
> +    {
> +      index += hash2;
> +      if (index >= size)
> +        index -= size;
> +
> +      slot = m_entries + index;
> +      if (is_empty (*slot))
> +        return slot;
> +      else if (is_deleted (*slot))
> +        abort ();
> +    }
> +}
> +
> +/* 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
> +   table must already exist.  Remember also that the place of the
> +   table entries is changed.  If memory allocation fails, this function
> +   will abort.  */
> +
> +         template<typename Descriptor, template<typename Type> class 
> Allocator>
> +void
> +hash_table<Descriptor, Allocator, true>::expand ()
> +{
> +  value_type *oentries = m_entries;
> +  unsigned int oindex = m_size_prime_index;
> +  size_t osize = size ();
> +  value_type *olimit = oentries + osize;
> +  size_t elts = elements ();
> +
> +  /* Resize only when table after removal of unused elements is either
> +     too full or too empty.  */
> +  unsigned int nindex;
> +  size_t nsize;
> +  if (elts * 2 > osize || (elts * 8 < osize && osize > 32))
> +    {
> +      nindex = hash_table_higher_prime_index (elts * 2);
> +      nsize = prime_tab[nindex].prime;
> +    }
> +  else
> +    {
> +      nindex = oindex;
> +      nsize = osize;
> +    }
> +
> +  value_type *nentries = Allocator <value_type> ::data_alloc (nsize);
> +  gcc_assert (nentries != NULL);
> +  m_entries = nentries;
> +  m_size = nsize;
> +  m_size_prime_index = nindex;
> +  m_n_elements -= m_n_deleted;
> +  m_n_deleted = 0;
> +
> +  value_type *p = oentries;
> +  do
> +    {
> +      value_type &x = *p;
> +
> +      if (!is_empty (x) && !is_deleted (x))
> +        {
> +          value_type *q = find_empty_slot_for_expand (Descriptor::hash (x));
> +
> +          *q = x;
> +        }
> +
> +      p++;
> +    }
> +  while (p < olimit);
> +
> +  Allocator <value_type> ::data_free (oentries);
> +}
> +
> +template<typename Descriptor, template<typename Type> class Allocator>
> +void
> +hash_table<Descriptor, Allocator, true>::empty ()
> +{
> +  size_t size = m_size;
> +  value_type *entries = m_entries;
> +  int i;
> +
> +  for (i = size - 1; i >= 0; i--)
> +    if (!is_empty (entries[i]) && !is_deleted (entries[i]))
> +      Descriptor::remove (entries[i]);
> +
> +  /* Instead of clearing megabyte, downsize the table.  */
> +  if (size > 1024*1024 / sizeof (PTR))
> +    {
> +      int nindex = hash_table_higher_prime_index (1024 / sizeof (PTR));
> +      int nsize = prime_tab[nindex].prime;
> +
> +      Allocator <value_type> ::data_free (m_entries);
> +      m_entries = Allocator <value_type> ::data_alloc (nsize);
> +      m_size = nsize;
> +      m_size_prime_index = nindex;
> +    }
> +  else
> +    memset (entries, 0, size * sizeof (value_type));
> +  m_n_deleted = 0;
> +  m_n_elements = 0;
> +}
> +
> +/* This function clears a specified SLOT in a hash table.  It is
> +   useful when you've already done the lookup and don't want to do it
> +   again. */
> +
> +template<typename Descriptor, template<typename Type> class Allocator>
> +void
> +hash_table<Descriptor, Allocator, true>::clear_slot (value_type *slot)
> +{
> +  if (slot < m_entries || slot >= m_entries + size ()
> +      || is_empty (*slot) || is_deleted (*slot))
> +    abort ();
> +
> +  Descriptor::remove (*slot);
> +
> +  mark_deleted (*slot);
> +  m_n_deleted++;
> +}
> +
> +/* This function searches for a hash table entry equal to the given
> +   COMPARABLE element starting with the given HASH value.  It cannot
> +   be used to insert or delete an element. */
> +
> +template<typename Descriptor, template<typename Type> class Allocator>
> +typename Descriptor::value_type &
> +hash_table<Descriptor, Allocator, true>
> +::find_with_hash (const compare_type &comparable, hashval_t hash)
> +{
> +  m_searches++;
> +  size_t size = m_size;
> +  hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
> +
> +  value_type *entry = &m_entries[index];
> +  if (is_empty (*entry)
> +      || (!is_deleted (*entry) && Descriptor::equal (*entry, comparable)))
> +    return *entry;
> +
> +  hashval_t hash2 = hash_table_mod2 (hash, m_size_prime_index);
> +  for (;;)
> +    {
> +      m_collisions++;
> +      index += hash2;
> +      if (index >= size)
> +        index -= size;
> +
> +      entry = &m_entries[index];
> +      if (is_empty (*entry)
> +          || (!is_deleted (*entry) && Descriptor::equal (*entry, 
> comparable)))
> +        return *entry;
> +    }
> +}
> +
> +/* This function searches for a hash table slot containing an entry
> +   equal to the given COMPARABLE element and starting with the given
> +   HASH.  To delete an entry, call this with insert=NO_INSERT, then
> +   call clear_slot on the slot returned (possibly after doing some
> +   checks).  To insert an entry, call this with insert=INSERT, then
> +   write the value you want into the returned slot.  When inserting an
> +   entry, NULL may be returned if memory allocation fails. */
> +
> +template<typename Descriptor, template<typename Type> class Allocator>
> +typename Descriptor::value_type *
> +hash_table<Descriptor, Allocator, true>
> +::find_slot_with_hash (const compare_type &comparable, hashval_t hash,
> +                      enum insert_option insert)
> +{
> +  if (insert == INSERT && m_size * 3 <= m_n_elements * 4)
> +    expand ();
> +
> +  m_searches++;
> +
> +  value_type *first_deleted_slot = NULL;
> +  hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
> +  hashval_t hash2 = hash_table_mod2 (hash, m_size_prime_index);
> +  value_type *entry = &m_entries[index];
> +  size_t size = m_size;
> +  if (is_empty (*entry))
> +    goto empty_entry;
> +  else if (is_deleted (*entry))
> +    first_deleted_slot = &m_entries[index];
> +  else if (Descriptor::equal (*entry, comparable))
> +    return &m_entries[index];
> +
> +  for (;;)
> +    {
> +      m_collisions++;
> +      index += hash2;
> +      if (index >= size)
> +       index -= size;
> +
> +      entry = &m_entries[index];
> +      if (is_empty (*entry))
> +       goto empty_entry;
> +      else if (is_deleted (*entry))
> +       {
> +         if (!first_deleted_slot)
> +           first_deleted_slot = &m_entries[index];
> +       }
> +      else if (Descriptor::equal (*entry, comparable))
> +       return &m_entries[index];
> +    }
> +
> + empty_entry:
> +  if (insert == NO_INSERT)
> +    return NULL;
> +
> +  if (first_deleted_slot)
> +    {
> +      m_n_deleted--;
> +      mark_empty (*first_deleted_slot);
> +      return first_deleted_slot;
> +    }
> +
> +  m_n_elements++;
> +  return &m_entries[index];
> +}
> +
> +/* This function deletes an element with the given COMPARABLE value
> +   from hash table starting with the given HASH.  If there is no
> +   matching element in the hash table, this function does nothing. */
> +
> +template<typename Descriptor, template<typename Type> class Allocator>
> +void
> +hash_table<Descriptor, Allocator, true>
> +::remove_elt_with_hash (const compare_type &comparable, hashval_t hash)
> +{
> +  value_type *slot = find_slot_with_hash (comparable, hash, NO_INSERT);
> +  if (is_empty (*slot))
> +    return;
> +
> +  Descriptor::remove (*slot);
> +
> +  mark_deleted (*slot);
> +  m_n_deleted++;
> +}
> +
> +/* This function scans over the entire hash table calling CALLBACK for
> +   each live entry.  If CALLBACK returns false, the iteration stops.
> +   ARGUMENT is passed as CALLBACK's second argument. */
> +
> +template<typename Descriptor,
> +         template<typename Type> class Allocator>
> +template<typename Argument,
> +         int (*Callback) (typename Descriptor::value_type *slot,
> +                          Argument argument)>
> +void
> +hash_table<Descriptor, Allocator, true>::traverse_noresize (Argument 
> argument)
> +{
> +  value_type *slot = m_entries;
> +  value_type *limit = slot + size ();
> +
> +  do
> +    {
> +      value_type &x = *slot;
> +
> +      if (!is_empty (x) && !is_deleted (x))
> +        if (! Callback (slot, argument))
> +          break;
> +    }
> +  while (++slot < limit);
> +}
> +
> +/* Like traverse_noresize, but does resize the table when it is too empty
> +   to improve effectivity of subsequent calls.  */
> +
> +template <typename Descriptor,
> +         template <typename Type> class Allocator>
> +template <typename Argument,
> +         int (*Callback) (typename Descriptor::value_type *slot,
> +                          Argument argument)>
> +void
> +hash_table<Descriptor, Allocator, true>::traverse (Argument argument)
> +{
> +  size_t size = m_size;
> +  if (elements () * 8 < size && size > 32)
> +    expand ();
> +
> +  traverse_noresize <Argument, Callback> (argument);
> +}
> +
> +/* Slide down the iterator slots until an active entry is found.  */
> +
> +template<typename Descriptor, template<typename Type> class Allocator>
> +void
> +hash_table<Descriptor, Allocator, true>::iterator::slide ()
> +{
> +  for ( ; m_slot < m_limit; ++m_slot )
> +    {
> +      value_type &x = *m_slot;
> +      if (!is_empty (x) && !is_deleted (x))
> +        return;
> +    }
> +  m_slot = NULL;
> +  m_limit = NULL;
> +}
> +
> +/* Bump the iterator.  */
> +
> +template<typename Descriptor, template<typename Type> class Allocator>
> +inline typename hash_table<Descriptor, Allocator, true>::iterator &
> +hash_table<Descriptor, Allocator, true>::iterator::operator ++ ()
>  {
>    ++m_slot;
>    slide ();
> @@ -846,7 +1511,7 @@ hash_table<Descriptor, Allocator>::iterator::operator ++ 
> ()
>
>  #define FOR_EACH_HASH_TABLE_ELEMENT(HTAB, RESULT, TYPE, ITER) \
>    for ((ITER) = (HTAB).begin (); \
> -       (ITER) != (HTAB).end () ? (RESULT = &*(ITER) , true) : false; \
> +       (ITER) != (HTAB).end () ? (RESULT = *(ITER) , true) : false; \
>         ++(ITER))
>
>  #endif /* TYPED_HASHTAB_H */
> diff --git a/gcc/tree-browser.c b/gcc/tree-browser.c
> index 8c03550..2a4db1b 100644
> --- a/gcc/tree-browser.c
> +++ b/gcc/tree-browser.c
> @@ -102,22 +102,13 @@ static tree TB_history_prev (void);
>  void browse_tree (tree);
>
>  /* Hashtable helpers.  */
> -struct tree_upper_hasher : typed_noop_remove <tree_node>
> +struct tree_upper_hasher : pointer_hash<tree_node>
>  {
> -  typedef tree_node value_type;
> -  typedef tree_node compare_type;
> -  static inline hashval_t hash (const value_type *);
> -  static inline bool equal (const value_type *, const compare_type *);
> +  static inline bool equal (const value_type &, const compare_type &);
>  };
>
> -inline hashval_t
> -tree_upper_hasher::hash (const value_type *v)
> -{
> -  return pointer_hash <value_type>::hash (v);
> -}
> -
>  inline bool
> -tree_upper_hasher::equal (const value_type *parent, const compare_type *node)
> +tree_upper_hasher::equal (const value_type &parent, const compare_type &node)
>  {
>    if (parent == NULL || node == NULL)
>      return 0;
> diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c
> index 7b0115d..3ed403a 100644
> --- a/gcc/tree-complex.c
> +++ b/gcc/tree-complex.c
> @@ -83,10 +83,9 @@ static vec<tree> complex_ssa_name_components;
>  static tree
>  cvc_lookup (unsigned int uid)
>  {
> -  struct int_tree_map *h, in;
> +  struct int_tree_map in;
>    in.uid = uid;
> -  h = complex_variable_components->find_with_hash (&in, uid);
> -  return h ? h->to : NULL;
> +  return complex_variable_components->find_with_hash (in, uid).to;
>  }
>
>  /* Insert the pair UID, TO into the complex_variable_components hashtable.  
> */
> @@ -94,14 +93,13 @@ cvc_lookup (unsigned int uid)
>  static void
>  cvc_insert (unsigned int uid, tree to)
>  {
> -  struct int_tree_map *h;
> -  int_tree_map **loc;
> +  int_tree_map h;
> +  int_tree_map *loc;
>
> -  h = XNEW (struct int_tree_map);
> -  h->uid = uid;
> -  h->to = to;
> +  h.uid = uid;
>    loc = complex_variable_components->find_slot_with_hash (h, uid, INSERT);
> -  *loc = h;
> +  loc->uid = uid;
> +  loc->to = to;
>  }
>
>  /* Return true if T is not a zero constant.  In the case of real values,
> diff --git a/gcc/tree-hasher.h b/gcc/tree-hasher.h
> index 6b28008..ae56a84 100644
> --- a/gcc/tree-hasher.h
> +++ b/gcc/tree-hasher.h
> @@ -30,28 +30,37 @@ struct int_tree_map {
>
>  /* Hashtable helpers.  */
>
> -struct int_tree_hasher : typed_free_remove <int_tree_map>
> +struct int_tree_hasher
>  {
>    typedef int_tree_map value_type;
>    typedef int_tree_map compare_type;
> -  static inline hashval_t hash (const value_type *);
> -  static inline bool equal (const value_type *, const compare_type *);
> +  typedef int store_values_directly;
> +  static inline hashval_t hash (const value_type &);
> +  static inline bool equal (const value_type &, const compare_type &);
> +  static bool is_deleted (const value_type &v)
> +    {
> +      return v.to == reinterpret_cast<tree> (1);
> +    }
> +  static void mark_deleted (value_type &v) { v.to = reinterpret_cast<tree> 
> (0x1); }
> +  static bool is_empty (const value_type &v) { return v.to == NULL; }
> +  static void mark_empty (value_type &v) { v.to = NULL; }
> +  static void remove (value_type &) {}
>  };
>
>  /* Hash a UID in a int_tree_map.  */
>
>  inline hashval_t
> -int_tree_hasher::hash (const value_type *item)
> +int_tree_hasher::hash (const value_type &item)
>  {
> -  return item->uid;
> +  return item.uid;
>  }
>
>  /* Return true if the uid in both int tree maps are equal.  */
>
>  inline bool
> -int_tree_hasher::equal (const value_type *a, const compare_type *b)
> +int_tree_hasher::equal (const value_type &a, const compare_type &b)
>  {
> -  return (a->uid == b->uid);
> +  return (a.uid == b.uid);
>  }
>
>  typedef hash_table <int_tree_hasher> int_tree_htab_type;
> diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
> index 1cdcc2f..96255f9 100644
> --- a/gcc/tree-into-ssa.c
> +++ b/gcc/tree-into-ssa.c
> @@ -203,20 +203,21 @@ typedef struct var_info_d *var_info_p;
>
>  struct var_info_hasher : typed_free_remove <var_info_d>
>  {
> -  typedef var_info_d value_type;
> -  typedef var_info_d compare_type;
> -  static inline hashval_t hash (const value_type *);
> -  static inline bool equal (const value_type *, const compare_type *);
> +  typedef var_info_d *value_type;
> +  typedef var_info_d *compare_type;
> +  typedef int store_values_directly;
> +  static inline hashval_t hash (const value_type &);
> +  static inline bool equal (const value_type &, const compare_type &);
>  };
>
>  inline hashval_t
> -var_info_hasher::hash (const value_type *p)
> +var_info_hasher::hash (const value_type &p)
>  {
>    return DECL_UID (p->var);
>  }
>
>  inline bool
> -var_info_hasher::equal (const value_type *p1, const compare_type *p2)
> +var_info_hasher::equal (const value_type &p1, const compare_type &p2)
>  {
>    return p1->var == p2->var;
>  }
> diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
> index 3ef4aa6..0c486bb 100644
> --- a/gcc/tree-parloops.c
> +++ b/gcc/tree-parloops.c
> @@ -489,8 +489,6 @@ take_address_of (tree obj, tree type, edge entry,
>                  int_tree_htab_type *decl_address, gimple_stmt_iterator *gsi)
>  {
>    int uid;
> -  int_tree_map **dslot;
> -  struct int_tree_map ielt, *nielt;
>    tree *var_p, name, addr;
>    gimple stmt;
>    gimple_seq stmts;
> @@ -511,9 +509,10 @@ take_address_of (tree obj, tree type, edge entry,
>       in the address and share it for all accesses and addresses based
>       on it.  */
>    uid = DECL_UID (TREE_OPERAND (TREE_OPERAND (*var_p, 0), 0));
> -  ielt.uid = uid;
> -  dslot = decl_address->find_slot_with_hash (&ielt, uid, INSERT);
> -  if (!*dslot)
> +  int_tree_map elt;
> +  elt.uid = uid;
> +  int_tree_map *slot = decl_address->find_slot (elt, INSERT);
> +  if (!slot->to)
>      {
>        if (gsi == NULL)
>         return NULL;
> @@ -527,13 +526,11 @@ take_address_of (tree obj, tree type, edge entry,
>        stmt = gimple_build_assign (name, addr);
>        gsi_insert_on_edge_immediate (entry, stmt);
>
> -      nielt = XNEW (struct int_tree_map);
> -      nielt->uid = uid;
> -      nielt->to = name;
> -      *dslot = nielt;
> +      slot->uid = uid;
> +      slot->to = name;
>      }
>    else
> -    name = (*dslot)->to;
> +    name = slot->to;
>
>    /* Express the address in terms of the canonical SSA name.  */
>    TREE_OPERAND (*var_p, 0) = name;
> @@ -822,10 +819,10 @@ separate_decls_in_region_name (tree name, 
> name_to_copy_table_type *name_copies,
>  {
>    tree copy, var, var_copy;
>    unsigned idx, uid, nuid;
> -  struct int_tree_map ielt, *nielt;
> +  struct int_tree_map ielt;
>    struct name_to_copy_elt elt, *nelt;
>    name_to_copy_elt **slot;
> -  int_tree_map **dslot;
> +  int_tree_map *dslot;
>
>    if (TREE_CODE (name) != SSA_NAME)
>      return name;
> @@ -858,29 +855,25 @@ separate_decls_in_region_name (tree name, 
> name_to_copy_table_type *name_copies,
>
>    uid = DECL_UID (var);
>    ielt.uid = uid;
> -  dslot = decl_copies->find_slot_with_hash (&ielt, uid, INSERT);
> -  if (!*dslot)
> +  dslot = decl_copies->find_slot_with_hash (ielt, uid, INSERT);
> +  if (!dslot->to)
>      {
>        var_copy = create_tmp_var (TREE_TYPE (var), get_name (var));
>        DECL_GIMPLE_REG_P (var_copy) = DECL_GIMPLE_REG_P (var);
> -      nielt = XNEW (struct int_tree_map);
> -      nielt->uid = uid;
> -      nielt->to = var_copy;
> -      *dslot = nielt;
> +      dslot->uid = uid;
> +      dslot->to = var_copy;
>
>        /* Ensure that when we meet this decl next time, we won't duplicate
>           it again.  */
>        nuid = DECL_UID (var_copy);
>        ielt.uid = nuid;
> -      dslot = decl_copies->find_slot_with_hash (&ielt, nuid, INSERT);
> -      gcc_assert (!*dslot);
> -      nielt = XNEW (struct int_tree_map);
> -      nielt->uid = nuid;
> -      nielt->to = var_copy;
> -      *dslot = nielt;
> +      dslot = decl_copies->find_slot_with_hash (ielt, nuid, INSERT);
> +      gcc_assert (!dslot->to);
> +      dslot->uid = nuid;
> +      dslot->to = var_copy;
>      }
>    else
> -    var_copy = ((struct int_tree_map *) *dslot)->to;
> +    var_copy = dslot->to;
>
>    replace_ssa_name_symbol (copy, var_copy);
>    return copy;
> @@ -944,7 +937,7 @@ separate_decls_in_region_debug (gimple stmt,
>    struct int_tree_map ielt;
>    struct name_to_copy_elt elt;
>    name_to_copy_elt **slot;
> -  int_tree_map **dslot;
> +  int_tree_map *dslot;
>
>    if (gimple_debug_bind_p (stmt))
>      var = gimple_debug_bind_get_var (stmt);
> @@ -956,13 +949,13 @@ separate_decls_in_region_debug (gimple stmt,
>      return true;
>    gcc_assert (DECL_P (var) && SSA_VAR_P (var));
>    ielt.uid = DECL_UID (var);
> -  dslot = decl_copies->find_slot_with_hash (&ielt, ielt.uid, NO_INSERT);
> +  dslot = decl_copies->find_slot_with_hash (ielt, ielt.uid, NO_INSERT);
>    if (!dslot)
>      return true;
>    if (gimple_debug_bind_p (stmt))
> -    gimple_debug_bind_set_var (stmt, ((struct int_tree_map *) *dslot)->to);
> +    gimple_debug_bind_set_var (stmt, dslot->to);
>    else if (gimple_debug_source_bind_p (stmt))
> -    gimple_debug_source_bind_set_var (stmt, ((struct int_tree_map *) 
> *dslot)->to);
> +    gimple_debug_source_bind_set_var (stmt, dslot->to);
>
>    FOR_EACH_PHI_OR_STMT_USE (use, stmt, oi, SSA_OP_USE)
>    {
> diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
> index 6c581ba..61e75b6 100644
> --- a/gcc/tree-ssa-dom.c
> +++ b/gcc/tree-ssa-dom.c
> @@ -158,21 +158,22 @@ static void free_expr_hash_elt (void *);
>
>  struct expr_elt_hasher
>  {
> -  typedef expr_hash_elt value_type;
> -  typedef expr_hash_elt compare_type;
> -  static inline hashval_t hash (const value_type *);
> -  static inline bool equal (const value_type *, const compare_type *);
> -  static inline void remove (value_type *);
> +  typedef expr_hash_elt *value_type;
> +  typedef expr_hash_elt *compare_type;
> +  typedef int store_values_directly;
> +  static inline hashval_t hash (const value_type &);
> +  static inline bool equal (const value_type &, const compare_type &);
> +  static inline void remove (value_type &);
>  };
>
>  inline hashval_t
> -expr_elt_hasher::hash (const value_type *p)
> +expr_elt_hasher::hash (const value_type &p)
>  {
>    return p->hash;
>  }
>
>  inline bool
> -expr_elt_hasher::equal (const value_type *p1, const compare_type *p2)
> +expr_elt_hasher::equal (const value_type &p1, const compare_type &p2)
>  {
>    gimple stmt1 = p1->stmt;
>    const struct hashable_expr *expr1 = &p1->expr;
> @@ -211,7 +212,7 @@ expr_elt_hasher::equal (const value_type *p1, const 
> compare_type *p2)
>  /* Delete an expr_hash_elt and reclaim its storage.  */
>
>  inline void
> -expr_elt_hasher::remove (value_type *element)
> +expr_elt_hasher::remove (value_type &element)
>  {
>    free_expr_hash_elt (element);
>  }
> diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
> index 4d0d6c2..4903f48 100644
> --- a/gcc/tree-ssa-reassoc.c
> +++ b/gcc/tree-ssa-reassoc.c
> @@ -1023,32 +1023,36 @@ static vec<oecount> cvec;
>
>  /* Oecount hashtable helpers.  */
>
> -struct oecount_hasher : typed_noop_remove <void>
> +struct oecount_hasher
>  {
> -  /* Note that this hash table stores integers, not pointers.
> -     So, observe the casting in the member functions.  */
> -  typedef void value_type;
> -  typedef void compare_type;
> -  static inline hashval_t hash (const value_type *);
> -  static inline bool equal (const value_type *, const compare_type *);
> +  typedef int value_type;
> +  typedef int compare_type;
> +  typedef int store_values_directly;
> +  static inline hashval_t hash (const value_type &);
> +  static inline bool equal (const value_type &, const compare_type &);
> +  static bool is_deleted (int &v) { return v == 1; }
> +  static void mark_deleted (int &e) { e = 1; }
> +  static bool is_empty (int &v) { return v == 0; }
> +  static void mark_empty (int &e) { e = 0; }
> +  static void remove (int &) {}
>  };
>
>  /* Hash function for oecount.  */
>
>  inline hashval_t
> -oecount_hasher::hash (const value_type *p)
> +oecount_hasher::hash (const value_type &p)
>  {
> -  const oecount *c = &cvec[(size_t)p - 42];
> +  const oecount *c = &cvec[p - 42];
>    return htab_hash_pointer (c->op) ^ (hashval_t)c->oecode;
>  }
>
>  /* Comparison function for oecount.  */
>
>  inline bool
> -oecount_hasher::equal (const value_type *p1, const compare_type *p2)
> +oecount_hasher::equal (const value_type &p1, const compare_type &p2)
>  {
> -  const oecount *c1 = &cvec[(size_t)p1 - 42];
> -  const oecount *c2 = &cvec[(size_t)p2 - 42];
> +  const oecount *c1 = &cvec[p1 - 42];
> +  const oecount *c2 = &cvec[p2 - 42];
>    return (c1->oecode == c2->oecode
>           && c1->op == c2->op);
>  }
> @@ -1473,23 +1477,23 @@ undistribute_ops_list (enum tree_code opcode,
>        FOR_EACH_VEC_ELT (subops[i], j, oe1)
>         {
>           oecount c;
> -         void **slot;
> -         size_t idx;
> +         int *slot;
> +         int idx;
>           c.oecode = oecode;
>           c.cnt = 1;
>           c.id = next_oecount_id++;
>           c.op = oe1->op;
>           cvec.safe_push (c);
>           idx = cvec.length () + 41;
> -         slot = ctable.find_slot ((void *)idx, INSERT);
> +         slot = ctable.find_slot (idx, INSERT);
>           if (!*slot)
>             {
> -             *slot = (void *)idx;
> +             *slot = idx;
>             }
>           else
>             {
>               cvec.pop ();
> -             cvec[(size_t)*slot - 42].cnt++;
> +             cvec[*slot - 42].cnt++;
>             }
>         }
>      }
> diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
> index e553e28..0ad22c7 100644
> --- a/gcc/tree-vectorizer.c
> +++ b/gcc/tree-vectorizer.c
> @@ -548,14 +548,14 @@ vectorize_loops (void)
>        for (hash_table<simd_array_to_simduid>::iterator iter
>            = simd_array_to_simduid_htab->begin ();
>            iter != simd_array_to_simduid_htab->end (); ++iter)
> -       if ((*iter).simduid != -1U)
> +       if ((*iter)->simduid != -1U)
>           {
> -           tree decl = (*iter).decl;
> +           tree decl = (*iter)->decl;
>             int vf = 1;
>             if (simduid_to_vf_htab)
>               {
>                 simduid_to_vf *p = NULL, data;
> -               data.simduid = (*iter).simduid;
> +               data.simduid = (*iter)->simduid;
>                 p = simduid_to_vf_htab->find (&data);
>                 if (p)
>                   vf = p->vf;
> --
> 2.0.0
>

Reply via email to