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 PR41032 - properly complete types, rewrite pieces of decl merging


This patch makes use of the freedom we get as gimple_types_compatible_p
is no longer the langhook for types_compatible_p.  PR41032 shows that
we need to complete and merge types properly.

This makes necessary to no longer hash complete types and incomplete 
variants of a type differenly.

There are two places we merge types - one is special because we have a
strong hint that the two types should be the same when we are about
to merge two decls.  In the other one we have to be careful not to
merge too much (but also need to make sure to merge enough for TBAA
to work properly).

A variant of the patch has passed bootstrap and tests on 
x86_64-unknown-linux-gnu, I am currently re-testing this final version.

Apart from the new testcase it also fixes excess errors from
gfortran.dg/bind_c_coms.f90.  I'll re-build SPEC 2000 with the
final version as well.

We should be able to rip out the SCC finding from type hashing again,
but I leave that for a future patch.

Ok for LTO?

Thanks,
Richard.

2009-08-13  Richard Guenther  <rguenther@suse.de>

	PR lto/41032
	* tree.c (free_lang_data): NULL the types_compatible_p langhook.
	* gimple.c (gtc_visited): Global type compatibility hashtable.
	(compare_field_offset): New helper function.
	(gimple_compare_types): Fold into ...
	(gimple_types_compatible_p): ... here.  Types with differing
	hash values are not compatible.  Adjust function now that it
	is no longer used as types_compatible_p langhook.  Complete
	incomplete pointer targets.
	(iterative_hash_type_name): New helper function.
	(iterative_hash_gimple_type): Do not hash type sizes.  Do not
	recurse into aggregate pointer targets.  Properly hash
	complex and vector types.  Hash the name of record types.
	(print_gimple_types_stats): Print stats of gtc_visited.
	* lto-symtab.c (lto_merge_qualifiers): Remove.
	(lto_merge_types): Likewise.
	(merge_incomplete_and_complete_type): New helper function.
	(maybe_merge_incomplete_and_complete_type): Likewise.
	(lto_symtab_compatible): Remove do_warn arg.  Complete types
	during decl merging.  Forcefully merge more types than
	elsewhere.  Do not compare DECL_MODE.
	(lto_symtab_prevailing_decl): Use gimple_types_compatible_p, not
	lto_symtab_compatible for finding the decl we merged with.

        lto/
	* lto-lang.c (LANG_HOOKS_TYPES_COMPATIBLE_P): Define to NULL.

	* gcc.dg/lto/20090812_0.c: New testcase.
	* gcc.dg/lto/20090812_1.c: Likewise.

Index: lto/gcc/gimple.c
===================================================================
*** lto.orig/gcc/gimple.c	2009-08-13 10:17:13.000000000 +0200
--- lto/gcc/gimple.c	2009-08-13 13:49:58.000000000 +0200
*************** along with GCC; see the file COPYING3.
*** 43,48 ****
--- 43,51 ----
  static htab_t gimple_types;
  static struct pointer_map_t *type_hash_cache;
  
+ /* Global type comparison cache.  */
+ static htab_t gtc_visited;
+ 
  #define DEFGSCODE(SYM, NAME, STRUCT)	NAME,
  const char *const gimple_code_name[] = {
  #include "gimple.def"
*************** gimple_call_copy_skip_args (gimple stmt,
*** 3081,3087 ****
  
  
  /* Structure used to maintain a cache of some type pairs compared by
!    gimple_compare_types when comparing aggregate types.  There are
     four possible values for SAME_P:
  
     	-2: The pair (T1, T2) has just been inserted in the table.
--- 3084,3090 ----
  
  
  /* Structure used to maintain a cache of some type pairs compared by
!    gimple_types_compatible_p when comparing aggregate types.  There are
     four possible values for SAME_P:
  
     	-2: The pair (T1, T2) has just been inserted in the table.
*************** compare_type_names_p (tree t1, tree t2)
*** 3199,3212 ****
    return false;
  }
  
! /* Recursive helper for gimple_types_compatible_p.  Return 1 iff T1
!    and T2 are structurally identical.  Otherwise, return 0.
!    VISITED_P points to a hash table of type pairs that have been
!    visited while comparing aggregate types.  This prevents infinite
!    recursion when comparing aggregates with self-referential fields.  */
  
! static int
! gimple_compare_types (tree t1, tree t2, htab_t *visited_p)
  {
    type_pair_t p = NULL;
  
--- 3202,3247 ----
    return false;
  }
  
! /* Return true if the field decls F1 and F2 are at the same offset.  */
  
! static bool
! compare_field_offset (tree f1, tree f2)
! {
!   if (DECL_OFFSET_ALIGN (f1) == DECL_OFFSET_ALIGN (f2))
!     return (operand_equal_p (DECL_FIELD_OFFSET (f1),
! 			     DECL_FIELD_OFFSET (f2), 0)
! 	    && tree_int_cst_equal (DECL_FIELD_BIT_OFFSET (f1),
! 				   DECL_FIELD_BIT_OFFSET (f2)));
! 
!   /* Fortran and C do not always agree on what DECL_OFFSET_ALIGN
!      should be, so handle differing ones specially by decomposing
!      the offset into a byte and bit offset manually.  */
!   if (host_integerp (DECL_FIELD_OFFSET (f1), 0)
!       && host_integerp (DECL_FIELD_OFFSET (f2), 0))
!     {
!       unsigned HOST_WIDE_INT byte_offset1, byte_offset2;
!       unsigned HOST_WIDE_INT bit_offset1, bit_offset2;
!       bit_offset1 = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (f1));
!       byte_offset1 = (TREE_INT_CST_LOW (DECL_FIELD_OFFSET (f1))
! 		      + bit_offset1 / BITS_PER_UNIT);
!       bit_offset2 = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (f2));
!       byte_offset2 = (TREE_INT_CST_LOW (DECL_FIELD_OFFSET (f2))
! 		      + bit_offset2 / BITS_PER_UNIT);
!       if (byte_offset1 != byte_offset2)
! 	return false;
!       return bit_offset1 % BITS_PER_UNIT == bit_offset2 % BITS_PER_UNIT;
!     }
! 
!   return false;
! }
! 
! static hashval_t gimple_type_hash (const void *);
! 
! /* 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;
  
*************** gimple_compare_types (tree t1, tree t2,
*** 3230,3238 ****
    if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
      goto different_types;
  
    /* If we've visited this type pair before (in the case of aggregates
       with self-referntial types), and we made a decision, return it.  */
!   p = lookup_type_pair (t1, t2, visited_p);
    if (p->same_p == 0 || p->same_p == 1)
      {
        /* We have already decided whether T1 and T2 are the
--- 3265,3279 ----
    if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
      goto different_types;
  
+   /* If the hash values of t1 and t2 are different the types can't be
+      possibly 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-referntial 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
*************** gimple_compare_types (tree t1, tree t2,
*** 3248,3260 ****
  
    gcc_assert (p->same_p == -2);
  
    /* 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;
  
-   if (!targetm.comp_type_attributes (t1, t2))
-     goto different_types;
- 
    /* For numerical types, the bounds must coincide.  */
    if (INTEGRAL_TYPE_P (t1)
        || SCALAR_FLOAT_TYPE_P (t1)
--- 3289,3301 ----
  
    gcc_assert (p->same_p == -2);
  
+   /* Mark the (T1, T2) comparison in progress.  */
+   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.  */
    if (INTEGRAL_TYPE_P (t1)
        || SCALAR_FLOAT_TYPE_P (t1)
*************** gimple_compare_types (tree t1, tree t2,
*** 3326,3332 ****
      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_compare_types (TREE_TYPE (t1), TREE_TYPE (t2), visited_p)
  	  || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2))
  	goto different_types;
        else
--- 3367,3373 ----
      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
*************** gimple_compare_types (tree t1, tree t2,
*** 3340,3376 ****
  	    goto same_types;
  	  else if (i1 == NULL_TREE || i2 == NULL_TREE)
  	    goto different_types;
  	  else
  	    {
  	      tree min1 = TYPE_MIN_VALUE (i1);
  	      tree min2 = TYPE_MIN_VALUE (i2);
  	      tree max1 = TYPE_MAX_VALUE (i1);
  	      tree max2 = TYPE_MAX_VALUE (i2);
- 	      bool min_equal_p = false;
- 	      bool max_equal_p = false;
- 
- 	      /* For variable-sized arrays, use the same notion as in the C
- 		 front end.  If either domain is variable, consider the types
- 		 compatible.  */
- 	      if (min1 == NULL_TREE && min2 == NULL_TREE)
- 		min_equal_p = true;
- 	      else if (min1 && TREE_CODE (min1) != INTEGER_CST)
- 		min_equal_p = true;
- 	      else if (min2 && TREE_CODE (min2) != INTEGER_CST)
- 		min_equal_p = true;
- 	      else if (min1 && min2 && operand_equal_p (min1, min2, 0))
- 		min_equal_p = true;
- 	      
- 	      if (max1 == NULL_TREE && max2 == NULL_TREE)
- 		max_equal_p = true;
- 	      else if (max1 && TREE_CODE (max1) != INTEGER_CST)
- 		max_equal_p = true;
- 	      else if (max2 && TREE_CODE (max2) != INTEGER_CST)
- 		max_equal_p = true;
- 	      else if (max1 && max2 && operand_equal_p (max1, max2, 0))
- 		max_equal_p = true;
  
! 	      if (min_equal_p && max_equal_p)
  		goto same_types;
  	      else
  		goto different_types;
--- 3381,3405 ----
  	    goto same_types;
  	  else if (i1 == NULL_TREE || i2 == NULL_TREE)
  	    goto different_types;
+ 	  /* If for a complete array type the possibly gimplified sizes
+ 	     are different the types are different.  */
+ 	  else if (((TYPE_SIZE (i1) != NULL) ^ (TYPE_SIZE (i2) != NULL))
+ 		   || (TYPE_SIZE (i1)
+ 		       && TYPE_SIZE (i2)
+ 		       && !operand_equal_p (TYPE_SIZE (i1), TYPE_SIZE (i2), 0)))
+ 	    goto different_types;
  	  else
  	    {
  	      tree min1 = TYPE_MIN_VALUE (i1);
  	      tree min2 = TYPE_MIN_VALUE (i2);
  	      tree max1 = TYPE_MAX_VALUE (i1);
  	      tree max2 = TYPE_MAX_VALUE (i2);
  
! 	      /* The minimum/maximum values have to be the same.  */
! 	      if ((min1 == min2
! 		   || (min1 && min2 && operand_equal_p (min1, min2, 0)))
! 		  && (max1 == max2
! 		      || (max1 && max2 && operand_equal_p (max1, max2, 0))))
  		goto same_types;
  	      else
  		goto different_types;
*************** gimple_compare_types (tree t1, tree t2,
*** 3379,3387 ****
  
      case METHOD_TYPE:
        /* Method types should belong to the same class.  */
!       if (!gimple_compare_types (TYPE_METHOD_BASETYPE (t1),
! 				 TYPE_METHOD_BASETYPE (t2),
! 				 visited_p))
  	goto different_types;
  
        /* Fallthru  */
--- 3408,3415 ----
  
      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  */
*************** gimple_compare_types (tree t1, tree t2,
*** 3389,3398 ****
      case FUNCTION_TYPE:
        /* Function types are the same if the return type and arguments types
  	 are the same.  */
!       if (!gimple_compare_types (TREE_TYPE (t1), TREE_TYPE (t2), visited_p))
  	goto different_types;
        else
  	{
  	  if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2))
  	    goto same_types;
  	  else
--- 3417,3429 ----
      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
  	{
+ 	  if (!targetm.comp_type_attributes (t1, t2))
+ 	    goto different_types;
+ 
  	  if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2))
  	    goto same_types;
  	  else
*************** gimple_compare_types (tree t1, tree t2,
*** 3403,3411 ****
  		   parms1 && parms2;
  		   parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
  		{
! 		  if (!gimple_compare_types (TREE_VALUE (parms1),
! 					     TREE_VALUE (parms2),
! 					     visited_p))
  		    goto different_types;
  		}
  
--- 3434,3441 ----
  		   parms1 && parms2;
  		   parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
  		{
! 		  if (!gimple_types_compatible_p (TREE_VALUE (parms1),
! 					     TREE_VALUE (parms2)))
  		    goto different_types;
  		}
  
*************** gimple_compare_types (tree t1, tree t2,
*** 3424,3432 ****
  	  if (TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
  	    goto different_types;
  
  	  /* Otherwise, pointer and reference types are the same if the
  	     pointed-to types are the same.  */
! 	  if (gimple_compare_types (TREE_TYPE (t1), TREE_TYPE (t2), visited_p))
  	    goto same_types;
  	  
  	  goto different_types;
--- 3454,3477 ----
  	  if (TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
  	    goto different_types;
  
+ 	  /* If one pointer points to an incomplete type variant of
+ 	     the other pointed-to type they are the same.  */
+ 	  if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2))
+ 	      && (!COMPLETE_TYPE_P (TREE_TYPE (t1))
+ 		  || !COMPLETE_TYPE_P (TREE_TYPE (t2)))
+ 	      && compare_type_names_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+ 	    {
+ 	      /* If t2 is complete we want to choose it instead of t1.
+ 		 There's no other way than copying t2 to t1 in this case.
+ 		 Yuck.  We'll just call this "completing" t1.  */
+ 	      if (COMPLETE_TYPE_P (TREE_TYPE (t2)))
+ 		memcpy (t1, t2, tree_size (t1));
+ 	      goto same_types;
+ 	    }
+ 
  	  /* 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;
*************** gimple_compare_types (tree t1, tree t2,
*** 3472,3498 ****
  	  /* For aggregate types, all the fields must be the same.  */
  	  tree f1, f2;
  
! 	  /* Mark the (T1, T2) comparison in progress.  */
! 	  p->same_p = -1;
! 
! 	  /* If either structure is empty, they should at least have
! 	     the same name.  */
! 	  if ((!TYPE_SIZE (t1) || !TYPE_SIZE (t2))
! 	      && compare_type_names_p (t1, t2))
! 	    goto same_types;
! 
! 	  /* Otherwise, compare every field.  */
  	  for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
  	       f1 && f2;
  	       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)
! 		  || !tree_int_cst_equal (DECL_FIELD_OFFSET (f1),
! 				          DECL_FIELD_OFFSET (f2))
! 		  || !gimple_compare_types (TREE_TYPE (f1),
! 					    TREE_TYPE (f2),
! 					    visited_p))
  		goto different_types;
  	    }
  
--- 3517,3532 ----
  	  /* For aggregate types, all the fields must be the same.  */
  	  tree f1, f2;
  
! 	  /* Compare every field.  */
  	  for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
  	       f1 && f2;
  	       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;
  	    }
  
*************** same_types:
*** 3522,3543 ****
  }
  
  
- /* Return 1 iff T1 and T2 are structurally identical.  Otherwise,
-    return 0.  */
- 
- int
- gimple_types_compatible_p (tree t1, tree t2)
- {
-   int same_p;
-   htab_t visited = NULL;
- 
-   same_p = gimple_compare_types (t1, t2, &visited);
- 
-   if (visited)
-     htab_delete (visited);
- 
-   return same_p;
- }
  
  
  /* Per pointer state for the SCC finding.  The on_sccstack flag
--- 3556,3561 ----
*************** visit (tree t, struct sccs *state, hashv
*** 3627,3632 ****
--- 3645,3666 ----
    return v;
  }
  
+ /* Hash the name of TYPE with the previous hash value V and return it.  */
+ 
+ static hashval_t
+ iterative_hash_type_name (tree type, hashval_t v)
+ {
+   tree name = TYPE_NAME (TYPE_MAIN_VARIANT (type));
+   if (!name)
+     return v;
+   if (TREE_CODE (name) == TYPE_DECL)
+     name = DECL_NAME (name);
+   if (!name)
+     return v;
+   gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
+   return iterative_hash_object (IDENTIFIER_HASH_VALUE (name), v);
+ }
+ 
  /* Returning a hash value for gimple type TYPE combined with VAL.
     SCCSTACK, SCCSTATE and SCCSTATE_OBSTACK are state for the DFS walk done.
  
*************** iterative_hash_gimple_type (tree type, h
*** 3668,3677 ****
       checked.  */
    v = iterative_hash_hashval_t (TREE_CODE (type), 0);
    v = iterative_hash_hashval_t (TYPE_QUALS (type), v);
-   v = iterative_hash_expr (TYPE_SIZE (type), v);
-   v = iterative_hash_expr (TYPE_SIZE_UNIT (type), v);
    v = iterative_hash_hashval_t (TREE_ADDRESSABLE (type), v);
  
    /* Incorporate common features of numerical types.  */
    if (INTEGRAL_TYPE_P (type)
        || SCALAR_FLOAT_TYPE_P (type)
--- 3702,3712 ----
       checked.  */
    v = iterative_hash_hashval_t (TREE_CODE (type), 0);
    v = iterative_hash_hashval_t (TYPE_QUALS (type), v);
    v = iterative_hash_hashval_t (TREE_ADDRESSABLE (type), v);
  
+   /* Do not hash the types size as this will cause differences in
+      hash values for the complete vs. the incomplete type variant.  */
+ 
    /* Incorporate common features of numerical types.  */
    if (INTEGRAL_TYPE_P (type)
        || SCALAR_FLOAT_TYPE_P (type)
*************** iterative_hash_gimple_type (tree type, h
*** 3682,3687 ****
--- 3717,3744 ----
        v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v);
      }
  
+   /* For pointer and reference types, fold in information about the type
+      pointed to but do not recurse into possibly incomplete types to
+      avoid hash differences for complete vs. incomplete types.  */
+   if (POINTER_TYPE_P (type))
+     {
+       if (AGGREGATE_TYPE_P (TREE_TYPE (type)))
+ 	{
+ 	  v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v);
+ 	  v = iterative_hash_type_name (type, v);
+ 	}
+       else
+ 	v = visit (TREE_TYPE (type), state, v,
+ 		   sccstack, sccstate, sccstate_obstack);
+     }
+ 
+   /* Recurse for aggregates with a single element.  */
+   if (TREE_CODE (type) == ARRAY_TYPE
+       || 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)
      {
*************** iterative_hash_gimple_type (tree type, h
*** 3706,3717 ****
        v = iterative_hash_hashval_t (na, v);
      }
  
-   /* For pointer and reference types, fold in information about the type
-      pointed to.  */
-   if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
-     v = visit (TREE_TYPE (type), state, v,
- 	       sccstack, sccstate, sccstate_obstack);
- 
    if (TREE_CODE (type) == RECORD_TYPE
        || TREE_CODE (type) == UNION_TYPE
        || TREE_CODE (type) == QUAL_UNION_TYPE)
--- 3763,3768 ----
*************** iterative_hash_gimple_type (tree type, h
*** 3719,3724 ****
--- 3770,3777 ----
        unsigned nf;
        tree f;
  
+       v = iterative_hash_type_name (type, v);
+ 
        for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f))
  	{
  	  v = visit (TREE_TYPE (f), state, v,
*************** print_gimple_types_stats (void)
*** 3866,3871 ****
--- 3919,3934 ----
  	     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");
  }
  
  
Index: lto/gcc/testsuite/gcc.dg/lto/20090812_0.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- lto/gcc/testsuite/gcc.dg/lto/20090812_0.c	2009-08-13 10:23:09.000000000 +0200
***************
*** 0 ****
--- 1,11 ----
+ struct X;
+ struct Y
+ {
+   struct X *p;
+   int i;
+ };
+ 
+ void foo (struct Y *p)
+ {
+   p->i = 1;
+ }
Index: lto/gcc/testsuite/gcc.dg/lto/20090812_1.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- lto/gcc/testsuite/gcc.dg/lto/20090812_1.c	2009-08-13 10:23:09.000000000 +0200
***************
*** 0 ****
--- 1,26 ----
+ /* struct X is complete in this TU, this causes us to not merge Y and
+    thus assign different alias-sets to them.  */
+ struct X
+ {
+   int i;
+ };
+ struct Y
+ {
+   struct X *p;
+   int i;
+ };
+ extern void abort (void);
+ extern void foo(struct Y *);
+ int __attribute__((noinline)) bar(struct Y *p)
+ {
+   p->i = 0;
+   foo (p);
+   return p->i;
+ }
+ int main()
+ {
+   struct Y y;
+   if (bar (&y) != 1)
+     abort ();
+   return 0;
+ }
Index: lto/gcc/lto-symtab.c
===================================================================
*** lto.orig/gcc/lto-symtab.c	2009-08-13 10:17:13.000000000 +0200
--- lto/gcc/lto-symtab.c	2009-08-13 11:20:51.000000000 +0200
*************** lto_symtab_maybe_init_hash_tables (void)
*** 143,202 ****
      }
  }
  
- /* Transfer qualifiers between TYPE_1 and TYPE_2 so that qualifiers
-    for both types are conservatively correct with respect to
-    optimization done before the merge.  */
- 
- static void
- lto_merge_qualifiers (tree type_1, tree type_2)
- {
-   /* If one is volatile, the other should also be.  */
-   if (TYPE_VOLATILE (type_2))
-     TYPE_VOLATILE (type_1) = 1;
-   else if (TYPE_VOLATILE (type_1))
-     TYPE_VOLATILE (type_2) = 1;
- 
-   /* If one type is writable, the other should also be.  */
-   if (!TYPE_READONLY (type_2))
-     TYPE_READONLY (type_1) = 0;
-   else if (!TYPE_READONLY (type_1))
-     TYPE_READONLY (type_2) = 0;
- 
-   /* If one type does not have the restrict qualifier, the other
-      should not have it either.  */
-   if (!TYPE_RESTRICT (type_2))
-     TYPE_RESTRICT (type_1) = 0;
-   else if (!TYPE_RESTRICT (type_1))
-     TYPE_RESTRICT (type_2) = 0;
- }
- 
- /* If TYPE_1 and TYPE_2 can be merged to form a common type, do it.
-    Specifically, if they are both array types that have the same element
-    type and one of them is a complete array type and the other isn't,
-    return the complete array type.  Otherwise return NULL_TREE. */
- 
- static tree
- lto_merge_types (tree type_1, tree type_2)
- {
-   if (TREE_CODE (type_1) == ARRAY_TYPE
-       && TREE_CODE (type_2) == ARRAY_TYPE
-       && !TYPE_ATTRIBUTES (type_1)
-       && !TYPE_ATTRIBUTES (type_2)
-       && gimple_types_compatible_p (TREE_TYPE (type_1), TREE_TYPE (type_2)))
-     {
-       lto_merge_qualifiers (type_1, type_2);
- 
-       if (COMPLETE_TYPE_P (type_1) && !COMPLETE_TYPE_P (type_2))
- 	return type_1;
-       else if (COMPLETE_TYPE_P (type_2) && !COMPLETE_TYPE_P (type_1))
- 	return type_2;
-       else
- 	return type_1;
-     }
- 
-   return NULL_TREE;
- }
- 
  /* Returns true iff the union of ATTRIBUTES_1 and ATTRIBUTES_2 can be
     applied to DECL.  */
  static bool
--- 143,148 ----
*************** external_aggregate_decl_p (tree decl)
*** 226,238 ****
  	  && AGGREGATE_TYPE_P (TREE_TYPE (decl)));
  }
  
  /* Check if OLD_DECL and NEW_DECL are compatible. */
  
  static bool
! lto_symtab_compatible (tree old_decl, tree new_decl, bool do_warn)
  {
    tree merged_type = NULL_TREE;
-   tree merged_result = NULL_TREE;
  
    if (TREE_CODE (old_decl) != TREE_CODE (new_decl))
      {
--- 172,234 ----
  	  && AGGREGATE_TYPE_P (TREE_TYPE (decl)));
  }
  
+ static bool maybe_merge_incomplete_and_complete_type (tree, tree);
+ 
+ /* Try to merge an incomplete type INCOMPLETE with a complete type
+    COMPLETE of same kinds.
+    Return true if they were merged, false otherwise.  */
+ 
+ static bool
+ merge_incomplete_and_complete_type (tree incomplete, tree complete)
+ {
+   /* For merging array types do some extra sanity checking.  */
+   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
+      that's difficult as we do not have links from the canonical type
+      back to all its children.  */
+   memcpy (incomplete, complete, tree_size (incomplete));
+ 
+   return true;
+ }
+ 
+ /* Try to merge a maybe complete / incomplete type pair TYPE1 and TYPE2.
+    Return true if they were merged, false otherwise.  */
+ 
+ static bool
+ maybe_merge_incomplete_and_complete_type (tree type1, tree type2)
+ {
+   bool res = false;
+ 
+   if (TREE_CODE (type1) != TREE_CODE (type2))
+     return false;
+ 
+   if (!COMPLETE_TYPE_P (type1) && COMPLETE_TYPE_P (type2))
+     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));
+ 
+   return res;
+ }
+ 
  /* Check if OLD_DECL and NEW_DECL are compatible. */
  
  static bool
! lto_symtab_compatible (tree old_decl, tree new_decl)
  {
    tree merged_type = NULL_TREE;
  
    if (TREE_CODE (old_decl) != TREE_CODE (new_decl))
      {
*************** lto_symtab_compatible (tree old_decl, tr
*** 259,274 ****
  	}
      }
  
    if (!gimple_types_compatible_p (TREE_TYPE (old_decl), TREE_TYPE (new_decl)))
      {
!       /* Allow an array type with unspecified bounds to
! 	 be merged with an array type whose bounds are specified, so
! 	 as to allow "extern int i[];" in one file to be combined with
! 	 "int i[3];" in another.  */
!       if (TREE_CODE (new_decl) == VAR_DECL)
! 	merged_type = lto_merge_types (TREE_TYPE (old_decl),
! 				       TREE_TYPE (new_decl));
!       else if (TREE_CODE (new_decl) == FUNCTION_DECL)
  	{
  	  if (!merged_type
  	      /* We want either of the types to have argument types,
--- 255,322 ----
  	}
      }
  
+   /* Handle external declarations with incomplete type or pointed-to
+      incomplete types by forcefully merging the types.
+      ???  In principle all types involved in the two decls should
+      be merged forcefully, for example without considering type or
+      field names.  */
+   if (TREE_CODE (old_decl) == VAR_DECL)
+     {
+       tree old_type = TREE_TYPE (old_decl);
+       tree 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_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_type) = old_type;
+ 		  DECL_SIZE (new_decl) = DECL_SIZE (old_decl);
+ 		  DECL_SIZE_UNIT (new_decl) = DECL_SIZE_UNIT (old_decl);
+ 		}
+ 	    }
+ 	}
+     }
+ 
    if (!gimple_types_compatible_p (TREE_TYPE (old_decl), TREE_TYPE (new_decl)))
      {
!       if (TREE_CODE (new_decl) == FUNCTION_DECL)
  	{
  	  if (!merged_type
  	      /* We want either of the types to have argument types,
*************** lto_symtab_compatible (tree old_decl, tr
*** 289,300 ****
  	      if (TYPE_ARG_TYPES (TREE_TYPE (old_decl)))
  		{
  		  merged_type = TREE_TYPE (old_decl);
- 		  merged_result = DECL_RESULT (old_decl);
  		}
  	      else
  		{
  		  merged_type = TREE_TYPE (new_decl);
- 		  merged_result = DECL_RESULT (new_decl);
  		}
  	    }
  
--- 337,346 ----
*************** lto_symtab_compatible (tree old_decl, tr
*** 309,334 ****
  	      if (!DECL_EXTERNAL (new_decl))
  		{
  		  merged_type = TREE_TYPE (new_decl);
- 		  merged_result = DECL_RESULT (new_decl);
  		}
  	      else
  		{
  		  merged_type = TREE_TYPE (old_decl);
- 		  merged_result = DECL_RESULT (old_decl);
  		}
  	    }
  	}
  
        if (!merged_type)
  	{
! 	  if (do_warn)
! 	    {
! 	      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;
  	}
      }
--- 355,375 ----
  	      if (!DECL_EXTERNAL (new_decl))
  		{
  		  merged_type = TREE_TYPE (new_decl);
  		}
  	      else
  		{
  		  merged_type = TREE_TYPE (old_decl);
  		}
  	    }
  	}
  
        if (!merged_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;
  	}
      }
*************** lto_symtab_compatible (tree old_decl, tr
*** 390,422 ****
        return false;
      }
  
!   if (DECL_MODE (old_decl) != DECL_MODE (new_decl))
!     {
!       /* We can arrive here when we are merging 'extern char foo[]' and
! 	 'char foo[SMALLNUM]'; the former is probably BLKmode and the
! 	 latter is not.  In such a case, we should have merged the types
! 	 already; detect it and don't complain.  We also need to handle
! 	 external aggregate declaration specially.  */
!       if ((TREE_CODE (TREE_TYPE (old_decl))
! 	   == TREE_CODE (TREE_TYPE (new_decl)))
! 	  && (((TREE_CODE (TREE_TYPE (old_decl)) != ARRAY_TYPE)
! 	       && ((external_aggregate_decl_p (old_decl)
! 		    && DECL_MODE (old_decl) == VOIDmode)
! 		   || (external_aggregate_decl_p (new_decl)
! 		       && DECL_MODE (new_decl) == VOIDmode)))
! 	      || ((TREE_CODE (TREE_TYPE (old_decl)) == ARRAY_TYPE)
! 		  && merged_type)))
! 	;
!       else
! 	{
! 	  error_at (DECL_SOURCE_LOCATION (new_decl),
! 		    "machine mode of %qD does not match original declaration",
! 		    new_decl);
! 	  inform (DECL_SOURCE_LOCATION (old_decl),
! 		  "previously declared here");
! 	  return false;
! 	}
!     }
  
    if (!lto_compatible_attributes_p (old_decl,
  				    DECL_ATTRIBUTES (old_decl),
--- 431,438 ----
        return false;
      }
  
!   /* Do not compare the modes of the decls.  The type compatibility
!      checks or the completing of types has properly dealt with all issues.  */
  
    if (!lto_compatible_attributes_p (old_decl,
  				    DECL_ATTRIBUTES (old_decl),
*************** lto_symtab_merge_decl (tree new_decl,
*** 594,600 ****
       Find a decl we can merge with or chain it in the list of decls
       for that symbol.  */
    while (old_decl
! 	 && !lto_symtab_compatible (old_decl, new_decl, true))
      old_decl = TREE_CHAIN (old_decl);
    if (!old_decl)
      {
--- 610,616 ----
       Find a decl we can merge with or chain it in the list of decls
       for that symbol.  */
    while (old_decl
! 	 && !lto_symtab_compatible (old_decl, new_decl))
      old_decl = TREE_CHAIN (old_decl);
    if (!old_decl)
      {
*************** lto_symtab_prevailing_decl (tree decl)
*** 702,708 ****
       with and return that.  */
    while (ret)
      {
!       if (lto_symtab_compatible (decl, ret, false))
  	return ret;
  
        ret = TREE_CHAIN (ret);
--- 718,724 ----
       with and return that.  */
    while (ret)
      {
!       if (gimple_types_compatible_p (TREE_TYPE (decl), TREE_TYPE (ret)))
  	return ret;
  
        ret = TREE_CHAIN (ret);

Index: lto/gcc/lto/lto-lang.c
===================================================================
*** lto.orig/gcc/lto/lto-lang.c	2009-07-30 12:05:23.000000000 +0200
--- lto/gcc/lto/lto-lang.c	2009-08-11 14:20:36.000000000 +0200
*************** static void lto_init_ts (void)
*** 1209,1215 ****
  #undef LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS
  #define LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS true
  #undef LANG_HOOKS_TYPES_COMPATIBLE_P
! #define LANG_HOOKS_TYPES_COMPATIBLE_P gimple_types_compatible_p
  
  /* Attribute hooks.  */
  #undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
--- 1209,1215 ----
  #undef LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS
  #define LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS true
  #undef LANG_HOOKS_TYPES_COMPATIBLE_P
! #define LANG_HOOKS_TYPES_COMPATIBLE_P NULL
  
  /* Attribute hooks.  */
  #undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
Index: lto/gcc/tree.c
===================================================================
*** lto.orig/gcc/tree.c	2009-08-11 12:59:25.000000000 +0200
--- lto/gcc/tree.c	2009-08-11 14:22:26.000000000 +0200
*************** free_lang_data (void)
*** 4796,4802 ****
  
    /* Reset some langhooks.  */
    lang_hooks.callgraph.analyze_expr = NULL;
!   lang_hooks.types_compatible_p = gimple_types_compatible_p;
  
    /* FIXME lto: We have to compute these names early.  */
    lang_hooks.dwarf_name = lhd_dwarf_name;
--- 4796,4802 ----
  
    /* Reset some langhooks.  */
    lang_hooks.callgraph.analyze_expr = NULL;
!   lang_hooks.types_compatible_p = NULL;
  
    /* FIXME lto: We have to compute these names early.  */
    lang_hooks.dwarf_name = lhd_dwarf_name;


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