From f85d24870891e785a86e1c394ca559953b262d2d Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Sun, 22 Nov 2015 00:59:49 +0100 Subject: [PATCH] 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 --- gcc/ChangeLog | 15 ++++++++ gcc/alias.c | 95 +++++++++++++++++++++++++++++++++++++---------- gcc/lto/ChangeLog | 9 ++++- gcc/lto/lto.c | 13 +++++-- gcc/tree.c | 22 +++++++++-- 5 files changed, 126 insertions(+), 28 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ee27e99b2c7..00db0ba305f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2015-11-21 Jan Hubicka + + * 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 * config/nvptx/nvptx.md (clz2): Use operand 1 for type. diff --git a/gcc/alias.c b/gcc/alias.c index 42605c24a6c..f3f79869a8b 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 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 49adea61104..410533710ae 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,4 +1,11 @@ -2015-11-11 Jan Hubicka +2015-11-21 Jan Hubicka + + * 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 * 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 36138e854d1..26614912e3b 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 d5a71a3ded9..779fe9386a2 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)); -- 2.30.2