> Hi,
> 
> PR 57539 revealed two problems with remapping reference descriptors
> during cloning of trees of inlined call graph nodes.  First, when
> indirect inlining is involved, we happily remove the reference
> descriptor itself by calling ipa_free_edge_args_substructures in
> ipa_propagate_indirect_call_infos.  Second, the current remapping code
> does not work because the global.inlined_to field of the destination
> caller is not yet set.
> 
> The patch below fixes the first problem by not calling the freeing
> function and the second one by making cgraph_clone_node set the
> required field prior to calling any duplication hooks (which is the
> only place where we have the pair of corresponding source and
> destination edge at our disposal so the duplication/remapping has to
> happen there).  I have also shortened the lists of corresponding
> references and cleared up the search loop a little.
> 
> I'll post a testcase in a separate patch.  This one bootstrapped and
> passed testsuite on x86_64-linux without any issues.  OK for trunk?
> 
> Thanks,
> 
> Martin
> 
> 
> 2013-06-10  Martin Jambor  <mjam...@suse.cz>
> 
>       PR tree-optimization/57539
>       * cgraphclones.c (cgraph_clone_node): Add parameter new_inlined_to, set
>       global.inlined_to of the new node to it.  All callers changed.
>       * ipa-inline-transform.c (clone_inlined_nodes): New variable
>       inlining_into, pass it to cgraph_clone_node.
>       * ipa-prop.c (ipa_propagate_indirect_call_infos): Do not call
>       ipa_free_edge_args_substructures.
>       (ipa_edge_duplication_hook): Only add edges from inlined nodes to
>       rdesc linked list.  Do not assert rdesc edges have inlined caller.
>       Assert we have found an rdesc in the rdesc list.

OK,
thanks
Honza
> 
> Index: src/gcc/cgraph.h
> ===================================================================
> --- src.orig/gcc/cgraph.h
> +++ src/gcc/cgraph.h
> @@ -707,7 +707,7 @@ struct cgraph_edge * cgraph_clone_edge (
>                                       unsigned, gcov_type, int, bool);
>  struct cgraph_node * cgraph_clone_node (struct cgraph_node *, tree, 
> gcov_type,
>                                       int, bool, vec<cgraph_edge_p>,
> -                                     bool);
> +                                     bool, struct cgraph_node *);
>  tree clone_function_name (tree decl, const char *);
>  struct cgraph_node * cgraph_create_virtual_clone (struct cgraph_node 
> *old_node,
>                                                 vec<cgraph_edge_p>,
> Index: src/gcc/cgraphclones.c
> ===================================================================
> --- src.orig/gcc/cgraphclones.c
> +++ src/gcc/cgraphclones.c
> @@ -167,13 +167,19 @@ cgraph_clone_edge (struct cgraph_edge *e
>     function's profile to reflect the fact that part of execution is handled
>     by node.  
>     When CALL_DUPLICATOIN_HOOK is true, the ipa passes are acknowledged about
> -   the new clone. Otherwise the caller is responsible for doing so later.  */
> +   the new clone. Otherwise the caller is responsible for doing so later.
> +
> +   If the new node is being inlined into another one, NEW_INLINED_TO should 
> be
> +   the outline function the new one is (even indirectly) inlined to.  All 
> hooks
> +   will see this in node's global.inlined_to, when invoked.  Can be NULL if 
> the
> +   node is not inlined.  */
>  
>  struct cgraph_node *
>  cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int 
> freq,
>                  bool update_original,
>                  vec<cgraph_edge_p> redirect_callers,
> -                bool call_duplication_hook)
> +                bool call_duplication_hook,
> +                struct cgraph_node *new_inlined_to)
>  {
>    struct cgraph_node *new_node = cgraph_create_empty_node ();
>    struct cgraph_edge *e;
> @@ -195,6 +201,7 @@ cgraph_clone_node (struct cgraph_node *n
>    new_node->symbol.externally_visible = false;
>    new_node->local.local = true;
>    new_node->global = n->global;
> +  new_node->global.inlined_to = new_inlined_to;
>    new_node->rtl = n->rtl;
>    new_node->count = count;
>    new_node->frequency = n->frequency;
> @@ -307,7 +314,7 @@ cgraph_create_virtual_clone (struct cgra
>  
>    new_node = cgraph_clone_node (old_node, new_decl, old_node->count,
>                               CGRAPH_FREQ_BASE, false,
> -                             redirect_callers, false);
> +                             redirect_callers, false, NULL);
>    /* Update the properties.
>       Make clone visible only within this translation unit.  Make sure
>       that is not weak also.
> Index: src/gcc/ipa-inline-transform.c
> ===================================================================
> --- src.orig/gcc/ipa-inline-transform.c
> +++ src/gcc/ipa-inline-transform.c
> @@ -132,6 +132,13 @@ void
>  clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
>                    bool update_original, int *overall_size)
>  {
> +  struct cgraph_node *inlining_into;
> +
> +  if (e->caller->global.inlined_to)
> +    inlining_into = e->caller->global.inlined_to;
> +  else
> +    inlining_into = e->caller;
> +
>    if (duplicate)
>      {
>        /* We may eliminate the need for out-of-line copy to be output.
> @@ -167,18 +174,15 @@ clone_inlined_nodes (struct cgraph_edge
>       {
>         struct cgraph_node *n;
>         n = cgraph_clone_node (e->callee, e->callee->symbol.decl,
> -                              e->count, e->frequency,
> -                              update_original, vNULL, true);
> +                              e->count, e->frequency, update_original,
> +                              vNULL, true, inlining_into);
>         cgraph_redirect_edge_callee (e, n);
>       }
>      }
>    else
>      symtab_dissolve_same_comdat_group_list ((symtab_node) e->callee);
>  
> -  if (e->caller->global.inlined_to)
> -    e->callee->global.inlined_to = e->caller->global.inlined_to;
> -  else
> -    e->callee->global.inlined_to = e->caller;
> +  e->callee->global.inlined_to = inlining_into;
>  
>    /* Recursively clone all bodies.  */
>    for (e = e->callee->callees; e; e = e->next_callee)
> Index: src/gcc/ipa-inline.c
> ===================================================================
> --- src.orig/gcc/ipa-inline.c
> +++ src/gcc/ipa-inline.c
> @@ -1315,7 +1315,7 @@ recursive_inlining (struct cgraph_edge *
>         /* We need original clone to copy around.  */
>         master_clone = cgraph_clone_node (node, node->symbol.decl,
>                                           node->count, CGRAPH_FREQ_BASE,
> -                                         false, vNULL, true);
> +                                         false, vNULL, true, NULL);
>         for (e = master_clone->callees; e; e = e->next_callee)
>           if (!e->inline_failed)
>             clone_inlined_nodes (e, true, false, NULL);
> Index: src/gcc/ipa-prop.c
> ===================================================================
> --- src.orig/gcc/ipa-prop.c
> +++ src/gcc/ipa-prop.c
> @@ -2683,9 +2683,6 @@ ipa_propagate_indirect_call_infos (struc
>    propagate_controlled_uses (cs);
>    changed = propagate_info_to_inlined_callees (cs, cs->callee, new_edges);
>  
> -  /* We do not keep jump functions of inlined edges up to date. Better to 
> free
> -     them so we do not access them accidentally.  */
> -  ipa_free_edge_args_substructures (IPA_EDGE_REF (cs));
>    return changed;
>  }
>  
> @@ -2815,9 +2812,12 @@ ipa_edge_duplication_hook (struct cgraph
>             dst_rdesc
>               = (struct ipa_cst_ref_desc *) pool_alloc (ipa_refdesc_pool);
>             dst_rdesc->cs = dst;
> -           dst_rdesc->next_duplicate = src_rdesc->next_duplicate;
> -           src_rdesc->next_duplicate = dst_rdesc;
>             dst_rdesc->refcount = src_rdesc->refcount;
> +           if (dst->caller->global.inlined_to)
> +             {
> +               dst_rdesc->next_duplicate = src_rdesc->next_duplicate;
> +               src_rdesc->next_duplicate = dst_rdesc;
> +             }
>             dst_jf->value.constant.rdesc = dst_rdesc;
>           }
>         else
> @@ -2832,13 +2832,10 @@ ipa_edge_duplication_hook (struct cgraph
>             for (dst_rdesc = src_rdesc->next_duplicate;
>                  dst_rdesc;
>                  dst_rdesc = dst_rdesc->next_duplicate)
> -             {
> -               gcc_assert (dst_rdesc->cs->caller->global.inlined_to);
> -               if (dst_rdesc->cs->caller->global.inlined_to
> -                   == dst->caller->global.inlined_to)
> -                 break;
> -             }
> -
> +             if (dst_rdesc->cs->caller->global.inlined_to
> +                 == dst->caller->global.inlined_to)
> +               break;
> +           gcc_assert (dst_rdesc);
>             dst_jf->value.constant.rdesc = dst_rdesc;
>           }
>       }
> Index: src/gcc/lto-cgraph.c
> ===================================================================
> --- src.orig/gcc/lto-cgraph.c
> +++ src/gcc/lto-cgraph.c
> @@ -951,7 +951,7 @@ input_node (struct lto_file_decl_data *f
>      {
>        node = cgraph_clone_node (cgraph (nodes[clone_ref]), fn_decl,
>                               0, CGRAPH_FREQ_BASE, false,
> -                             vNULL, false);
> +                             vNULL, false, NULL);
>      }
>    else
>      node = cgraph_get_create_node (fn_decl);

Reply via email to