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,

Reply via email to