aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2013-08-02 16:38:15 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2013-08-02 14:38:15 +0000
commitaf15184ab60cc2c2caf47964734c3e123bc04f7c (patch)
tree1cccd5c74a32da024ef7d68be27022345b749039 /gcc/ipa.c
parent01e54ef86f407385b0f2bb7afb5748f0db31bce8 (diff)
downloadgcc-af15184ab60cc2c2caf47964734c3e123bc04f7c.zip
gcc-af15184ab60cc2c2caf47964734c3e123bc04f7c.tar.gz
gcc-af15184ab60cc2c2caf47964734c3e123bc04f7c.tar.bz2
cgraph.c (cgraph_function_body_availability): Do not check cgrpah flags.
* cgraph.c (cgraph_function_body_availability): Do not check cgrpah flags. * cgraph.h (symtab_for_node_and_aliases, symtab_nonoverwritable_alias, symtab_node_availability): Declare. * ipa.c (can_replace_by_local_alias): New. (function_and_variable_visibility): Use it. * symtab.c (symtab_for_node_and_aliases, symtab_nonoverwritable_alias_1, symtab_nonoverwritable_alias): New. Co-Authored-By: Martin Liska <marxin.liska@gmail.com> From-SVN: r201439
Diffstat (limited to 'gcc/ipa.c')
-rw-r--r--gcc/ipa.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/gcc/ipa.c b/gcc/ipa.c
index 085454d..f42de4d 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -751,6 +751,21 @@ varpool_externally_visible_p (struct varpool_node *vnode)
return false;
}
+/* Return true if reference to NODE can be replaced by a local alias.
+ Local aliases save dynamic linking overhead and enable more optimizations.
+ */
+
+bool
+can_replace_by_local_alias (symtab_node node)
+{
+ return (symtab_node_availability (node) > AVAIL_OVERWRITABLE
+ && !DECL_EXTERNAL (node->symbol.decl)
+ && (!DECL_ONE_ONLY (node->symbol.decl)
+ || node->symbol.resolution == LDPR_PREVAILING_DEF
+ || node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
+ || node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP));
+}
+
/* Mark visibility of all functions.
A local function is one whose calls can occur only in the current
@@ -872,7 +887,36 @@ function_and_variable_visibility (bool whole_program)
}
}
FOR_EACH_DEFINED_FUNCTION (node)
- node->local.local = cgraph_local_node_p (node);
+ {
+ node->local.local = cgraph_local_node_p (node);
+
+ /* If we know that function can not be overwritten by a different semantics
+ and moreover its section can not be discarded, replace all direct calls
+ by calls to an nonoverwritable alias. This make dynamic linking
+ cheaper and enable more optimization.
+
+ TODO: We can also update virtual tables. */
+ if (node->callers && can_replace_by_local_alias ((symtab_node)node))
+ {
+ struct cgraph_node *alias = cgraph (symtab_nonoverwritable_alias ((symtab_node) node));
+
+ if (alias != node)
+ {
+ while (node->callers)
+ {
+ struct cgraph_edge *e = node->callers;
+
+ cgraph_redirect_edge_callee (e, alias);
+ if (!flag_wpa)
+ {
+ push_cfun (DECL_STRUCT_FUNCTION (e->caller->symbol.decl));
+ cgraph_redirect_edge_call_stmt_to_callee (e);
+ pop_cfun ();
+ }
+ }
+ }
+ }
+ }
FOR_EACH_VARIABLE (vnode)
{
/* weak flag makes no sense on local variables. */