> Hi,
> 
> this patch fixes PR 60640 by creating thunks to clones when that is
> necessary to properly redirect edges to them.  I mostly does what
> cgraph_add_thunk does and what analyze_function does to thunks.  It
> fixes the testcases on trunk (it does not apply to 4.8, I have not
> looked how easily fixable that it) and passes bootstrap and testing on
> x86_64-linux.
> 
> OK for trunk?
> 
> Thanks,
> 
> Martin
> 
> 
> 2014-03-26  Martin Jambor  <mjam...@suse.cz>
> 
>       * cgraph.h (cgraph_clone_node): New parameter added to declaration.
>       Adjust all callers.
>       * cgraphclones.c (build_function_type_skip_args): Moved upwards in the
>       file.
>       (build_function_decl_skip_args): Likewise.
>       (duplicate_thunk_for_node): New function.
>       (redirect_edge_duplicating_thunks): Likewise.
>       (cgraph_clone_node): New parameter args_to_skip, pass it to
>       redirect_edge_duplicating_thunks which is called instead of
>       cgraph_redirect_edge_callee.
>       (cgraph_create_virtual_clone): Pass args_to_skip to cgraph_clone_node.
> +/* Duplicate thunk THUNK but make it to refer to NODE.  ARGS_TO_SKIP, if
> +   non-NULL, determines which parameters should be omitted.  */
> +
> +static cgraph_node *
> +duplicate_thunk_for_node (cgraph_node *thunk, cgraph_node *node,
> +                       bitmap args_to_skip)
> +{
> +  cgraph_node *new_thunk, *thunk_of;
> +  thunk_of = cgraph_function_or_thunk_node (thunk->callees->callee);
> +
> +  if (thunk_of->thunk.thunk_p)
> +    node = duplicate_thunk_for_node (thunk_of, node, args_to_skip);
> +
> +  tree new_decl;
> +  if (!args_to_skip)
> +    new_decl = copy_node (thunk->decl);
> +  else
> +    new_decl = build_function_decl_skip_args (thunk->decl, args_to_skip, 
> false);
> +
> +  gcc_checking_assert (!DECL_STRUCT_FUNCTION (new_decl));
> +  gcc_checking_assert (!DECL_INITIAL (new_decl));
> +  gcc_checking_assert (!DECL_RESULT (new_decl));
> +  gcc_checking_assert (!DECL_RTL_SET_P (new_decl));
> +
> +  DECL_NAME (new_decl) = clone_function_name (thunk->decl, 
> "artificial_thunk");
> +  SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
> +  DECL_EXTERNAL (new_decl) = 0;
> +  DECL_SECTION_NAME (new_decl) = NULL;
> +  DECL_COMDAT_GROUP (new_decl) = 0;
> +  TREE_PUBLIC (new_decl) = 0;
> +  DECL_COMDAT (new_decl) = 0;
> +  DECL_WEAK (new_decl) = 0;
> +  DECL_VIRTUAL_P (new_decl) = 0;
> +  DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
> +  DECL_STATIC_DESTRUCTOR (new_decl) = 0;

We probably ought to factor out this to common subfunction.
> +
> +  new_thunk = cgraph_create_node (new_decl);
> +  new_thunk->definition = true;
> +  new_thunk->thunk = thunk->thunk;
> +  new_thunk->unique_name = in_lto_p;
> +  new_thunk->externally_visible = 0;
> +  new_thunk->local.local = 1;
> +  new_thunk->lowered = true;
> +  new_thunk->former_clone_of = thunk->decl;
> +
> +  struct cgraph_edge *e = cgraph_create_edge (new_thunk, node, NULL, 0,
> +                                           CGRAPH_FREQ_BASE);
> +  e->call_stmt_cannot_inline_p = true;
> +  cgraph_call_edge_duplication_hooks (thunk->callees, e);
> +  if (!expand_thunk (new_thunk, false))
> +    new_thunk->analyzed = true;
> +  cgraph_call_node_duplication_hooks (thunk, new_thunk);
> +  return new_thunk;
> +}
> +
> +/* If E does not lead to a thunk, simply redirect it to N.  Otherwise create
> +   one or more equivalent thunks for N and redirect E to the first in the
> +   chain.  */
> +
> +void
> +redirect_edge_duplicating_thunks (struct cgraph_edge *e, struct cgraph_node 
> *n,
> +                               bitmap args_to_skip)
> +{
> +  cgraph_node *orig_to = cgraph_function_or_thunk_node (e->callee);
> +  if (orig_to->thunk.thunk_p)
> +    n = duplicate_thunk_for_node (orig_to, n, args_to_skip);

Is there anything that would pevent us from creating a new thunk for each call?

Also I think you need to avoid this logic when THIS parameter is being 
optimized out
(i.e. it is part of skip_args)
Thanks for looking into this!

Honza

Reply via email to