> gcc/ChangeLog:
> 
>       * Makefile.in: Add attr-callback.o to OBJS.
>       * builtin-attrs.def (ATTR_CALLBACK): Callback attr identifier.
>       (DEF_CALLBACK_ATTRIBUTE): Macro for callback attr creation.
>       (GOMP): Attrs for libgomp functions.
>       (OACC): Attrs for oacc functions.
>       (ATTR_CALLBACK_GOMP_LIST): ATTR_NOTHROW_LIST with GOMP callback
>       attr added.
>       (ATTR_CALLBACK_OACC_LIST): ATTR_NOTHROW_LIST with OACC callback
>       attr added.
>       * cgraph.cc (cgraph_add_edge_to_call_site_hash): Always hash the
>       callback-carrying edge.
>       (cgraph_node::get_edge): Always return the callback-carrying
>       edge.
>       (cgraph_edge::set_call_stmt): Add cascade for callback edges,
>       rename update_speculative to update_derived_edges.
>       (symbol_table::create_edge): Allow callback edges to share call
>       statements, initialize new flags.
>       (cgraph_edge::make_callback): New method, derives a new callback
>       edge.
>       (cgraph_edge::get_callback_carrying_edge): New method.
>       (cgraph_edge::first_callback_edge): Likewise.
>       (cgraph_edge::next_callback_edge): Likewise.
>       (cgraph_edge::purge_callback_edges): Likewise.
>       (cgraph_edge::redirect_callee): When redirecting a callback
>       edge, redirect its ref as well.
>       (cgraph_edge::redirect_call_stmt_to_callee): Add callback edge
>       redirection logic, set update_derived_edges to true if
>       redirecting callback-carrying edge.
>       (cgraph_node::remove_callers): Add cascade for callback edges.
>       (cgraph_edge::dump_edge_flags): Add callback flag printing.
>       (cgraph_node::verify_node): Add sanity checks for callback
>       edges.
>       * cgraph.h: Add new flags and 16 bit callback_id to cgraph_edge
>       class.
>       * cgraphclones.cc (cgraph_edge::clone): Copy over callback data.
>       * ipa-cp.cc (purge_useless_callback_edges): New function,
>       deletes callback edges when necessary.
>       (ipcp_decision_stage): Call purge_useless_callback_edges.
>       * ipa-fnsummary.cc (ipa_call_summary_t::duplicate): Add an
>       exception for callback edges.
>       (analyze_function_body): Copy summary from callback-carrying to
>       callback edge.
>       * ipa-inline-analysis.cc (do_estimate_growth_1): Skip callback
>       edges when estimating growth.
>       * ipa-inline-transform.cc (inline_transform): Add redirection
>       cascade for callback edges.
>       * ipa-inline.cc (can_inline_edge_p): Never inline callback
>       edges.
>       * ipa-param-manipulation.cc
>       (drop_decl_attribute_if_params_changed_p): New function.
>       (ipa_param_adjustments::build_new_function_type): Add
>       args_modified out parameter.
>       (ipa_param_adjustments::adjust_decl): Drop callback attrs when
>       modifying args.
>       * ipa-param-manipulation.h: Change decl of
>       build_new_function_type.
>       * ipa-prop.cc (ipa_duplicate_jump_function): Add declaration.
>       (init_callback_edge_summary): New function.
>       (ipa_compute_jump_functions_for_edge): Add callback edge
>       creation logic.
>       * lto-cgraph.cc (lto_output_edge): Stream out callback data.
>       (input_edge): Input callback data.
>       * omp-builtins.def (BUILT_IN_GOACC_PARALLEL): Use new attr list.
>       (BUILT_IN_GOMP_PARALLEL_LOOP_STATIC): Likewise.
>       (BUILT_IN_GOMP_PARALLEL_LOOP_GUIDED): Likewise.
>       (BUILT_IN_GOMP_PARALLEL_LOOP_NONMONOTONIC_DYNAMIC): Likewise.
>       (BUILT_IN_GOMP_PARALLEL_LOOP_NONMONOTONIC_RUNTIME): Likewise.
>       (BUILT_IN_GOMP_PARALLEL): Likewise.
>       (BUILT_IN_GOMP_PARALLEL_SECTIONS): Likewise.
>       (BUILT_IN_GOMP_TEAMS_REG): Likewise.
>       * tree-core.h (ECF_CB_1_2): New constant for callback(1,2).
>       (ECF_CB_2_4): New constant for callback(2,4).
>       * tree-inline.cc (copy_bb): Copy callback edges when copying
>       callback-carrying edge.
>       (redirect_all_calls): Redirect callback edges.
>       * tree.cc (set_call_expr_flags): Create callback attrs according
>       to the ECF_CB constants.
>       * attr-callback.cc: New file.
>       * attr-callback.h: New file.
> 
> gcc/c-family/ChangeLog:
> 
>       * c-attribs.cc: Define callback attribute.
> 
> gcc/fortran/ChangeLog:
> 
>       * f95-lang.cc (ATTR_CALLBACK_GOMP_LIST): New attr list
>       corresponding to the list in builtin-attrs.def.
>       (ATTR_CALLBACK_OACC_LIST): Likewise.
> 
> gcc/testsuite/ChangeLog:
> 
>       * gcc.dg/ipa/ipcp-cb-spec1.c: New test.
>       * gcc.dg/ipa/ipcp-cb-spec2.c: New test.
>       * gcc.dg/ipa/ipcp-cb1.c: New test.
> diff --git a/gcc/ipa-inline.cc b/gcc/ipa-inline.cc
> index 0cf97a80687..b0f7394e7a4 100644
> --- a/gcc/ipa-inline.cc
> +++ b/gcc/ipa-inline.cc
> @@ -373,6 +373,11 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
>  {
>    gcc_checking_assert (e->inline_failed);
>  
> +  /* Never inline callback edges, since the call doesn't exist in
> +     reality.  */
> +  if (e->callback)
> +    return false;
> +
>    if (cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR)

can_inline_edge_p is kind of perforance critical and for that reason we
have notion of permanent errors in inline_failed for edges that will
never ever be able to be inlined no matter what.

Please add CIF_CALLBACK_EDGE with CIF_FINAL_ERROR type and arrange
inline_failed to be set to it, so the check above can be omitted.

> @@ -9973,7 +9974,22 @@ set_call_expr_flags (tree decl, int flags)
>      DECL_ATTRIBUTES (decl)
>        = tree_cons (get_identifier ("expected_throw"),
>                  NULL, DECL_ATTRIBUTES (decl));
> -  /* Looping const or pure is implied by noreturn.
> +
> +  if (flags & ECF_CB_1_2)
> +    {
> +      tree attr = callback_build_attr (1, 1, 2);
> +      TREE_CHAIN (attr) = DECL_ATTRIBUTES (decl);
> +      DECL_ATTRIBUTES (decl) = attr;
> +    }
> +
> +  if (flags & ECF_CB_2_4)
> +    {
> +      tree attr = callback_build_attr (2, 1, 4);
> +      TREE_CHAIN (attr) = DECL_ATTRIBUTES (decl);
> +      DECL_ATTRIBUTES (decl) = attr;
> +    }
> +
> +    /* Looping const or pure is implied by noreturn.
This is ugly.  ECF_* is really primarly meant to be used by
flags_from_decl_or_type and similar functions to simply handling of
common flags (such as pure/const) and Richi is in favour of not adding
extra flags there (i.e. for reproducible/nonsequential).  Here the
problem is that the same flags are abused by fortran builtin
construction to add the attributes flags_from_decl_or_type checks.
Sadly I do not see an easy way to cleanup fortran's builtin machinery.

I would add comment at their definition making it clear those are only
to be used to create builtins.

Looking through the discussion, I think there is an agreement about
backend bits, so I think it is practical to push the patch after change
above and and handle rest incrementally.

So patch is OK with changes above, but please wait a day for Jabub, Richard
and/or Fortran maintiners to chime in on the ECF change.


>       There is currently no way to declare looping const or looping pure 
> alone.  */
>    gcc_assert (!(flags & ECF_LOOPING_CONST_OR_PURE)
>             || ((flags & ECF_NORETURN) && (flags & (ECF_CONST | ECF_PURE))));
> -- 
> 2.50.1
> 

Reply via email to