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] Fix PR44871 C/C++ interoperability with LTO


This fixes the issue that we both emit an annoying warning about
mismatched types when you mix C and C++ with the same headers and
also makes sure we assign the same alias-sets to those types.

The patch builds on the split-out TYPE_CANONICAL computation code
(which still shares the main parts of the type hashing and merging
code) by also separating out the hash value by means of introducing
a separate hashtable to store it.

The idea is simple (and convincing) - for computing TYPE_CANONICAL
we shouldn't look at "names", in particular whether in the GIMPLE
IL you can assign a variable of type T to a variable of type T1
shouldn't depend on its name (or the name of a field), but it
should depend on things that might remotely have an effect on
generated code or type consistency.

Bootstrapped and tested on x86_64-unknown-linux-gnu, SPEC 2k6 tested,
LTO bootstrap in progress.

Ok for trunk if that succeeds?

Thanks,
Richard.

2010-11-29  Richard Guenther  <rguenther@suse.de>

	PR lto/44871
	* gimple.c (canonical_type_hash_cache): New hashtable.
	(gimple_type_hash): Make a wrapper around ...
	(gimple_type_hash_1): ... this.  Take gtc_mode argument.
	(gimple_canonical_type_hash): Likewise.
	(gtc_visit): Take a gtc_mode argument.
	(gimple_types_compatible_p_1): Likewise. Do not compare struct
	tag names or field names when computing canonical types.
	(gimple_types_compatible_p): Adjust.
	(visit): Take a gtc_mode argument.
	(iterative_hash_gimple_type): Likewise.  Do not hash struct tag
	names or field names when computing hashes of canonical types.
	(gimple_register_canonical_type): Use gimple_canonical_type_hash
	for the hash.
	(print_gimple_types_stats): Dump stats of canonical_type_hash_cache.
	(free_gimple_type_tables): Free canonical_type_hash_cache.

	* g++.dg/lto/20101126-1_0.C: New testcase.
	* g++.dg/lto/20101126-1_1.c: Likewise.

Index: gcc/testsuite/g++.dg/lto/20101126-1_0.C
===================================================================
*** gcc/testsuite/g++.dg/lto/20101126-1_0.C	(revision 0)
--- gcc/testsuite/g++.dg/lto/20101126-1_0.C	(revision 0)
***************
*** 0 ****
--- 1,5 ----
+ typedef struct { int i; } T1;
+ typedef T1 T2;
+ extern T1 a;
+ extern T2 b;
+ int main() { return a.i + b.i; }
Index: gcc/testsuite/g++.dg/lto/20101126-1_1.c
===================================================================
*** gcc/testsuite/g++.dg/lto/20101126-1_1.c	(revision 0)
--- gcc/testsuite/g++.dg/lto/20101126-1_1.c	(revision 0)
***************
*** 0 ****
--- 1,4 ----
+ typedef struct { int i; } T1;
+ typedef T1 T2;
+ T1 a;
+ T2 b;
Index: gcc/gimple.c
===================================================================
*** gcc/gimple.c	(revision 167235)
--- gcc/gimple.c	(working copy)
*************** static GTY((if_marked ("ggc_marked_p"),
*** 48,53 ****
--- 48,55 ----
    htab_t gimple_canonical_types;
  static GTY((if_marked ("tree_int_map_marked_p"), param_is (struct tree_int_map)))
    htab_t type_hash_cache;
+ static GTY((if_marked ("tree_int_map_marked_p"), param_is (struct tree_int_map)))
+   htab_t canonical_type_hash_cache;
  
  /* Global type comparison cache.  This is by TYPE_UID for space efficiency
     and thus cannot use and does not need GC.  */
*************** gimple_call_copy_skip_args (gimple stmt,
*** 3132,3138 ****
  }
  
  
! static hashval_t gimple_type_hash (const void *);
  
  /* Structure used to maintain a cache of some type pairs compared by
     gimple_types_compatible_p when comparing aggregate types.  There are
--- 3134,3140 ----
  }
  
  
! static hashval_t gimple_type_hash_1 (const void *, enum gtc_mode);
  
  /* Structure used to maintain a cache of some type pairs compared by
     gimple_types_compatible_p when comparing aggregate types.  There are
*************** gtc_visit (tree t1, tree t2, enum gtc_mo
*** 3475,3481 ****
    /* If the hash values of t1 and t2 are different the types can't
       possibly be the same.  This helps keeping the type-pair hashtable
       small, only tracking comparisons for hash collisions.  */
!   if (gimple_type_hash (t1) != gimple_type_hash (t2))
      return false;
  
    /* Allocate a new cache entry for this comparison.  */
--- 3477,3483 ----
    /* If the hash values of t1 and t2 are different the types can't
       possibly be the same.  This helps keeping the type-pair hashtable
       small, only tracking comparisons for hash collisions.  */
!   if (gimple_type_hash_1 (t1, mode) != gimple_type_hash_1 (t2, mode))
      return false;
  
    /* Allocate a new cache entry for this comparison.  */
*************** gimple_types_compatible_p_1 (tree t1, tr
*** 3758,3765 ****
  	tree f1, f2;
  
  	/* The struct tags shall compare equal.  */
! 	if (!compare_type_names_p (TYPE_MAIN_VARIANT (t1),
! 				   TYPE_MAIN_VARIANT (t2), false))
  	  goto different_types;
  
  	/* For aggregate types, all the fields must be the same.  */
--- 3760,3768 ----
  	tree f1, f2;
  
  	/* The struct tags shall compare equal.  */
! 	if (mode == GTC_MERGE
! 	    && !compare_type_names_p (TYPE_MAIN_VARIANT (t1),
! 				      TYPE_MAIN_VARIANT (t2), false))
  	  goto different_types;
  
  	/* For aggregate types, all the fields must be the same.  */
*************** gimple_types_compatible_p_1 (tree t1, tr
*** 3768,3774 ****
  	     f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
  	  {
  	    /* The fields must have the same name, offset and type.  */
! 	    if (DECL_NAME (f1) != DECL_NAME (f2)
  		|| DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
  		|| !gimple_compare_field_offset (f1, f2)
  		|| !gtc_visit (TREE_TYPE (f1), TREE_TYPE (f2), mode,
--- 3771,3778 ----
  	     f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
  	  {
  	    /* The fields must have the same name, offset and type.  */
! 	    if ((mode == GTC_MERGE
! 		 && DECL_NAME (f1) != DECL_NAME (f2))
  		|| DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
  		|| !gimple_compare_field_offset (f1, f2)
  		|| !gtc_visit (TREE_TYPE (f1), TREE_TYPE (f2), mode,
*************** gimple_types_compatible_p (tree t1, tree
*** 3911,3917 ****
    /* If the hash values of t1 and t2 are different the types can't
       possibly be the same.  This helps keeping the type-pair hashtable
       small, only tracking comparisons for hash collisions.  */
!   if (gimple_type_hash (t1) != gimple_type_hash (t2))
      return false;
  
    /* If we've visited this type pair before (in the case of aggregates
--- 3915,3921 ----
    /* If the hash values of t1 and t2 are different the types can't
       possibly be the same.  This helps keeping the type-pair hashtable
       small, only tracking comparisons for hash collisions.  */
!   if (gimple_type_hash_1 (t1, mode) != gimple_type_hash_1 (t2, mode))
      return false;
  
    /* If we've visited this type pair before (in the case of aggregates
*************** gimple_types_compatible_p (tree t1, tree
*** 3940,3946 ****
  
  static hashval_t
  iterative_hash_gimple_type (tree, hashval_t, VEC(tree, heap) **,
! 			    struct pointer_map_t *, struct obstack *);
  
  /* DFS visit the edge from the callers type with state *STATE to T.
     Update the callers type hash V with the hash for T if it is not part
--- 3944,3951 ----
  
  static hashval_t
  iterative_hash_gimple_type (tree, hashval_t, VEC(tree, heap) **,
! 			    struct pointer_map_t *, struct obstack *,
! 			    enum gtc_mode);
  
  /* DFS visit the edge from the callers type with state *STATE to T.
     Update the callers type hash V with the hash for T if it is not part
*************** static hashval_t
*** 3951,3957 ****
  visit (tree t, struct sccs *state, hashval_t v,
         VEC (tree, heap) **sccstack,
         struct pointer_map_t *sccstate,
!        struct obstack *sccstate_obstack)
  {
    struct sccs *cstate = NULL;
    struct tree_int_map m;
--- 3956,3962 ----
  visit (tree t, struct sccs *state, hashval_t v,
         VEC (tree, heap) **sccstack,
         struct pointer_map_t *sccstate,
!        struct obstack *sccstate_obstack, enum gtc_mode mode)
  {
    struct sccs *cstate = NULL;
    struct tree_int_map m;
*************** visit (tree t, struct sccs *state, hashv
*** 3960,3966 ****
    /* 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);
  
--- 3965,3973 ----
    /* 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 (mode == GTC_MERGE
! 			      ? type_hash_cache : canonical_type_hash_cache,
! 			      &m, NO_INSERT))
        && *slot)
      return iterative_hash_hashval_t (((struct tree_int_map *) *slot)->to, v);
  
*************** visit (tree t, struct sccs *state, hashv
*** 3971,3977 ****
        hashval_t tem;
        /* Not yet visited.  DFS recurse.  */
        tem = iterative_hash_gimple_type (t, v,
! 					sccstack, sccstate, sccstate_obstack);
        if (!cstate)
  	cstate = (struct sccs *)* pointer_map_contains (sccstate, t);
        state->low = MIN (state->low, cstate->low);
--- 3978,3985 ----
        hashval_t tem;
        /* Not yet visited.  DFS recurse.  */
        tem = iterative_hash_gimple_type (t, v,
! 					sccstack, sccstate, sccstate_obstack,
! 					mode);
        if (!cstate)
  	cstate = (struct sccs *)* pointer_map_contains (sccstate, t);
        state->low = MIN (state->low, cstate->low);
*************** static hashval_t
*** 4022,4028 ****
  iterative_hash_gimple_type (tree type, hashval_t val,
  			    VEC(tree, heap) **sccstack,
  			    struct pointer_map_t *sccstate,
! 			    struct obstack *sccstate_obstack)
  {
    hashval_t v;
    void **slot;
--- 4030,4037 ----
  iterative_hash_gimple_type (tree type, hashval_t val,
  			    VEC(tree, heap) **sccstack,
  			    struct pointer_map_t *sccstate,
! 			    struct obstack *sccstate_obstack,
! 			    enum gtc_mode mode)
  {
    hashval_t v;
    void **slot;
*************** iterative_hash_gimple_type (tree type, h
*** 4068,4078 ****
  	{
  	  v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v);
  	  v = iterative_hash_name
! 	      (TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (type))), v);
  	}
        else
  	v = visit (TREE_TYPE (type), state, v,
! 		   sccstack, sccstate, sccstate_obstack);
      }
  
    /* For integer types hash the types min/max values and the string flag.  */
--- 4077,4087 ----
  	{
  	  v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v);
  	  v = iterative_hash_name
! 		(TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (type))), v);
  	}
        else
  	v = visit (TREE_TYPE (type), state, v,
! 		   sccstack, sccstate, sccstate_obstack, mode);
      }
  
    /* For integer types hash the types min/max values and the string flag.  */
*************** iterative_hash_gimple_type (tree type, h
*** 4093,4099 ****
      {
        v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
        v = visit (TYPE_DOMAIN (type), state, v,
! 		 sccstack, sccstate, sccstate_obstack);
      }
  
    /* Recurse for aggregates with a single element type.  */
--- 4102,4108 ----
      {
        v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
        v = visit (TYPE_DOMAIN (type), state, v,
! 		 sccstack, sccstate, sccstate_obstack, mode);
      }
  
    /* Recurse for aggregates with a single element type.  */
*************** iterative_hash_gimple_type (tree type, h
*** 4101,4107 ****
        || TREE_CODE (type) == COMPLEX_TYPE
        || TREE_CODE (type) == VECTOR_TYPE)
      v = visit (TREE_TYPE (type), state, v,
! 	       sccstack, sccstate, sccstate_obstack);
  
    /* Incorporate function return and argument types.  */
    if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
--- 4110,4116 ----
        || TREE_CODE (type) == COMPLEX_TYPE
        || TREE_CODE (type) == VECTOR_TYPE)
      v = visit (TREE_TYPE (type), state, v,
! 	       sccstack, sccstate, sccstate_obstack, mode);
  
    /* Incorporate function return and argument types.  */
    if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
*************** iterative_hash_gimple_type (tree type, h
*** 4112,4129 ****
        /* For method types also incorporate their parent class.  */
        if (TREE_CODE (type) == METHOD_TYPE)
  	v = visit (TYPE_METHOD_BASETYPE (type), state, v,
! 		   sccstack, sccstate, sccstate_obstack);
  
        /* For result types allow mismatch in completeness.  */
        if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
  	{
  	  v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v);
  	  v = iterative_hash_name
! 	      (TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (type))), v);
  	}
        else
  	v = visit (TREE_TYPE (type), state, v,
! 		   sccstack, sccstate, sccstate_obstack);
  
        for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p))
  	{
--- 4121,4138 ----
        /* For method types also incorporate their parent class.  */
        if (TREE_CODE (type) == METHOD_TYPE)
  	v = visit (TYPE_METHOD_BASETYPE (type), state, v,
! 		   sccstack, sccstate, sccstate_obstack, mode);
  
        /* For result types allow mismatch in completeness.  */
        if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
  	{
  	  v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v);
  	  v = iterative_hash_name
! 		(TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (type))), v);
  	}
        else
  	v = visit (TREE_TYPE (type), state, v,
! 		   sccstack, sccstate, sccstate_obstack, mode);
  
        for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p))
  	{
*************** iterative_hash_gimple_type (tree type, h
*** 4132,4142 ****
  	    {
  	      v = iterative_hash_hashval_t (TREE_CODE (TREE_VALUE (p)), v);
  	      v = iterative_hash_name
! 		  (TYPE_NAME (TYPE_MAIN_VARIANT (TREE_VALUE (p))), v);
  	    }
  	  else
  	    v = visit (TREE_VALUE (p), state, v,
! 		       sccstack, sccstate, sccstate_obstack);
  	  na++;
  	}
  
--- 4141,4151 ----
  	    {
  	      v = iterative_hash_hashval_t (TREE_CODE (TREE_VALUE (p)), v);
  	      v = iterative_hash_name
! 		    (TYPE_NAME (TYPE_MAIN_VARIANT (TREE_VALUE (p))), v);
  	    }
  	  else
  	    v = visit (TREE_VALUE (p), state, v,
! 		       sccstack, sccstate, sccstate_obstack, mode);
  	  na++;
  	}
  
*************** iterative_hash_gimple_type (tree type, h
*** 4150,4162 ****
        unsigned nf;
        tree f;
  
!       v = iterative_hash_name (TYPE_NAME (TYPE_MAIN_VARIANT (type)), v);
  
        for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f))
  	{
! 	  v = iterative_hash_name (DECL_NAME (f), v);
  	  v = visit (TREE_TYPE (f), state, v,
! 		     sccstack, sccstate, sccstate_obstack);
  	  nf++;
  	}
  
--- 4159,4173 ----
        unsigned nf;
        tree f;
  
!       if (mode == GTC_MERGE)
! 	v = iterative_hash_name (TYPE_NAME (TYPE_MAIN_VARIANT (type)), v);
  
        for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f))
  	{
! 	  if (mode == GTC_MERGE)
! 	    v = iterative_hash_name (DECL_NAME (f), v);
  	  v = visit (TREE_TYPE (f), state, v,
! 		     sccstack, sccstate, sccstate_obstack, mode);
  	  nf++;
  	}
  
*************** iterative_hash_gimple_type (tree type, h
*** 4181,4187 ****
  	  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;
  	}
--- 4192,4200 ----
  	  cstate->on_sccstack = false;
  	  m->base.from = x;
  	  m->to = cstate->u.hash;
! 	  slot = htab_find_slot (mode == GTC_MERGE
! 				 ? type_hash_cache : canonical_type_hash_cache,
! 				 m, INSERT);
  	  gcc_assert (!*slot);
  	  *slot = (void *) m;
  	}
*************** iterative_hash_gimple_type (tree type, h
*** 4201,4207 ****
     types according to gimple_types_compatible_p.  */
  
  static hashval_t
! gimple_type_hash (const void *p)
  {
    const_tree t = (const_tree) p;
    VEC(tree, heap) *sccstack = NULL;
--- 4214,4220 ----
     types according to gimple_types_compatible_p.  */
  
  static hashval_t
! gimple_type_hash_1 (const void *p, enum gtc_mode mode)
  {
    const_tree t = (const_tree) p;
    VEC(tree, heap) *sccstack = NULL;
*************** gimple_type_hash (const void *p)
*** 4211,4222 ****
    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);
  
--- 4224,4242 ----
    void **slot;
    struct tree_int_map m;
  
!   if (mode == GTC_MERGE
!       && type_hash_cache == NULL)
      type_hash_cache = htab_create_ggc (512, tree_int_map_hash,
  				       tree_int_map_eq, NULL);
+   else if (mode == GTC_DIAG
+ 	   && canonical_type_hash_cache == NULL)
+     canonical_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 (mode == GTC_MERGE
! 			      ? type_hash_cache : canonical_type_hash_cache,
! 			      &m, NO_INSERT))
        && *slot)
      return iterative_hash_hashval_t (((struct tree_int_map *) *slot)->to, 0);
  
*************** gimple_type_hash (const void *p)
*** 4225,4231 ****
    sccstate = pointer_map_create ();
    gcc_obstack_init (&sccstate_obstack);
    val = iterative_hash_gimple_type (CONST_CAST_TREE (t), 0,
! 				    &sccstack, sccstate, &sccstate_obstack);
    VEC_free (tree, heap, sccstack);
    pointer_map_destroy (sccstate);
    obstack_free (&sccstate_obstack, NULL);
--- 4245,4252 ----
    sccstate = pointer_map_create ();
    gcc_obstack_init (&sccstate_obstack);
    val = iterative_hash_gimple_type (CONST_CAST_TREE (t), 0,
! 				    &sccstack, sccstate, &sccstate_obstack,
! 				    mode);
    VEC_free (tree, heap, sccstack);
    pointer_map_destroy (sccstate);
    obstack_free (&sccstate_obstack, NULL);
*************** gimple_type_hash (const void *p)
*** 4233,4238 ****
--- 4254,4271 ----
    return val;
  }
  
+ static hashval_t
+ gimple_type_hash (const void *p)
+ {
+   return gimple_type_hash_1 (p, GTC_MERGE);
+ }
+ 
+ static hashval_t
+ gimple_canonical_type_hash (const void *p)
+ {
+   return gimple_type_hash_1 (p, GTC_DIAG);
+ }
+ 
  
  /* Returns nonzero if P1 and P2 are equal.  */
  
*************** gimple_register_canonical_type (tree t)
*** 4400,4406 ****
      gimple_register_canonical_type (TYPE_MAIN_VARIANT (t));
  
    if (gimple_canonical_types == NULL)
!     gimple_canonical_types = htab_create_ggc (16381, gimple_type_hash,
  					      gimple_canonical_type_eq, 0);
  
    slot = htab_find_slot (gimple_canonical_types, t, INSERT);
--- 4433,4439 ----
      gimple_register_canonical_type (TYPE_MAIN_VARIANT (t));
  
    if (gimple_canonical_types == NULL)
!     gimple_canonical_types = htab_create_ggc (16381, gimple_canonical_type_hash,
  					      gimple_canonical_type_eq, 0);
  
    slot = htab_find_slot (gimple_canonical_types, t, INSERT);
*************** print_gimple_types_stats (void)
*** 4440,4445 ****
--- 4473,4488 ----
  	     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 (gimple_canonical_types)
      fprintf (stderr, "GIMPLE canonical type table: size %ld, %ld elements, "
  	     "%ld searches, %ld collisions (ratio: %f)\n",
*************** print_gimple_types_stats (void)
*** 4450,4465 ****
  	     htab_collisions (gimple_canonical_types));
    else
      fprintf (stderr, "GIMPLE canonical 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",
--- 4493,4508 ----
  	     htab_collisions (gimple_canonical_types));
    else
      fprintf (stderr, "GIMPLE canonical type table is empty\n");
!   if (canonical_type_hash_cache)
!     fprintf (stderr, "GIMPLE canonical type hash table: size %ld, %ld elements, "
  	     "%ld searches, %ld collisions (ratio: %f)\n",
! 	     (long) htab_size (canonical_type_hash_cache),
! 	     (long) htab_elements (canonical_type_hash_cache),
! 	     (long) canonical_type_hash_cache->searches,
! 	     (long) canonical_type_hash_cache->collisions,
! 	     htab_collisions (canonical_type_hash_cache));
    else
!     fprintf (stderr, "GIMPLE canonical 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)
*** 4496,4501 ****
--- 4539,4549 ----
        htab_delete (type_hash_cache);
        type_hash_cache = NULL;
      }
+   if (canonical_type_hash_cache)
+     {
+       htab_delete (canonical_type_hash_cache);
+       canonical_type_hash_cache = NULL;
+     }
    if (gtc_visited)
      {
        htab_delete (gtc_visited);


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