summaryrefslogtreecommitdiff
path: root/gcc/ipa.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2010-11-20 21:10:46 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2010-11-20 21:10:46 +0000
commit6e673e69bfe6589a313a77485a3e74d6aa4ad6e7 (patch)
tree840116a4decf1497419fc4f57051a92015fa008f /gcc/ipa.c
parent1f853e71e00f2dadb92039894f5a722fe4cc6fee (diff)
downloadgcc-6e673e69bfe6589a313a77485a3e74d6aa4ad6e7.tar.gz
* cgraph.c (ld_plugin_symbol_resolution_names): New.
(dump_cgraph_node): Dump resolution. * cgraph.h (ld_plugin_symbol_resolution_names): Declare. (cgraph_comdat_can_be_unshared_p): Dclare. * lto-streamer-out.c (produce_symtab): Use cgraph_comdat_can_be_unshared_p. * ipa.c (cgraph_address_taken_from_non_vtable_p): New function. (cgraph_comdat_can_be_unshared_p): New function based on logic in cgraph_externally_visible_p. (cgraph_externally_visible_p): Use it. (varpool_externally_visible_p): Virtual tables can be unshared. * varpool.c (dump_varpool_node): Dump resolution. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166985 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ipa.c')
-rw-r--r--gcc/ipa.c90
1 files changed, 69 insertions, 21 deletions
diff --git a/gcc/ipa.c b/gcc/ipa.c
index 3742f84e53b..28e6872ef7f 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -588,6 +588,56 @@ ipa_discover_readonly_nonaddressable_vars (void)
fprintf (dump_file, "\n");
}
+/* Return true when there is a reference to node and it is not vtable. */
+static bool
+cgraph_address_taken_from_non_vtable_p (struct cgraph_node *node)
+{
+ int i;
+ struct ipa_ref *ref;
+ for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
+ {
+ struct varpool_node *node;
+ if (ref->refered_type == IPA_REF_CGRAPH)
+ return true;
+ node = ipa_ref_varpool_node (ref);
+ if (!DECL_VIRTUAL_P (node->decl))
+ return true;
+ }
+ return false;
+}
+
+/* COMDAT functions must be shared only if they have address taken,
+ otherwise we can produce our own private implementation with
+ -fwhole-program.
+ Return true when turning COMDAT functoin static can not lead to wrong
+ code when the resulting object links with a library defining same COMDAT.
+
+ Virtual functions do have their addresses taken from the vtables,
+ but in C++ there is no way to compare their addresses for equality. */
+
+bool
+cgraph_comdat_can_be_unshared_p (struct cgraph_node *node)
+{
+ if ((cgraph_address_taken_from_non_vtable_p (node)
+ && !DECL_VIRTUAL_P (node->decl))
+ || !node->analyzed)
+ return false;
+ if (node->same_comdat_group)
+ {
+ struct cgraph_node *next;
+
+ /* If more than one function is in the same COMDAT group, it must
+ be shared even if just one function in the comdat group has
+ address taken. */
+ for (next = node->same_comdat_group;
+ next != node; next = next->same_comdat_group)
+ if (cgraph_address_taken_from_non_vtable_p (node)
+ && !DECL_VIRTUAL_P (next->decl))
+ return false;
+ }
+ return true;
+}
+
/* Return true when function NODE should be considered externally visible. */
static bool
@@ -613,6 +663,15 @@ cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program, bool
if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (node->decl)))
return true;
+ /* When doing LTO or whole program, we can bring COMDAT functoins static.
+ This improves code quality and we know we will duplicate them at most twice
+ (in the case that we are not using plugin and link with object file
+ implementing same COMDAT) */
+ if ((in_lto_p || whole_program)
+ && DECL_COMDAT (node->decl)
+ && cgraph_comdat_can_be_unshared_p (node))
+ return false;
+
/* See if we have linker information about symbol not being used or
if we need to make guess based on the declaration.
@@ -635,27 +694,6 @@ cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program, bool
;
else if (!whole_program)
return true;
- /* COMDAT functions must be shared only if they have address taken,
- otherwise we can produce our own private implementation with
- -fwhole-program. */
- else if (DECL_COMDAT (node->decl))
- {
- if (node->address_taken || !node->analyzed)
- return true;
- if (node->same_comdat_group)
- {
- struct cgraph_node *next;
-
- /* If more than one function is in the same COMDAT group, it must
- be shared even if just one function in the comdat group has
- address taken. */
- for (next = node->same_comdat_group;
- next != node;
- next = next->same_comdat_group)
- if (next->address_taken || !next->analyzed)
- return true;
- }
- }
if (MAIN_NAME_P (DECL_NAME (node->decl)))
return true;
@@ -701,6 +739,16 @@ varpool_externally_visible_p (struct varpool_node *vnode, bool aliased)
if (!alias && vnode->resolution == LDPR_PREVAILING_DEF_IRONLY)
return false;
+ /* As a special case, the COMDAT virutal tables can be unshared.
+ In LTO mode turn vtables into static variables. The variable is readonly,
+ so this does not enable more optimization, but referring static var
+ is faster for dynamic linking. Also this match logic hidding vtables
+ from LTO symbol tables. */
+ if ((in_lto_p || flag_whole_program)
+ && !vnode->force_output
+ && DECL_COMDAT (vnode->decl) && DECL_VIRTUAL_P (vnode->decl))
+ return false;
+
/* When doing link time optimizations, hidden symbols become local. */
if (in_lto_p
&& (DECL_VISIBILITY (vnode->decl) == VISIBILITY_HIDDEN