This makes us use a pointer-map for the hashtable in lto_tree_ref_encoder which avoids gazillion of malloc/free calls.
LTO bootstrapped on x86_64-unknown-linux-gnu, testing in progress. Richard. 2013-06-18 Richard Biener <rguent...@suse.de> * Makefile.in (LTO_STREAMER_H): Add pointer-set.h dependency. * lto-streamer.h: Include pointer-set.h. (struct lto_decl_slot): Remove. (struct lto_tree_ref_encoder): Make tree_hash_table a pointer-map. Remove next_index entry. (lto_hash_decl_slot_node, lto_eq_decl_slot_node, lto_hash_type_slot_node, lto_eq_type_slot_node): Remove. (lto_init_tree_ref_encoder): Adjust. (lto_destroy_tree_ref_encoder): Likewise. * lto-section-out.c (lto_hash_decl_slot_node, lto_eq_decl_slot_node, lto_hash_type_slot_node, lto_eq_type_slot_node): Remove. (lto_output_decl_index): Adjust. (lto_new_out_decl_state): Likewise. (lto_record_function_out_decl_state): Likewise. * lto-streamer-out.c (copy_function): Likewise. Index: gcc/lto-streamer.h =================================================================== *** gcc/lto-streamer.h (revision 200165) --- gcc/lto-streamer.h (working copy) *************** along with GCC; see the file COPYING3. *** 33,38 **** --- 33,39 ---- #include "alloc-pool.h" #include "gcov-io.h" #include "diagnostic.h" + #include "pointer-set.h" /* Define when debugging the LTO streamer. This causes the writer to output the numeric value for the memory address of the tree node *************** struct GTY(()) lto_tree_ref_table *** 474,494 **** }; - /* Mapping between trees and slots in an array. */ - struct lto_decl_slot - { - tree t; - int slot_num; - }; - - /* The lto_tree_ref_encoder struct is used to encode trees into indices. */ struct lto_tree_ref_encoder { ! htab_t tree_hash_table; /* Maps pointers to indices. */ ! unsigned int next_index; /* Next available index. */ ! vec<tree> trees; /* Maps indices to pointers. */ }; --- 475,486 ---- }; /* The lto_tree_ref_encoder struct is used to encode trees into indices. */ struct lto_tree_ref_encoder { ! pointer_map_t *tree_hash_table; /* Maps pointers to indices. */ ! vec<tree> trees; /* Maps indices to pointers. */ }; *************** extern void lto_value_range_error (const *** 788,797 **** HOST_WIDE_INT) ATTRIBUTE_NORETURN; /* In lto-section-out.c */ - extern hashval_t lto_hash_decl_slot_node (const void *); - extern int lto_eq_decl_slot_node (const void *, const void *); - extern hashval_t lto_hash_type_slot_node (const void *); - extern int lto_eq_type_slot_node (const void *, const void *); extern void lto_begin_section (const char *, bool); extern void lto_end_section (void); extern void lto_write_stream (struct lto_output_stream *); --- 780,785 ---- *************** lto_tag_check_range (enum LTO_tags actua *** 1007,1017 **** /* Initialize an lto_out_decl_buffer ENCODER. */ static inline void ! lto_init_tree_ref_encoder (struct lto_tree_ref_encoder *encoder, ! htab_hash hash_fn, htab_eq eq_fn) { ! encoder->tree_hash_table = htab_create (37, hash_fn, eq_fn, free); ! encoder->next_index = 0; encoder->trees.create (0); } --- 995,1003 ---- /* Initialize an lto_out_decl_buffer ENCODER. */ static inline void ! lto_init_tree_ref_encoder (struct lto_tree_ref_encoder *encoder) { ! encoder->tree_hash_table = pointer_map_create (); encoder->trees.create (0); } *************** lto_destroy_tree_ref_encoder (struct lto *** 1023,1029 **** { /* Hash table may be delete already. */ if (encoder->tree_hash_table) ! htab_delete (encoder->tree_hash_table); encoder->trees.release (); } --- 1009,1015 ---- { /* Hash table may be delete already. */ if (encoder->tree_hash_table) ! pointer_map_destroy (encoder->tree_hash_table); encoder->trees.release (); } Index: gcc/lto-section-out.c =================================================================== *** gcc/lto-section-out.c (revision 200165) --- gcc/lto-section-out.c (working copy) *************** static vec<lto_out_decl_state_ptr> decl_ *** 48,107 **** generate the decl directory later. */ vec<lto_out_decl_state_ptr> lto_function_decl_states; - /* Returns a hash code for P. */ - - hashval_t - lto_hash_decl_slot_node (const void *p) - { - const struct lto_decl_slot *ds = (const struct lto_decl_slot *) p; - - /* - return (hashval_t) DECL_UID (ds->t); - */ - return (hashval_t) TREE_HASH (ds->t); - } - - - /* Returns nonzero if P1 and P2 are equal. */ - - int - lto_eq_decl_slot_node (const void *p1, const void *p2) - { - const struct lto_decl_slot *ds1 = - (const struct lto_decl_slot *) p1; - const struct lto_decl_slot *ds2 = - (const struct lto_decl_slot *) p2; - - /* - return DECL_UID (ds1->t) == DECL_UID (ds2->t); - */ - return ds1->t == ds2->t; - } - - - /* Returns a hash code for P. */ - - hashval_t - lto_hash_type_slot_node (const void *p) - { - const struct lto_decl_slot *ds = (const struct lto_decl_slot *) p; - return (hashval_t) TYPE_UID (ds->t); - } - /* Returns nonzero if P1 and P2 are equal. */ - - int - lto_eq_type_slot_node (const void *p1, const void *p2) - { - const struct lto_decl_slot *ds1 = - (const struct lto_decl_slot *) p1; - const struct lto_decl_slot *ds2 = - (const struct lto_decl_slot *) p2; - - return TYPE_UID (ds1->t) == TYPE_UID (ds2->t); - } - /***************************************************************************** Output routines shared by all of the serialization passes. *****************************************************************************/ --- 48,55 ---- *************** lto_output_decl_index (struct lto_output *** 278,306 **** tree name, unsigned int *this_index) { void **slot; - struct lto_decl_slot d_slot; int index; bool new_entry_p = FALSE; ! d_slot.t = name; ! slot = htab_find_slot (encoder->tree_hash_table, &d_slot, INSERT); if (*slot == NULL) { ! struct lto_decl_slot *new_slot ! = (struct lto_decl_slot *) xmalloc (sizeof (struct lto_decl_slot)); ! index = encoder->next_index++; ! ! new_slot->t = name; ! new_slot->slot_num = index; ! *slot = new_slot; encoder->trees.safe_push (name); new_entry_p = TRUE; } else ! { ! struct lto_decl_slot *old_slot = (struct lto_decl_slot *)*slot; ! index = old_slot->slot_num; ! } if (obs) streamer_write_uhwi_stream (obs, index); --- 234,252 ---- tree name, unsigned int *this_index) { void **slot; int index; bool new_entry_p = FALSE; ! slot = pointer_map_insert (encoder->tree_hash_table, name); if (*slot == NULL) { ! index = encoder->trees.length (); ! *slot = (void *)(uintptr_t) index; encoder->trees.safe_push (name); new_entry_p = TRUE; } else ! index = (uintptr_t) *slot; if (obs) streamer_write_uhwi_stream (obs, index); *************** lto_new_out_decl_state (void) *** 440,462 **** { struct lto_out_decl_state *state = XCNEW (struct lto_out_decl_state); int i; - htab_hash hash_fn; - htab_eq eq_fn; for (i = 0; i < LTO_N_DECL_STREAMS; i++) ! { ! if (i == LTO_DECL_STREAM_TYPE) ! { ! hash_fn = lto_hash_type_slot_node; ! eq_fn = lto_eq_type_slot_node; ! } ! else ! { ! hash_fn = lto_hash_decl_slot_node; ! eq_fn = lto_eq_decl_slot_node; ! } ! lto_init_tree_ref_encoder (&state->streams[i], hash_fn, eq_fn); ! } return state; } --- 386,394 ---- { struct lto_out_decl_state *state = XCNEW (struct lto_out_decl_state); int i; for (i = 0; i < LTO_N_DECL_STREAMS; i++) ! lto_init_tree_ref_encoder (&state->streams[i]); return state; } *************** lto_record_function_out_decl_state (tree *** 514,520 **** for (i = 0; i < LTO_N_DECL_STREAMS; i++) if (state->streams[i].tree_hash_table) { ! htab_delete (state->streams[i].tree_hash_table); state->streams[i].tree_hash_table = NULL; } state->fn_decl = fn_decl; --- 446,452 ---- for (i = 0; i < LTO_N_DECL_STREAMS; i++) if (state->streams[i].tree_hash_table) { ! pointer_map_destroy (state->streams[i].tree_hash_table); state->streams[i].tree_hash_table = NULL; } state->fn_decl = fn_decl; Index: gcc/lto-streamer-out.c =================================================================== *** gcc/lto-streamer-out.c (revision 200165) --- gcc/lto-streamer-out.c (working copy) *************** copy_function (struct cgraph_node *node) *** 1922,1930 **** So just copy the vector. All the encoders in the in state must be empty where we reach here. */ gcc_assert (lto_tree_ref_encoder_size (encoder) == 0); for (j = 0; j < n; j++) encoder->trees.safe_push (trees[j]); - encoder->next_index = n; } lto_free_section_data (file_data, LTO_section_function_body, name, --- 1922,1930 ---- So just copy the vector. All the encoders in the in state must be empty where we reach here. */ gcc_assert (lto_tree_ref_encoder_size (encoder) == 0); + encoder->trees.reserve_exact (n); for (j = 0; j < n; j++) encoder->trees.safe_push (trees[j]); } lto_free_section_data (file_data, LTO_section_function_body, name,