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
This commit is contained in:
parent
01e54ef86f
commit
af15184ab6
5 changed files with 146 additions and 2 deletions
|
@ -1,3 +1,14 @@
|
|||
2013-08-02 Jan Hubicka <jh@suse.cz>
|
||||
Martin Liska <marxin.liska@gmail.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2013-08-02 Vladimir Makarov <vmakarov@redhat.com>
|
||||
|
||||
PR rtl-optimization/57963
|
||||
|
|
|
@ -1697,7 +1697,6 @@ enum availability
|
|||
cgraph_function_body_availability (struct cgraph_node *node)
|
||||
{
|
||||
enum availability avail;
|
||||
gcc_assert (cgraph_function_flags_ready);
|
||||
if (!node->symbol.analyzed)
|
||||
avail = AVAIL_NOT_AVAILABLE;
|
||||
else if (node->local.local)
|
||||
|
|
|
@ -597,6 +597,12 @@ symtab_node symtab_alias_ultimate_target (symtab_node,
|
|||
enum availability *avail = NULL);
|
||||
bool symtab_resolve_alias (symtab_node node, symtab_node target);
|
||||
void fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target);
|
||||
bool symtab_for_node_and_aliases (symtab_node,
|
||||
bool (*) (symtab_node, void *),
|
||||
void *,
|
||||
bool);
|
||||
symtab_node symtab_nonoverwritable_alias (symtab_node);
|
||||
enum availability symtab_node_availability (symtab_node);
|
||||
|
||||
/* In cgraph.c */
|
||||
void dump_cgraph (FILE *);
|
||||
|
|
46
gcc/ipa.c
46
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. */
|
||||
|
|
84
gcc/symtab.c
84
gcc/symtab.c
|
@ -1014,4 +1014,88 @@ symtab_resolve_alias (symtab_node node, symtab_node target)
|
|||
symtab_alias_ultimate_target (target, NULL)->symbol.address_taken = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Call calback on NODE and aliases associated to NODE.
|
||||
When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
|
||||
skipped. */
|
||||
|
||||
bool
|
||||
symtab_for_node_and_aliases (symtab_node node,
|
||||
bool (*callback) (symtab_node, void *),
|
||||
void *data,
|
||||
bool include_overwritable)
|
||||
{
|
||||
int i;
|
||||
struct ipa_ref *ref;
|
||||
|
||||
if (callback (node, data))
|
||||
return true;
|
||||
for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++)
|
||||
if (ref->use == IPA_REF_ALIAS)
|
||||
{
|
||||
symtab_node alias = ref->referring;
|
||||
if (include_overwritable
|
||||
|| symtab_node_availability (alias) > AVAIL_OVERWRITABLE)
|
||||
if (symtab_for_node_and_aliases (alias, callback, data,
|
||||
include_overwritable))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Worker searching nonoverwritable alias. */
|
||||
|
||||
static bool
|
||||
symtab_nonoverwritable_alias_1 (symtab_node node, void *data)
|
||||
{
|
||||
if (decl_binds_to_current_def_p (node->symbol.decl))
|
||||
{
|
||||
*(symtab_node *)data = node;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If NODE can not be overwriten by static or dynamic linker to point to different
|
||||
definition, return NODE. Otherwise look for alias with such property and if
|
||||
none exists, introduce new one. */
|
||||
|
||||
symtab_node
|
||||
symtab_nonoverwritable_alias (symtab_node node)
|
||||
{
|
||||
tree new_decl;
|
||||
symtab_node new_node = NULL;
|
||||
symtab_for_node_and_aliases (node, symtab_nonoverwritable_alias_1,
|
||||
(void *)&new_node, true);
|
||||
if (new_node)
|
||||
return new_node;
|
||||
|
||||
new_decl = copy_node (node->symbol.decl);
|
||||
DECL_NAME (new_decl) = clone_function_name (node->symbol.decl, "localalias");
|
||||
if (TREE_CODE (new_decl) == FUNCTION_DECL)
|
||||
DECL_STRUCT_FUNCTION (new_decl) = NULL;
|
||||
DECL_INITIAL (new_decl) = NULL;
|
||||
SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
|
||||
SET_DECL_RTL (new_decl, NULL);
|
||||
|
||||
/* Update the properties. */
|
||||
DECL_EXTERNAL (new_decl) = 0;
|
||||
if (DECL_ONE_ONLY (node->symbol.decl))
|
||||
DECL_SECTION_NAME (new_decl) = NULL;
|
||||
DECL_COMDAT_GROUP (new_decl) = 0;
|
||||
TREE_PUBLIC (new_decl) = 0;
|
||||
DECL_COMDAT (new_decl) = 0;
|
||||
DECL_WEAK (new_decl) = 0;
|
||||
DECL_VIRTUAL_P (new_decl) = 0;
|
||||
if (TREE_CODE (new_decl) == FUNCTION_DECL)
|
||||
{
|
||||
DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
|
||||
DECL_STATIC_DESTRUCTOR (new_decl) = 0;
|
||||
new_node = (symtab_node) cgraph_create_function_alias (new_decl, node->symbol.decl);
|
||||
}
|
||||
else
|
||||
new_node = (symtab_node) varpool_create_variable_alias (new_decl, node->symbol.decl);
|
||||
symtab_resolve_alias (new_node, node);
|
||||
return new_node;
|
||||
}
|
||||
#include "gt-symtab.h"
|
||||
|
|
Loading…
Add table
Reference in a new issue