> 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
>