mirror of git://gcc.gnu.org/git/gcc.git
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
|
|
@ -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>
|
2013-08-02 Vladimir Makarov <vmakarov@redhat.com>
|
||||||
|
|
||||||
PR rtl-optimization/57963
|
PR rtl-optimization/57963
|
||||||
|
|
|
||||||
|
|
@ -1697,7 +1697,6 @@ enum availability
|
||||||
cgraph_function_body_availability (struct cgraph_node *node)
|
cgraph_function_body_availability (struct cgraph_node *node)
|
||||||
{
|
{
|
||||||
enum availability avail;
|
enum availability avail;
|
||||||
gcc_assert (cgraph_function_flags_ready);
|
|
||||||
if (!node->symbol.analyzed)
|
if (!node->symbol.analyzed)
|
||||||
avail = AVAIL_NOT_AVAILABLE;
|
avail = AVAIL_NOT_AVAILABLE;
|
||||||
else if (node->local.local)
|
else if (node->local.local)
|
||||||
|
|
|
||||||
|
|
@ -597,6 +597,12 @@ symtab_node symtab_alias_ultimate_target (symtab_node,
|
||||||
enum availability *avail = NULL);
|
enum availability *avail = NULL);
|
||||||
bool symtab_resolve_alias (symtab_node node, symtab_node target);
|
bool symtab_resolve_alias (symtab_node node, symtab_node target);
|
||||||
void fixup_same_cpp_alias_visibility (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 */
|
/* In cgraph.c */
|
||||||
void dump_cgraph (FILE *);
|
void dump_cgraph (FILE *);
|
||||||
|
|
|
||||||
44
gcc/ipa.c
44
gcc/ipa.c
|
|
@ -751,6 +751,21 @@ varpool_externally_visible_p (struct varpool_node *vnode)
|
||||||
return false;
|
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.
|
/* Mark visibility of all functions.
|
||||||
|
|
||||||
A local function is one whose calls can occur only in the current
|
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)
|
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)
|
FOR_EACH_VARIABLE (vnode)
|
||||||
{
|
{
|
||||||
/* weak flag makes no sense on local variables. */
|
/* 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;
|
symtab_alias_ultimate_target (target, NULL)->symbol.address_taken = true;
|
||||||
return 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"
|
#include "gt-symtab.h"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue