On Mon, May 2, 2011 at 4:38 PM, Richard Guenther
<richard.guent...@gmail.com> wrote:
> On Mon, May 2, 2011 at 4:16 PM, Jan Hubicka <hubi...@ucw.cz> wrote:
>> 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;
>
> If you skip node_map you can end up with false entries for re-used
> trees.  So I don't think that's a good idea.

Or we can safely mark the whole struct as non-GC (and also allocate
it that way).

Richard.

> Richard.
>
>>
>>    /* The nodes pickled so far.  */
>>    VEC(tree,heap) *nodes;
>>
>

Reply via email to