Commit a0276c00 by Jan Hubicka Committed by Jan Hubicka

class.c (layout_class_type): Set TYPE_CXX_ODR_P for as-base type copy.



	* class.c (layout_class_type): Set TYPE_CXX_ODR_P for as-base
	type copy.

	* ipa-devirt.c (odr_type_d): Add tbaa_enabled flag.
	(add_type_duplicate): When odr hash is not allocated, to nothing.
	(odr_based_tbaa_p): New function.
	(set_type_canonical_for_odr_type): New function.
	* ipa-utils.h (enable_odr_based_tbaa, odr_based_tbaa_p,
	set_type_canonical_for_odr_type): New.
	* tree.c (gimple_canonical_types_compatible_p): ODR types with
	ODR based TBAA are not equivalent to non-ODR types.

	* lto-common.c: Include demangle.h and tree-pretty-print.h
	(type_streaming_finished): New static var.
	(gimple_register_canonical_type_1): Return updated hash; handle ODR
	types.
	(iterative_hash_canonical_type): Update use of
	gimple_register_canonical_type_1.

	* g++.dg/lto/alias-2_0.C: New testcase.
	* g++.dg/lto/alias-2_1.C: New testcase.

From-SVN: r272749
parent ef874db6
2019-06-27 Jan Hubicka <jh@suse.cz>
* ipa-devirt.c (odr_type_d): Add tbaa_enabled flag.
(add_type_duplicate): When odr hash is not allocated, to nothing.
(odr_based_tbaa_p): New function.
(set_type_canonical_for_odr_type): New function.
* ipa-utils.h (enable_odr_based_tbaa, odr_based_tbaa_p,
set_type_canonical_for_odr_type): New.
* tree.c (gimple_canonical_types_compatible_p): ODR types with
ODR based TBAA are not equivalent to non-ODR types.
2019-06-27 Martin Liska <mliska@suse.cz>
PR tree-optimization/90974
......
2019-06-27 Jan Hubicka <jh@suse.cz>
* class.c (layout_class_type): Set TYPE_CXX_ODR_P for as-base
type copy.
2019-06-27 Martin Liska <mliska@suse.cz>
* class.c (adjust_clone_args): Remove obviously
......
......@@ -6393,6 +6393,7 @@ layout_class_type (tree t, tree *virtuals_p)
SET_TYPE_ALIGN (base_t, rli->record_align);
TYPE_USER_ALIGN (base_t) = TYPE_USER_ALIGN (t);
TYPE_TYPELESS_STORAGE (base_t) = TYPE_TYPELESS_STORAGE (t);
TYPE_CXX_ODR_P (base_t) = TYPE_CXX_ODR_P (t);
/* Copy the non-static data members of T. This will include its
direct non-virtual bases & vtable. */
......
......@@ -213,6 +213,8 @@ struct GTY(()) odr_type_d
bool odr_violated;
/* Set when virtual table without RTTI previaled table with. */
bool rtti_broken;
/* Set when the canonical type is determined using the type name. */
bool tbaa_enabled;
};
/* Return TRUE if all derived types of T are known and thus
......@@ -1610,6 +1612,9 @@ add_type_duplicate (odr_type val, tree type)
val->types_set->add (type);
if (!odr_hash)
return NULL;
gcc_checking_assert (can_be_name_hashed_p (type)
&& can_be_name_hashed_p (val->type));
......@@ -1989,6 +1994,46 @@ prevailing_odr_type (tree type)
return t->type;
}
/* Set tbaa_enabled flag for TYPE. */
void
enable_odr_based_tbaa (tree type)
{
odr_type t = get_odr_type (type, true);
t->tbaa_enabled = true;
}
/* True if canonical type of TYPE is determined using ODR name. */
bool
odr_based_tbaa_p (const_tree type)
{
if (!RECORD_OR_UNION_TYPE_P (type))
return false;
odr_type t = get_odr_type (const_cast <tree> (type), false);
if (!t || !t->tbaa_enabled)
return false;
return true;
}
/* Set TYPE_CANONICAL of type and all its variants and duplicates
to CANONICAL. */
void
set_type_canonical_for_odr_type (tree type, tree canonical)
{
odr_type t = get_odr_type (type, false);
unsigned int i;
tree tt;
for (tree t2 = t->type; t2; t2 = TYPE_NEXT_VARIANT (t2))
TYPE_CANONICAL (t2) = canonical;
if (t->types)
FOR_EACH_VEC_ELT (*t->types, i, tt)
for (tree t2 = tt; t2; t2 = TYPE_NEXT_VARIANT (t2))
TYPE_CANONICAL (t2) = canonical;
}
/* Return true if we reported some ODR violation on TYPE. */
bool
......
......@@ -93,6 +93,9 @@ bool odr_or_derived_type_p (const_tree t);
bool odr_types_equivalent_p (tree type1, tree type2);
bool odr_type_violation_reported_p (tree type);
tree prevailing_odr_type (tree type);
void enable_odr_based_tbaa (tree type);
bool odr_based_tbaa_p (const_tree type);
void set_type_canonical_for_odr_type (tree type, tree canonical);
/* Return vector containing possible targets of polymorphic call E.
If COMPLETEP is non-NULL, store true if the list is complete.
......
/* Top-level LTO routines.
Copyright (C) 2009-2018 Free Software Foundation, Inc.
Copyright (C) 2009-2019 Free Software Foundation, Inc.
Contributed by CodeSourcery, Inc.
This file is part of GCC.
......@@ -56,6 +56,11 @@ along with GCC; see the file COPYING3. If not see
#include "attribs.h"
#include "builtins.h"
#include "lto-common.h"
#include "tree-pretty-print.h"
/* True when no new types are going to be streamd from the global stream. */
static bool type_streaming_finished = false;
GTY(()) tree first_personality_decl;
......@@ -217,9 +222,14 @@ static hash_map<const_tree, hashval_t> *canonical_type_hash_cache;
static unsigned long num_canonical_type_hash_entries;
static unsigned long num_canonical_type_hash_queries;
/* Types postponed for registration to the canonical type table.
During streaming we postpone all TYPE_CXX_ODR_P types so we can alter
decide whether there is conflict with non-ODR type or not. */
static GTY(()) vec<tree, va_gc> *types_to_register = NULL;
static void iterative_hash_canonical_type (tree type, inchash::hash &hstate);
static hashval_t gimple_canonical_type_hash (const void *p);
static void gimple_register_canonical_type_1 (tree t, hashval_t hash);
static hashval_t gimple_register_canonical_type_1 (tree t, hashval_t hash);
/* Returning a hash value for gimple type TYPE.
......@@ -357,9 +367,9 @@ iterative_hash_canonical_type (tree type, inchash::hash &hstate)
optimal order. To avoid quadratic behavior also register the
type here. */
v = hash_canonical_type (type);
gimple_register_canonical_type_1 (type, v);
v = gimple_register_canonical_type_1 (type, v);
}
hstate.add_int (v);
hstate.merge_hash (v);
}
/* Returns the hash for a canonical type P. */
......@@ -388,7 +398,7 @@ gimple_canonical_type_eq (const void *p1, const void *p2)
/* Main worker for gimple_register_canonical_type. */
static void
static hashval_t
gimple_register_canonical_type_1 (tree t, hashval_t hash)
{
void **slot;
......@@ -397,6 +407,75 @@ gimple_register_canonical_type_1 (tree t, hashval_t hash)
&& type_with_alias_set_p (t)
&& canonical_type_used_p (t));
/* ODR types for which there is no ODR violation and we did not record
structurally equivalent non-ODR type can be treated as unique by their
name.
hash passed to gimple_register_canonical_type_1 is a structural hash
that we can use to lookup structurally equivalent non-ODR type.
In case we decide to treat type as unique ODR type we recompute hash based
on name and let TBAA machinery know about our decision. */
if (RECORD_OR_UNION_TYPE_P (t)
&& odr_type_p (t) && !odr_type_violation_reported_p (t))
{
/* Here we rely on fact that all non-ODR types was inserted into
canonical type hash and thus we can safely detect conflicts between
ODR types and interoperable non-ODR types. */
gcc_checking_assert (type_streaming_finished
&& TYPE_MAIN_VARIANT (t) == t);
slot = htab_find_slot_with_hash (gimple_canonical_types, t, hash,
NO_INSERT);
if (slot && !TYPE_CXX_ODR_P (*(tree *)slot))
{
tree nonodr = *(tree *)slot;
if (symtab->dump_file)
{
fprintf (symtab->dump_file,
"ODR and non-ODR type conflict: ");
print_generic_expr (symtab->dump_file, t);
fprintf (symtab->dump_file, " and ");
print_generic_expr (symtab->dump_file, nonodr);
fprintf (symtab->dump_file, " mangled:%s\n",
IDENTIFIER_POINTER
(DECL_ASSEMBLER_NAME (TYPE_NAME (t))));
}
/* Set canonical for T and all other ODR equivalent duplicates
including incomplete structures. */
set_type_canonical_for_odr_type (t, nonodr);
}
else
{
tree prevail = prevailing_odr_type (t);
if (symtab->dump_file)
{
fprintf (symtab->dump_file,
"New canonical ODR type: ");
print_generic_expr (symtab->dump_file, t);
fprintf (symtab->dump_file, " mangled:%s\n",
IDENTIFIER_POINTER
(DECL_ASSEMBLER_NAME (TYPE_NAME (t))));
}
/* Set canonical for T and all other ODR equivalent duplicates
including incomplete structures. */
set_type_canonical_for_odr_type (t, prevail);
enable_odr_based_tbaa (t);
if (!type_in_anonymous_namespace_p (t))
hash = htab_hash_string (IDENTIFIER_POINTER
(DECL_ASSEMBLER_NAME
(TYPE_NAME (t))));
else
hash = TYPE_UID (t);
/* All variants of t now have TYPE_CANONICAL set to prevail.
Update canonical type hash cache accordingly. */
num_canonical_type_hash_entries++;
bool existed_p = canonical_type_hash_cache->put (prevail, hash);
gcc_checking_assert (!existed_p);
}
return hash;
}
slot = htab_find_slot_with_hash (gimple_canonical_types, t, hash, INSERT);
if (*slot)
{
......@@ -413,6 +492,7 @@ gimple_register_canonical_type_1 (tree t, hashval_t hash)
bool existed_p = canonical_type_hash_cache->put (t, hash);
gcc_assert (!existed_p);
}
return hash;
}
/* Register type T in the global type table gimple_types and set
......@@ -464,6 +544,34 @@ lto_register_canonical_types (tree node, bool first_p)
gimple_register_canonical_type (node);
}
/* Finish canonical type calculation: after all units has been streamed in we
can check if given ODR type structurally conflicts with a non-ODR type. In
the first case we set type canonical according to the canonical type hash.
In the second case we use type names. */
static void
lto_register_canonical_types_for_odr_types ()
{
tree t;
unsigned int i;
if (!types_to_register)
return;
type_streaming_finished = true;
/* Be sure that no types derived from ODR types was
not inserted into the hash table. */
if (flag_checking)
FOR_EACH_VEC_ELT (*types_to_register, i, t)
gcc_assert (!TYPE_CANONICAL (t));
/* Register all remaining types. */
FOR_EACH_VEC_ELT (*types_to_register, i, t)
if (!TYPE_CANONICAL (t))
gimple_register_canonical_type (t);
}
/* Remember trees that contains references to declarations. */
vec <tree, va_gc> *tree_with_vars;
......@@ -1657,6 +1765,7 @@ unify_scc (struct data_in *data_in, unsigned from,
}
/* Read all the symbols from buffer DATA, using descriptors in DECL_DATA.
RESOLUTIONS is the set of symbols picked by the linker (read from the
resolution file when the linker plugin is being used). */
......@@ -1749,12 +1858,23 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data,
num_prevailing_types++;
lto_fixup_prevailing_type (t);
/* Compute the canonical type of all types.
/* Compute the canonical type of all non-ODR types.
Delay ODR types for the end of merging process - the canonical
type for those can be computed using the (unique) name however
we want to do this only if units in other languages do not
contain structurally equivalent type.
Because SCC components are streamed in random (hash) order
we may have encountered the type before while registering
type canonical of a derived type in the same SCC. */
if (!TYPE_CANONICAL (t))
gimple_register_canonical_type (t);
{
if (!RECORD_OR_UNION_TYPE_P (t)
|| !TYPE_CXX_ODR_P (t))
gimple_register_canonical_type (t);
else if (COMPLETE_TYPE_P (t))
vec_safe_push (types_to_register, t);
}
if (TYPE_MAIN_VARIANT (t) == t && odr_type_p (t))
register_odr_type (t);
}
......@@ -2605,6 +2725,8 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
ggc_free(decl_data);
real_file_decl_data = NULL;
lto_register_canonical_types_for_odr_types ();
if (resolution_file_name)
fclose (resolution);
......
2019-06-27 Jan Hubicka <jh@suse.cz>
* g++.dg/lto/alias-2_0.C: New testcase.
* g++.dg/lto/alias-2_1.C: New testcase.
2019-06-27 Jakub Jelinek <jakub@redhat.com>
PR target/90991
......
/* { dg-lto-do run } */
/* { dg-lto-options { { -O2 -flto } } } */
/* With LTO we consider all pointers to incomplete types to be possibly
aliasing. This makes *bptr to alias with aptr.
For C++ ODR types we however can work out that they are actually
different. */
#include <string.h>
typedef int (*fnptr) ();
__attribute__ ((used))
struct a *aptr;
__attribute__ ((used))
struct b **bptr = (struct b**)&aptr;
extern void init ();
extern void inline_me_late (int);
int
main (int argc, char **argv)
{
init ();
aptr = 0;
inline_me_late (argc);
if (!__builtin_constant_p (aptr == 0))
__builtin_abort ();
return (size_t)aptr;
}
#include <string.h>
struct a {int a;} a;
struct b {int b;} b;
extern struct b **bptr;
void
inline_me_late (int argc)
{
if (argc == -1)
*bptr = (struct b *)(size_t)1;
}
void
init()
{
a.a=1;
b.b=2;
}
......@@ -14101,6 +14101,7 @@ gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
gcc_assert (!trust_type_canonical
|| (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. */
......@@ -14118,6 +14119,14 @@ gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2);
}
/* For types where we do ODR based TBAA the canonical type is always
set correctly, so we know that types are different if their
canonical types does not match. */
if (trust_type_canonical
&& (odr_type_p (t1) && odr_based_tbaa_p (t1))
!= (odr_type_p (t2) && odr_based_tbaa_p (t2)))
return false;
/* 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));
if (code != tree_code_for_canonical_type_merging (TREE_CODE (t2)))
......
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