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][LTO] Fix PR41576, hide gimple_types_compatible_p better


This patch fixes PR41576 and on the way does multiple things:

 - free the various hashtables we fill during type merging.  We can do
   so after the cgraph and functions are materialized

 - Make gimple_types_compatible_p a internal function with an extra
   mode that can be used during symbol merging via the new
   gimple_types_structurally_equivalent_p that identifies layout
   compatible types that we still can't merge.

 - Make the symtab merger use gimple_types_structurally_equivalent_p
   when deciding to when to emit a warning and simplify code in there
   somewhat.

It's already big enough - in a followup I will try to reduce the
excessive amount of warnings we create for actual mismatches by
delaying these warnings.  Currently there are O(n^2) warnings with
n translation units.  For example zeusmp has float vs. double
mismatches and we print

pressure.f:139:0: warning: type of 'erfloor' does not match original 
declaration
printd.f:281:0: note: previously declared here
pdv_d.f:165:0: warning: type of 'erfloor' does not match original 
declaration
pressure.f:139:0: note: previously declared here
pdv.f:153:0: warning: type of 'erfloor' does not match original 
declaration
pressure.f:139:0: note: previously declared here
nudt.f:311:0: warning: type of 'erfloor' does not match original 
declaration
pressure.f:139:0: note: previously declared here
newdt.f:233:0: warning: type of 'erfloor' does not match original 
declaration
pressure.f:139:0: note: previously declared here
mstart.f:136:0: warning: type of 'erfloor' does not match original 
declaration
pressure.f:139:0: note: previously declared here
...

How do we want to present a warning that in units {A,B,C} the
type is float while in units {D,E,F} it is double?  Is it enough
to pick one pair and say Type in A does not match type in F?

Bootstrapped and tested on x86_64-unknown-linux-gnu, ok?

Thanks,
Richard.

2009-10-06  Richard Guenther  <rguenther@suse.de>

	PR lto/41576
	* gimple.c (gtse_visited): New global.
	(gimple_force_type_merge): Force equivalence in gtse_visited.
	(gimple_types_compatible_p): Rename to ...
	(compare_and_maybe_complete_types): ... this, make it a static
	worker also implementing a structural comparison mode.
	(gimple_types_structurally_equivalent_p): New function.
	(gimple_type_eq): Use compare_and_maybe_complete_types.
	(print_gimple_types_stats): Rename to ...
	(free_gimple_type_tables): ... this.  Also free the type
	merging hash tables.
	* gimple.h (gimple_types_compatible_p): Remove.
	(gimple_types_structurally_equivalent_p): Declare.
	(print_gimple_types_stats): Remove.
	(free_gimple_type_tables): Declare.
	* lto-streamer.c (print_lto_report): Do not call
	print_gimple_types_stats.
	* lto-symtab.c (merge_incomplete_and_complete_type): Use
	gimple_types_structurally_equivalent_p.
	(maybe_merge_incomplete_and_complete_type): Simplify.
	(lto_symtab_compatible): Use gimple_types_structurally_equivalent_p.
	Simplify and properly fixup types we complete or forcefully merge.
	Complain only about structurally incompatible types and provide
	a simple TBAA fixup for others.
	(lto_symtab_prevailing_decl): Use
	gimple_types_structurally_equivalent_p.

	lto/
	* lto.c (lto_main): Free the gimple type merging hash tables.

	* gfortran.dg/lto/20091005-1_0.f90: New testcase.
	* gfortran.dg/lto/20091005-1_1.f90: Likewise.
	* gcc.dg/lto/20091006-2_0.c: Likewise.
	* gcc.dg/lto/20091006-2_1.c: Likewise.
	* gcc.dg/lto/20091006-2_2.c: Likewise.

Index: trunk/gcc/testsuite/gfortran.dg/lto/20091005-1_0.f90
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gfortran.dg/lto/20091005-1_0.f90	2009-10-06 14:19:25.000000000 +0200
***************
*** 0 ****
--- 1,7 ----
+ ! { dg-lto-do run }
+ subroutine foo
+   common /bar/ a, b
+   integer(4) :: a ,b
+   a = 1
+   b = 2
+ end
Index: trunk/gcc/testsuite/gfortran.dg/lto/20091005-1_1.f90
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gfortran.dg/lto/20091005-1_1.f90	2009-10-06 14:19:25.000000000 +0200
***************
*** 0 ****
--- 1,6 ----
+ program test
+   common /bar/ c, d
+   integer(4) :: c, d
+   call foo
+   if (c/=1 .or. d/=2) call abort
+ end program test
Index: trunk/gcc/gimple.c
===================================================================
*** trunk.orig/gcc/gimple.c	2009-10-06 14:15:42.000000000 +0200
--- trunk/gcc/gimple.c	2009-10-06 14:57:51.000000000 +0200
*************** static struct pointer_map_t *type_hash_c
*** 46,51 ****
--- 46,52 ----
  
  /* Global type comparison cache.  */
  static htab_t gtc_visited;
+ static htab_t gtse_visited;
  
  /* All the tuples have their operand vector (if present) at the very bottom
     of the structure.  Therefore, the offset required to find the
*************** gimple_force_type_merge (tree t1, tree t
*** 3112,3117 ****
--- 3113,3120 ----
       they now compare compatible.  */
    p = lookup_type_pair (t1, t2, &gtc_visited);
    p->same_p = 1;
+   p = lookup_type_pair (t1, t2, &gtse_visited);
+   p->same_p = 1;
  }
  
  
*************** compare_field_offset (tree f1, tree f2)
*** 3184,3194 ****
    return false;
  }
  
! /* Return 1 iff T1 and T2 are structurally identical.
!    Otherwise, return 0.  */
  
! int
! gimple_types_compatible_p (tree t1, tree t2)
  {
    type_pair_t p = NULL;
  
--- 3187,3199 ----
    return false;
  }
  
! /* If STRUCTURALLY_P is false return 1 iff T1 and T2 are identical.
!    If STRUCTURALLY_P is true return 1 iff T1 and T2 are structurally
!    identical.  Otherwise, return 0.  Use CACHE for caching queries.  */
  
! static int
! compare_and_maybe_complete_types (tree t1, tree t2,
! 				  bool structurally_p, htab_t *cache)
  {
    type_pair_t p = NULL;
  
*************** gimple_types_compatible_p (tree t1, tree
*** 3209,3226 ****
      goto same_types;
  
    /* Can't be the same type if they have different CV qualifiers.  */
!   if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
      goto different_types;
  
    /* 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 0;
  
    /* If we've visited this type pair before (in the case of aggregates
       with self-referential types), and we made a decision, return it.  */
!   p = lookup_type_pair (t1, t2, &gtc_visited);
    if (p->same_p == 0 || p->same_p == 1)
      {
        /* We have already decided whether T1 and T2 are the
--- 3214,3234 ----
      goto same_types;
  
    /* Can't be the same type if they have different CV qualifiers.  */
!   if (!structurally_p
!       && TYPE_QUALS (t1) != TYPE_QUALS (t2))
      goto different_types;
  
    /* 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.  For
!      structural comparison we can't use this trick though.  */
!   if (!structurally_p
!       && gimple_type_hash (t1) != gimple_type_hash (t2))
      return 0;
  
    /* If we've visited this type pair before (in the case of aggregates
       with self-referential types), and we made a decision, return it.  */
!   p = lookup_type_pair (t1, t2, cache);
    if (p->same_p == 0 || p->same_p == 1)
      {
        /* We have already decided whether T1 and T2 are the
*************** gimple_types_compatible_p (tree t1, tree
*** 3240,3246 ****
    p->same_p = -1;
  
    /* If their attributes are not the same they can't be the same type.  */
!   if (!attribute_list_equal (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2)))
      goto different_types;
  
    /* For numerical types, the bounds must coincide.  */
--- 3248,3255 ----
    p->same_p = -1;
  
    /* If their attributes are not the same they can't be the same type.  */
!   if (!structurally_p
!       && !attribute_list_equal (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2)))
      goto different_types;
  
    /* For numerical types, the bounds must coincide.  */
*************** gimple_types_compatible_p (tree t1, tree
*** 3261,3266 ****
--- 3270,3279 ----
  	  || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
  	goto different_types;
  
+       /* Structurally the types are now equivalent.  */
+       if (structurally_p)
+ 	goto same_types;
+ 
        /* For non-enumeral types, check type bounds.  FIXME lto, we
  	 cannot check bounds on enumeral types because different front
  	 ends will produce different values.  In C, enumeral types are
*************** gimple_types_compatible_p (tree t1, tree
*** 3314,3320 ****
      case ARRAY_TYPE:
        /* Array types are the same if the element types are the same and
  	 the number of elements are the same.  */
!       if (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))
  	  || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2))
  	goto different_types;
        else
--- 3327,3334 ----
      case ARRAY_TYPE:
        /* Array types are the same if the element types are the same and
  	 the number of elements are the same.  */
!       if (!compare_and_maybe_complete_types (TREE_TYPE (t1), TREE_TYPE (t2),
! 					     structurally_p, cache)
  	  || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2))
  	goto different_types;
        else
*************** gimple_types_compatible_p (tree t1, tree
*** 3355,3362 ****
  
      case METHOD_TYPE:
        /* Method types should belong to the same class.  */
!       if (!gimple_types_compatible_p (TYPE_METHOD_BASETYPE (t1),
! 				 TYPE_METHOD_BASETYPE (t2)))
  	goto different_types;
  
        /* Fallthru  */
--- 3369,3377 ----
  
      case METHOD_TYPE:
        /* Method types should belong to the same class.  */
!       if (!compare_and_maybe_complete_types (TYPE_METHOD_BASETYPE (t1),
! 					     TYPE_METHOD_BASETYPE (t2),
! 					     structurally_p, cache))
  	goto different_types;
  
        /* Fallthru  */
*************** gimple_types_compatible_p (tree t1, tree
*** 3364,3370 ****
      case FUNCTION_TYPE:
        /* Function types are the same if the return type and arguments types
  	 are the same.  */
!       if (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
  	goto different_types;
        else
  	{
--- 3379,3386 ----
      case FUNCTION_TYPE:
        /* Function types are the same if the return type and arguments types
  	 are the same.  */
!       if (!compare_and_maybe_complete_types (TREE_TYPE (t1), TREE_TYPE (t2),
! 					     structurally_p, cache))
  	goto different_types;
        else
  	{
*************** gimple_types_compatible_p (tree t1, tree
*** 3381,3388 ****
  		   parms1 && parms2;
  		   parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
  		{
! 		  if (!gimple_types_compatible_p (TREE_VALUE (parms1),
! 					     TREE_VALUE (parms2)))
  		    goto different_types;
  		}
  
--- 3397,3405 ----
  		   parms1 && parms2;
  		   parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
  		{
! 		  if (!compare_and_maybe_complete_types (TREE_VALUE (parms1),
! 							 TREE_VALUE (parms2),
! 							 structurally_p, cache))
  		    goto different_types;
  		}
  
*************** gimple_types_compatible_p (tree t1, tree
*** 3396,3401 ****
--- 3413,3423 ----
      case POINTER_TYPE:
      case REFERENCE_TYPE:
  	{
+ 	  /* If we compare types structurally all pointer types are
+ 	     compatible.  */
+ 	  if (structurally_p)
+ 	    goto same_types;
+ 
  	  /* If the two pointers have different ref-all attributes,
  	     they can't be the same type.  */
  	  if (TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
*************** gimple_types_compatible_p (tree t1, tree
*** 3416,3422 ****
  
  	  /* Otherwise, pointer and reference types are the same if the
  	     pointed-to types are the same.  */
! 	  if (gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
  	    goto same_types;
  	  
  	  goto different_types;
--- 3438,3445 ----
  
  	  /* Otherwise, pointer and reference types are the same if the
  	     pointed-to types are the same.  */
! 	  if (compare_and_maybe_complete_types (TREE_TYPE (t1), TREE_TYPE (t2),
! 						structurally_p, cache))
  	    goto same_types;
  	  
  	  goto different_types;
*************** gimple_types_compatible_p (tree t1, tree
*** 3468,3477 ****
  	       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)
  		  || !compare_field_offset (f1, f2)
! 		  || !gimple_types_compatible_p (TREE_TYPE (f1),
! 					    TREE_TYPE (f2)))
  		goto different_types;
  	    }
  
--- 3491,3502 ----
  	       f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
  	    {
  	      /* The fields must have the same name, offset and type.  */
! 	      if ((!structurally_p
! 		   && DECL_NAME (f1) != DECL_NAME (f2))
  		  || !compare_field_offset (f1, f2)
! 		  || !compare_and_maybe_complete_types (TREE_TYPE (f1),
! 							TREE_TYPE (f2),
! 							structurally_p, cache))
  		goto different_types;
  	    }
  
*************** gimple_types_compatible_p (tree t1, tree
*** 3489,3495 ****
  
        /* Fallthru  */
      case COMPLEX_TYPE:
!       if (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
  	goto different_types;
        goto same_types;
  
--- 3514,3521 ----
  
        /* Fallthru  */
      case COMPLEX_TYPE:
!       if (!compare_and_maybe_complete_types (TREE_TYPE (t1), TREE_TYPE (t2),
! 					     structurally_p, cache))
  	goto different_types;
        goto same_types;
  
*************** same_types:
*** 3510,3516 ****
--- 3536,3552 ----
    return 1;
  }
  
+ int
+ gimple_types_compatible_p (tree type1, tree type2)
+ {
+   return compare_and_maybe_complete_types (type1, type2, false, &gtc_visited);
+ }
  
+ int
+ gimple_types_structurally_equivalent_p (tree type1, tree type2)
+ {
+   return compare_and_maybe_complete_types (type1, type2, true, &gtse_visited);
+ }
  
  
  /* Per pointer state for the SCC finding.  The on_sccstack flag
*************** gimple_type_eq (const void *p1, const vo
*** 3801,3807 ****
  {
    const_tree t1 = (const_tree) p1;
    const_tree t2 = (const_tree) p2;
!   return gimple_types_compatible_p (CONST_CAST_TREE (t1), CONST_CAST_TREE (t2));
  }
  
  
--- 3837,3845 ----
  {
    const_tree t1 = (const_tree) p1;
    const_tree t2 = (const_tree) p2;
!   return compare_and_maybe_complete_types (CONST_CAST_TREE (t1),
! 					   CONST_CAST_TREE (t2),
! 					   false, &gtc_visited);
  }
  
  
*************** gimple_register_type (tree t)
*** 3883,3913 ****
  }
  
  
! /* Show statistics on references to the global type table gimple_types.  */
  
  void
! print_gimple_types_stats (void)
  {
    if (gimple_types)
!     fprintf (stderr, "GIMPLE type table: size %ld, %ld elements, "
! 	     "%ld searches, %ld collisions (ratio: %f)\n",
! 	     (long) htab_size (gimple_types),
! 	     (long) htab_elements (gimple_types),
! 	     (long) gimple_types->searches,
! 	     (long) gimple_types->collisions,
! 	     htab_collisions (gimple_types));
!   else
!     fprintf (stderr, "GIMPLE type table is empty\n");
    if (gtc_visited)
!     fprintf (stderr, "GIMPLE type comparison table: size %ld, %ld elements, "
! 	     "%ld searches, %ld collisions (ratio: %f)\n",
! 	     (long) htab_size (gtc_visited),
! 	     (long) htab_elements (gtc_visited),
! 	     (long) gtc_visited->searches,
! 	     (long) gtc_visited->collisions,
! 	     htab_collisions (gtc_visited));
!   else
!     fprintf (stderr, "GIMPLE type comparison table is empty\n");
  }
  
  
--- 3921,3985 ----
  }
  
  
! /* Free the gimple type hashtables used for LTO type merging.
!    Show statistics on references to the global type table gimple_types.  */
  
  void
! free_gimple_type_tables (void)
  {
+   if (flag_lto_report)
+     {
+       if (gimple_types)
+ 	fprintf (stderr, "GIMPLE type table: size %ld, %ld elements, "
+ 		 "%ld searches, %ld collisions (ratio: %f)\n",
+ 		 (long) htab_size (gimple_types),
+ 		 (long) htab_elements (gimple_types),
+ 		 (long) gimple_types->searches,
+ 		 (long) gimple_types->collisions,
+ 		 htab_collisions (gimple_types));
+       else
+ 	fprintf (stderr, "GIMPLE type table is empty\n");
+       if (gtc_visited)
+ 	fprintf (stderr, "GIMPLE type comparison table: size %ld, %ld "
+ 		 "elements, %ld searches, %ld collisions (ratio: %f)\n",
+ 		 (long) htab_size (gtc_visited),
+ 		 (long) htab_elements (gtc_visited),
+ 		 (long) gtc_visited->searches,
+ 		 (long) gtc_visited->collisions,
+ 		 htab_collisions (gtc_visited));
+       else
+ 	fprintf (stderr, "GIMPLE type comparison table is empty\n");
+       if (gtse_visited)
+ 	fprintf (stderr, "GIMPLE structural comparison table: size %ld, %ld "
+ 		 "elements, %ld searches, %ld collisions (ratio: %f)\n",
+ 		 (long) htab_size (gtse_visited),
+ 		 (long) htab_elements (gtse_visited),
+ 		 (long) gtse_visited->searches,
+ 		 (long) gtse_visited->collisions,
+ 		 htab_collisions (gtse_visited));
+       else
+ 	fprintf (stderr, "GIMPLE structural comparison table is empty\n");
+     }
    if (gimple_types)
!     {
!       htab_delete (gimple_types);
!       gimple_types = NULL;
!     }
!   if (type_hash_cache)
!     {
!       pointer_map_destroy (type_hash_cache);
!       type_hash_cache = NULL;
!     }
    if (gtc_visited)
!     {
!       htab_delete (gtc_visited);
!       gtc_visited = NULL;
!     }
!   if (gtse_visited)
!     {
!       htab_delete (gtse_visited);
!       gtse_visited = NULL;
!     }
  }
  
  
Index: trunk/gcc/gimple.h
===================================================================
*** trunk.orig/gcc/gimple.h	2009-10-06 14:15:42.000000000 +0200
--- trunk/gcc/gimple.h	2009-10-06 14:19:25.000000000 +0200
*************** extern tree get_call_expr_in (tree t);
*** 917,924 ****
  extern void recalculate_side_effects (tree);
  extern void gimple_force_type_merge (tree, tree);
  extern int gimple_types_compatible_p (tree, tree);
  extern tree gimple_register_type (tree);
! extern void print_gimple_types_stats (void);
  extern tree gimple_unsigned_type (tree);
  extern tree gimple_signed_type (tree);
  extern alias_set_type gimple_get_alias_set (tree);
--- 917,925 ----
  extern void recalculate_side_effects (tree);
  extern void gimple_force_type_merge (tree, tree);
  extern int gimple_types_compatible_p (tree, tree);
+ extern int gimple_types_structurally_equivalent_p (tree, tree);
  extern tree gimple_register_type (tree);
! extern void free_gimple_type_tables (void);
  extern tree gimple_unsigned_type (tree);
  extern tree gimple_signed_type (tree);
  extern alias_set_type gimple_get_alias_set (tree);
Index: trunk/gcc/lto-streamer.c
===================================================================
*** trunk.orig/gcc/lto-streamer.c	2009-10-06 14:15:42.000000000 +0200
--- trunk/gcc/lto-streamer.c	2009-10-06 14:19:25.000000000 +0200
*************** print_lto_report (void)
*** 196,202 ****
  	   lto_stats.num_function_bodies);
  
    fprintf (stderr, "[%s] ", s);
-   print_gimple_types_stats ();
  
    for (i = 0; i < NUM_TREE_CODES; i++)
      if (lto_stats.num_trees[i])
--- 196,201 ----
Index: trunk/gcc/lto-symtab.c
===================================================================
*** trunk.orig/gcc/lto-symtab.c	2009-10-06 14:15:42.000000000 +0200
--- trunk/gcc/lto-symtab.c	2009-10-06 14:19:25.000000000 +0200
*************** merge_incomplete_and_complete_type (tree
*** 122,129 ****
    if (TREE_CODE (incomplete) == ARRAY_TYPE
        && !maybe_merge_incomplete_and_complete_type (TREE_TYPE (incomplete),
  						    TREE_TYPE (complete))
!       && !gimple_types_compatible_p (TREE_TYPE (incomplete),
! 				     TREE_TYPE (complete)))
      return false;
  
    /* ??? Ideally we would do this by means of a common canonical type, but
--- 122,129 ----
    if (TREE_CODE (incomplete) == ARRAY_TYPE
        && !maybe_merge_incomplete_and_complete_type (TREE_TYPE (incomplete),
  						    TREE_TYPE (complete))
!       && !gimple_types_structurally_equivalent_p (TREE_TYPE (incomplete),
! 						  TREE_TYPE (complete)))
      return false;
  
    /* ??? Ideally we would do this by means of a common canonical type, but
*************** maybe_merge_incomplete_and_complete_type
*** 149,159 ****
      res = merge_incomplete_and_complete_type (type1, type2);
    else if (COMPLETE_TYPE_P (type1) && !COMPLETE_TYPE_P (type2))
      res = merge_incomplete_and_complete_type (type2, type1);
! 
!   /* Recurse on pointer targets.  */
!   if (!res
!       && POINTER_TYPE_P (type1)
!       && POINTER_TYPE_P (type2))
      res = maybe_merge_incomplete_and_complete_type (TREE_TYPE (type1),
  						    TREE_TYPE (type2));
  
--- 149,157 ----
      res = merge_incomplete_and_complete_type (type1, type2);
    else if (COMPLETE_TYPE_P (type1) && !COMPLETE_TYPE_P (type2))
      res = merge_incomplete_and_complete_type (type2, type1);
!   else if (POINTER_TYPE_P (type1)
! 	   && POINTER_TYPE_P (type2))
!     /* Recurse on pointer targets.  */
      res = maybe_merge_incomplete_and_complete_type (TREE_TYPE (type1),
  						    TREE_TYPE (type2));
  
*************** lto_symtab_compatible (tree old_decl, tr
*** 192,201 ****
  	}
      }
  
    if (TREE_CODE (new_decl) == FUNCTION_DECL)
      {
!       if (!gimple_types_compatible_p (TREE_TYPE (old_decl),
! 				      TREE_TYPE (new_decl)))
  	/* If we don't have a merged type yet...sigh.  The linker
  	   wouldn't complain if the types were mismatched, so we
  	   probably shouldn't either.  Just use the type from
--- 190,201 ----
  	}
      }
  
+   /* The types of both decls have been registered and merged already,
+      full compatibility equals to pointer equivalence now.  */
+ 
    if (TREE_CODE (new_decl) == FUNCTION_DECL)
      {
!       if (TREE_TYPE (old_decl) != TREE_TYPE (new_decl))
  	/* If we don't have a merged type yet...sigh.  The linker
  	   wouldn't complain if the types were mismatched, so we
  	   probably shouldn't either.  Just use the type from
*************** lto_symtab_compatible (tree old_decl, tr
*** 216,282 ****
       field names.  */
    old_type = TREE_TYPE (old_decl);
    new_type = TREE_TYPE (new_decl);
! 
!   if (DECL_EXTERNAL (old_decl) || DECL_EXTERNAL (new_decl))
!     maybe_merge_incomplete_and_complete_type (old_type, new_type);
!   else if (POINTER_TYPE_P (old_type)
! 	   && POINTER_TYPE_P (new_type))
!     maybe_merge_incomplete_and_complete_type (TREE_TYPE (old_type),
! 					      TREE_TYPE (new_type));
! 
!   /* For array types we have to accept external declarations with
!      different sizes than the actual definition (164.gzip).
!      ???  We could emit a warning here.  */
!   if (TREE_CODE (old_type) == TREE_CODE (new_type)
!       && TREE_CODE (old_type) == ARRAY_TYPE
!       && COMPLETE_TYPE_P (old_type)
!       && COMPLETE_TYPE_P (new_type)
!       && tree_int_cst_compare (TYPE_SIZE (old_type),
! 			       TYPE_SIZE (new_type)) != 0
!       && gimple_types_compatible_p (TREE_TYPE (old_type),
! 				    TREE_TYPE (new_type)))
!     {
!       /* If only one is external use the type of the non-external decl.
! 	 Else use the larger one and also adjust the decl size.
! 	 ???  Directional merging would allow us to simply pick the
! 	 larger one instead of rewriting it.  */
!       if (DECL_EXTERNAL (old_decl) ^ DECL_EXTERNAL (new_decl))
  	{
! 	  if (DECL_EXTERNAL (old_decl))
! 	    TREE_TYPE (old_decl) = new_type;
! 	  else if (DECL_EXTERNAL (new_decl))
! 	    TREE_TYPE (new_decl) = old_type;
  	}
!       else
  	{
! 	  if (tree_int_cst_compare (TYPE_SIZE (old_type),
! 				    TYPE_SIZE (new_type)) < 0)
  	    {
! 	      TREE_TYPE (old_decl) = new_type;
! 	      DECL_SIZE (old_decl) = DECL_SIZE (new_decl);
! 	      DECL_SIZE_UNIT (old_decl) = DECL_SIZE_UNIT (new_decl);
  	    }
  	  else
  	    {
! 	      TREE_TYPE (new_decl) = old_type;
! 	      DECL_SIZE (new_decl) = DECL_SIZE (old_decl);
! 	      DECL_SIZE_UNIT (new_decl) = DECL_SIZE_UNIT (old_decl);
  	    }
  	}
      }
  
!   /* We can tolerate differences in type qualification, the
!      qualification of the prevailing definition will prevail.  */
!   old_type = TYPE_MAIN_VARIANT (TREE_TYPE (old_decl));
!   new_type = TYPE_MAIN_VARIANT (TREE_TYPE (new_decl));
!   if (!gimple_types_compatible_p (old_type, new_type))
!     {
!       if (warning_at (DECL_SOURCE_LOCATION (new_decl), 0,
! 		      "type of %qD does not match original declaration",
! 		      new_decl))
! 	inform (DECL_SOURCE_LOCATION (old_decl),
! 		"previously declared here");
!       return false;
      }
  
    /* ???  We might want to emit a warning here if type qualification
--- 216,301 ----
       field names.  */
    old_type = TREE_TYPE (old_decl);
    new_type = TREE_TYPE (new_decl);
!   if (old_type != new_type)
!     {
!       bool res = false;
!       if (DECL_EXTERNAL (old_decl) || DECL_EXTERNAL (new_decl))
! 	res = maybe_merge_incomplete_and_complete_type (old_type, new_type);
!       else if (POINTER_TYPE_P (old_type)
! 	       && POINTER_TYPE_P (new_type))
! 	res = maybe_merge_incomplete_and_complete_type (TREE_TYPE (old_type),
! 							TREE_TYPE (new_type));
!       /* If we completed any type based on the symbol equivalency register
!          and apply the new equivalencies.  */
!       if (res)
  	{
! 	  TREE_TYPE (old_decl) = old_type = gimple_register_type (old_type);
! 	  TREE_TYPE (new_decl) = new_type = gimple_register_type (new_type);
  	}
! 
!       /* For array types we have to accept external declarations with
! 	 different sizes than the actual definition (164.gzip).
! 	 ???  We could emit a warning here.  */
!       if (TREE_CODE (old_type) == TREE_CODE (new_type)
! 	  && TREE_CODE (old_type) == ARRAY_TYPE
! 	  && COMPLETE_TYPE_P (old_type)
! 	  && COMPLETE_TYPE_P (new_type)
! 	  && tree_int_cst_compare (TYPE_SIZE (old_type),
! 				   TYPE_SIZE (new_type)) != 0
! 	  && gimple_types_structurally_equivalent_p (TREE_TYPE (old_type),
! 						     TREE_TYPE (new_type)))
  	{
! 	  /* If only one is external use the type of the non-external decl.
! 	     Else use the larger one and also adjust the decl size.
! 	     ???  Directional merging would allow us to simply pick the
! 	     larger one instead of rewriting it.  */
! 	  if (DECL_EXTERNAL (old_decl) ^ DECL_EXTERNAL (new_decl))
  	    {
! 	      if (DECL_EXTERNAL (old_decl))
! 		TREE_TYPE (old_decl) = old_type = new_type;
! 	      else if (DECL_EXTERNAL (new_decl))
! 		TREE_TYPE (new_decl) = new_type = old_type;
  	    }
  	  else
  	    {
! 	      if (tree_int_cst_compare (TYPE_SIZE (old_type),
! 					TYPE_SIZE (new_type)) < 0)
! 		{
! 		  TREE_TYPE (old_decl) = old_type = new_type;
! 		  DECL_SIZE (old_decl) = DECL_SIZE (new_decl);
! 		  DECL_SIZE_UNIT (old_decl) = DECL_SIZE_UNIT (new_decl);
! 		}
! 	      else
! 		{
! 		  TREE_TYPE (new_decl) = new_type = old_type;
! 		  DECL_SIZE (new_decl) = DECL_SIZE (old_decl);
! 		  DECL_SIZE_UNIT (new_decl) = DECL_SIZE_UNIT (old_decl);
! 		}
  	    }
  	}
      }
  
!   if (old_type != new_type)
!     {
!       if (!gimple_types_structurally_equivalent_p (old_type, new_type))
! 	{
! 	  if (warning_at (DECL_SOURCE_LOCATION (new_decl), 0,
! 			  "type of %qD does not match original declaration",
! 			  new_decl))
! 	    inform (DECL_SOURCE_LOCATION (old_decl),
! 		    "previously declared here");
! 	  return false;
! 	}
! 
!       /* We can tolerate differences in types as long as the type
! 	 structure is compatible.
! 	 ???  For TBAA we should force the reaching non-equivalent
! 	 type-pairs to have the same alias-set here.  Simply do so
! 	 for the outermost type for now.  */
!       old_type = gimple_register_type (TYPE_MAIN_VARIANT (old_type));
!       new_type = gimple_register_type (TYPE_MAIN_VARIANT (new_type));
!       if (flag_strict_aliasing)
! 	TYPE_ALIAS_SET (new_type) = get_alias_set (old_type);
      }
  
    /* ???  We might want to emit a warning here if type qualification
*************** lto_symtab_prevailing_decl (tree decl)
*** 688,694 ****
       with and return that.  */
    while (ret)
      {
!       if (gimple_types_compatible_p (TREE_TYPE (decl), TREE_TYPE (ret->decl)))
  	return ret->decl;
  
        ret = ret->next;
--- 707,714 ----
       with and return that.  */
    while (ret)
      {
!       if (gimple_types_structurally_equivalent_p (TREE_TYPE (decl),
! 						  TREE_TYPE (ret->decl)))
  	return ret->decl;
  
        ret = ret->next;
Index: trunk/gcc/lto/lto.c
===================================================================
*** trunk.orig/gcc/lto/lto.c	2009-10-06 14:15:42.000000000 +0200
--- trunk/gcc/lto/lto.c	2009-10-06 14:19:25.000000000 +0200
*************** read_cgraph_and_symbols (unsigned nfiles
*** 1835,1840 ****
--- 1835,1843 ----
    /* Fixup all decls and types.  */
    lto_fixup_decls (all_file_decl_data);
  
+   /* Free the type hash tables.  */
+   free_gimple_type_tables ();
+ 
    /* FIXME lto. This loop needs to be changed to use the pass manager to
       call the ipa passes directly.  */
    if (!errorcount)
Index: trunk/gcc/testsuite/gcc.dg/lto/20091006-2_0.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/lto/20091006-2_0.c	2009-10-06 14:57:00.000000000 +0200
***************
*** 0 ****
--- 1,4 ----
+ /* { dg-lto-do link } */
+ 
+ extern int a[10];
+ int main() { return 0; }
Index: trunk/gcc/testsuite/gcc.dg/lto/20091006-2_1.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/lto/20091006-2_1.c	2009-10-06 14:56:44.000000000 +0200
***************
*** 0 ****
--- 1 ----
+ int a[16];
Index: trunk/gcc/testsuite/gcc.dg/lto/20091006-2_2.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/lto/20091006-2_2.c	2009-10-06 14:56:48.000000000 +0200
***************
*** 0 ****
--- 1 ----
+ extern int a[14];


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