On Mon, 1 Jun 2015, Jan Hubicka wrote: > Hi, > this patch removes the check for TREE_CODE of pointer types when computing > canonical types. It also adds a testcase for fortran C_PTR type that should be > compatible with all C pointers. Can someone familiar with Fortran double check > that the testcase is indeed defined by the standard? > > I needed to hack get_alias_set because TYPE_CANONICAL of ptr_type_node is no > longer ptr_type_node. This is ugly, but I plan to drop that code path anyway. > (the idea is to get type merging correct and then enable the non-LTO scheme > of get_alias_set for LTO, too). > > Bootstrapped/regtested ppc64-linux, OK?
Ok. Thanks, Richard. > Honza > > * alias.c (get_alias_set): Be ready for TYPE_CANONICAL > of ptr_type_node to not be ptr_to_node. > * tree.c (gimple_types_compatible_p): Do not match TREE_CODE of > TREE_TYPE of pointers > > * lto.c (hash_canonical_type): Do not hash TREE_CODE of TREE_TYPE of > pointers. > > * gfortran.dg/lto/bind_c-1_0.f90: New testcase. > * gfortran.dg/lto/bind_c-1_1.c: New testcase. > Index: alias.c > =================================================================== > --- alias.c (revision 223891) > +++ alias.c (working copy) > @@ -1076,8 +1076,9 @@ > } > /* In LTO the rules above needs to be part of canonical type machinery. > For now just punt. */ > - else if (POINTER_TYPE_P (t) && t != ptr_type_node && in_lto_p) > - set = get_alias_set (ptr_type_node); > + else if (POINTER_TYPE_P (t) > + && t != TYPE_CANONICAL (ptr_type_node) && in_lto_p) > + set = get_alias_set (TYPE_CANONICAL (ptr_type_node)); > > /* Otherwise make a new alias set for this type. */ > else > Index: lto/lto.c > =================================================================== > --- lto/lto.c (revision 223891) > +++ lto/lto.c (working copy) > @@ -342,12 +342,12 @@ > if (TREE_CODE (type) == COMPLEX_TYPE) > hstate.add_int (TYPE_UNSIGNED (type)); > > - /* For pointer and reference types, fold in information about the type > - pointed to but do not recurse to the pointed-to type. */ > + /* Fortran standard define C_PTR type that is compatible with every > + C pointer. For this reason we need to glob all pointers into one. > + Still pointers in different address spaces are not compatible. */ > if (POINTER_TYPE_P (type)) > { > hstate.add_int (TYPE_ADDR_SPACE (TREE_TYPE (type))); > - hstate.add_int (TREE_CODE (TREE_TYPE (type))); > } > > /* For integer types hash only the string flag. */ > Index: testsuite/gfortran.dg/lto/bind_c-1_0.f90 > =================================================================== > --- testsuite/gfortran.dg/lto/bind_c-1_0.f90 (revision 0) > +++ testsuite/gfortran.dg/lto/bind_c-1_0.f90 (working copy) > @@ -0,0 +1,21 @@ > +! { dg-do run } > +! { dg-lto-options {{ -O3 -flto }} } > +! This testcase will abort if C_PTR is not interoperable with both int * > +! and float * > +module lto_type_merge_test > + use, intrinsic :: iso_c_binding > + implicit none > + > + type, bind(c) :: MYFTYPE_1 > + type(c_ptr) :: ptr > + type(c_ptr) :: ptrb > + end type MYFTYPE_1 > + > + type(myftype_1), bind(c, name="myVar") :: myVar > + > +contains > + subroutine types_test() bind(c) > + myVar%ptr = myVar%ptrb > + end subroutine types_test > +end module lto_type_merge_test > + > Index: testsuite/gfortran.dg/lto/bind_c-1_1.c > =================================================================== > --- testsuite/gfortran.dg/lto/bind_c-1_1.c (revision 0) > +++ testsuite/gfortran.dg/lto/bind_c-1_1.c (working copy) > @@ -0,0 +1,36 @@ > +#include <stdlib.h> > +/* interopse with myftype_1 */ > +typedef struct { > + float *ptr; > + int *ptr2; > +} myctype_t; > + > + > +extern void abort(void); > +void types_test(void); > +/* declared in the fortran module */ > +extern myctype_t myVar; > + > +int main(int argc, char **argv) > +{ > + myctype_t *cptr; > + asm("":"=r"(cptr):"0"(&myVar)); > + cptr->ptr = (float *)(size_t) (void *)1; > + cptr->ptr2 = (int *)(size_t) (void *)2; > + > + types_test(); > + > + if(cptr->ptr != (float *)(size_t) (void *)2) > + abort(); > + if(cptr->ptr2 != (int *)(size_t) (void *)2) > + abort(); > + myVar.ptr2 = (int *)(size_t) (void *)3; > + types_test(); > + > + if(myVar.ptr != (float *)(size_t) (void *)3) > + abort(); > + if(myVar.ptr2 != (int *)(size_t) (void *)3) > + abort(); > + return 0; > +} > + > Index: tree.c > =================================================================== > --- tree.c (revision 223891) > +++ tree.c (working copy) > @@ -12909,18 +12910,14 @@ > && TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)) > return false; > > - /* For canonical type comparisons we do not want to build SCCs > - so we cannot compare pointed-to types. But we can, for now, > - require the same pointed-to type kind and match what > - useless_type_conversion_p would do. */ > + /* Fortran standard define C_PTR type that is compatible with every > + C pointer. For this reason we need to glob all pointers into one. > + Still pointers in different address spaces are not compatible. */ > if (POINTER_TYPE_P (t1)) > { > if (TYPE_ADDR_SPACE (TREE_TYPE (t1)) > != TYPE_ADDR_SPACE (TREE_TYPE (t2))) > return false; > - > - if (TREE_CODE (TREE_TYPE (t1)) != TREE_CODE (TREE_TYPE (t2))) > - return false; > } > > /* Tail-recurse to components. */ > Index: tree.h > =================================================================== > --- tree.h (revision 223891) > +++ tree.h (working copy) > @@ -4598,7 +4598,28 @@ > extern void DEBUG_FUNCTION verify_type (const_tree t); > extern bool gimple_canonical_types_compatible_p (const_tree, const_tree, > bool trust_type_canonical = > true); > +/* Return simplified tree code of type that is used for canonical type > merging. */ > +inline enum tree_code > +tree_code_for_canonical_type_merging (enum tree_code code) > +{ > + /* By C standard, each enumerated type shall be compatible with char, > + a signed integer, or an unsigned integer. The choice of type is > + implementation defined (in our case it depends on -fshort-enum). > > + For this reason we make no distinction between ENUMERAL_TYPE and INTEGER > + type and compare only by their signedness and precision. */ > + if (code == ENUMERAL_TYPE) > + return INTEGER_TYPE; > + /* To allow inter-operability between languages having references and > + C, we consider reference types and pointers alike. Note that this is > + not strictly necessary for C-Fortran 2008 interoperability because > + Fortran define C_PTR type that needs to be compatible with C pointers > + and we handle this one as ptr_type_node. */ > + if (code == REFERENCE_TYPE) > + return POINTER_TYPE; > + return code; > +} > + > #define tree_map_eq tree_map_base_eq > extern unsigned int tree_map_hash (const void *); > #define tree_map_marked_p tree_map_base_marked_p > > -- Richard Biener <rguent...@suse.de> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Dilip Upmanyu, Graham Norton, HRB 21284 (AG Nuernberg)