Hi,
according to oprofile, libiberty hashing takes about 30% of streaming in time
and according to callgrind, the most busy cache is node_map cache in the
streamer.

This patch turns it into pointer-map that also saves about 400MB of memory
and is bit prettier.  I get about 8-10% speedup on Mozilla streaming.
There are other uses of tree_int map, I could probably convert them, too.

Bootstrapped/regtested x86_64-linux, OK?

Honza

        * lto-streamer.c (lto_streamer_cache_insert_1,
        lto_streamer_cache_lookup, lto_streamer_cache_create,
        lto_streamer_cache_delete): Use pointer map instead of hashtable.
        * lto-streamer.h (lto_streamer_cache_d): Turn node_map into pointer_map.
Index: lto-streamer.c
===================================================================
*** lto-streamer.c      (revision 173251)
--- lto-streamer.c      (working copy)
*************** lto_streamer_cache_insert_1 (struct lto_
*** 348,373 ****
                             bool insert_at_next_slot_p)
  {
    void **slot;
-   struct tree_int_map d_entry, *entry;
    unsigned ix;
    bool existed_p;
  
    gcc_assert (t);
  
!   d_entry.base.from = t;
!   slot = htab_find_slot (cache->node_map, &d_entry, INSERT);
!   if (*slot == NULL)
      {
        /* Determine the next slot to use in the cache.  */
        if (insert_at_next_slot_p)
        ix = VEC_length (tree, cache->nodes);
        else
        ix = *ix_p;
! 
!       entry = (struct tree_int_map *)pool_alloc (cache->node_map_entries);
!       entry->base.from = t;
!       entry->to = ix;
!       *slot = entry;
  
        lto_streamer_cache_add_to_node_array (cache, ix, t);
  
--- 348,367 ----
                             bool insert_at_next_slot_p)
  {
    void **slot;
    unsigned ix;
    bool existed_p;
  
    gcc_assert (t);
  
!   slot = pointer_map_insert (cache->node_map, t);
!   if (!*slot)
      {
        /* Determine the next slot to use in the cache.  */
        if (insert_at_next_slot_p)
        ix = VEC_length (tree, cache->nodes);
        else
        ix = *ix_p;
!        *slot = (void *)(size_t) (ix);
  
        lto_streamer_cache_add_to_node_array (cache, ix, t);
  
*************** lto_streamer_cache_insert_1 (struct lto_
*** 376,383 ****
      }
    else
      {
!       entry = (struct tree_int_map *) *slot;
!       ix = entry->to;
  
        if (!insert_at_next_slot_p && ix != *ix_p)
        {
--- 370,376 ----
      }
    else
      {
!       ix = (size_t) *slot;
  
        if (!insert_at_next_slot_p && ix != *ix_p)
        {
*************** lto_streamer_cache_lookup (struct lto_st
*** 442,455 ****
                           unsigned *ix_p)
  {
    void **slot;
-   struct tree_int_map d_slot;
    bool retval;
    unsigned ix;
  
    gcc_assert (t);
  
!   d_slot.base.from = t;
!   slot = htab_find_slot (cache->node_map, &d_slot, NO_INSERT);
    if (slot == NULL)
      {
        retval = false;
--- 435,446 ----
                           unsigned *ix_p)
  {
    void **slot;
    bool retval;
    unsigned ix;
  
    gcc_assert (t);
  
!   slot = pointer_map_contains  (cache->node_map, t);
    if (slot == NULL)
      {
        retval = false;
*************** lto_streamer_cache_lookup (struct lto_st
*** 458,464 ****
    else
      {
        retval = true;
!       ix = ((struct tree_int_map *) *slot)->to;
      }
  
    if (ix_p)
--- 449,455 ----
    else
      {
        retval = true;
!       ix = (size_t) *slot;
      }
  
    if (ix_p)
*************** lto_streamer_cache_create (void)
*** 608,618 ****
  
    cache = XCNEW (struct lto_streamer_cache_d);
  
!   cache->node_map = htab_create (101, tree_int_map_hash, tree_int_map_eq, 
NULL);
! 
!   cache->node_map_entries = create_alloc_pool ("node map",
!                                              sizeof (struct tree_int_map),
!                                              100);
  
    /* Load all the well-known tree nodes that are always created by
       the compiler on startup.  This prevents writing them out
--- 599,605 ----
  
    cache = XCNEW (struct lto_streamer_cache_d);
  
!   cache->node_map = pointer_map_create ();
  
    /* Load all the well-known tree nodes that are always created by
       the compiler on startup.  This prevents writing them out
*************** lto_streamer_cache_delete (struct lto_st
*** 636,643 ****
    if (c == NULL)
      return;
  
!   htab_delete (c->node_map);
!   free_alloc_pool (c->node_map_entries);
    VEC_free (tree, heap, c->nodes);
    free (c);
  }
--- 623,629 ----
    if (c == NULL)
      return;
  
!   pointer_map_destroy (c->node_map);
    VEC_free (tree, heap, c->nodes);
    free (c);
  }
Index: lto-streamer.h
===================================================================
*** lto-streamer.h      (revision 173251)
--- lto-streamer.h      (working copy)
*************** typedef void (lto_free_section_data_f) (
*** 346,355 ****
  struct lto_streamer_cache_d
  {
    /* The mapping between tree nodes and slots into the nodes array.  */
!   htab_t node_map;
! 
!   /* Node map to store entries into.  */
!   alloc_pool node_map_entries;
  
    /* The nodes pickled so far.  */
    VEC(tree,heap) *nodes;
--- 346,352 ----
  struct lto_streamer_cache_d
  {
    /* The mapping between tree nodes and slots into the nodes array.  */
!   struct pointer_map_t GTY((skip)) *node_map;
  
    /* The nodes pickled so far.  */
    VEC(tree,heap) *nodes;

Reply via email to