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

Reply via email to