public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH][LTO] Kill forced type merging code
@ 2009-10-16 21:12 Richard Guenther
  2009-10-16 21:13 ` Diego Novillo
  0 siblings, 1 reply; 2+ messages in thread
From: Richard Guenther @ 2009-10-16 21:12 UTC (permalink / raw)
  To: gcc-patches; +Cc: Diego Novillo


This is one of the more ugly pieces that was needed before the rest
worked well enough.  Appearantly we do not need it any longer so
this patch removes it again.  Yay.  The patch also simplifies
the compatibility logic in lto-symtab according to an older patch
that I didn't apply yet (well - almost all pieces are in by now
in some form).  In particular it stops us from warning for
type incompatibilities that are handled correctly by the
existing TBAA code - which is cases of incomplete vs. complete
types (we do have testcases for that, they were handled by the
forced type merging code).

I verified we no longer need the code by building and running
SPEC 2006.  Bootstrapped and tested on x86_64-unknown-linux-gnu, ok?

Thanks,
Richard.

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

	* lto-symtab.c (merge_incomplete_and_complete_type): Remove.
	(maybe_merge_incomplete_and_complete_type): Likewise.
	(lto_symtab_merge): Do not call them.  Do not warn for
	complete vs. incomplete compatible types.
	(lto_symtab_merge_decls_2): Simplify.
	* gimple.c (gimple_force_type_merge): Remove.
	(gimple_types_compatible_p): Make it static.
	* gimple.h (gimple_force_type_merge): Remove.
	(gimple_types_compatible_p): Likewise.


Index: gcc/lto-symtab.c
===================================================================
*** gcc/lto-symtab.c	(revision 152909)
--- gcc/lto-symtab.c	(working copy)
*************** lto_symtab_get_resolution (tree decl)
*** 182,238 ****
  }
  
  
- 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.  */
-   gimple_force_type_merge (incomplete, complete);
- 
-   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;
- }
- 
  /* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
     all edges and removing the old node.  */
  
--- 182,187 ----
*************** lto_symtab_merge (lto_symtab_entry_t pre
*** 300,307 ****
  
    if (TREE_CODE (decl) == FUNCTION_DECL)
      {
!       if (!gimple_types_compatible_p (TREE_TYPE (prevailing_decl),
! 				      TREE_TYPE (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
--- 249,255 ----
  
    if (TREE_CODE (decl) == FUNCTION_DECL)
      {
!       if (TREE_TYPE (prevailing_decl) != TREE_TYPE (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_merge (lto_symtab_entry_t pre
*** 315,346 ****
  
    /* Now we exclusively deal with VAR_DECLs.  */
  
!   /* 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.  */
!   prevailing_type = TREE_TYPE (prevailing_decl);
!   type = TREE_TYPE (decl);
! 
!   /* If the types are structurally equivalent we can use the knowledge
!      that both bind to the same symbol to complete incomplete types
!      of external declarations or of pointer targets.
!      ???  We should apply this recursively to aggregate members here
!      and get rid of the completion in gimple_types_compatible_p.  */
!   if (DECL_EXTERNAL (prevailing_decl) || DECL_EXTERNAL (decl))
!     maybe_merge_incomplete_and_complete_type (prevailing_type, type);
!   else if (POINTER_TYPE_P (prevailing_type)
! 	   && POINTER_TYPE_P (type))
!     maybe_merge_incomplete_and_complete_type (TREE_TYPE (prevailing_type),
! 					      TREE_TYPE (type));
  
    /* We can tolerate differences in type qualification, the
!      qualification of the prevailing definition will prevail.  */
    prevailing_type = TYPE_MAIN_VARIANT (TREE_TYPE (prevailing_decl));
    type = TYPE_MAIN_VARIANT (TREE_TYPE (decl));
!   if (!gimple_types_compatible_p (prevailing_type, type))
!     return false;
  
    /* ???  We might want to emit a warning here if type qualification
       differences were spotted.  Do not do this unconditionally though.  */
--- 263,318 ----
  
    /* Now we exclusively deal with VAR_DECLs.  */
  
!   /* Sharing a global symbol is a strong hint that two types are
!      compatible.  We could use this information to complete
!      incomplete pointed-to types more aggressively here, ignoring
!      mismatches in both field and tag names.  It's difficult though
!      to guarantee that this does not have side-effects on merging
!      more compatible types from other translation units though.  */
  
    /* We can tolerate differences in type qualification, the
!      qualification of the prevailing definition will prevail.
!      ???  In principle we might want to only warn for structurally
!      incompatible types here, but unless we have protective measures
!      for TBAA in place that would hide useful information.  */
    prevailing_type = TYPE_MAIN_VARIANT (TREE_TYPE (prevailing_decl));
    type = TYPE_MAIN_VARIANT (TREE_TYPE (decl));
! 
!   /* We have to register and fetch canonical types here as the global
!      fixup process didn't yet run.  */
!   prevailing_type = gimple_register_type (prevailing_type);
!   type = gimple_register_type (type);
!   if (prevailing_type != type)
!     {
!       if (COMPLETE_TYPE_P (type))
! 	return false;
! 
!       /* If type is incomplete then avoid warnings in the cases
! 	 that TBAA handles just fine.  */
! 
!       if (TREE_CODE (prevailing_type) != TREE_CODE (type))
! 	return false;
! 
!       if (TREE_CODE (prevailing_type) == ARRAY_TYPE)
! 	{
! 	  tree tem1 = TREE_TYPE (prevailing_type);
! 	  tree tem2 = TREE_TYPE (type);
! 	  while (TREE_CODE (tem1) == ARRAY_TYPE
! 		 && TREE_CODE (tem2) == ARRAY_TYPE)
! 	    {
! 	      tem1 = TREE_TYPE (tem1);
! 	      tem2 = TREE_TYPE (tem2);
! 	    }
! 
! 	  if (TREE_CODE (tem1) != TREE_CODE (tem2))
! 	    return false;
! 
! 	  if (gimple_register_type (tem1) != gimple_register_type (tem2))
! 	    return false;
! 	}
! 
!       /* Fallthru.  Compatible enough.  */
!     }
  
    /* ???  We might want to emit a warning here if type qualification
       differences were spotted.  Do not do this unconditionally though.  */
*************** lto_symtab_merge_decls_2 (void **slot)
*** 505,512 ****
    /* Diagnose all mismatched re-declarations.  */
    for (i = 0; VEC_iterate (tree, mismatches, i, decl); ++i)
      {
!       if (!gimple_types_compatible_p (TREE_TYPE (prevailing->decl),
! 				      TREE_TYPE (decl)))
  	diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
  				   "type of %qD does not match original "
  				   "declaration", decl);
--- 477,483 ----
    /* Diagnose all mismatched re-declarations.  */
    for (i = 0; VEC_iterate (tree, mismatches, i, decl); ++i)
      {
!       if (TREE_TYPE (prevailing->decl) != TREE_TYPE (decl))
  	diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
  				   "type of %qD does not match original "
  				   "declaration", decl);
Index: gcc/gimple.c
===================================================================
*** gcc/gimple.c	(revision 152909)
--- gcc/gimple.c	(working copy)
*************** lookup_type_pair (tree t1, tree t2, htab
*** 3090,3124 ****
  }
  
  
- /* Force merging the type T2 into the type T1.  */
- 
- void
- gimple_force_type_merge (tree t1, tree t2)
- {
-   void **slot;
-   type_pair_t p;
- 
-   /* There's no other way than copying t2 to t1 in this case.
-      Yuck.  We'll just call this "completing" t1.  */
-   memcpy (t1, t2, tree_size (t1));
- 
-   /* Adjust the hash value of T1 if it was computed already.  Otherwise
-      we would be forced to not hash fields of structs to match the
-      hash value of an incomplete struct.  */
-   if (type_hash_cache
-       && (slot = pointer_map_contains (type_hash_cache, t1)) != NULL)
-     {
-       gimple_type_hash (t2);
-       *slot = *pointer_map_contains (type_hash_cache, t2);
-     }
- 
-   /* Adjust cached comparison results for T1 and T2 to make sure
-      they now compare compatible.  */
-   p = lookup_type_pair (t1, t2, &gtc_visited, &gtc_ob);
-   p->same_p = 1;
- }
- 
- 
  /* Return true if T1 and T2 have the same name.  If FOR_COMPLETION_P is
     true then if any type has no name return false, otherwise return
     true if both types have no names.  */
--- 3090,3095 ----
*************** compare_field_offset (tree f1, tree f2)
*** 3196,3202 ****
  /* 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;
--- 3167,3173 ----
  /* Return 1 iff T1 and T2 are structurally identical.
     Otherwise, return 0.  */
  
! static int
  gimple_types_compatible_p (tree t1, tree t2)
  {
    type_pair_t p = NULL;
*************** gimple_types_compatible_p (tree t1, tree
*** 3404,3510 ****
  
      case POINTER_TYPE:
      case REFERENCE_TYPE:
! 	{
! 	  /* 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))
! 	    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))
! 	      && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t1))
! 	      && (!COMPLETE_TYPE_P (TREE_TYPE (t1))
! 		  || !COMPLETE_TYPE_P (TREE_TYPE (t2)))
! 	      && compare_type_names_p (TREE_TYPE (t1), TREE_TYPE (t2), true))
! 	    {
! 	      /* Replace the pointed-to incomplete type with the
! 		 complete one.  */
! 	      if (COMPLETE_TYPE_P (TREE_TYPE (t2)))
! 		TREE_TYPE (t1) = TREE_TYPE (t2);
! 	      else
! 		TREE_TYPE (t2) = TREE_TYPE (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;
- 	}
- 
-     case ENUMERAL_TYPE:
- 	{
- 	  /* For enumeral types, all the values must be the same.  */
- 	  tree v1, v2;
  
! 	  if (TYPE_VALUES (t1) == TYPE_VALUES (t2))
  	    goto same_types;
  
! 	  for (v1 = TYPE_VALUES (t1), v2 = TYPE_VALUES (t2);
! 	       v1 && v2;
! 	       v1 = TREE_CHAIN (v1), v2 = TREE_CHAIN (v2))
! 	    {
! 	      tree c1 = TREE_VALUE (v1);
! 	      tree c2 = TREE_VALUE (v2);
  
! 	      if (TREE_CODE (c1) == CONST_DECL)
! 		c1 = DECL_INITIAL (c1);
  
! 	      if (TREE_CODE (c2) == CONST_DECL)
! 		c2 = DECL_INITIAL (c2);
  
! 	      if (tree_int_cst_equal (c1, c2) != 1)
! 		goto different_types;
! 	    }
  
! 	  /* If one enumeration has more values than the other, they
! 	     are not the same.  */
! 	  if (v1 || v2)
! 	    goto different_types;
  
! 	  goto same_types;
! 	}
  
      case RECORD_TYPE:
      case UNION_TYPE:
      case QUAL_UNION_TYPE:
! 	{
! 	  tree f1, f2;
! 
! 	  /* If one type requires structural equality checks and the
! 	     other doesn't, do not merge the types.  */
! 	  if (TYPE_STRUCTURAL_EQUALITY_P (t1)
! 	      != TYPE_STRUCTURAL_EQUALITY_P (t2))
! 	    goto different_types;
  
! 	  /* 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.  */
! 	  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;
! 	    }
  
! 	  /* If one aggregate has more fields than the other, they
! 	     are not the same.  */
! 	  if (f1 || f2)
! 	    goto different_types;
  
! 	  goto same_types;
! 	}
  
      case VECTOR_TYPE:
        if (TYPE_VECTOR_SUBPARTS (t1) != TYPE_VECTOR_SUBPARTS (t2))
--- 3375,3481 ----
  
      case POINTER_TYPE:
      case REFERENCE_TYPE:
!       {
! 	/* 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))
  	  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))
! 	    && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t1))
! 	    && (!COMPLETE_TYPE_P (TREE_TYPE (t1))
! 		|| !COMPLETE_TYPE_P (TREE_TYPE (t2)))
! 	    && compare_type_names_p (TREE_TYPE (t1), TREE_TYPE (t2), true))
! 	  {
! 	    /* Replace the pointed-to incomplete type with the
! 	       complete one.  */
! 	    if (COMPLETE_TYPE_P (TREE_TYPE (t2)))
! 	      TREE_TYPE (t1) = TREE_TYPE (t2);
! 	    else
! 	      TREE_TYPE (t2) = TREE_TYPE (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;
!       }
  
!     case ENUMERAL_TYPE:
!       {
! 	/* For enumeral types, all the values must be the same.  */
! 	tree v1, v2;
  
! 	if (TYPE_VALUES (t1) == TYPE_VALUES (t2))
! 	  goto same_types;
  
! 	for (v1 = TYPE_VALUES (t1), v2 = TYPE_VALUES (t2);
! 	     v1 && v2;
! 	     v1 = TREE_CHAIN (v1), v2 = TREE_CHAIN (v2))
! 	  {
! 	    tree c1 = TREE_VALUE (v1);
! 	    tree c2 = TREE_VALUE (v2);
! 
! 	    if (TREE_CODE (c1) == CONST_DECL)
! 	      c1 = DECL_INITIAL (c1);
! 
! 	    if (TREE_CODE (c2) == CONST_DECL)
! 	      c2 = DECL_INITIAL (c2);
! 
! 	    if (tree_int_cst_equal (c1, c2) != 1)
! 	      goto different_types;
! 	  }
! 
! 	/* If one enumeration has more values than the other, they
! 	   are not the same.  */
! 	if (v1 || v2)
! 	  goto different_types;
  
! 	goto same_types;
!       }
  
      case RECORD_TYPE:
      case UNION_TYPE:
      case QUAL_UNION_TYPE:
!       {
! 	tree f1, f2;
  
! 	/* If one type requires structural equality checks and the
! 	   other doesn't, do not merge the types.  */
! 	if (TYPE_STRUCTURAL_EQUALITY_P (t1)
! 	    != TYPE_STRUCTURAL_EQUALITY_P (t2))
! 	  goto different_types;
  
! 	/* 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.  */
! 	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;
! 	  }
! 
! 	/* If one aggregate has more fields than the other, they
! 	   are not the same.  */
! 	if (f1 || f2)
! 	  goto different_types;
  
! 	goto same_types;
!       }
  
      case VECTOR_TYPE:
        if (TYPE_VECTOR_SUBPARTS (t1) != TYPE_VECTOR_SUBPARTS (t2))
Index: gcc/gimple.h
===================================================================
*** gcc/gimple.h	(revision 152909)
--- gcc/gimple.h	(working copy)
*************** extern bool is_gimple_call_addr (tree);
*** 915,922 ****
  extern tree get_call_expr_in (tree t);
  
  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 void free_gimple_type_tables (void);
--- 915,920 ----

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH][LTO] Kill forced type merging code
  2009-10-16 21:12 [PATCH][LTO] Kill forced type merging code Richard Guenther
@ 2009-10-16 21:13 ` Diego Novillo
  0 siblings, 0 replies; 2+ messages in thread
From: Diego Novillo @ 2009-10-16 21:13 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

On Fri, Oct 16, 2009 at 16:58, Richard Guenther <rguenther@suse.de> wrote:

> 2009-10-16  Richard Guenther  <rguenther@suse.de>
>
>        * lto-symtab.c (merge_incomplete_and_complete_type): Remove.
>        (maybe_merge_incomplete_and_complete_type): Likewise.
>        (lto_symtab_merge): Do not call them.  Do not warn for
>        complete vs. incomplete compatible types.
>        (lto_symtab_merge_decls_2): Simplify.
>        * gimple.c (gimple_force_type_merge): Remove.
>        (gimple_types_compatible_p): Make it static.
>        * gimple.h (gimple_force_type_merge): Remove.
>        (gimple_types_compatible_p): Likewise.

Whee!  OK.


Diego.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2009-10-16 21:12 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-10-16 21:12 [PATCH][LTO] Kill forced type merging code Richard Guenther
2009-10-16 21:13 ` Diego Novillo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).