Commit f85d2487 by Jan Hubicka Committed by Jan Hubicka

lto.c (iterative_hash_canonical_type): Always recurse for pointers.


	* lto.c (iterative_hash_canonical_type): Always recurse for pointers.
	(gimple_register_canonical_type_1): Check that pointers do not get
	canonical types.
	(gimple_register_canonical_type): Do not register pointers.

	* tree.c (build_pointer_type_for_mode,build_reference_type_for_mode):
	In LTO we do not compute TYPE_CANONICAL of pointers.
	(gimple_canonical_types_compatible_p): Improve coments; sanity check
	that pointers do not have canonical type that would make us believe
	they are different.
	* alias.c (get_alias_set): Do structural type equality on pointers;
	enable pointer path for LTO; also glob pointer to vector with pointer
	to vector element; glob pointers and references for LTO; do more strict
	sanity checking about build_pointer_type returning the canonical type
	which is also the main variant.
	(record_component_aliases): When component type is pointer and we
	do LTO; record void_type_node alias set.

From-SVN: r230715
parent feb391fc
2015-11-21 Jan Hubicka <hubicka@ucw.cz>
* tree.c (build_pointer_type_for_mode,build_reference_type_for_mode):
In LTO we do not compute TYPE_CANONICAL of pointers.
(gimple_canonical_types_compatible_p): Improve coments; sanity check
that pointers do not have canonical type that would make us believe
they are different.
* alias.c (get_alias_set): Do structural type equality on pointers;
enable pointer path for LTO; also glob pointer to vector with pointer
to vector element; glob pointers and references for LTO; do more strict
sanity checking about build_pointer_type returning the canonical type
which is also the main variant.
(record_component_aliases): When component type is pointer and we
do LTO; record void_type_node alias set.
2015-11-21 Nathan Sidwell <nathan@acm.org>
* config/nvptx/nvptx.md (clz<mode>2): Use operand 1 for type.
......@@ -869,13 +869,23 @@ get_alias_set (tree t)
set = lang_hooks.get_alias_set (t);
if (set != -1)
return set;
return 0;
/* Handle structure type equality for pointer types. This is easy
to do, because the code bellow ignore canonical types on these anyway.
This is important for LTO, where TYPE_CANONICAL for pointers can not
be meaningfuly computed by the frotnend. */
if (!POINTER_TYPE_P (t))
{
/* In LTO we set canonical types for all types where it makes
sense to do so. Double check we did not miss some type. */
gcc_checking_assert (!in_lto_p || !type_with_alias_set_p (t));
return 0;
}
}
else
{
t = TYPE_CANONICAL (t);
gcc_checking_assert (!TYPE_STRUCTURAL_EQUALITY_P (t));
}
t = TYPE_CANONICAL (t);
/* The canonical type should not require structural equality checks. */
gcc_checking_assert (!TYPE_STRUCTURAL_EQUALITY_P (t));
/* If this is a type with a known alias set, return it. */
if (TYPE_ALIAS_SET_KNOWN_P (t))
......@@ -952,20 +962,23 @@ get_alias_set (tree t)
ptr_type_node but that is a bad idea, because it prevents disabiguations
in between pointers. For Firefox this accounts about 20% of all
disambiguations in the program. */
else if (POINTER_TYPE_P (t) && t != ptr_type_node && !in_lto_p)
else if (POINTER_TYPE_P (t) && t != ptr_type_node)
{
tree p;
auto_vec <bool, 8> reference;
/* Unnest all pointers and references.
We also want to make pointer to array equivalent to pointer to its
element. So skip all array types, too. */
We also want to make pointer to array/vector equivalent to pointer to
its element (see the reasoning above). Skip all those types, too. */
for (p = t; POINTER_TYPE_P (p)
|| (TREE_CODE (p) == ARRAY_TYPE && !TYPE_NONALIASED_COMPONENT (p));
|| (TREE_CODE (p) == ARRAY_TYPE && !TYPE_NONALIASED_COMPONENT (p))
|| TREE_CODE (p) == VECTOR_TYPE;
p = TREE_TYPE (p))
{
if (TREE_CODE (p) == REFERENCE_TYPE)
reference.safe_push (true);
/* In LTO we want languages that use references to be compatible
with languages that use pointers. */
reference.safe_push (true && !in_lto_p);
if (TREE_CODE (p) == POINTER_TYPE)
reference.safe_push (false);
}
......@@ -981,7 +994,7 @@ get_alias_set (tree t)
set = get_alias_set (ptr_type_node);
else
{
/* Rebuild pointer type from starting from canonical types using
/* Rebuild pointer type starting from canonical types using
unqualified pointers and references only. This way all such
pointers will have the same alias set and will conflict with
each other.
......@@ -998,9 +1011,15 @@ get_alias_set (tree t)
p = build_reference_type (p);
else
p = build_pointer_type (p);
p = TYPE_CANONICAL (TYPE_MAIN_VARIANT (p));
gcc_checking_assert (p == TYPE_MAIN_VARIANT (p));
/* build_pointer_type should always return the canonical type.
For LTO TYPE_CANOINCAL may be NULL, because we do not compute
them. Be sure that frontends do not glob canonical types of
pointers in unexpected way and that p == TYPE_CANONICAL (p)
in all other cases. */
gcc_checking_assert (!TYPE_CANONICAL (p)
|| p == TYPE_CANONICAL (p));
}
gcc_checking_assert (TYPE_CANONICAL (p) == p);
/* Assign the alias set to both p and t.
We can not call get_alias_set (p) here as that would trigger
......@@ -1015,11 +1034,12 @@ get_alias_set (tree t)
}
}
}
/* In LTO the rules above needs to be part of canonical type machinery.
For now just punt. */
else if (POINTER_TYPE_P (t)
&& t != TYPE_CANONICAL (ptr_type_node) && in_lto_p)
set = get_alias_set (TYPE_CANONICAL (ptr_type_node));
/* Alias set of ptr_type_node is special and serve as universal pointer which
is TBAA compatible with every other pointer type. Be sure we have the
alias set built even for LTO which otherwise keeps all TYPE_CANONICAL
of pointer types NULL. */
else if (t == ptr_type_node)
set = new_alias_set ();
/* Otherwise make a new alias set for this type. */
else
......@@ -1155,7 +1175,42 @@ record_component_aliases (tree type)
case QUAL_UNION_TYPE:
for (field = TYPE_FIELDS (type); field != 0; field = DECL_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL && !DECL_NONADDRESSABLE_P (field))
record_alias_subset (superset, get_alias_set (TREE_TYPE (field)));
{
/* LTO type merging does not make any difference between
component pointer types. We may have
struct foo {int *a;};
as TYPE_CANONICAL of
struct bar {float *a;};
Because accesses to int * and float * do not alias, we would get
false negative when accessing the same memory location by
float ** and bar *. We thus record the canonical type as:
struct {void *a;};
void * is special cased and works as a universal pointer type.
Accesses to it conflicts with accesses to any other pointer
type. */
tree t = TREE_TYPE (field);
if (in_lto_p)
{
/* VECTOR_TYPE and ARRAY_TYPE share the alias set with their
element type and that type has to be normalized to void *,
too, in the case it is a pointer. */
while ((TREE_CODE (t) == ARRAY_TYPE
&& (!COMPLETE_TYPE_P (t)
|| TYPE_NONALIASED_COMPONENT (t)))
|| TREE_CODE (t) == VECTOR_TYPE)
t = TREE_TYPE (t);
if (POINTER_TYPE_P (t))
t = ptr_type_node;
}
record_alias_subset (superset, get_alias_set (t));
}
break;
case COMPLEX_TYPE:
......
2015-11-11 Jan Hubicka <hubicka@ucw.cz>
2015-11-21 Jan Hubicka <hubicka@ucw.cz>
* lto.c (iterative_hash_canonical_type): Always recurse for pointers.
(gimple_register_canonical_type_1): Check that pointers do not get
canonical types.
(gimple_register_canonical_type): Do not register pointers.
2015-11-21 Jan Hubicka <hubicka@ucw.cz>
* lto-symtab.c (warn_type_compatibility_p): Do not set ODR mismatch
flag for types that are not ODR; fix loop walking parameters.
......
......@@ -388,8 +388,13 @@ iterative_hash_canonical_type (tree type, inchash::hash &hstate)
/* All type variants have same TYPE_CANONICAL. */
type = TYPE_MAIN_VARIANT (type);
/* We do not compute TYPE_CANONICAl of POINTER_TYPE because the aliasing
code never use it anyway. */
if (POINTER_TYPE_P (type))
v = hash_canonical_type (type);
/* An already processed type. */
if (TYPE_CANONICAL (type))
else if (TYPE_CANONICAL (type))
{
type = TYPE_CANONICAL (type);
v = gimple_canonical_type_hash (type);
......@@ -437,7 +442,9 @@ gimple_register_canonical_type_1 (tree t, hashval_t hash)
{
void **slot;
gcc_checking_assert (TYPE_P (t) && !TYPE_CANONICAL (t));
gcc_checking_assert (TYPE_P (t) && !TYPE_CANONICAL (t)
&& type_with_alias_set_p (t)
&& !POINTER_TYPE_P (t));
slot = htab_find_slot_with_hash (gimple_canonical_types, t, hash, INSERT);
if (*slot)
......@@ -470,7 +477,7 @@ gimple_register_canonical_type_1 (tree t, hashval_t hash)
static void
gimple_register_canonical_type (tree t)
{
if (TYPE_CANONICAL (t) || !type_with_alias_set_p (t))
if (TYPE_CANONICAL (t) || !type_with_alias_set_p (t) || POINTER_TYPE_P (t))
return;
/* Canonical types are same among all complete variants. */
......
......@@ -7919,7 +7919,8 @@ build_pointer_type_for_mode (tree to_type, machine_mode mode,
TYPE_NEXT_PTR_TO (t) = TYPE_POINTER_TO (to_type);
TYPE_POINTER_TO (to_type) = t;
if (TYPE_STRUCTURAL_EQUALITY_P (to_type))
/* During LTO we do not set TYPE_CANONICAL of pointers and references. */
if (TYPE_STRUCTURAL_EQUALITY_P (to_type) || in_lto_p)
SET_TYPE_STRUCTURAL_EQUALITY (t);
else if (TYPE_CANONICAL (to_type) != to_type || could_alias)
TYPE_CANONICAL (t)
......@@ -7987,7 +7988,8 @@ build_reference_type_for_mode (tree to_type, machine_mode mode,
TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (to_type);
TYPE_REFERENCE_TO (to_type) = t;
if (TYPE_STRUCTURAL_EQUALITY_P (to_type))
/* During LTO we do not set TYPE_CANONICAL of pointers and references. */
if (TYPE_STRUCTURAL_EQUALITY_P (to_type) || in_lto_p)
SET_TYPE_STRUCTURAL_EQUALITY (t);
else if (TYPE_CANONICAL (to_type) != to_type || could_alias)
TYPE_CANONICAL (t)
......@@ -13224,7 +13226,9 @@ type_with_interoperable_signedness (const_tree type)
TBAA is concerned.
This function is used both by lto.c canonical type merging and by the
verifier. If TRUST_TYPE_CANONICAL we do not look into structure of types
that have TYPE_CANONICAL defined and assume them equivalent. */
that have TYPE_CANONICAL defined and assume them equivalent. This is useful
only for LTO because only in these cases TYPE_CANONICAL equivalence
correspond to one defined by gimple_canonical_types_compatible_p. */
bool
gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
......@@ -13265,9 +13269,19 @@ gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
|| (type_with_alias_set_p (t1) && type_with_alias_set_p (t2)));
/* If the types have been previously registered and found equal
they still are. */
if (TYPE_CANONICAL (t1) && TYPE_CANONICAL (t2)
&& trust_type_canonical)
return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2);
{
/* Do not use TYPE_CANONICAL of pointer types. For LTO streamed types
they are always NULL, but they are set to non-NULL for types
constructed by build_pointer_type and variants. In this case the
TYPE_CANONICAL is more fine grained than the equivalnce we test (where
all pointers are considered equal. Be sure to not return false
negatives. */
gcc_checking_assert (!POINTER_TYPE_P (t1) && !POINTER_TYPE_P (t2));
return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2);
}
/* Can't be the same type if the types don't have the same code. */
enum tree_code code = tree_code_for_canonical_type_merging (TREE_CODE (t1));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment