This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Re-enable ggc-collect during LTO streaming


This re-enables ggc-collecting during LTO-in streaming by moving the
type hash and table to GC memory.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2010-09-08  Richard Guenther  <rguenther@suse.de>

	* gimple.c (gimple_types, type_hash_cache): Move to GC memory.
	(visit): Adjust.
	(iterative_hash_gimple_type): Likewise.
	(gimple_type_hash): Likewise.
	(gimple_register_type): Likewise.
	(print_gimple_types_stats): Likewise.
	(free_gimple_type_tables): Likewise.

	lto/
	* lto.c (read_cgraph_and_symbols): Collect again after each
	file.

Index: gcc/gimple.c
===================================================================
*** gcc/gimple.c.orig	2010-09-08 11:30:18.000000000 +0200
--- gcc/gimple.c	2010-09-08 12:58:49.000000000 +0200
*************** along with GCC; see the file COPYING3.
*** 36,50 ****
  #include "flags.h"
  #include "alias.h"
  #include "demangle.h"
  
  /* Global type table.  FIXME lto, it should be possible to re-use some
     of the type hashing routines in tree.c (type_hash_canon, type_hash_lookup,
     etc), but those assume that types were built with the various
     build_*_type routines which is not the case with the streamer.  */
! static htab_t gimple_types;
! static struct pointer_map_t *type_hash_cache;
  
! /* Global type comparison cache.  */
  static htab_t gtc_visited;
  static struct obstack gtc_ob;
  
--- 36,54 ----
  #include "flags.h"
  #include "alias.h"
  #include "demangle.h"
+ #include "langhooks.h"
  
  /* Global type table.  FIXME lto, it should be possible to re-use some
     of the type hashing routines in tree.c (type_hash_canon, type_hash_lookup,
     etc), but those assume that types were built with the various
     build_*_type routines which is not the case with the streamer.  */
! static GTY((if_marked ("ggc_marked_p"), param_is (union tree_node)))
!   htab_t gimple_types;
! static GTY((if_marked ("tree_int_map_marked_p"), param_is (struct tree_int_map)))
!   htab_t type_hash_cache;
  
! /* Global type comparison cache.  This is by TYPE_UID for space efficiency
!    and thus cannot use and does not need GC.  */
  static htab_t gtc_visited;
  static struct obstack gtc_ob;
  
*************** visit (tree t, struct sccs *state, hashv
*** 3916,3927 ****
         struct obstack *sccstate_obstack)
  {
    struct sccs *cstate = NULL;
    void **slot;
  
    /* If there is a hash value recorded for this type then it can't
       possibly be part of our parent SCC.  Simply mix in its hash.  */
!   if ((slot = pointer_map_contains (type_hash_cache, t)))
!     return iterative_hash_hashval_t ((hashval_t) (size_t) *slot, v);
  
    if ((slot = pointer_map_contains (sccstate, t)) != NULL)
      cstate = (struct sccs *)*slot;
--- 3920,3934 ----
         struct obstack *sccstate_obstack)
  {
    struct sccs *cstate = NULL;
+   struct tree_int_map m;
    void **slot;
  
    /* If there is a hash value recorded for this type then it can't
       possibly be part of our parent SCC.  Simply mix in its hash.  */
!   m.base.from = t;
!   if ((slot = htab_find_slot (type_hash_cache, &m, NO_INSERT))
!       && *slot)
!     return iterative_hash_hashval_t (((struct tree_int_map *) *slot)->to, v);
  
    if ((slot = pointer_map_contains (sccstate, t)) != NULL)
      cstate = (struct sccs *)*slot;
*************** iterative_hash_gimple_type (tree type, h
*** 3988,3996 ****
    struct sccs *state;
  
  #ifdef ENABLE_CHECKING
!   /* Not visited during this DFS walk nor during previous walks.  */
!   gcc_assert (!pointer_map_contains (type_hash_cache, type)
! 	      && !pointer_map_contains (sccstate, type));
  #endif
    state = XOBNEW (sccstate_obstack, struct sccs);
    *pointer_map_insert (sccstate, type) = state;
--- 3995,4002 ----
    struct sccs *state;
  
  #ifdef ENABLE_CHECKING
!   /* Not visited during this DFS walk.  */
!   gcc_assert (!pointer_map_contains (sccstate, type));
  #endif
    state = XOBNEW (sccstate_obstack, struct sccs);
    *pointer_map_insert (sccstate, type) = state;
*************** iterative_hash_gimple_type (tree type, h
*** 4137,4148 ****
        do
  	{
  	  struct sccs *cstate;
  	  x = VEC_pop (tree, *sccstack);
- 	  gcc_assert (!pointer_map_contains (type_hash_cache, x));
  	  cstate = (struct sccs *)*pointer_map_contains (sccstate, x);
  	  cstate->on_sccstack = false;
! 	  slot = pointer_map_insert (type_hash_cache, x);
! 	  *slot = (void *) (size_t) cstate->u.hash;
  	}
        while (x != type);
      }
--- 4143,4157 ----
        do
  	{
  	  struct sccs *cstate;
+ 	  struct tree_int_map *m = ggc_alloc_cleared_tree_int_map ();
  	  x = VEC_pop (tree, *sccstack);
  	  cstate = (struct sccs *)*pointer_map_contains (sccstate, x);
  	  cstate->on_sccstack = false;
! 	  m->base.from = x;
! 	  m->to = cstate->u.hash;
! 	  slot = htab_find_slot (type_hash_cache, m, INSERT);
! 	  gcc_assert (!*slot);
! 	  *slot = (void *) m;
  	}
        while (x != type);
      }
*************** gimple_type_hash (const void *p)
*** 4168,4179 ****
    struct obstack sccstate_obstack;
    hashval_t val;
    void **slot;
  
    if (type_hash_cache == NULL)
!     type_hash_cache = pointer_map_create ();
  
!   if ((slot = pointer_map_contains (type_hash_cache, p)) != NULL)
!     return iterative_hash_hashval_t ((hashval_t) (size_t) *slot, 0);
  
    /* Perform a DFS walk and pre-hash all reachable types.  */
    next_dfs_num = 1;
--- 4177,4192 ----
    struct obstack sccstate_obstack;
    hashval_t val;
    void **slot;
+   struct tree_int_map m;
  
    if (type_hash_cache == NULL)
!     type_hash_cache = htab_create_ggc (512, tree_int_map_hash,
! 				       tree_int_map_eq, NULL);
  
!   m.base.from = CONST_CAST_TREE (t);
!   if ((slot = htab_find_slot (type_hash_cache, &m, NO_INSERT))
!       && *slot)
!     return iterative_hash_hashval_t (((struct tree_int_map *) *slot)->to, 0);
  
    /* Perform a DFS walk and pre-hash all reachable types.  */
    next_dfs_num = 1;
*************** gimple_register_type (tree t)
*** 4226,4232 ****
      gimple_register_type (TYPE_MAIN_VARIANT (t));
  
    if (gimple_types == NULL)
!     gimple_types = htab_create (16381, gimple_type_hash, gimple_type_eq, 0);
  
    slot = htab_find_slot (gimple_types, t, INSERT);
    if (*slot
--- 4239,4245 ----
      gimple_register_type (TYPE_MAIN_VARIANT (t));
  
    if (gimple_types == NULL)
!     gimple_types = htab_create_ggc (16381, gimple_type_hash, gimple_type_eq, 0);
  
    slot = htab_find_slot (gimple_types, t, INSERT);
    if (*slot
*************** print_gimple_types_stats (void)
*** 4312,4317 ****
--- 4325,4340 ----
  	     htab_collisions (gimple_types));
    else
      fprintf (stderr, "GIMPLE type table is empty\n");
+   if (type_hash_cache)
+     fprintf (stderr, "GIMPLE type hash table: size %ld, %ld elements, "
+ 	     "%ld searches, %ld collisions (ratio: %f)\n",
+ 	     (long) htab_size (type_hash_cache),
+ 	     (long) htab_elements (type_hash_cache),
+ 	     (long) type_hash_cache->searches,
+ 	     (long) type_hash_cache->collisions,
+ 	     htab_collisions (type_hash_cache));
+   else
+     fprintf (stderr, "GIMPLE type hash table is empty\n");
    if (gtc_visited)
      fprintf (stderr, "GIMPLE type comparison table: size %ld, %ld "
  	     "elements, %ld searches, %ld collisions (ratio: %f)\n",
*************** free_gimple_type_tables (void)
*** 4340,4346 ****
      }
    if (type_hash_cache)
      {
!       pointer_map_destroy (type_hash_cache);
        type_hash_cache = NULL;
      }
    if (gtc_visited)
--- 4363,4369 ----
      }
    if (type_hash_cache)
      {
!       htab_delete (type_hash_cache);
        type_hash_cache = NULL;
      }
    if (gtc_visited)
Index: gcc/lto/lto.c
===================================================================
*** gcc/lto/lto.c.orig	2010-09-07 18:41:54.000000000 +0200
--- gcc/lto/lto.c	2010-09-08 12:52:05.000000000 +0200
*************** read_cgraph_and_symbols (unsigned nfiles
*** 1789,1796 ****
  
        lto_obj_file_close (current_lto_file);
        current_lto_file = NULL;
!       /* ???  We'd want but can't ggc_collect () here as the type merging
!          code in gimple.c uses hashtables that are not ggc aware.  */
      }
  
    lto_flatten_files (decl_data, count, last_file_ix);
--- 1789,1795 ----
  
        lto_obj_file_close (current_lto_file);
        current_lto_file = NULL;
!       ggc_collect ();
      }
  
    lto_flatten_files (decl_data, count, last_file_ix);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]