Hi,
this is first patch that makes function body management more consistent to what
happens with variables. We now no longer incorrectly call
cgraph_release_function_body
for decls that are shared during LTO streaming and I fixed ipa.c to make proper
reachability analysis of partial symtabs seen during ltrans.
Bootstrapped/regtested x86_64-linux, also tested on firefox LTO, comitted.
Honza
* lto-symtab.c (lto_cgraph_replace_node): Release function body.
* cgraph.c (cgraph_remove_node): Do not release function body
when in cgraph streaming.
* ipa.c (process_references, symtab_remove_unreachable_nodes): Objects
in other partitions are not considered reachable; fix handling of
clones.
Index: lto-symtab.c
===================================================================
*** lto-symtab.c (revision 201225)
--- lto-symtab.c (working copy)
*************** lto_cgraph_replace_node (struct cgraph_n
*** 80,85 ****
--- 80,88 ----
/* Redirect incomming references. */
ipa_clone_referring ((symtab_node)prevailing_node, &node->symbol.ref_list);
+ if (node->symbol.decl != prevailing_node->symbol.decl)
+ cgraph_release_function_body (node);
+
/* Finally remove the replaced node. */
cgraph_remove_node (node);
}
Index: cgraph.c
===================================================================
*** cgraph.c (revision 201225)
--- cgraph.c (working copy)
*************** cgraph_remove_node (struct cgraph_node *
*** 1384,1398 ****
itself is kept in the cgraph even after it is compiled. Check whether
we are done with this body and reclaim it proactively if this is the
case.
*/
! n = cgraph_get_node (node->symbol.decl);
! if (!n
! || (!n->clones && !n->clone_of && !n->global.inlined_to
! && (cgraph_global_info_ready
! && (TREE_ASM_WRITTEN (n->symbol.decl)
! || DECL_EXTERNAL (n->symbol.decl)
! || !n->symbol.analyzed
! || n->symbol.in_other_partition))))
! cgraph_release_function_body (node);
node->symbol.decl = NULL;
if (node->call_site_hash)
--- 1384,1401 ----
itself is kept in the cgraph even after it is compiled. Check whether
we are done with this body and reclaim it proactively if this is the
case.
*/
! if (cgraph_state != CGRAPH_LTO_STREAMING)
! {
! n = cgraph_get_node (node->symbol.decl);
! if (!n
! || (!n->clones && !n->clone_of && !n->global.inlined_to
! && (cgraph_global_info_ready
! && (TREE_ASM_WRITTEN (n->symbol.decl)
! || DECL_EXTERNAL (n->symbol.decl)
! || !n->symbol.analyzed
! || (!flag_wpa && n->symbol.in_other_partition)))))
! cgraph_release_function_body (node);
! }
node->symbol.decl = NULL;
if (node->call_site_hash)
Index: ipa.c
===================================================================
*** ipa.c (revision 201225)
--- ipa.c (working copy)
*************** process_references (struct ipa_ref_list
*** 138,144 ****
{
symtab_node node = ref->referred;
! if (node->symbol.definition
&& ((!DECL_EXTERNAL (node->symbol.decl) || node->symbol.alias)
|| (before_inlining_p
/* We use variable constructors during late complation for
--- 138,144 ----
{
symtab_node node = ref->referred;
! if (node->symbol.definition && !node->symbol.in_other_partition
&& ((!DECL_EXTERNAL (node->symbol.decl) || node->symbol.alias)
|| (before_inlining_p
/* We use variable constructors during late complation for
*************** symtab_remove_unreachable_nodes (bool be
*** 236,241 ****
--- 236,242 ----
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
*************** symtab_remove_unreachable_nodes (bool be
*** 250,256 ****
/* Mark variables that are obviously needed. */
FOR_EACH_DEFINED_VARIABLE (vnode)
! if (!varpool_can_remove_if_no_refs (vnode))
{
pointer_set_insert (reachable, vnode);
enqueue_node ((symtab_node)vnode, &first, reachable);
--- 251,258 ----
/* Mark variables that are obviously needed. */
FOR_EACH_DEFINED_VARIABLE (vnode)
! if (!varpool_can_remove_if_no_refs (vnode)
! && !vnode->symbol.in_other_partition)
{
pointer_set_insert (reachable, vnode);
enqueue_node ((symtab_node)vnode, &first, reachable);
*************** symtab_remove_unreachable_nodes (bool be
*** 296,301 ****
--- 298,304 ----
for (e = cnode->callees; e; e = e->next_callee)
{
if (e->callee->symbol.definition
+ && !e->callee->symbol.in_other_partition
&& (!e->inline_failed
|| !DECL_EXTERNAL (e->callee->symbol.decl)
|| e->callee->symbol.alias
*************** symtab_remove_unreachable_nodes (bool be
*** 306,327 ****
/* When inline clone exists, mark body to be preserved so when
removing
offline copy of the function we don't kill it. */
! if (!cnode->symbol.alias && cnode->global.inlined_to)
pointer_set_insert (body_needed_for_clonning,
cnode->symbol.decl);
- }
! /* For non-inline clones, force their origins to the boundary and
ensure
! that body is not removed. */
! while (cnode->clone_of
! && !gimple_has_body_p (cnode->symbol.decl))
! {
! bool noninline = cnode->clone_of->symbol.decl !=
cnode->symbol.decl;
! cnode = cnode->clone_of;
! if (noninline)
! {
! pointer_set_insert (body_needed_for_clonning,
cnode->symbol.decl);
! enqueue_node ((symtab_node)cnode, &first, reachable);
! break;
}
}
}
--- 309,328 ----
/* When inline clone exists, mark body to be preserved so when
removing
offline copy of the function we don't kill it. */
! if (cnode->global.inlined_to)
pointer_set_insert (body_needed_for_clonning,
cnode->symbol.decl);
! /* For non-inline clones, force their origins to the boundary and
ensure
! that body is not removed. */
! while (cnode->clone_of)
! {
! bool noninline = cnode->clone_of->symbol.decl !=
cnode->symbol.decl;
! cnode = cnode->clone_of;
! if (noninline)
! {
! pointer_set_insert (body_needed_for_clonning,
cnode->symbol.decl);
! enqueue_node ((symtab_node)cnode, &first, reachable);
! }
}
}
}
*************** symtab_remove_unreachable_nodes (bool be
*** 358,363 ****
--- 359,366 ----
{
if (!pointer_set_contains (body_needed_for_clonning,
node->symbol.decl))
cgraph_release_function_body (node);
+ else if (!node->clone_of)
+ gcc_assert (DECL_RESULT (node->symbol.decl));
if (node->symbol.definition)
{
if (file)
*************** symtab_remove_unreachable_nodes (bool be
*** 366,371 ****
--- 369,377 ----
changed = true;
}
}
+ else
+ gcc_assert (node->clone_of || !cgraph_function_with_gimple_body_p (node)
+ || DECL_RESULT (node->symbol.decl));
}
/* Inline clones might be kept around so their materializing allows further