aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2015-11-22 00:59:49 +0100
committerJan Hubicka <hubicka@gcc.gnu.org>2015-11-21 23:59:49 +0000
commitf85d24870891e785a86e1c394ca559953b262d2d (patch)
tree8ce584973badca7655229ceeb55de6f4eed7e8d7 /gcc
parentfeb391fc5d47f7bd3860fe192a7a73531cbde77f (diff)
downloadgcc-f85d24870891e785a86e1c394ca559953b262d2d.zip
gcc-f85d24870891e785a86e1c394ca559953b262d2d.tar.gz
gcc-f85d24870891e785a86e1c394ca559953b262d2d.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/alias.c95
-rw-r--r--gcc/lto/ChangeLog9
-rw-r--r--gcc/lto/lto.c13
-rw-r--r--gcc/tree.c22
5 files changed, 126 insertions, 28 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ee27e99..00db0ba 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+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.
diff --git a/gcc/alias.c b/gcc/alias.c
index 42605c2..f3f7986 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -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:
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 49adea6..4105337 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,4 +1,11 @@
-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.
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 36138e8..2661491 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -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. */
diff --git a/gcc/tree.c b/gcc/tree.c
index d5a71a3..779fe93 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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));