mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-18 23:51:08 +08:00
lto-symtab.c (lto_cgraph_replace_node): Kill same body alias code.
* lto-symtab.c (lto_cgraph_replace_node): Kill same body alias code. (lto_symtab_resolve_can_prevail_p): Likewise. (lto_symtab_merge_cgraph_nodes): Update merging of aliases. * cgraph.c (same_body_aliases_done): New global var. (cgraph_same_body_alias_1): Rename to ... (cgraph_create_function_alias): ... this one; reorg to new representation. (cgraph_same_body_alias): Use cgraph_create_function_alias; record references when asked to. (cgraph_add_thunk): Fix formating. (cgraph_get_node): Kill same body alias code. (cgraph_node_for_asm): Likewise. (cgraph_remove_same_body_alias): Remove. (cgraph_remove_node): Kill same body alias code. (cgraph_mark_address_taken_node): Mark also the aliased function as having address taken. (dump_cgraph_node): Dump same body aliases. (cgraph_for_node_thunks_and_aliases): Update for new alias representation. (cgraph_for_node_and_aliases): Likewise. * cgraph.h (same_body): Kll pointer. (same_body_alias): Update comment. (same_body_aliases_done): Declare. (cgraph_remove_same_body_alias): Remove declaration. (cgraph_create_function_alias): Declare. (cgraph_process_same_body_aliases): Declare. (cgraph_function_with_gimple_body_p): Check for alias. (cgraph_can_remove_if_no_direct_calls_p): Look for aliases. (cgraph_alias_aliased_node): New function. (cgraph_function_node): Update for new aliases. (cgraph_function_or_thunk_node): Likewise. * ipa-inline-transform.c (can_remove_node_now_p): Look for aliases. (inline_call): Remove dead aliases. * cgraphunit.c (cgraph_decide_is_function_needed): Disable assembler name hack for same body aliases. (clone_of_p): Look through aliases. (verify_cgraph_node): Verify aliases. (cgraph_analyze_function): Analyze aliases; fixup C++ bugs. (cgraph_process_same_body_aliases): New function. (process_function_and_variable_attributes): Disable weakref warning on alias. (cgraph_analyze_functions): Handle aliases. (cgraph_mark_functions_to_output): Handle aliases same way as thunks. (assemble_thunks): Rename to ... (assemble_thunks_and_aliases): ... this one; handle aliases, too. (cgraph_expand_function): Remove alias output code. (cgraph_output_in_order): Skip aliases. (cgraph_preserve_function_body_p): Aliases don't need preserving. * ipa-ref.c (ipa_ref_use_name): Add alias reference. (ipa_record_reference): Do not assert on alias references. (ipa_ref_has_aliases_p): New function. * ipa-ref.h (enum ipa_ref_use): Add IPA_REF_ALIAS. (ipa_ref_has_aliases_p): Declare. * lto-cgraph.c (lto_output_node): Handle aliases. (input_node): Likewise. * lto-streamer-out.c (lto_output): Skip aliases. (produce_symtab): Kill same_body_alias code. * ipa-utils.c (ipa_reverse_postorder): Add FIXME. (ipa_reverse_postorder): Use cgraph_only_called_directly_or_aliased_p. * ipa-inline.c (update_caller_keys): Walk aliases. (inline_small_functions): Fix thinko in previous patch. * ipa.c (cgraph_externally_visible_p): Do not walk aliases. (function_and_variable_visibility): Do not walk same body aliases. * tree-ssa-structalias.c (associate_varinfo_to_alias): New function. (ipa_pta_execute): Use it. * lto.c (add_cgraph_node_to_partition_1): Break out from ... (add_cgraph_node_to_partition) ... here; walk aliases. (lto_1_to_1_map): Remove same body alias code. (promote_fn): Likewise. (lto_promote_cross_file_statics): Update comment. * decl2.c (cp_write_global_declarations): Process aliases; look trhough same body aliases. From-SVN: r174952
This commit is contained in:
parent
c44ddf9615
commit
39e2db00da
@ -1,3 +1,71 @@
|
||||
2011-06-11 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* lto-symtab.c (lto_cgraph_replace_node): Kill same body alias code.
|
||||
(lto_symtab_resolve_can_prevail_p): Likewise.
|
||||
(lto_symtab_merge_cgraph_nodes): Update merging of aliases.
|
||||
* cgraph.c (same_body_aliases_done): New global var.
|
||||
(cgraph_same_body_alias_1): Rename to ...
|
||||
(cgraph_create_function_alias): ... this one; reorg to new
|
||||
representation.
|
||||
(cgraph_same_body_alias): Use cgraph_create_function_alias;
|
||||
record references when asked to.
|
||||
(cgraph_add_thunk): Fix formating.
|
||||
(cgraph_get_node): Kill same body alias code.
|
||||
(cgraph_node_for_asm): Likewise.
|
||||
(cgraph_remove_same_body_alias): Remove.
|
||||
(cgraph_remove_node): Kill same body alias code.
|
||||
(cgraph_mark_address_taken_node): Mark also the aliased function
|
||||
as having address taken.
|
||||
(dump_cgraph_node): Dump same body aliases.
|
||||
(cgraph_for_node_thunks_and_aliases): Update for new alias
|
||||
representation.
|
||||
(cgraph_for_node_and_aliases): Likewise.
|
||||
* cgraph.h (same_body): Kll pointer.
|
||||
(same_body_alias): Update comment.
|
||||
(same_body_aliases_done): Declare.
|
||||
(cgraph_remove_same_body_alias): Remove declaration.
|
||||
(cgraph_create_function_alias): Declare.
|
||||
(cgraph_process_same_body_aliases): Declare.
|
||||
(cgraph_function_with_gimple_body_p): Check for alias.
|
||||
(cgraph_can_remove_if_no_direct_calls_p): Look for aliases.
|
||||
(cgraph_alias_aliased_node): New function.
|
||||
(cgraph_function_node): Update for new aliases.
|
||||
(cgraph_function_or_thunk_node): Likewise.
|
||||
* ipa-inline-transform.c (can_remove_node_now_p): Look for aliases.
|
||||
(inline_call): Remove dead aliases.
|
||||
* cgraphunit.c (cgraph_decide_is_function_needed): Disable assembler name
|
||||
hack for same body aliases.
|
||||
(clone_of_p): Look through aliases.
|
||||
(verify_cgraph_node): Verify aliases.
|
||||
(cgraph_analyze_function): Analyze aliases; fixup C++ bugs.
|
||||
(cgraph_process_same_body_aliases): New function.
|
||||
(process_function_and_variable_attributes): Disable weakref warning on
|
||||
alias.
|
||||
(cgraph_analyze_functions): Handle aliases.
|
||||
(cgraph_mark_functions_to_output): Handle aliases same way as thunks.
|
||||
(assemble_thunks): Rename to ...
|
||||
(assemble_thunks_and_aliases): ... this one; handle aliases, too.
|
||||
(cgraph_expand_function): Remove alias output code.
|
||||
(cgraph_output_in_order): Skip aliases.
|
||||
(cgraph_preserve_function_body_p): Aliases don't need preserving.
|
||||
* ipa-ref.c (ipa_ref_use_name): Add alias reference.
|
||||
(ipa_record_reference): Do not assert on alias references.
|
||||
(ipa_ref_has_aliases_p): New function.
|
||||
* ipa-ref.h (enum ipa_ref_use): Add IPA_REF_ALIAS.
|
||||
(ipa_ref_has_aliases_p): Declare.
|
||||
* lto-cgraph.c (lto_output_node): Handle aliases.
|
||||
(input_node): Likewise.
|
||||
* lto-streamer-out.c (lto_output): Skip aliases.
|
||||
(produce_symtab): Kill same_body_alias code.
|
||||
* ipa-utils.c (ipa_reverse_postorder): Add FIXME.
|
||||
(ipa_reverse_postorder): Use cgraph_only_called_directly_or_aliased_p.
|
||||
* ipa-inline.c (update_caller_keys): Walk aliases.
|
||||
(inline_small_functions): Fix thinko in previous patch.
|
||||
* ipa.c (cgraph_externally_visible_p): Do not walk aliases.
|
||||
(function_and_variable_visibility): Do not walk same body aliases.
|
||||
* tree-ssa-structalias.c (associate_varinfo_to_alias): New function.
|
||||
(ipa_pta_execute): Use it.
|
||||
|
||||
2011-06-11 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
* config/i386/sse.md (vec_dupv4sf): Correct mode of forced register.
|
||||
|
180
gcc/cgraph.c
180
gcc/cgraph.c
@ -208,6 +208,9 @@ static GTY(()) struct cgraph_node *free_nodes;
|
||||
Do not GTY((delete)) this list so UIDs gets reliably recycled. */
|
||||
static GTY(()) struct cgraph_edge *free_edges;
|
||||
|
||||
/* Did procss_same_body_aliases run? */
|
||||
bool same_body_aliases_done;
|
||||
|
||||
/* Macros to access the next item in the list of free cgraph nodes and
|
||||
edges. */
|
||||
#define NEXT_FREE_NODE(NODE) (NODE)->next
|
||||
@ -542,33 +545,23 @@ cgraph_get_create_node (tree decl)
|
||||
/* Mark ALIAS as an alias to DECL. DECL_NODE is cgraph node representing
|
||||
the function body is associated with (not neccesarily cgraph_node (DECL). */
|
||||
|
||||
static struct cgraph_node *
|
||||
cgraph_same_body_alias_1 (struct cgraph_node *decl_node, tree alias, tree decl)
|
||||
struct cgraph_node *
|
||||
cgraph_create_function_alias (tree alias, tree decl)
|
||||
{
|
||||
struct cgraph_node key, *alias_node, **slot;
|
||||
struct cgraph_node *alias_node;
|
||||
|
||||
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
|
||||
gcc_assert (TREE_CODE (alias) == FUNCTION_DECL);
|
||||
|
||||
key.decl = alias;
|
||||
|
||||
slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key, INSERT);
|
||||
|
||||
/* If the cgraph_node has been already created, fail. */
|
||||
if (*slot)
|
||||
return NULL;
|
||||
|
||||
alias_node = cgraph_allocate_node ();
|
||||
alias_node->decl = alias;
|
||||
alias_node->same_body_alias = 1;
|
||||
alias_node->same_body = decl_node;
|
||||
alias_node->previous = NULL;
|
||||
if (decl_node->same_body)
|
||||
decl_node->same_body->previous = alias_node;
|
||||
alias_node->next = decl_node->same_body;
|
||||
alias_node = cgraph_get_create_node (alias);
|
||||
gcc_assert (!alias_node->local.finalized);
|
||||
alias_node->thunk.alias = decl;
|
||||
decl_node->same_body = alias_node;
|
||||
*slot = alias_node;
|
||||
alias_node->local.finalized = true;
|
||||
alias_node->alias = 1;
|
||||
|
||||
if ((TREE_PUBLIC (alias) && !DECL_COMDAT (alias) && !DECL_EXTERNAL (alias))
|
||||
|| (DECL_VIRTUAL_P (alias)
|
||||
&& (DECL_COMDAT (alias) || DECL_EXTERNAL (alias))))
|
||||
cgraph_mark_reachable_node (alias_node);
|
||||
return alias_node;
|
||||
}
|
||||
|
||||
@ -578,16 +571,24 @@ cgraph_same_body_alias_1 (struct cgraph_node *decl_node, tree alias, tree decl)
|
||||
and cgraph_get_node (ALIAS) transparently returns cgraph_get_node (DECL). */
|
||||
|
||||
struct cgraph_node *
|
||||
cgraph_same_body_alias (struct cgraph_node *decl_node, tree alias, tree decl)
|
||||
cgraph_same_body_alias (struct cgraph_node *decl_node ATTRIBUTE_UNUSED, tree alias, tree decl)
|
||||
{
|
||||
struct cgraph_node *n;
|
||||
#ifndef ASM_OUTPUT_DEF
|
||||
/* If aliases aren't supported by the assembler, fail. */
|
||||
return NULL;
|
||||
#endif
|
||||
/* Langhooks can create same body aliases of symbols not defined.
|
||||
Those are useless. Drop them on the floor. */
|
||||
if (cgraph_global_info_ready)
|
||||
return NULL;
|
||||
|
||||
/*gcc_assert (!assembler_name_hash);*/
|
||||
|
||||
return cgraph_same_body_alias_1 (decl_node, alias, decl);
|
||||
n = cgraph_create_function_alias (alias, decl);
|
||||
n->same_body_alias = true;
|
||||
if (same_body_aliases_done)
|
||||
ipa_record_reference (n, NULL, cgraph_get_node (decl), NULL, IPA_REF_ALIAS,
|
||||
NULL);
|
||||
return n;
|
||||
}
|
||||
|
||||
/* Add thunk alias into callgraph. The alias declaration is ALIAS and it
|
||||
@ -633,6 +634,7 @@ cgraph_add_thunk (struct cgraph_node *decl_node ATTRIBUTE_UNUSED,
|
||||
|| (DECL_VIRTUAL_P (decl)
|
||||
&& (DECL_COMDAT (decl) || DECL_EXTERNAL (decl))))
|
||||
cgraph_mark_reachable_node (node);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -678,11 +680,7 @@ cgraph_get_node (const_tree decl)
|
||||
NO_INSERT);
|
||||
|
||||
if (slot && *slot)
|
||||
{
|
||||
node = *slot;
|
||||
if (node->same_body_alias)
|
||||
node = node->same_body;
|
||||
}
|
||||
node = *slot;
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -745,21 +743,6 @@ cgraph_node_for_asm (tree asmname)
|
||||
so lets hope for the best. */
|
||||
if (!*slot)
|
||||
*slot = node;
|
||||
if (node->same_body)
|
||||
{
|
||||
struct cgraph_node *alias;
|
||||
|
||||
for (alias = node->same_body; alias; alias = alias->next)
|
||||
{
|
||||
hashval_t hash;
|
||||
name = DECL_ASSEMBLER_NAME (alias->decl);
|
||||
hash = decl_assembler_name_hash (name);
|
||||
slot = htab_find_slot_with_hash (assembler_name_hash, name,
|
||||
hash, INSERT);
|
||||
if (!*slot)
|
||||
*slot = alias;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -770,8 +753,6 @@ cgraph_node_for_asm (tree asmname)
|
||||
if (slot)
|
||||
{
|
||||
node = (struct cgraph_node *) *slot;
|
||||
if (node->same_body_alias)
|
||||
node = node->same_body;
|
||||
return node;
|
||||
}
|
||||
return NULL;
|
||||
@ -1432,44 +1413,6 @@ cgraph_release_function_body (struct cgraph_node *node)
|
||||
DECL_INITIAL (node->decl) = error_mark_node;
|
||||
}
|
||||
|
||||
/* Remove same body alias node. */
|
||||
|
||||
void
|
||||
cgraph_remove_same_body_alias (struct cgraph_node *node)
|
||||
{
|
||||
void **slot;
|
||||
int uid = node->uid;
|
||||
|
||||
gcc_assert (node->same_body_alias);
|
||||
if (node->previous)
|
||||
node->previous->next = node->next;
|
||||
else
|
||||
node->same_body->same_body = node->next;
|
||||
if (node->next)
|
||||
node->next->previous = node->previous;
|
||||
node->next = NULL;
|
||||
node->previous = NULL;
|
||||
slot = htab_find_slot (cgraph_hash, node, NO_INSERT);
|
||||
if (*slot == node)
|
||||
htab_clear_slot (cgraph_hash, slot);
|
||||
if (assembler_name_hash)
|
||||
{
|
||||
tree name = DECL_ASSEMBLER_NAME (node->decl);
|
||||
slot = htab_find_slot_with_hash (assembler_name_hash, name,
|
||||
decl_assembler_name_hash (name),
|
||||
NO_INSERT);
|
||||
if (slot && *slot == node)
|
||||
htab_clear_slot (assembler_name_hash, slot);
|
||||
}
|
||||
|
||||
/* Clear out the node to NULL all pointers and add the node to the free
|
||||
list. */
|
||||
memset (node, 0, sizeof(*node));
|
||||
node->uid = uid;
|
||||
NEXT_FREE_NODE (node) = free_nodes;
|
||||
free_nodes = node;
|
||||
}
|
||||
|
||||
/* Remove the node from cgraph. */
|
||||
|
||||
void
|
||||
@ -1631,9 +1574,6 @@ cgraph_remove_node (struct cgraph_node *node)
|
||||
}
|
||||
}
|
||||
|
||||
while (node->same_body)
|
||||
cgraph_remove_same_body_alias (node->same_body);
|
||||
|
||||
if (node->same_comdat_group)
|
||||
{
|
||||
struct cgraph_node *prev;
|
||||
@ -1747,6 +1687,14 @@ cgraph_mark_address_taken_node (struct cgraph_node *node)
|
||||
{
|
||||
gcc_assert (!node->global.inlined_to);
|
||||
cgraph_mark_reachable_node (node);
|
||||
/* FIXME: address_taken flag is used both as a shortcut for testing whether
|
||||
IPA_REF_ADDR reference exists (and thus it should be set on node
|
||||
representing alias we take address of) and as a test whether address
|
||||
of the object was taken (and thus it should be set on node alias is
|
||||
referring to). We should remove the first use and the remove the
|
||||
following set. */
|
||||
node->address_taken = 1;
|
||||
node = cgraph_function_or_thunk_node (node, NULL);
|
||||
node->address_taken = 1;
|
||||
}
|
||||
|
||||
@ -1902,6 +1850,15 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
|
||||
(int)node->thunk.virtual_value,
|
||||
(int)node->thunk.virtual_offset_p);
|
||||
}
|
||||
if (node->alias && node->thunk.alias)
|
||||
{
|
||||
fprintf (f, " alias of %s",
|
||||
lang_hooks.decl_printable_name (node->thunk.alias, 2));
|
||||
if (DECL_ASSEMBLER_NAME_SET_P (node->thunk.alias))
|
||||
fprintf (f, " (asm: %s)",
|
||||
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->thunk.alias)));
|
||||
fprintf (f, "\n");
|
||||
}
|
||||
|
||||
fprintf (f, " called by: ");
|
||||
|
||||
@ -1952,19 +1909,6 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
|
||||
if (indirect_calls_count)
|
||||
fprintf (f, " has %i outgoing edges for indirect calls.\n",
|
||||
indirect_calls_count);
|
||||
|
||||
if (node->same_body)
|
||||
{
|
||||
struct cgraph_node *n;
|
||||
fprintf (f, " aliases:");
|
||||
for (n = node->same_body; n; n = n->next)
|
||||
{
|
||||
fprintf (f, " %s/%i", cgraph_node_name (n), n->uid);
|
||||
if (DECL_ASSEMBLER_NAME_SET_P (n->decl))
|
||||
fprintf (f, " (asm: %s)", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (n->decl)));
|
||||
}
|
||||
fprintf (f, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2614,18 +2558,24 @@ cgraph_for_node_thunks_and_aliases (struct cgraph_node *node,
|
||||
bool include_overwritable)
|
||||
{
|
||||
struct cgraph_edge *e;
|
||||
struct cgraph_node *alias;
|
||||
int i;
|
||||
struct ipa_ref *ref;
|
||||
|
||||
if (callback (node, data))
|
||||
return true;
|
||||
for (alias = node->same_body; alias; alias = alias->next)
|
||||
if (callback (alias, data))
|
||||
return true;
|
||||
for (e = node->callers; e; e = e->next_caller)
|
||||
if (e->caller->thunk.thunk_p
|
||||
&& (include_overwritable
|
||||
|| cgraph_function_body_availability (e->caller) > AVAIL_OVERWRITABLE))
|
||||
|| cgraph_function_body_availability (e->caller)))
|
||||
cgraph_for_node_thunks_and_aliases (e->caller, callback, data, include_overwritable);
|
||||
for (i = 0; ipa_ref_list_refering_iterate (&node->ref_list, i, ref); i++)
|
||||
if (ref->use == IPA_REF_ALIAS)
|
||||
{
|
||||
struct cgraph_node *alias = ipa_ref_refering_node (ref);
|
||||
if (include_overwritable
|
||||
|| cgraph_function_body_availability (alias) > AVAIL_OVERWRITABLE)
|
||||
cgraph_for_node_thunks_and_aliases (alias, callback, data, include_overwritable);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2637,15 +2587,21 @@ bool
|
||||
cgraph_for_node_and_aliases (struct cgraph_node *node,
|
||||
bool (*callback) (struct cgraph_node *, void *),
|
||||
void *data,
|
||||
bool include_overwritable ATTRIBUTE_UNUSED)
|
||||
bool include_overwritable)
|
||||
{
|
||||
struct cgraph_node *alias;
|
||||
int i;
|
||||
struct ipa_ref *ref;
|
||||
|
||||
if (callback (node, data))
|
||||
return true;
|
||||
for (alias = node->same_body; alias; alias = alias->next)
|
||||
if (callback (alias, data))
|
||||
return true;
|
||||
for (i = 0; ipa_ref_list_refering_iterate (&node->ref_list, i, ref); i++)
|
||||
if (ref->use == IPA_REF_ALIAS)
|
||||
{
|
||||
struct cgraph_node *alias = ipa_ref_refering_node (ref);
|
||||
if (include_overwritable
|
||||
|| cgraph_function_body_availability (alias) > AVAIL_OVERWRITABLE)
|
||||
cgraph_for_node_and_aliases (alias, callback, data, include_overwritable);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
54
gcc/cgraph.h
54
gcc/cgraph.h
@ -165,9 +165,6 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node {
|
||||
struct cgraph_node *prev_sibling_clone;
|
||||
struct cgraph_node *clones;
|
||||
struct cgraph_node *clone_of;
|
||||
/* For normal nodes pointer to the list of alias and thunk nodes,
|
||||
in alias/thunk nodes pointer to the normal node. */
|
||||
struct cgraph_node *same_body;
|
||||
/* Circular list of nodes in the same comdat group if non-NULL. */
|
||||
struct cgraph_node *same_comdat_group;
|
||||
/* For functions with many calls sites it holds map from call expression
|
||||
@ -236,8 +233,7 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node {
|
||||
unsigned process : 1;
|
||||
/* Set for aliases once they got through assemble_alias. */
|
||||
unsigned alias : 1;
|
||||
/* Set for alias and thunk nodes, same_body points to the node they are alias
|
||||
of and they are linked through the next/previous pointers. */
|
||||
/* Set for aliases created as C++ same body aliases. */
|
||||
unsigned same_body_alias : 1;
|
||||
/* How commonly executed the node is. Initialized during branch
|
||||
probabilities pass. */
|
||||
@ -463,6 +459,7 @@ extern GTY(()) struct cgraph_node *cgraph_new_nodes;
|
||||
|
||||
extern GTY(()) struct cgraph_asm_node *cgraph_asm_nodes;
|
||||
extern GTY(()) int cgraph_order;
|
||||
extern bool same_body_aliases_done;
|
||||
|
||||
/* In cgraph.c */
|
||||
void dump_cgraph (FILE *);
|
||||
@ -488,7 +485,6 @@ struct cgraph_node * cgraph_get_create_node (tree);
|
||||
struct cgraph_node * cgraph_same_body_alias (struct cgraph_node *, tree, tree);
|
||||
struct cgraph_node * cgraph_add_thunk (struct cgraph_node *, tree, tree, bool, HOST_WIDE_INT,
|
||||
HOST_WIDE_INT, tree, tree);
|
||||
void cgraph_remove_same_body_alias (struct cgraph_node *);
|
||||
struct cgraph_node *cgraph_node_for_asm (tree);
|
||||
struct cgraph_edge *cgraph_edge (struct cgraph_node *, gimple);
|
||||
void cgraph_set_call_stmt (struct cgraph_edge *, gimple);
|
||||
@ -508,6 +504,7 @@ struct cgraph_edge * cgraph_clone_edge (struct cgraph_edge *,
|
||||
struct cgraph_node * cgraph_clone_node (struct cgraph_node *, tree, gcov_type,
|
||||
int, bool, VEC(cgraph_edge_p,heap) *,
|
||||
bool);
|
||||
struct cgraph_node *cgraph_create_function_alias (tree, tree);
|
||||
|
||||
void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *);
|
||||
void cgraph_make_edge_direct (struct cgraph_edge *, struct cgraph_node *,
|
||||
@ -577,6 +574,7 @@ void tree_function_versioning (tree, tree, VEC (ipa_replace_map_p,gc)*, bool, bi
|
||||
bitmap, basic_block);
|
||||
void record_references_in_initializer (tree, bool);
|
||||
bool cgraph_process_new_functions (void);
|
||||
void cgraph_process_same_body_aliases (void);
|
||||
|
||||
bool cgraph_decide_is_function_needed (struct cgraph_node *, tree);
|
||||
|
||||
@ -746,7 +744,7 @@ cgraph_next_defined_function (struct cgraph_node *node)
|
||||
static inline bool
|
||||
cgraph_function_with_gimple_body_p (struct cgraph_node *node)
|
||||
{
|
||||
return node->analyzed && !node->thunk.thunk_p;
|
||||
return node->analyzed && !node->thunk.thunk_p && !node->alias;
|
||||
}
|
||||
|
||||
/* Return first function with body defined. */
|
||||
@ -934,7 +932,8 @@ cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node)
|
||||
if (DECL_EXTERNAL (node->decl))
|
||||
return true;
|
||||
return (!node->address_taken
|
||||
&& cgraph_can_remove_if_no_direct_calls_and_refs_p (node));
|
||||
&& cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
|
||||
&& !ipa_ref_has_aliases_p (&node->ref_list));
|
||||
}
|
||||
|
||||
/* Return true when function NODE can be removed from callgraph
|
||||
@ -968,6 +967,20 @@ htab_t constant_pool_htab (void);
|
||||
/* FIXME: inappropriate dependency of cgraph on IPA. */
|
||||
#include "ipa-ref-inline.h"
|
||||
|
||||
/* Return node that alias N is aliasing. */
|
||||
|
||||
static inline struct cgraph_node *
|
||||
cgraph_alias_aliased_node (struct cgraph_node *n)
|
||||
{
|
||||
struct ipa_ref *ref;
|
||||
|
||||
ipa_ref_list_reference_iterate (&n->ref_list, 0, ref);
|
||||
gcc_checking_assert (ref->use == IPA_REF_ALIAS);
|
||||
if (ref->refered_type == IPA_REF_CGRAPH)
|
||||
return ipa_ref_node (ref);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Given NODE, walk the alias chain to return the function NODE is alias of.
|
||||
Walk through thunk, too.
|
||||
When AVAILABILITY is non-NULL, get minimal availablity in the chain. */
|
||||
@ -979,11 +992,13 @@ cgraph_function_node (struct cgraph_node *node, enum availability *availability)
|
||||
*availability = cgraph_function_body_availability (node);
|
||||
while (node)
|
||||
{
|
||||
if (node->thunk.thunk_p)
|
||||
if (node->alias && node->analyzed)
|
||||
node = cgraph_alias_aliased_node (node);
|
||||
else if (node->thunk.thunk_p)
|
||||
node = node->callees->callee;
|
||||
else
|
||||
return node;
|
||||
if (availability)
|
||||
if (node && availability)
|
||||
{
|
||||
enum availability a;
|
||||
a = cgraph_function_body_availability (node);
|
||||
@ -991,6 +1006,8 @@ cgraph_function_node (struct cgraph_node *node, enum availability *availability)
|
||||
*availability = a;
|
||||
}
|
||||
}
|
||||
if (*availability)
|
||||
*availability = AVAIL_NOT_AVAILABLE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1003,7 +1020,22 @@ cgraph_function_or_thunk_node (struct cgraph_node *node, enum availability *avai
|
||||
{
|
||||
if (availability)
|
||||
*availability = cgraph_function_body_availability (node);
|
||||
return node;
|
||||
while (node)
|
||||
{
|
||||
if (node->alias && node->analyzed)
|
||||
node = cgraph_alias_aliased_node (node);
|
||||
else
|
||||
return node;
|
||||
if (node && availability)
|
||||
{
|
||||
enum availability a;
|
||||
a = cgraph_function_body_availability (node);
|
||||
if (a < *availability)
|
||||
*availability = a;
|
||||
}
|
||||
}
|
||||
if (*availability)
|
||||
*availability = AVAIL_NOT_AVAILABLE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
186
gcc/cgraphunit.c
186
gcc/cgraphunit.c
@ -167,6 +167,7 @@ cgraph_decide_is_function_needed (struct cgraph_node *node, tree decl)
|
||||
the name later after finalizing the function and the fact is noticed
|
||||
in assemble_name then. This is arguably a bug. */
|
||||
if (DECL_ASSEMBLER_NAME_SET_P (decl)
|
||||
&& (!node->thunk.thunk_p && !node->same_body_alias)
|
||||
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
|
||||
return true;
|
||||
|
||||
@ -391,6 +392,8 @@ cgraph_mark_if_needed (tree decl)
|
||||
static bool
|
||||
clone_of_p (struct cgraph_node *node, struct cgraph_node *node2)
|
||||
{
|
||||
node = cgraph_function_or_thunk_node (node, NULL);
|
||||
node2 = cgraph_function_or_thunk_node (node2, NULL);
|
||||
while (node != node2 && node2)
|
||||
node2 = node2->clone_of;
|
||||
return node2 != NULL;
|
||||
@ -619,6 +622,36 @@ verify_cgraph_node (struct cgraph_node *node)
|
||||
while (n != node);
|
||||
}
|
||||
|
||||
if (node->analyzed && node->alias)
|
||||
{
|
||||
bool ref_found = false;
|
||||
int i;
|
||||
struct ipa_ref *ref;
|
||||
|
||||
if (node->callees)
|
||||
{
|
||||
error ("Alias has call edges");
|
||||
error_found = true;
|
||||
}
|
||||
for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
|
||||
if (ref->use != IPA_REF_ALIAS)
|
||||
{
|
||||
error ("Alias has non-alias refernece");
|
||||
error_found = true;
|
||||
}
|
||||
else if (ref_found)
|
||||
{
|
||||
error ("Alias has more than one alias reference");
|
||||
error_found = true;
|
||||
}
|
||||
else
|
||||
ref_found = true;
|
||||
if (!ref_found)
|
||||
{
|
||||
error ("Analyzed alias has no reference");
|
||||
error_found = true;
|
||||
}
|
||||
}
|
||||
if (node->analyzed && node->thunk.thunk_p)
|
||||
{
|
||||
if (!node->callees)
|
||||
@ -669,19 +702,17 @@ verify_cgraph_node (struct cgraph_node *node)
|
||||
}
|
||||
if (!e->indirect_unknown_callee)
|
||||
{
|
||||
if (e->callee->same_body_alias)
|
||||
{
|
||||
error ("edge points to same body alias:");
|
||||
debug_tree (e->callee->decl);
|
||||
error_found = true;
|
||||
}
|
||||
else if (!e->callee->global.inlined_to
|
||||
&& decl
|
||||
&& cgraph_get_node (decl)
|
||||
&& (e->callee->former_clone_of
|
||||
!= cgraph_get_node (decl)->decl)
|
||||
&& !clone_of_p (cgraph_get_node (decl),
|
||||
e->callee))
|
||||
if (!e->callee->global.inlined_to
|
||||
&& decl
|
||||
&& cgraph_get_node (decl)
|
||||
&& (e->callee->former_clone_of
|
||||
!= cgraph_get_node (decl)->decl)
|
||||
/* IPA-CP sometimes redirect edge to clone and then back to the former
|
||||
function. This ping-pong has to go, eventaully. */
|
||||
&& (cgraph_function_or_thunk_node (cgraph_get_node (decl), NULL)
|
||||
!= cgraph_function_or_thunk_node (e->callee, NULL))
|
||||
&& !clone_of_p (cgraph_get_node (decl),
|
||||
e->callee))
|
||||
{
|
||||
error ("edge points to wrong declaration:");
|
||||
debug_tree (e->callee->decl);
|
||||
@ -781,7 +812,53 @@ cgraph_analyze_function (struct cgraph_node *node)
|
||||
tree save = current_function_decl;
|
||||
tree decl = node->decl;
|
||||
|
||||
if (node->thunk.thunk_p)
|
||||
if (node->alias && node->thunk.alias)
|
||||
{
|
||||
struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias);
|
||||
if (!VEC_length (ipa_ref_t, node->ref_list.references))
|
||||
ipa_record_reference (node, NULL, tgt, NULL, IPA_REF_ALIAS, NULL);
|
||||
if (node->same_body_alias)
|
||||
{
|
||||
DECL_VIRTUAL_P (node->decl) = DECL_VIRTUAL_P (node->thunk.alias);
|
||||
DECL_DECLARED_INLINE_P (node->decl)
|
||||
= DECL_DECLARED_INLINE_P (node->thunk.alias);
|
||||
DECL_DISREGARD_INLINE_LIMITS (node->decl)
|
||||
= DECL_DISREGARD_INLINE_LIMITS (node->thunk.alias);
|
||||
}
|
||||
|
||||
/* Fixup visibility nonsences C++ frontend produce on same body aliases. */
|
||||
if (TREE_PUBLIC (node->decl) && node->same_body_alias)
|
||||
{
|
||||
DECL_EXTERNAL (node->decl) = DECL_EXTERNAL (node->thunk.alias);
|
||||
if (DECL_COMDAT (node->thunk.alias))
|
||||
{
|
||||
DECL_COMDAT (node->decl) = 1;
|
||||
DECL_COMDAT_GROUP (node->decl) = DECL_COMDAT_GROUP (node->thunk.alias);
|
||||
if (DECL_ONE_ONLY (node->thunk.alias) && !node->same_comdat_group)
|
||||
{
|
||||
struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias);
|
||||
node->same_comdat_group = tgt;
|
||||
if (!tgt->same_comdat_group)
|
||||
tgt->same_comdat_group = node;
|
||||
else
|
||||
{
|
||||
struct cgraph_node *n;
|
||||
for (n = tgt->same_comdat_group;
|
||||
n->same_comdat_group != tgt;
|
||||
n = n->same_comdat_group)
|
||||
;
|
||||
n->same_comdat_group = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cgraph_mark_reachable_node (cgraph_alias_aliased_node (node));
|
||||
if (node->address_taken)
|
||||
cgraph_mark_address_taken_node (cgraph_alias_aliased_node (node));
|
||||
if (cgraph_decide_is_function_needed (node, node->decl))
|
||||
cgraph_mark_needed_node (node);
|
||||
}
|
||||
else if (node->thunk.thunk_p)
|
||||
{
|
||||
cgraph_create_edge (node, cgraph_get_node (node->thunk.alias),
|
||||
NULL, 0, CGRAPH_FREQ_BASE);
|
||||
@ -809,6 +886,26 @@ cgraph_analyze_function (struct cgraph_node *node)
|
||||
current_function_decl = save;
|
||||
}
|
||||
|
||||
/* C++ frontend produce same body aliases all over the place, even before PCH
|
||||
gets streamed out. It relies on us linking the aliases with their function
|
||||
in order to do the fixups, but ipa-ref is not PCH safe. Consequentely we
|
||||
first produce aliases without links, but once C++ FE is sure he won't sream
|
||||
PCH we build the links via this function. */
|
||||
|
||||
void
|
||||
cgraph_process_same_body_aliases (void)
|
||||
{
|
||||
struct cgraph_node *node;
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
if (node->same_body_alias
|
||||
&& !VEC_length (ipa_ref_t, node->ref_list.references))
|
||||
{
|
||||
struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias);
|
||||
ipa_record_reference (node, NULL, tgt, NULL, IPA_REF_ALIAS, NULL);
|
||||
}
|
||||
same_body_aliases_done = true;
|
||||
}
|
||||
|
||||
/* Process attributes common for vars and functions. */
|
||||
|
||||
static void
|
||||
@ -880,7 +977,7 @@ process_function_and_variable_attributes (struct cgraph_node *first,
|
||||
cgraph_mark_needed_node (node);
|
||||
}
|
||||
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
|
||||
&& node->local.finalized)
|
||||
&& (node->local.finalized && !node->alias))
|
||||
{
|
||||
warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wattributes,
|
||||
"%<weakref%> attribute ignored"
|
||||
@ -979,6 +1076,7 @@ cgraph_analyze_functions (void)
|
||||
weak alias attribute to kill its body. See
|
||||
gcc.c-torture/compile/20011119-1.c */
|
||||
if (!DECL_STRUCT_FUNCTION (decl)
|
||||
&& (!node->alias || !node->thunk.alias)
|
||||
&& !node->thunk.thunk_p)
|
||||
{
|
||||
cgraph_reset_node (node);
|
||||
@ -1046,11 +1144,13 @@ cgraph_analyze_functions (void)
|
||||
next = node->next;
|
||||
|
||||
if (node->local.finalized && !gimple_has_body_p (decl)
|
||||
&& (!node->alias || !node->thunk.alias)
|
||||
&& !node->thunk.thunk_p)
|
||||
cgraph_reset_node (node);
|
||||
|
||||
if (!node->reachable
|
||||
&& (gimple_has_body_p (decl) || node->thunk.thunk_p))
|
||||
&& (gimple_has_body_p (decl) || node->thunk.thunk_p
|
||||
|| (node->alias && node->thunk.alias)))
|
||||
{
|
||||
if (cgraph_dump_file)
|
||||
fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
|
||||
@ -1060,6 +1160,7 @@ cgraph_analyze_functions (void)
|
||||
else
|
||||
node->next_needed = NULL;
|
||||
gcc_assert (!node->local.finalized || node->thunk.thunk_p
|
||||
|| node->alias
|
||||
|| gimple_has_body_p (decl));
|
||||
gcc_assert (node->analyzed == node->local.finalized);
|
||||
}
|
||||
@ -1157,9 +1258,11 @@ cgraph_mark_functions_to_output (void)
|
||||
outside the current compilation unit. */
|
||||
if (node->analyzed
|
||||
&& !node->thunk.thunk_p
|
||||
&& !node->alias
|
||||
&& !node->global.inlined_to
|
||||
&& (!cgraph_only_called_directly_p (node)
|
||||
|| (e && node->reachable))
|
||||
|| ((e || ipa_ref_has_aliases_p (&node->ref_list))
|
||||
&& node->reachable))
|
||||
&& !TREE_ASM_WRITTEN (decl)
|
||||
&& !DECL_EXTERNAL (decl))
|
||||
{
|
||||
@ -1170,7 +1273,7 @@ cgraph_mark_functions_to_output (void)
|
||||
for (next = node->same_comdat_group;
|
||||
next != node;
|
||||
next = next->same_comdat_group)
|
||||
if (!next->thunk.thunk_p)
|
||||
if (!next->thunk.thunk_p && !next->alias)
|
||||
next->process = 1;
|
||||
}
|
||||
}
|
||||
@ -1190,6 +1293,7 @@ cgraph_mark_functions_to_output (void)
|
||||
are inside partition, we can end up not removing the body since we no longer
|
||||
have analyzed node pointing to it. */
|
||||
&& !node->in_other_partition
|
||||
&& !node->alias
|
||||
&& !DECL_EXTERNAL (decl))
|
||||
{
|
||||
dump_cgraph_node (stderr, node);
|
||||
@ -1219,7 +1323,7 @@ cgraph_mark_functions_to_output (void)
|
||||
&& !DECL_EXTERNAL (decl))
|
||||
{
|
||||
dump_cgraph_node (stderr, node);
|
||||
internal_error ("failed to reclaim unneeded function");
|
||||
internal_error ("failed to reclaim unneeded functionin same comdat group");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -1569,23 +1673,35 @@ assemble_thunk (struct cgraph_node *node)
|
||||
}
|
||||
|
||||
|
||||
/* Assemble thunks asociated to NODE. */
|
||||
|
||||
/* Assemble thunks and aliases asociated to NODE. */
|
||||
|
||||
static void
|
||||
assemble_thunks (struct cgraph_node *node)
|
||||
assemble_thunks_and_aliases (struct cgraph_node *node)
|
||||
{
|
||||
struct cgraph_edge *e;
|
||||
int i;
|
||||
struct ipa_ref *ref;
|
||||
|
||||
for (e = node->callers; e;)
|
||||
if (e->caller->thunk.thunk_p)
|
||||
{
|
||||
struct cgraph_node *thunk = e->caller;
|
||||
|
||||
e = e->next_caller;
|
||||
assemble_thunks (thunk);
|
||||
assemble_thunks_and_aliases (thunk);
|
||||
assemble_thunk (thunk);
|
||||
}
|
||||
else
|
||||
e = e->next_caller;
|
||||
for (i = 0; ipa_ref_list_refering_iterate (&node->ref_list, i, ref); i++)
|
||||
if (ref->use == IPA_REF_ALIAS)
|
||||
{
|
||||
struct cgraph_node *alias = ipa_ref_refering_node (ref);
|
||||
assemble_alias (alias->decl,
|
||||
DECL_ASSEMBLER_NAME (alias->thunk.alias));
|
||||
assemble_thunks_and_aliases (alias);
|
||||
}
|
||||
}
|
||||
|
||||
/* Expand function specified by NODE. */
|
||||
@ -1600,27 +1716,7 @@ cgraph_expand_function (struct cgraph_node *node)
|
||||
|
||||
announce_function (decl);
|
||||
node->process = 0;
|
||||
if (node->same_body)
|
||||
{
|
||||
struct cgraph_node *alias, *next;
|
||||
bool saved_alias = node->alias;
|
||||
for (alias = node->same_body;
|
||||
alias && alias->next; alias = alias->next)
|
||||
;
|
||||
/* Walk aliases in the order they were created; it is possible that
|
||||
thunks refers to the aliases made earlier. */
|
||||
for (; alias; alias = next)
|
||||
{
|
||||
next = alias->previous;
|
||||
if (!alias->thunk.thunk_p)
|
||||
assemble_alias (alias->decl,
|
||||
DECL_ASSEMBLER_NAME (alias->thunk.alias));
|
||||
}
|
||||
node->alias = saved_alias;
|
||||
cgraph_process_new_functions ();
|
||||
}
|
||||
|
||||
assemble_thunks (node);
|
||||
assemble_thunks_and_aliases (node);
|
||||
gcc_assert (node->lowered);
|
||||
|
||||
/* Generate RTL for the body of DECL. */
|
||||
@ -1736,7 +1832,7 @@ cgraph_output_in_order (void)
|
||||
|
||||
for (pf = cgraph_nodes; pf; pf = pf->next)
|
||||
{
|
||||
if (pf->process && !pf->thunk.thunk_p)
|
||||
if (pf->process && !pf->thunk.thunk_p && !pf->alias)
|
||||
{
|
||||
i = pf->order;
|
||||
gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
|
||||
@ -1810,7 +1906,7 @@ bool
|
||||
cgraph_preserve_function_body_p (struct cgraph_node *node)
|
||||
{
|
||||
gcc_assert (cgraph_global_info_ready);
|
||||
gcc_assert (!node->same_body_alias);
|
||||
gcc_assert (!node->alias && !node->thunk.thunk_p);
|
||||
|
||||
/* Look if there is any clone around. */
|
||||
if (node->clones)
|
||||
|
@ -1,3 +1,8 @@
|
||||
2011-06-11 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* decl2.c (cp_write_global_declarations): Process aliases; look trhough
|
||||
same body aliases.
|
||||
|
||||
2011-06-10 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
|
||||
PR c++/41769
|
||||
|
@ -3672,6 +3672,8 @@ cp_write_global_declarations (void)
|
||||
if (pch_file)
|
||||
c_common_write_pch ();
|
||||
|
||||
cgraph_process_same_body_aliases ();
|
||||
|
||||
/* Handle -fdump-ada-spec[-slim] */
|
||||
if (dump_enabled_p (TDI_ada))
|
||||
{
|
||||
@ -3869,6 +3871,8 @@ cp_write_global_declarations (void)
|
||||
struct cgraph_node *node, *next;
|
||||
|
||||
node = cgraph_get_node (decl);
|
||||
if (node->same_body_alias)
|
||||
node = cgraph_alias_aliased_node (node);
|
||||
|
||||
cgraph_for_node_and_aliases (node, clear_decl_external,
|
||||
NULL, true);
|
||||
|
@ -3363,9 +3363,8 @@ cp_fix_function_decl_p (tree decl)
|
||||
|
||||
/* Don't fix same_body aliases. Although they don't have their own
|
||||
CFG, they share it with what they alias to. */
|
||||
if (!node
|
||||
|| node->decl == decl
|
||||
|| !node->same_body)
|
||||
if (!node || !node->alias
|
||||
|| !VEC_length (ipa_ref_t, node->ref_list.references))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -88,6 +88,7 @@ can_remove_node_now_p (struct cgraph_node *node)
|
||||
can remove its offline copy, but we would need to keep unanalyzed node in
|
||||
the callgraph so references can point to it. */
|
||||
return (!node->address_taken
|
||||
&& !ipa_ref_has_aliases_p (&node->ref_list)
|
||||
&& cgraph_can_remove_if_no_direct_calls_p (node)
|
||||
/* Inlining might enable more devirtualizing, so we want to remove
|
||||
those only after all devirtualizable virtual calls are processed.
|
||||
@ -192,7 +193,22 @@ inline_call (struct cgraph_edge *e, bool update_original,
|
||||
/* If aliases are involved, redirect edge to the actual destination and
|
||||
possibly remove the aliases. */
|
||||
if (e->callee != callee)
|
||||
cgraph_redirect_edge_callee (e, callee);
|
||||
{
|
||||
struct cgraph_node *alias = e->callee, *next_alias;
|
||||
cgraph_redirect_edge_callee (e, callee);
|
||||
while (alias && alias != callee)
|
||||
{
|
||||
if (!alias->callers
|
||||
&& can_remove_node_now_p (alias))
|
||||
{
|
||||
next_alias = cgraph_alias_aliased_node (alias);
|
||||
cgraph_remove_node (alias);
|
||||
alias = next_alias;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
clone_inlined_nodes (e, true, update_original, overall_size);
|
||||
|
||||
|
@ -965,6 +965,8 @@ update_caller_keys (fibheap_t heap, struct cgraph_node *node,
|
||||
struct cgraph_edge *check_inlinablity_for)
|
||||
{
|
||||
struct cgraph_edge *edge;
|
||||
int i;
|
||||
struct ipa_ref *ref;
|
||||
|
||||
if (!inline_summary (node)->inlinable
|
||||
|| cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE
|
||||
@ -973,6 +975,13 @@ update_caller_keys (fibheap_t heap, struct cgraph_node *node,
|
||||
if (!bitmap_set_bit (updated_nodes, node->uid))
|
||||
return;
|
||||
|
||||
for (i = 0; ipa_ref_list_refering_iterate (&node->ref_list, i, ref); i++)
|
||||
if (ref->use == IPA_REF_ALIAS)
|
||||
{
|
||||
struct cgraph_node *alias = ipa_ref_refering_node (ref);
|
||||
update_caller_keys (heap, alias, updated_nodes, check_inlinablity_for);
|
||||
}
|
||||
|
||||
for (edge = node->callers; edge; edge = edge->next_caller)
|
||||
if (edge->inline_failed)
|
||||
{
|
||||
@ -1451,7 +1460,7 @@ inline_small_functions (void)
|
||||
where = edge->caller;
|
||||
while (where->global.inlined_to)
|
||||
{
|
||||
if (where->decl == edge->callee->decl)
|
||||
if (where->decl == callee->decl)
|
||||
outer_node = where, depth++;
|
||||
where = where->callers->caller;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "target.h"
|
||||
#include "cgraph.h"
|
||||
|
||||
static const char *ipa_ref_use_name[] = {"read","write","addr"};
|
||||
static const char *ipa_ref_use_name[] = {"read","write","addr","alias"};
|
||||
|
||||
/* Return ipa reference from REFERING_NODE or REFERING_VARPOOL_NODE
|
||||
to REFERED_NODE or REFERED_VARPOOL_NODE. USE_TYPE specify type
|
||||
@ -46,6 +46,7 @@ ipa_record_reference (struct cgraph_node *refering_node,
|
||||
gcc_assert ((!refering_node) ^ (!refering_varpool_node));
|
||||
gcc_assert ((!refered_node) ^ (!refered_varpool_node));
|
||||
gcc_assert (!stmt || refering_node);
|
||||
gcc_assert (use_type != IPA_REF_ALIAS || !stmt);
|
||||
|
||||
list = (refering_node ? &refering_node->ref_list
|
||||
: &refering_varpool_node->ref_list);
|
||||
@ -73,7 +74,7 @@ ipa_record_reference (struct cgraph_node *refering_node,
|
||||
{
|
||||
ref->refered.cgraph_node = refered_node;
|
||||
ref->refered_type = IPA_REF_CGRAPH;
|
||||
gcc_assert (use_type == IPA_REF_ADDR);
|
||||
gcc_assert (use_type == IPA_REF_ADDR || use_type == IPA_REF_ALIAS);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -241,3 +242,15 @@ ipa_ref_cannot_lead_to_return (struct ipa_ref *ref)
|
||||
{
|
||||
return cgraph_node_cannot_return (ipa_ref_refering_node (ref));
|
||||
}
|
||||
|
||||
/* Return true if list contains an alias. */
|
||||
bool
|
||||
ipa_ref_has_aliases_p (struct ipa_ref_list *ref_list)
|
||||
{
|
||||
struct ipa_ref *ref;
|
||||
int i;
|
||||
for (i = 0; ipa_ref_list_refering_iterate (ref_list, i, ref); i++)
|
||||
if (ref->use == IPA_REF_ALIAS)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -27,7 +27,8 @@ enum GTY(()) ipa_ref_use
|
||||
{
|
||||
IPA_REF_LOAD,
|
||||
IPA_REF_STORE,
|
||||
IPA_REF_ADDR
|
||||
IPA_REF_ADDR,
|
||||
IPA_REF_ALIAS
|
||||
};
|
||||
|
||||
/* Type of refering or refered type. */
|
||||
@ -89,4 +90,4 @@ void ipa_dump_refering (FILE *, struct ipa_ref_list *);
|
||||
void ipa_clone_references (struct cgraph_node *, struct varpool_node *, struct ipa_ref_list *);
|
||||
void ipa_clone_refering (struct cgraph_node *, struct varpool_node *, struct ipa_ref_list *);
|
||||
bool ipa_ref_cannot_lead_to_return (struct ipa_ref *);
|
||||
|
||||
bool ipa_ref_has_aliases_p (struct ipa_ref_list *);
|
||||
|
@ -234,7 +234,8 @@ ipa_free_postorder_info (void)
|
||||
}
|
||||
|
||||
/* Fill array order with all nodes with output flag set in the reverse
|
||||
topological order. Return the number of elements in the array. */
|
||||
topological order. Return the number of elements in the array.
|
||||
FIXME: While walking, consider aliases, too. */
|
||||
|
||||
int
|
||||
ipa_reverse_postorder (struct cgraph_node **order)
|
||||
@ -260,7 +261,7 @@ ipa_reverse_postorder (struct cgraph_node **order)
|
||||
&& (pass
|
||||
|| (!node->address_taken
|
||||
&& !node->global.inlined_to
|
||||
&& !cgraph_only_called_directly_p (node))))
|
||||
&& !cgraph_only_called_directly_or_aliased_p (node))))
|
||||
{
|
||||
node2 = node;
|
||||
if (!node->callers)
|
||||
|
26
gcc/ipa.c
26
gcc/ipa.c
@ -581,9 +581,9 @@ cgraph_comdat_can_be_unshared_p (struct cgraph_node *node)
|
||||
/* Return true when function NODE should be considered externally visible. */
|
||||
|
||||
static bool
|
||||
cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program, bool aliased)
|
||||
cgraph_externally_visible_p (struct cgraph_node *node,
|
||||
bool whole_program, bool aliased)
|
||||
{
|
||||
struct cgraph_node *alias;
|
||||
if (!node->local.finalized)
|
||||
return false;
|
||||
if (!DECL_COMDAT (node->decl)
|
||||
@ -630,18 +630,6 @@ cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program, bool
|
||||
&& 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.
|
||||
|
||||
Even if the linker clams the symbol is unused, never bring internal
|
||||
symbols that are declared by user as used or externally visible.
|
||||
This is needed for i.e. references from asm statements. */
|
||||
for (alias = node->same_body; alias; alias = alias->next)
|
||||
if (alias->resolution != LDPR_PREVAILING_DEF_IRONLY)
|
||||
break;
|
||||
if (!alias && node->resolution == LDPR_PREVAILING_DEF_IRONLY)
|
||||
return false;
|
||||
|
||||
/* When doing link time optimizations, hidden symbols become local. */
|
||||
if (in_lto_p
|
||||
&& (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN
|
||||
@ -881,12 +869,9 @@ function_and_variable_visibility (bool whole_program)
|
||||
if (!node->local.externally_visible && node->analyzed
|
||||
&& !DECL_EXTERNAL (node->decl))
|
||||
{
|
||||
struct cgraph_node *alias;
|
||||
gcc_assert (whole_program || in_lto_p || !TREE_PUBLIC (node->decl));
|
||||
cgraph_make_decl_local (node->decl);
|
||||
node->resolution = LDPR_PREVAILING_DEF_IRONLY;
|
||||
for (alias = node->same_body; alias; alias = alias->next)
|
||||
cgraph_make_decl_local (alias->decl);
|
||||
if (node->same_comdat_group)
|
||||
/* cgraph_externally_visible_p has already checked all other nodes
|
||||
in the group and they will all be made local. We need to
|
||||
@ -900,8 +885,7 @@ function_and_variable_visibility (bool whole_program)
|
||||
{
|
||||
struct cgraph_node *decl_node = node;
|
||||
|
||||
while (decl_node->thunk.thunk_p)
|
||||
decl_node = decl_node->callees->callee;
|
||||
decl_node = cgraph_function_node (decl_node->callees->callee, NULL);
|
||||
|
||||
/* Thunks have the same visibility as function they are attached to.
|
||||
For some reason C++ frontend don't seem to care. I.e. in
|
||||
@ -933,9 +917,9 @@ function_and_variable_visibility (bool whole_program)
|
||||
if (DECL_EXTERNAL (decl_node->decl))
|
||||
DECL_EXTERNAL (node->decl) = 1;
|
||||
}
|
||||
node->local.local = cgraph_local_node_p (node);
|
||||
|
||||
}
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
node->local.local = cgraph_local_node_p (node);
|
||||
for (vnode = varpool_nodes; vnode; vnode = vnode->next)
|
||||
{
|
||||
/* weak flag makes no sense on local variables. */
|
||||
|
@ -504,7 +504,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
|
||||
|| referenced_from_other_partition_p (&node->ref_list, set, vset)), 1);
|
||||
bp_pack_value (&bp, node->lowered, 1);
|
||||
bp_pack_value (&bp, in_other_partition, 1);
|
||||
bp_pack_value (&bp, node->alias, 1);
|
||||
bp_pack_value (&bp, node->alias && !boundary_p, 1);
|
||||
bp_pack_value (&bp, node->frequency, 2);
|
||||
bp_pack_value (&bp, node->only_called_at_startup, 1);
|
||||
bp_pack_value (&bp, node->only_called_at_exit, 1);
|
||||
@ -523,32 +523,15 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
|
||||
node->thunk.fixed_offset);
|
||||
lto_output_uleb128_stream (ob->main_stream,
|
||||
node->thunk.virtual_value);
|
||||
lto_output_fn_decl_index (ob->decl_state, ob->main_stream,
|
||||
node->thunk.alias);
|
||||
}
|
||||
|
||||
if (node->same_body)
|
||||
if ((node->alias || node->thunk.thunk_p) && !boundary_p)
|
||||
{
|
||||
struct cgraph_node *alias;
|
||||
unsigned long alias_count = 1;
|
||||
for (alias = node->same_body; alias->next; alias = alias->next)
|
||||
alias_count++;
|
||||
lto_output_uleb128_stream (ob->main_stream, alias_count);
|
||||
do
|
||||
{
|
||||
lto_output_fn_decl_index (ob->decl_state, ob->main_stream,
|
||||
alias->decl);
|
||||
lto_output_fn_decl_index (ob->decl_state, ob->main_stream,
|
||||
alias->thunk.alias);
|
||||
gcc_assert (cgraph_get_node (alias->thunk.alias) == node);
|
||||
lto_output_enum (ob->main_stream, ld_plugin_symbol_resolution,
|
||||
LDPR_NUM_KNOWN, alias->resolution);
|
||||
alias = alias->previous;
|
||||
}
|
||||
while (alias);
|
||||
lto_output_int_in_range (ob->main_stream, 0, 1,
|
||||
node->thunk.alias != NULL);
|
||||
if (node->thunk.alias != NULL)
|
||||
lto_output_fn_decl_index (ob->decl_state, ob->main_stream,
|
||||
node->thunk.alias);
|
||||
}
|
||||
else
|
||||
lto_output_uleb128_stream (ob->main_stream, 0);
|
||||
}
|
||||
|
||||
/* Output the varpool NODE to OB.
|
||||
@ -997,7 +980,6 @@ input_node (struct lto_file_decl_data *file_data,
|
||||
struct bitpack_d bp;
|
||||
unsigned decl_index;
|
||||
int ref = LCC_NOT_FOUND, ref2 = LCC_NOT_FOUND;
|
||||
unsigned long same_body_count = 0;
|
||||
int clone_ref;
|
||||
|
||||
clone_ref = lto_input_sleb128 (ib);
|
||||
@ -1043,31 +1025,20 @@ input_node (struct lto_file_decl_data *file_data,
|
||||
int type = lto_input_uleb128 (ib);
|
||||
HOST_WIDE_INT fixed_offset = lto_input_uleb128 (ib);
|
||||
HOST_WIDE_INT virtual_value = lto_input_uleb128 (ib);
|
||||
tree real_alias;
|
||||
|
||||
decl_index = lto_input_uleb128 (ib);
|
||||
real_alias = lto_file_decl_data_get_fn_decl (file_data, decl_index);
|
||||
node->thunk.fixed_offset = fixed_offset;
|
||||
node->thunk.this_adjusting = (type & 2);
|
||||
node->thunk.virtual_value = virtual_value;
|
||||
node->thunk.virtual_offset_p = (type & 4);
|
||||
node->thunk.alias = real_alias;
|
||||
}
|
||||
|
||||
same_body_count = lto_input_uleb128 (ib);
|
||||
while (same_body_count-- > 0)
|
||||
if (node->thunk.thunk_p || node->alias)
|
||||
{
|
||||
tree alias_decl, real_alias;
|
||||
struct cgraph_node *alias;
|
||||
|
||||
decl_index = lto_input_uleb128 (ib);
|
||||
alias_decl = lto_file_decl_data_get_fn_decl (file_data, decl_index);
|
||||
decl_index = lto_input_uleb128 (ib);
|
||||
real_alias = lto_file_decl_data_get_fn_decl (file_data, decl_index);
|
||||
alias = cgraph_same_body_alias (node, alias_decl, real_alias);
|
||||
gcc_assert (alias);
|
||||
alias->resolution = lto_input_enum (ib, ld_plugin_symbol_resolution,
|
||||
LDPR_NUM_KNOWN);
|
||||
if (lto_input_int_in_range (ib, "alias nonzero flag", 0, 1))
|
||||
{
|
||||
decl_index = lto_input_uleb128 (ib);
|
||||
node->thunk.alias = lto_file_decl_data_get_fn_decl (file_data,
|
||||
decl_index);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
@ -2253,6 +2253,7 @@ lto_output (cgraph_node_set set, varpool_node_set vset)
|
||||
{
|
||||
node = lto_cgraph_encoder_deref (encoder, i);
|
||||
if (lto_cgraph_encoder_encode_body_p (encoder, node)
|
||||
&& !node->alias
|
||||
&& !node->thunk.thunk_p)
|
||||
{
|
||||
#ifdef ENABLE_CHECKING
|
||||
@ -2551,7 +2552,7 @@ produce_symtab (struct output_block *ob,
|
||||
struct lto_streamer_cache_d *cache = ob->writer_cache;
|
||||
char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL);
|
||||
struct pointer_set_t *seen;
|
||||
struct cgraph_node *node, *alias;
|
||||
struct cgraph_node *node;
|
||||
struct varpool_node *vnode, *valias;
|
||||
struct lto_output_stream stream;
|
||||
lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder;
|
||||
@ -2584,8 +2585,6 @@ produce_symtab (struct output_block *ob,
|
||||
if (node->alias || node->global.inlined_to)
|
||||
continue;
|
||||
write_symbol (cache, &stream, node->decl, seen, false);
|
||||
for (alias = node->same_body; alias; alias = alias->next)
|
||||
write_symbol (cache, &stream, alias->decl, seen, true);
|
||||
}
|
||||
for (i = 0; i < lto_cgraph_encoder_size (encoder); i++)
|
||||
{
|
||||
@ -2598,8 +2597,6 @@ produce_symtab (struct output_block *ob,
|
||||
if (node->alias || node->global.inlined_to)
|
||||
continue;
|
||||
write_symbol (cache, &stream, node->decl, seen, false);
|
||||
for (alias = node->same_body; alias; alias = alias->next)
|
||||
write_symbol (cache, &stream, alias->decl, seen, true);
|
||||
}
|
||||
|
||||
/* Write all variables. */
|
||||
|
@ -209,7 +209,6 @@ lto_cgraph_replace_node (struct cgraph_node *node,
|
||||
struct cgraph_node *prevailing_node)
|
||||
{
|
||||
struct cgraph_edge *e, *next;
|
||||
bool no_aliases_please = false;
|
||||
bool compatible_p;
|
||||
|
||||
if (cgraph_dump_file)
|
||||
@ -223,13 +222,6 @@ lto_cgraph_replace_node (struct cgraph_node *node,
|
||||
(IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)))));
|
||||
}
|
||||
|
||||
if (prevailing_node->same_body_alias)
|
||||
{
|
||||
if (prevailing_node->thunk.thunk_p)
|
||||
no_aliases_please = true;
|
||||
prevailing_node = prevailing_node->same_body;
|
||||
}
|
||||
|
||||
/* Merge node flags. */
|
||||
if (node->needed)
|
||||
cgraph_mark_needed_node (prevailing_node);
|
||||
@ -259,36 +251,8 @@ lto_cgraph_replace_node (struct cgraph_node *node,
|
||||
/* Redirect incomming references. */
|
||||
ipa_clone_refering (prevailing_node, NULL, &node->ref_list);
|
||||
|
||||
/* If we have aliases, redirect them to the prevailing node. */
|
||||
if (!node->same_body_alias && node->same_body)
|
||||
{
|
||||
struct cgraph_node *alias, *last;
|
||||
/* We prevail aliases/tunks by a thunk. This is doable but
|
||||
would need thunk combination. Hopefully no ABI changes will
|
||||
every be crazy enough. */
|
||||
gcc_assert (!no_aliases_please);
|
||||
|
||||
for (alias = node->same_body; alias; alias = alias->next)
|
||||
{
|
||||
last = alias;
|
||||
gcc_assert (alias->same_body_alias);
|
||||
alias->same_body = prevailing_node;
|
||||
}
|
||||
last->next = prevailing_node->same_body;
|
||||
/* Node with aliases is prevailed by alias.
|
||||
We could handle this, but combining thunks together will be tricky.
|
||||
Hopefully this does not happen. */
|
||||
if (prevailing_node->same_body)
|
||||
prevailing_node->same_body->previous = last;
|
||||
prevailing_node->same_body = node->same_body;
|
||||
node->same_body = NULL;
|
||||
}
|
||||
|
||||
/* Finally remove the replaced node. */
|
||||
if (node->same_body_alias)
|
||||
cgraph_remove_same_body_alias (node);
|
||||
else
|
||||
cgraph_remove_node (node);
|
||||
cgraph_remove_node (node);
|
||||
}
|
||||
|
||||
/* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
|
||||
@ -472,9 +436,7 @@ lto_symtab_resolve_can_prevail_p (lto_symtab_entry_t e)
|
||||
|
||||
/* For functions we need a non-discarded body. */
|
||||
if (TREE_CODE (e->decl) == FUNCTION_DECL)
|
||||
return (e->node
|
||||
&& (e->node->analyzed
|
||||
|| (e->node->same_body_alias && e->node->same_body->analyzed)));
|
||||
return (e->node && e->node->analyzed);
|
||||
|
||||
/* A variable should have a size. */
|
||||
else if (TREE_CODE (e->decl) == VAR_DECL)
|
||||
@ -816,20 +778,14 @@ lto_symtab_merge_cgraph_nodes_1 (void **slot, void *data ATTRIBUTE_UNUSED)
|
||||
void
|
||||
lto_symtab_merge_cgraph_nodes (void)
|
||||
{
|
||||
struct cgraph_node *node, *alias, *next;
|
||||
struct cgraph_node *node;
|
||||
lto_symtab_maybe_init_hash_table ();
|
||||
htab_traverse (lto_symtab_identifiers, lto_symtab_merge_cgraph_nodes_1, NULL);
|
||||
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
{
|
||||
if (node->thunk.thunk_p)
|
||||
node->thunk.alias = lto_symtab_prevailing_decl (node->thunk.alias);
|
||||
for (alias = node->same_body; alias; alias = next)
|
||||
{
|
||||
next = alias->next;
|
||||
alias->thunk.alias = lto_symtab_prevailing_decl (alias->thunk.alias);
|
||||
}
|
||||
}
|
||||
if ((node->thunk.thunk_p || node->alias)
|
||||
&& node->thunk.alias)
|
||||
node->thunk.alias = lto_symtab_prevailing_decl (node->thunk.alias);
|
||||
}
|
||||
|
||||
/* Given the decl DECL, return the prevailing decl with the same name. */
|
||||
|
@ -1,3 +1,12 @@
|
||||
2011-06-11 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* lto.c (add_cgraph_node_to_partition_1): Break out from ...
|
||||
(add_cgraph_node_to_partition) ... here; walk aliases.
|
||||
(lto_1_to_1_map): Remove same body alias code.
|
||||
(promote_fn): Likewise.
|
||||
(lto_promote_cross_file_statics): Update comment.
|
||||
|
||||
|
||||
2011-06-07 Diego Novillo <dnovillo@google.com>
|
||||
|
||||
* lto.c (uniquify_nodes): Move code to register decls to
|
||||
|
@ -1319,7 +1319,7 @@ add_references_to_partition (ltrans_partition part, struct ipa_ref_list *refs)
|
||||
for (i = 0; ipa_ref_list_reference_iterate (refs, i, ref); i++)
|
||||
{
|
||||
if (ref->refered_type == IPA_REF_CGRAPH
|
||||
&& DECL_COMDAT (ipa_ref_node (ref)->decl)
|
||||
&& DECL_COMDAT (cgraph_function_node (ipa_ref_node (ref), NULL)->decl)
|
||||
&& !cgraph_node_in_set_p (ipa_ref_node (ref), part->cgraph_set))
|
||||
add_cgraph_node_to_partition (part, ipa_ref_node (ref));
|
||||
else
|
||||
@ -1330,20 +1330,21 @@ add_references_to_partition (ltrans_partition part, struct ipa_ref_list *refs)
|
||||
}
|
||||
}
|
||||
|
||||
/* Add NODE to partition as well as the inline callees and referred comdats into partition PART. */
|
||||
/* Worker for add_cgraph_node_to_partition. */
|
||||
|
||||
static void
|
||||
add_cgraph_node_to_partition (ltrans_partition part, struct cgraph_node *node)
|
||||
static bool
|
||||
add_cgraph_node_to_partition_1 (struct cgraph_node *node, void *data)
|
||||
{
|
||||
struct cgraph_edge *e;
|
||||
cgraph_node_set_iterator csi;
|
||||
ltrans_partition part = (ltrans_partition) data;
|
||||
|
||||
/* If NODE is already there, we have nothing to do. */
|
||||
csi = cgraph_node_set_find (part->cgraph_set, node);
|
||||
if (!csi_end_p (csi))
|
||||
return;
|
||||
|
||||
part->insns += inline_summary (node)->self_size;
|
||||
/* non-COMDAT aliases of COMDAT functions needs to be output just once. */
|
||||
if (!DECL_COMDAT (node->decl)
|
||||
&& !node->global.inlined_to
|
||||
&& node->aux)
|
||||
{
|
||||
gcc_assert (node->thunk.thunk_p || node->alias);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (node->aux)
|
||||
{
|
||||
@ -1353,26 +1354,45 @@ add_cgraph_node_to_partition (ltrans_partition part, struct cgraph_node *node)
|
||||
cgraph_node_name (node), node->uid);
|
||||
}
|
||||
node->aux = (void *)((size_t)node->aux + 1);
|
||||
cgraph_node_set_add (part->cgraph_set, node);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Add NODE to partition as well as the inline callees and referred comdats into partition PART. */
|
||||
|
||||
static void
|
||||
add_cgraph_node_to_partition (ltrans_partition part, struct cgraph_node *node)
|
||||
{
|
||||
struct cgraph_edge *e;
|
||||
cgraph_node_set_iterator csi;
|
||||
struct cgraph_node *n;
|
||||
|
||||
/* We always decide on functions, not associated thunks and aliases. */
|
||||
node = cgraph_function_node (node, NULL);
|
||||
|
||||
/* If NODE is already there, we have nothing to do. */
|
||||
csi = cgraph_node_set_find (part->cgraph_set, node);
|
||||
if (!csi_end_p (csi))
|
||||
return;
|
||||
|
||||
cgraph_for_node_thunks_and_aliases (node, add_cgraph_node_to_partition_1, part, true);
|
||||
|
||||
part->insns += inline_summary (node)->self_size;
|
||||
|
||||
|
||||
cgraph_node_set_add (part->cgraph_set, node);
|
||||
|
||||
/* Thunks always must go along with function they reffer to. */
|
||||
if (node->thunk.thunk_p)
|
||||
add_cgraph_node_to_partition (part, node->callees->callee);
|
||||
for (e = node->callers; e; e = e->next_caller)
|
||||
if (e->caller->thunk.thunk_p)
|
||||
add_cgraph_node_to_partition (part, e->caller);
|
||||
|
||||
for (e = node->callees; e; e = e->next_callee)
|
||||
if ((!e->inline_failed || DECL_COMDAT (e->callee->decl))
|
||||
if ((!e->inline_failed
|
||||
|| DECL_COMDAT (cgraph_function_node (e->callee, NULL)->decl))
|
||||
&& !cgraph_node_in_set_p (e->callee, part->cgraph_set))
|
||||
add_cgraph_node_to_partition (part, e->callee);
|
||||
|
||||
add_references_to_partition (part, &node->ref_list);
|
||||
|
||||
if (node->same_comdat_group
|
||||
&& !cgraph_node_in_set_p (node->same_comdat_group, part->cgraph_set))
|
||||
add_cgraph_node_to_partition (part, node->same_comdat_group);
|
||||
if (node->same_comdat_group)
|
||||
for (n = node->same_comdat_group; n != node; n = n->same_comdat_group)
|
||||
add_cgraph_node_to_partition (part, n);
|
||||
}
|
||||
|
||||
/* Add VNODE to partition as well as comdat references partition PART. */
|
||||
@ -1500,7 +1520,6 @@ lto_1_to_1_map (void)
|
||||
continue;
|
||||
|
||||
file_data = node->local.lto_file_data;
|
||||
gcc_assert (!node->same_body_alias);
|
||||
|
||||
if (file_data)
|
||||
{
|
||||
@ -1900,17 +1919,6 @@ promote_fn (struct cgraph_node *node)
|
||||
TREE_PUBLIC (node->decl) = 1;
|
||||
DECL_VISIBILITY (node->decl) = VISIBILITY_HIDDEN;
|
||||
DECL_VISIBILITY_SPECIFIED (node->decl) = true;
|
||||
if (node->same_body)
|
||||
{
|
||||
struct cgraph_node *alias;
|
||||
for (alias = node->same_body;
|
||||
alias; alias = alias->next)
|
||||
{
|
||||
TREE_PUBLIC (alias->decl) = 1;
|
||||
DECL_VISIBILITY (alias->decl) = VISIBILITY_HIDDEN;
|
||||
DECL_VISIBILITY_SPECIFIED (alias->decl) = true;
|
||||
}
|
||||
}
|
||||
if (cgraph_dump_file)
|
||||
fprintf (cgraph_dump_file,
|
||||
"Promoting function as hidden: %s/%i\n",
|
||||
@ -1944,8 +1952,8 @@ lto_promote_cross_file_statics (void)
|
||||
set = part->cgraph_set;
|
||||
vset = part->varpool_set;
|
||||
|
||||
/* If node has either address taken (and we have no clue from where)
|
||||
or it is called from other partition, it needs to be globalized. */
|
||||
/* If node called or referred to from other partition, it needs to be
|
||||
globalized. */
|
||||
for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
|
||||
{
|
||||
struct cgraph_node *node = csi_node (csi);
|
||||
|
@ -6675,6 +6675,16 @@ gate_ipa_pta (void)
|
||||
struct pt_solution ipa_escaped_pt
|
||||
= { true, false, false, false, false, false, false, NULL };
|
||||
|
||||
/* Associate node with varinfo DATA. Worker for
|
||||
cgraph_for_node_and_aliases. */
|
||||
static bool
|
||||
associate_varinfo_to_alias (struct cgraph_node *node, void *data)
|
||||
{
|
||||
if (node->alias || node->thunk.thunk_p)
|
||||
insert_vi_for_tree (node->decl, (varinfo_t)data);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Execute the driver for IPA PTA. */
|
||||
static unsigned int
|
||||
ipa_pta_execute (void)
|
||||
@ -6690,22 +6700,17 @@ ipa_pta_execute (void)
|
||||
/* Build the constraints. */
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
{
|
||||
struct cgraph_node *alias;
|
||||
varinfo_t vi;
|
||||
|
||||
/* Nodes without a body are not interesting. Especially do not
|
||||
visit clones at this point for now - we get duplicate decls
|
||||
there for inline clones at least. */
|
||||
if (!gimple_has_body_p (node->decl)
|
||||
if (!cgraph_function_with_gimple_body_p (node)
|
||||
|| node->clone_of)
|
||||
continue;
|
||||
|
||||
vi = create_function_info_for (node->decl,
|
||||
alias_get_name (node->decl));
|
||||
|
||||
/* Associate the varinfo node with all aliases. */
|
||||
for (alias = node->same_body; alias; alias = alias->next)
|
||||
insert_vi_for_tree (alias->decl, vi);
|
||||
alias_get_name (node->decl));
|
||||
cgraph_for_node_and_aliases (node, associate_varinfo_to_alias, vi, true);
|
||||
}
|
||||
|
||||
/* Create constraints for global variables and their initializers. */
|
||||
@ -6737,7 +6742,7 @@ ipa_pta_execute (void)
|
||||
tree old_func_decl;
|
||||
|
||||
/* Nodes without a body are not interesting. */
|
||||
if (!gimple_has_body_p (node->decl)
|
||||
if (!cgraph_function_with_gimple_body_p (node)
|
||||
|| node->clone_of)
|
||||
continue;
|
||||
|
||||
@ -6846,7 +6851,7 @@ ipa_pta_execute (void)
|
||||
struct cgraph_edge *e;
|
||||
|
||||
/* Nodes without a body are not interesting. */
|
||||
if (!gimple_has_body_p (node->decl)
|
||||
if (!cgraph_function_with_gimple_body_p (node)
|
||||
|| node->clone_of)
|
||||
continue;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user