mirror of git://gcc.gnu.org/git/gcc.git
re PR lto/68881 (UNRESOLVED/FAIL: gcc.dg/lto/attr-weakref-1 -O2 -flto)
PR ipa/68881 * cgraph.h (symtab_node::copy_visibility_from): New function. * symtab.c (symtab_node::copy_visibility_from): New function. * ipa-visibility.c (optimize_weakref): New function. (function_and_variable_visibility): Use it. From-SVN: r234708
This commit is contained in:
parent
e8661ad6cf
commit
ed2a53e7ca
|
|
@ -1,3 +1,11 @@
|
|||
2016-03-30 Jan Hubicka <hubicka@ucw.cz>
|
||||
|
||||
PR ipa/68881
|
||||
* cgraph.h (symtab_node::copy_visibility_from): New function.
|
||||
* symtab.c (symtab_node::copy_visibility_from): New function.
|
||||
* ipa-visibility.c (optimize_weakref): New function.
|
||||
(function_and_variable_visibility): Use it.
|
||||
|
||||
2016-04-04 Martin Liska <mliska@suse.cz>
|
||||
|
||||
PR hsa/70402
|
||||
|
|
|
|||
|
|
@ -293,6 +293,9 @@ public:
|
|||
/* Make DECL local. */
|
||||
void make_decl_local (void);
|
||||
|
||||
/* Copy visibility from N. */
|
||||
void copy_visibility_from (symtab_node *n);
|
||||
|
||||
/* Return desired alignment of the definition. This is NOT alignment useful
|
||||
to access THIS, because THIS may be interposable and DECL_ALIGN should
|
||||
be used instead. It however must be guaranteed when output definition
|
||||
|
|
|
|||
|
|
@ -452,6 +452,84 @@ update_visibility_by_resolution_info (symtab_node * node)
|
|||
}
|
||||
}
|
||||
|
||||
/* Try to get rid of weakref. */
|
||||
|
||||
static void
|
||||
optimize_weakref (symtab_node *node)
|
||||
{
|
||||
#ifdef ASM_OUTPUT_DEF
|
||||
bool aliases_supported = true;
|
||||
#else
|
||||
bool aliases_supported = false;
|
||||
#endif
|
||||
bool strip_weakref = false;
|
||||
bool static_alias = false;
|
||||
|
||||
gcc_assert (node->weakref);
|
||||
|
||||
/* Weakrefs with no target defined can not be optimized. */
|
||||
if (!node->analyzed)
|
||||
return;
|
||||
symtab_node *target = node->get_alias_target ();
|
||||
|
||||
/* Weakrefs to weakrefs can be optimized only if target can be. */
|
||||
if (target->weakref)
|
||||
optimize_weakref (target);
|
||||
if (target->weakref)
|
||||
return;
|
||||
|
||||
/* If we have definition of weakref's target and we know it binds locally,
|
||||
we can turn weakref to static alias. */
|
||||
if (target->definition && decl_binds_to_current_def_p (target->decl)
|
||||
&& aliases_supported)
|
||||
strip_weakref = static_alias = true;
|
||||
/* Otherwise we can turn weakref into transparent alias. This transformation
|
||||
may break asm statements which directly refers to symbol name and expect
|
||||
GNU as to translate it via .weakref directive. So do not optimize when
|
||||
DECL_PRESERVED is set and .weakref is supported. */
|
||||
else if ((!DECL_PRESERVE_P (target->decl)
|
||||
|| IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (node->decl)))
|
||||
&& !DECL_WEAK (target->decl)
|
||||
&& !DECL_EXTERNAL (target->decl)
|
||||
&& ((target->definition && !target->can_be_discarded_p ())
|
||||
|| target->resolution != LDPR_UNDEF))
|
||||
strip_weakref = true;
|
||||
if (!strip_weakref)
|
||||
return;
|
||||
node->weakref = false;
|
||||
IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (node->decl)) = 0;
|
||||
TREE_CHAIN (DECL_ASSEMBLER_NAME (node->decl)) = NULL_TREE;
|
||||
DECL_ATTRIBUTES (node->decl) = remove_attribute ("weakref",
|
||||
DECL_ATTRIBUTES
|
||||
(node->decl));
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "Optimizing weakref %s %s\n",
|
||||
node->name(),
|
||||
static_alias ? "as static alias" : "as transparent alias");
|
||||
|
||||
if (static_alias)
|
||||
{
|
||||
/* make_decl_local will shortcircuit if it doesn't see TREE_PUBLIC.
|
||||
be sure it really clears the WEAK flag. */
|
||||
TREE_PUBLIC (node->decl) = true;
|
||||
node->make_decl_local ();
|
||||
node->forced_by_abi = false;
|
||||
node->resolution = LDPR_PREVAILING_DEF_IRONLY;
|
||||
node->externally_visible = false;
|
||||
gcc_assert (!DECL_WEAK (node->decl));
|
||||
node->transparent_alias = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
symtab->change_decl_assembler_name
|
||||
(node->decl, DECL_ASSEMBLER_NAME (node->get_alias_target ()->decl));
|
||||
node->transparent_alias = true;
|
||||
node->copy_visibility_from (target);
|
||||
}
|
||||
gcc_assert (node->alias);
|
||||
}
|
||||
|
||||
/* Decide on visibility of all symbols. */
|
||||
|
||||
static unsigned int
|
||||
|
|
@ -594,6 +672,8 @@ function_and_variable_visibility (bool whole_program)
|
|||
}
|
||||
|
||||
update_visibility_by_resolution_info (node);
|
||||
if (node->weakref)
|
||||
optimize_weakref (node);
|
||||
}
|
||||
FOR_EACH_DEFINED_FUNCTION (node)
|
||||
{
|
||||
|
|
@ -660,6 +740,8 @@ function_and_variable_visibility (bool whole_program)
|
|||
|| ! (ADDR_SPACE_GENERIC_P
|
||||
(TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl))))))
|
||||
DECL_COMMON (vnode->decl) = 0;
|
||||
if (vnode->weakref)
|
||||
optimize_weakref (vnode);
|
||||
}
|
||||
FOR_EACH_DEFINED_VARIABLE (vnode)
|
||||
{
|
||||
|
|
|
|||
55
gcc/symtab.c
55
gcc/symtab.c
|
|
@ -1287,6 +1287,61 @@ symtab_node::make_decl_local (void)
|
|||
SYMBOL_REF_WEAK (symbol) = DECL_WEAK (decl);
|
||||
}
|
||||
|
||||
/* Copy visibility from N.
|
||||
This is useful when THIS becomes a transparent alias of N. */
|
||||
|
||||
void
|
||||
symtab_node::copy_visibility_from (symtab_node *n)
|
||||
{
|
||||
gcc_checking_assert (n->weakref == weakref);
|
||||
|
||||
ipa_ref *ref;
|
||||
for (unsigned i = 0; iterate_direct_aliases (i, ref); i++)
|
||||
{
|
||||
struct symtab_node *alias = ref->referring;
|
||||
if (alias->transparent_alias)
|
||||
alias->copy_visibility_from (n);
|
||||
}
|
||||
|
||||
if (TREE_CODE (decl) == VAR_DECL)
|
||||
{
|
||||
DECL_COMMON (decl) = DECL_COMMON (n->decl);
|
||||
/* ADDRESSABLE flag is not defined for public symbols. */
|
||||
if (TREE_PUBLIC (decl) && !TREE_PUBLIC (n->decl))
|
||||
TREE_ADDRESSABLE (decl) = 1;
|
||||
TREE_STATIC (decl) = TREE_STATIC (n->decl);
|
||||
}
|
||||
else gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
|
||||
|
||||
DECL_COMDAT (decl) = DECL_COMDAT (n->decl);
|
||||
DECL_WEAK (decl) = DECL_WEAK (n->decl);
|
||||
DECL_EXTERNAL (decl) = DECL_EXTERNAL (n->decl);
|
||||
DECL_VISIBILITY_SPECIFIED (decl) = DECL_VISIBILITY_SPECIFIED (n->decl);
|
||||
DECL_VISIBILITY (decl) = DECL_VISIBILITY (n->decl);
|
||||
TREE_PUBLIC (decl) = TREE_PUBLIC (n->decl);
|
||||
DECL_DLLIMPORT_P (decl) = DECL_DLLIMPORT_P (n->decl);
|
||||
resolution = n->resolution;
|
||||
set_comdat_group (n->get_comdat_group ());
|
||||
call_for_symbol_and_aliases (symtab_node::set_section,
|
||||
const_cast<char *>(n->get_section ()), true);
|
||||
externally_visible = n->externally_visible;
|
||||
if (!DECL_RTL_SET_P (decl))
|
||||
return;
|
||||
|
||||
/* Update rtl flags. */
|
||||
make_decl_rtl (decl);
|
||||
|
||||
rtx rtl = DECL_RTL (decl);
|
||||
if (!MEM_P (rtl))
|
||||
return;
|
||||
|
||||
rtx symbol = XEXP (rtl, 0);
|
||||
if (GET_CODE (symbol) != SYMBOL_REF)
|
||||
return;
|
||||
|
||||
SYMBOL_REF_WEAK (symbol) = DECL_WEAK (decl);
|
||||
}
|
||||
|
||||
/* Walk the alias chain to return the symbol NODE is alias of.
|
||||
If NODE is not an alias, return NODE.
|
||||
Assumes NODE is known to be alias. */
|
||||
|
|
|
|||
Loading…
Reference in New Issue