* cgraph.c (cgraph_release_function_body): Use used_as_abstract_origin.
(cgraph_release_function_body): Likewise.
(cgraph_can_remove_if_no_direct_calls_p): Likewise.
* cgraph.h (cgrpah_node): Rename abstract_and_needed
to used_as_abstract_origin.
* tree-inline-transfrom.c (can_remove_node_now_p_1): Do not remove
symbols used as abstract origins.
* cgraphunit.c (analyze_functions): Update.
* ipa.c (symtab_remove_unreachable_nodes): Recompute used_as_abstract_origin.
* tree-inline.c (tree_function_versioning): Update
used_as_abstract_origin; be ready for DECL_RESULT and DECL_ARGUMENTS to be
NULL.
* lto-symtab.c (lto_symtab_merge_symbols): Merge duplicated nodes for abstract functions.
* cgraph.h (symtab_real_symbol_p): Abstract declarations are not real symbols.
From-SVN: r201408
+2013-08-01 Jan Hubicka <jh@suse.cz>
+
+ * cgraph.c (cgraph_release_function_body): Use used_as_abstract_origin.
+ (cgraph_release_function_body): Likewise.
+ (cgraph_can_remove_if_no_direct_calls_p): Likewise.
+ * cgraph.h (cgrpah_node): Rename abstract_and_needed
+ to used_as_abstract_origin.
+ * tree-inline-transfrom.c (can_remove_node_now_p_1): Do not remove
+ symbols used as abstract origins.
+ * cgraphunit.c (analyze_functions): Update.
+ * ipa.c (symtab_remove_unreachable_nodes): Recompute used_as_abstract_origin.
+ * tree-inline.c (tree_function_versioning): Update
+ used_as_abstract_origin; be ready for DECL_RESULT and DECL_ARGUMENTS to be
+ NULL.
+
+ * lto-symtab.c (lto_symtab_merge_symbols): Merge duplicated nodes for abstract functions.
+ * cgraph.h (symtab_real_symbol_p): Abstract declarations are not real symbols.
+
2013-08-01 Jan Hubicka <jh@suse.cz>
* profile.c (compute_value_histograms): Fix thinko.
cgraph_release_function_body (struct cgraph_node *node)
{
node->ipa_transforms_to_apply.release ();
- if (!node->abstract_and_needed && cgraph_state != CGRAPH_STATE_PARSING)
+ if (!node->used_as_abstract_origin && cgraph_state != CGRAPH_STATE_PARSING)
{
DECL_RESULT (node->symbol.decl) = NULL;
DECL_ARGUMENTS (node->symbol.decl) = NULL;
/* If the node is abstract and needed, then do not clear DECL_INITIAL
of its associated function function declaration because it's
needed to emit debug info later. */
- if (!node->abstract_and_needed && DECL_INITIAL (node->symbol.decl))
+ if (!node->used_as_abstract_origin && DECL_INITIAL (node->symbol.decl))
DECL_INITIAL (node->symbol.decl) = error_mark_node;
release_function_body (node->symbol.decl);
}
/* Set when decl is an abstract function pointed to by the
ABSTRACT_DECL_ORIGIN of a reachable function. */
- unsigned abstract_and_needed : 1;
+ unsigned used_as_abstract_origin : 1;
/* Set once the function is lowered (i.e. its CFG is built). */
unsigned lowered : 1;
/* Set once the function has been instantiated and its callee
{
struct cgraph_node *cnode;
+ if (DECL_ABSTRACT (node->symbol.decl))
+ return false;
if (!is_a <cgraph_node> (node))
return true;
cnode = cgraph (node);
if (cnode->global.inlined_to)
return false;
- if (cnode->abstract_and_needed)
- return false;
return true;
}
#endif /* GCC_CGRAPH_H */
{
struct cgraph_node *origin_node
= cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl));
- origin_node->abstract_and_needed = true;
+ origin_node->used_as_abstract_origin = true;
}
}
else
the callgraph so references can point to it. */
return (!node->symbol.address_taken
&& !ipa_ref_has_aliases_p (&node->symbol.ref_list)
+ && !node->used_as_abstract_origin
&& 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.
This is mostly when they can be referenced externally. Inline clones
are special since their declarations are shared with master clone and thus
cgraph_can_remove_if_no_direct_calls_and_refs_p should not be called on them. */
- FOR_EACH_DEFINED_FUNCTION (node)
- if (!node->global.inlined_to
- && !node->symbol.in_other_partition
- && (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
- /* Keep around virtual functions for possible devirtualization. */
- || (before_inlining_p
- && DECL_VIRTUAL_P (node->symbol.decl))))
- {
- gcc_assert (!node->global.inlined_to);
- pointer_set_insert (reachable, node);
- enqueue_node ((symtab_node)node, &first, reachable);
- }
- else
- gcc_assert (!node->symbol.aux);
+ FOR_EACH_FUNCTION (node)
+ {
+ node->used_as_abstract_origin = false;
+ if (node->symbol.definition
+ && !node->global.inlined_to
+ && (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
+ /* Keep around virtual functions for possible devirtualization. */
+ || (before_inlining_p
+ && DECL_VIRTUAL_P (node->symbol.decl))))
+ {
+ gcc_assert (!node->global.inlined_to);
+ pointer_set_insert (reachable, node);
+ enqueue_node ((symtab_node)node, &first, reachable);
+ }
+ else
+ gcc_assert (!node->symbol.aux);
+ }
/* Mark variables that are obviously needed. */
FOR_EACH_DEFINED_VARIABLE (vnode)
node->symbol.aux = (void *)2;
else
{
+ if (DECL_ABSTRACT_ORIGIN (node->symbol.decl))
+ {
+ struct cgraph_node *origin_node
+ = cgraph_get_create_real_symbol_node (DECL_ABSTRACT_ORIGIN (node->symbol.decl));
+ origin_node->used_as_abstract_origin = true;
+ enqueue_node ((symtab_node) origin_node, &first, reachable);
+ }
/* If any symbol in a comdat group is reachable, force
all other in the same comdat group to be also reachable. */
if (node->symbol.same_comdat_group)
bp_pack_value (&bp, node->symbol.forced_by_abi, 1);
bp_pack_value (&bp, node->symbol.unique_name, 1);
bp_pack_value (&bp, node->symbol.address_taken, 1);
- bp_pack_value (&bp, node->abstract_and_needed, 1);
bp_pack_value (&bp, tag == LTO_symtab_analyzed_node
&& !DECL_EXTERNAL (node->symbol.decl)
&& !DECL_COMDAT (node->symbol.decl)
node->symbol.forced_by_abi = bp_unpack_value (bp, 1);
node->symbol.unique_name = bp_unpack_value (bp, 1);
node->symbol.address_taken = bp_unpack_value (bp, 1);
- node->abstract_and_needed = bp_unpack_value (bp, 1);
node->symbol.used_from_other_partition = bp_unpack_value (bp, 1);
node->lowered = bp_unpack_value (bp, 1);
node->symbol.analyzed = tag == LTO_symtab_analyzed_node;
&& (cnode2 = cgraph_get_node (node->symbol.decl))
&& cnode2 != cnode)
lto_cgraph_replace_node (cnode2, cnode);
+
+ /* Abstract functions may have duplicated cgraph nodes attached;
+ remove them. */
+ else if (cnode && DECL_ABSTRACT (cnode->symbol.decl)
+ && (cnode2 = cgraph_get_node (node->symbol.decl))
+ && cnode2 != cnode)
+ cgraph_remove_node (cnode2);
symtab_insert_node_to_hashtable ((symtab_node)node);
}
}
DECL_ARTIFICIAL (new_decl) = 1;
DECL_ABSTRACT_ORIGIN (new_decl) = DECL_ORIGIN (old_decl);
+ if (DECL_ORIGIN (old_decl) == old_decl)
+ old_version_node->used_as_abstract_origin = true;
DECL_FUNCTION_PERSONALITY (new_decl) = DECL_FUNCTION_PERSONALITY (old_decl);
/* Prepare the data structures for the tree copy. */
old_entry_block = ENTRY_BLOCK_PTR_FOR_FUNCTION
(DECL_STRUCT_FUNCTION (old_decl));
+ DECL_RESULT (new_decl) = DECL_RESULT (old_decl);
+ DECL_ARGUMENTS (new_decl) = DECL_ARGUMENTS (old_decl);
initialize_cfun (new_decl, old_decl,
old_entry_block->count);
DECL_STRUCT_FUNCTION (new_decl)->gimple_df->ipa_pta