[PATCH] Assign the same alias-set to all pointers

Richard Guenther rguenther@suse.de
Tue Jun 1 16:16:00 GMT 2010


See $subject.  Main reasoning can be seen in the huge comment
before the case in get_alias_set below.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Comments?

Thanks,
Richard.

2010-06-01  Richard Guenther  <rguenther@suse.de>

	* gimple.c (gimple_get_alias_set): Remove pointer special-casing.
	* alias.c (get_alias_set): Canonicalize pointers with the same mode.
	Fix incomplete array type fallback alias-set.

Index: gcc/gimple.c
===================================================================
*** gcc/gimple.c	(revision 160100)
--- gcc/gimple.c	(working copy)
*************** gimple_get_alias_set (tree t)
*** 4310,4372 ****
        if (t1 != t)
  	return get_alias_set (t1);
      }
-   else if (POINTER_TYPE_P (t))
-     {
-       /* From the common C and C++ langhook implementation:
- 
- 	 Unfortunately, there is no canonical form of a pointer type.
- 	 In particular, if we have `typedef int I', then `int *', and
- 	 `I *' are different types.  So, we have to pick a canonical
- 	 representative.  We do this below.
- 
- 	 Technically, this approach is actually more conservative that
- 	 it needs to be.  In particular, `const int *' and `int *'
- 	 should be in different alias sets, according to the C and C++
- 	 standard, since their types are not the same, and so,
- 	 technically, an `int **' and `const int **' cannot point at
- 	 the same thing.
- 
- 	 But, the standard is wrong.  In particular, this code is
- 	 legal C++:
- 
- 	 int *ip;
- 	 int **ipp = &ip;
- 	 const int* const* cipp = ipp;
- 	 And, it doesn't make sense for that to be legal unless you
- 	 can dereference IPP and CIPP.  So, we ignore cv-qualifiers on
- 	 the pointed-to types.  This issue has been reported to the
- 	 C++ committee.  */
- 
-       /* In addition to the above canonicalization issue with LTO
-          we should also canonicalize `T (*)[]' to `T *' avoiding
- 	 alias issues with pointer-to element types and pointer-to
- 	 array types.
- 
- 	 Likewise we need to deal with the situation of incomplete
- 	 pointed-to types and make `*(struct X **)&a' and
- 	 `*(struct X {} **)&a' alias.  Otherwise we will have to
- 	 guarantee that all pointer-to incomplete type variants
- 	 will be replaced by pointer-to complete type variants if
- 	 they are available.
- 
- 	 With LTO the convenient situation of using `void *' to
- 	 access and store any pointer type will also become
- 	 more apparent (and `void *' is just another pointer-to
- 	 incomplete type).  Assigning alias-set zero to `void *'
- 	 and all pointer-to incomplete types is a not appealing
- 	 solution.  Assigning an effective alias-set zero only
- 	 affecting pointers might be - by recording proper subset
- 	 relationships of all pointer alias-sets.
- 
- 	 Pointer-to function types are another grey area which
- 	 needs caution.  Globbing them all into one alias-set
- 	 or the above effective zero set would work.  */
- 
-       /* For now just assign the same alias-set to all pointers.
-          That's simple and avoids all the above problems.  */
-       if (t != ptr_type_node)
- 	return get_alias_set (ptr_type_node);
-     }
  
    return -1;
  }
--- 4310,4315 ----
Index: gcc/alias.c
===================================================================
*** gcc/alias.c	(revision 160100)
--- gcc/alias.c	(working copy)
*************** get_alias_set (tree t)
*** 694,719 ****
        t = TREE_TYPE (t);
      }
  
!   /* Variant qualifiers don't affect the alias set, so get the main
!      variant.  */
!   t = TYPE_MAIN_VARIANT (t);
! 
!   /* Always use the canonical type as well.  If this is a type that
!      requires structural comparisons to identify compatible types
!      use alias set zero.  */
!   if (TYPE_STRUCTURAL_EQUALITY_P (t))
      {
!       /* Allow the language to specify another alias set for this
! 	 type.  */
!       set = lang_hooks.get_alias_set (t);
!       if (set != -1)
! 	return set;
!       return 0;
      }
-   t = TYPE_CANONICAL (t);
-   /* Canonical types shouldn't form a tree nor should the canonical
-      type require structural equality checks.  */
-   gcc_assert (!TYPE_STRUCTURAL_EQUALITY_P (t) && TYPE_CANONICAL (t) == t);
  
    /* If this is a type with a known alias set, return it.  */
    if (TYPE_ALIAS_SET_KNOWN_P (t))
--- 694,785 ----
        t = TREE_TYPE (t);
      }
  
!   /* Canonicalize the type.  */
!   if (POINTER_TYPE_P (t))
      {
!       /* From the common C and C++ langhook implementation:
! 
! 	 Unfortunately, there is no canonical form of a pointer type.
! 	 In particular, if we have `typedef int I', then `int *', and
! 	 `I *' are different types.  So, we have to pick a canonical
! 	 representative.  We do this below.
! 
! 	 Technically, this approach is actually more conservative that
! 	 it needs to be.  In particular, `const int *' and `int *'
! 	 should be in different alias sets, according to the C and C++
! 	 standard, since their types are not the same, and so,
! 	 technically, an `int **' and `const int **' cannot point at
! 	 the same thing.
! 
! 	 But, the standard is wrong.  In particular, this code is
! 	 legal C++:
! 
! 	 int *ip;
! 	 int **ipp = &ip;
! 	 const int* const* cipp = ipp;
! 	 And, it doesn't make sense for that to be legal unless you
! 	 can dereference IPP and CIPP.  So, we ignore cv-qualifiers on
! 	 the pointed-to types.  This issue has been reported to the
! 	 C++ committee.  */
! 
!       /* In addition to the above canonicalization issue with LTO
!          we should also canonicalize `T (*)[]' to `T *' avoiding
! 	 alias issues with pointer-to element types and pointer-to
! 	 array types.
! 
! 	 Likewise we need to deal with the situation of incomplete
! 	 pointed-to types and make `*(struct X **)&a' and
! 	 `*(struct X {} **)&a' alias.  Otherwise we will have to
! 	 guarantee that all pointer-to incomplete type variants
! 	 will be replaced by pointer-to complete type variants if
! 	 they are available.
! 
! 	 With LTO the convenient situation of using `void *' to
! 	 access and store any pointer type will also become
! 	 more apparent (and `void *' is just another pointer-to
! 	 incomplete type).  Assigning alias-set zero to `void *'
! 	 and all pointer-to incomplete types is a not appealing
! 	 solution.  Assigning an effective alias-set zero only
! 	 affecting pointers might be - by recording proper subset
! 	 relationships of all pointer alias-sets.
! 
! 	 Pointer-to function types are another grey area which
! 	 needs caution.  Globbing them all into one alias-set
! 	 or the above effective zero set would work.  */
! 
!       /* For now just assign the same alias-set to all pointers.
!          That's simple and avoids all the above problems.
! 	 Do so by canonicalizing all pointer types to void * pointers,
! 	 but allow different pointer modes to have different alias-sets.  */
!       if (TYPE_MODE (t) == TYPE_MODE (ptr_type_node))
! 	t = ptr_type_node;
!       else
! 	t = build_pointer_type_for_mode (void_type_node,
! 					 TYPE_MODE (t), false);
!     }
!   else
!     {
!       /* Variant qualifiers don't affect the alias set, so get the main
! 	 variant.  */
!       t = TYPE_MAIN_VARIANT (t);
! 
!       /* Always use the canonical type as well.  If this is a type that
! 	 requires structural comparisons to identify compatible types
! 	 use alias set zero.  */
!       if (TYPE_STRUCTURAL_EQUALITY_P (t))
! 	{
! 	  /* Allow the language to specify another alias set for this
! 	     type.  */
! 	  set = lang_hooks.get_alias_set (t);
! 	  if (set != -1)
! 	    return set;
! 	  return 0;
! 	}
!       t = TYPE_CANONICAL (t);
!       /* Canonical types shouldn't form a tree nor should the canonical
! 	 type require structural equality checks.  */
!       gcc_assert (!TYPE_STRUCTURAL_EQUALITY_P (t) && TYPE_CANONICAL (t) == t);
      }
  
    /* If this is a type with a known alias set, return it.  */
    if (TYPE_ALIAS_SET_KNOWN_P (t))
*************** get_alias_set (tree t)
*** 724,730 ****
      {
        /* For arrays with unknown size the conservative answer is the
  	 alias set of the element type.  */
!       if (TREE_CODE (t) == ARRAY_TYPE)
  	return get_alias_set (TREE_TYPE (t));
  
        /* But return zero as a conservative answer for incomplete types.  */
--- 790,797 ----
      {
        /* For arrays with unknown size the conservative answer is the
  	 alias set of the element type.  */
!       if (TREE_CODE (t) == ARRAY_TYPE
! 	  && !TYPE_NONALIASED_COMPONENT (t))
  	return get_alias_set (TREE_TYPE (t));
  
        /* But return zero as a conservative answer for incomplete types.  */
*************** get_alias_set (tree t)
*** 739,746 ****
    /* There are no objects of FUNCTION_TYPE, so there's no point in
       using up an alias set for them.  (There are, of course, pointers
       and references to functions, but that's different.)  */
!   else if (TREE_CODE (t) == FUNCTION_TYPE
! 	   || TREE_CODE (t) == METHOD_TYPE)
      set = 0;
  
    /* Unless the language specifies otherwise, let vector types alias
--- 806,813 ----
    /* There are no objects of FUNCTION_TYPE, so there's no point in
       using up an alias set for them.  (There are, of course, pointers
       and references to functions, but that's different.)  */
!   if (TREE_CODE (t) == FUNCTION_TYPE
!       || TREE_CODE (t) == METHOD_TYPE)
      set = 0;
  
    /* Unless the language specifies otherwise, let vector types alias



More information about the Gcc-patches mailing list