Commit ed2a53e7 by Jan Hubicka Committed by Jan Hubicka

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
parent e8661ad6
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)
{
......
......@@ -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. */
......
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