This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][LTO] Fix PR41576, hide gimple_types_compatible_p better
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Diego Novillo <dnovillo at google dot com>
- Date: Tue, 6 Oct 2009 17:39:34 +0200 (CEST)
- Subject: [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, >c_visited);
p->same_p = 1;
+ p = lookup_type_pair (t1, t2, >se_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, >c_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, >c_visited);
+ }
+ int
+ gimple_types_structurally_equivalent_p (tree type1, tree type2)
+ {
+ return compare_and_maybe_complete_types (type1, type2, true, >se_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, >c_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];