Hi,
current functions that appear as abstract origin of other function gets
abstract_and_needed flag set.  This flag is then not maintained in any way,
but it is used by cgraph_remove_node to avoid removing block tree dneeded later
by dwarf2out.

This patch makes the tracking more explicit. Unreachable function removal now
maintains the info about what is used as abstract origin.
I also renamed the flag to used_as_abstract_origin, since abstract_and_needed
suggest that function is DECL_ABSTRACT that is not the rule.

This ensures that all abstract origin functions do have nodes attached and this
info can be used in free_lang_data and LTO streaming/partitioning (currently we
do not bother to ship the trees into LTO partitions that needs them)


Bootstrapped/regtested ppc64-linux and in earlier version x86_64-linux, 
comitted.

Honza

        * 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.
Index: cgraph.c
===================================================================
*** cgraph.c    (revision 201291)
--- cgraph.c    (working copy)
*************** void
*** 1316,1322 ****
  cgraph_release_function_body (struct cgraph_node *node)
  {
    node->ipa_transforms_to_apply.release ();
!   if (!node->abstract_and_needed && cgraph_state != CGRAPH_STATE_PARSING)
      {
        DECL_RESULT (node->symbol.decl) = NULL;
        DECL_ARGUMENTS (node->symbol.decl) = NULL;
--- 1317,1323 ----
  cgraph_release_function_body (struct cgraph_node *node)
  {
    node->ipa_transforms_to_apply.release ();
!   if (!node->used_as_abstract_origin && cgraph_state != CGRAPH_STATE_PARSING)
      {
        DECL_RESULT (node->symbol.decl) = NULL;
        DECL_ARGUMENTS (node->symbol.decl) = NULL;
*************** cgraph_release_function_body (struct cgr
*** 1324,1330 ****
    /* 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))
      DECL_INITIAL (node->symbol.decl) = error_mark_node;
    release_function_body (node->symbol.decl);
  }
--- 1325,1331 ----
    /* 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->used_as_abstract_origin && DECL_INITIAL (node->symbol.decl))
      DECL_INITIAL (node->symbol.decl) = error_mark_node;
    release_function_body (node->symbol.decl);
  }
Index: cgraph.h
===================================================================
*** cgraph.h    (revision 201291)
--- cgraph.h    (working copy)
*************** struct GTY(()) cgraph_node {
*** 303,309 ****
  
    /* Set when decl is an abstract function pointed to by the
       ABSTRACT_DECL_ORIGIN of a reachable function.  */
!   unsigned abstract_and_needed : 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
--- 303,309 ----
  
    /* Set when decl is an abstract function pointed to by the
       ABSTRACT_DECL_ORIGIN of a reachable function.  */
!   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
Index: ipa-inline-transform.c
===================================================================
*** ipa-inline-transform.c      (revision 201291)
--- ipa-inline-transform.c      (working copy)
*************** can_remove_node_now_p_1 (struct cgraph_n
*** 87,92 ****
--- 87,93 ----
       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.
Index: cgraphunit.c
===================================================================
*** cgraphunit.c        (revision 201291)
--- cgraphunit.c        (working copy)
*************** analyze_functions (void)
*** 925,931 ****
                {
                  struct cgraph_node *origin_node
                  = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl));
!                 origin_node->abstract_and_needed = true;
                }
            }
          else
--- 925,931 ----
                {
                  struct cgraph_node *origin_node
                  = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl));
!                 origin_node->used_as_abstract_origin = true;
                }
            }
          else
Index: ipa.c
===================================================================
*** ipa.c       (revision 201291)
--- ipa.c       (working copy)
*************** symtab_remove_unreachable_nodes (bool be
*** 234,253 ****
       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);
  
    /* Mark variables that are obviously needed.  */
    FOR_EACH_DEFINED_VARIABLE (vnode)
--- 234,256 ----
       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_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)
*************** symtab_remove_unreachable_nodes (bool be
*** 272,277 ****
--- 275,287 ----
        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)
Index: tree-inline.c
===================================================================
*** tree-inline.c       (revision 201291)
--- tree-inline.c       (working copy)
*************** tree_function_versioning (tree old_decl,
*** 5085,5090 ****
--- 5085,5092 ----
  
    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.  */
*************** tree_function_versioning (tree old_decl,
*** 5122,5127 ****
--- 5124,5131 ----
  
    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

Reply via email to