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;