aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa-visibility.c
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2016-04-04 11:26:29 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2016-04-04 09:26:29 +0000
commited2a53e7ca7aafa5fea5316c7fdebdc77fb8f327 (patch)
tree046b846b874b04d1165f5b13e3c53c3879ea4558 /gcc/ipa-visibility.c
parente8661ad6cfb1d6773a8613270250ab69c7faa95c (diff)
downloadgcc-ed2a53e7ca7aafa5fea5316c7fdebdc77fb8f327.zip
gcc-ed2a53e7ca7aafa5fea5316c7fdebdc77fb8f327.tar.gz
gcc-ed2a53e7ca7aafa5fea5316c7fdebdc77fb8f327.tar.bz2
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
Diffstat (limited to 'gcc/ipa-visibility.c')
-rw-r--r--gcc/ipa-visibility.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c
index 8198a3d..e4c3f7c 100644
--- a/gcc/ipa-visibility.c
+++ b/gcc/ipa-visibility.c
@@ -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)
{