https://gcc.gnu.org/g:a0c4cba52a5dc7db28810b44b209982df8144c37
commit a0c4cba52a5dc7db28810b44b209982df8144c37 Author: Josef Melcr <melcr...@fit.cvut.cz> Date: Wed Dec 4 19:27:44 2024 +0100 omp-cp: Move callback attr from callee to caller, add it to builtins gcc/ChangeLog: * builtin-attrs.def (ATTR_CALLBACK): Add attribute definition (DEF_CALLBACK_ATTRIBUTE_NOTHROW): New macro for creating callback attribute (ATTR_NOTHROW_CALLBACK_GOMP_LIST): New attr list * gimple.h (gimple_omp_parallel_set_child_fn): Remove callback attribute addition * ipa-prop.cc (ipa_duplicate_jump_function): Declare (calc_callback_args_idx): Refactor (ipa_compute_jump_functions_for_edge): Change calc_callback_args_idx call (ipa_copy_ith_jump_func): Remove function * omp-builtins.def (BUILT_IN_GOMP_PARALLEL): Change attr list to callback list gcc/c-family/ChangeLog: * c-attribs.cc (handle_callback_attribute): Add attribute handler Signed-off-by: Josef Melcr <melcr...@fit.cvut.cz> Diff: --- gcc/builtin-attrs.def | 10 +++ gcc/c-family/c-attribs.cc | 36 +++++++++- gcc/gimple.h | 10 +-- gcc/ipa-prop.cc | 171 +++++++++++++--------------------------------- gcc/omp-builtins.def | 2 +- 5 files changed, 95 insertions(+), 134 deletions(-) diff --git a/gcc/builtin-attrs.def b/gcc/builtin-attrs.def index 1b8885c933cf..8a0b3463adcb 100644 --- a/gcc/builtin-attrs.def +++ b/gcc/builtin-attrs.def @@ -121,6 +121,7 @@ DEF_ATTR_IDENT (ATTR_TM_TMPURE, "transaction_pure") DEF_ATTR_IDENT (ATTR_RETURNS_TWICE, "returns_twice") DEF_ATTR_IDENT (ATTR_RETURNS_NONNULL, "returns_nonnull") DEF_ATTR_IDENT (ATTR_WARN_UNUSED_RESULT, "warn_unused_result") +DEF_ATTR_IDENT (ATTR_CALLBACK, "callback") DEF_ATTR_TREE_LIST (ATTR_NOVOPS_LIST, ATTR_NOVOPS, ATTR_NULL, ATTR_NULL) @@ -387,6 +388,15 @@ DEF_FORMAT_ATTRIBUTE_NOTHROW(STRFMON,3,3_4) #undef DEF_FORMAT_ATTRIBUTE_NOTHROW #undef DEF_FORMAT_ATTRIBUTE_BOTH +/* Callback attr */ +#define DEF_CALLBACK_ATTRIBUTE_NOTHROW(TYPE, CA, VALUES) \ + DEF_ATTR_TREE_LIST (ATTR_CALLBACK_##TYPE##_NOTHROW_##VALUES, ATTR_CALLBACK,\ + ATTR_NOTHROW_NONNULL_##CA, ATTR_LIST_##VALUES) + +DEF_CALLBACK_ATTRIBUTE_NOTHROW(GOMP, 1, 2) +DEF_ATTR_TREE_LIST(ATTR_NOTHROW_CALLBACK_GOMP_LIST, ATTR_CALLBACK, ATTR_CALLBACK_GOMP_NOTHROW_2, ATTR_NOTHROW_LIST) +#undef DEF_CALLBACK_ATTRIBUTE_NOTHROW + /* Transactional memory variants of the above. */ DEF_ATTR_TREE_LIST (ATTR_TM_NOTHROW_LIST, diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index c342e7a1e55f..6fb1f8d034d1 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -188,6 +188,7 @@ static tree handle_retain_attribute (tree *, tree, tree, int, bool *); static tree handle_fd_arg_attribute (tree *, tree, tree, int, bool *); static tree handle_flag_enum_attribute (tree *, tree, tree, int, bool *); static tree handle_null_terminated_string_arg_attribute (tree *, tree, tree, int, bool *); +static tree handle_callback_attribute (tree *, tree, tree, int, bool *); /* Helper to define attribute exclusions. */ #define ATTR_EXCL(name, function, type, variable) \ @@ -465,6 +466,7 @@ const struct attribute_spec c_common_gnu_attributes[] = handle_tm_attribute, NULL }, { "transaction_may_cancel_outer", 0, 0, false, true, false, false, handle_tm_attribute, NULL }, + { "callback", 1, -1, true, false, false, false, handle_callback_attribute, NULL}, /* ??? These two attributes didn't make the transition from the Intel language document to the multi-vendor language document. */ { "transaction_pure", 0, 0, false, true, false, false, @@ -643,7 +645,6 @@ const struct attribute_spec c_common_gnu_attributes[] = handle_flag_enum_attribute, NULL }, { "null_terminated_string_arg", 1, 1, false, true, true, false, handle_null_terminated_string_arg_attribute, NULL}, - { "callback", 0, 0, true, false, false, false, NULL, NULL} }; const struct scoped_attribute_specs c_common_gnu_attribute_table = @@ -5192,6 +5193,39 @@ get_argument (tree fndecl, unsigned argno) return NULL_TREE; } +static tree +handle_callback_attribute (tree *node, tree name, tree args, + int ARG_UNUSED (flags), + bool ARG_UNUSED (*no_add_attrs)) +{ + tree decl = *node; + if (TREE_CODE (decl) != FUNCTION_DECL) + { + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute can only be used on functions", name); + } + tree callback_fn_idx_node = args; + for (int i = 0; i < 3; + i++, callback_fn_idx_node = TREE_VALUE (callback_fn_idx_node)) + ; + int callback_fn_idx = TREE_INT_CST_LOW (callback_fn_idx_node) - 1; + if (callback_fn_idx < 0) + error_at (DECL_SOURCE_LOCATION (decl), + "callback function position out of range"); + // + // tree cfn = get_argument (decl, callback_fn_idx); + // if (cfn == NULL_TREE) + // error_at(DECL_SOURCE_LOCATION(decl), "couldnt retrieve callback function + // from arguments"); + // + // if (TREE_CODE(cfn) != ADDR_EXPR || TREE_CODE(TREE_OPERAND(cfn, 0)) != + // FUNCTION_DECL) + // error_at(DECL_SOURCE_LOCATION(decl), "argument no. %d is not a fndecl", + // callback_fn_idx); + // + return NULL_TREE; +} + /* Attempt to append attribute access specification ATTRSPEC, optionally described by the human-readable string ATTRSTR, for type T, to one in ATTRS. VBLIST is an optional list of bounds of variable length array diff --git a/gcc/gimple.h b/gcc/gimple.h index faae38491fea..b40f3e8009a1 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -5817,15 +5817,7 @@ inline void gimple_omp_parallel_set_child_fn (gomp_parallel *omp_parallel_stmt, tree child_fn) { - if (child_fn != NULL_TREE - && !lookup_attribute ("callback", DECL_ATTRIBUTES (child_fn))) - { - tree attrs = tree_cons (get_identifier ("callback"), NULL, - DECL_ATTRIBUTES (child_fn)); - decl_attributes (&child_fn, attrs, 0); - } - - omp_parallel_stmt->child_fn = child_fn; + omp_parallel_stmt->child_fn = child_fn; } /* Return the artificial argument used to send variables and values diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc index 11404bdd3aff..ae0e32b1fe65 100644 --- a/gcc/ipa-prop.cc +++ b/gcc/ipa-prop.cc @@ -325,6 +325,10 @@ ipa_get_param_decl_index (class ipa_node_params *info, tree ptree) return ipa_get_param_decl_index_1 (info->descriptors, ptree); } +static void +ipa_duplicate_jump_function (cgraph_edge *src, cgraph_edge *dst, + ipa_jump_func *src_jf, ipa_jump_func *dst_jf); + /* Populate the param_decl field in parameter DESCRIPTORS that correspond to NODE. */ @@ -2314,21 +2318,46 @@ ipa_set_jfunc_vr (ipa_jump_func *jf, const ipa_vr &vr) ipa_set_jfunc_vr (jf, tmp); } +static void +calc_callback_args_idx (cgraph_edge *og, cgraph_edge *cbe) +{ + gcc_checking_assert (cbe->callback); + ipa_edge_args *args = ipa_edge_args_sum->get_create (cbe); + int argn = 0; + tree arg; + tree cb_args + = lookup_attribute ("callback", DECL_ATTRIBUTES (og->callee->decl)); + for (arg = TREE_CHAIN (TREE_VALUE (cb_args)); arg; + arg = TREE_CHAIN (arg), argn++) + ; + vec_safe_grow_cleared (args->jump_functions, argn, true); + vec_safe_grow_cleared (args->callback_args, argn, true); + gcc_checking_assert (cb_args); + int idx = 0; + for (arg = TREE_CHAIN (cb_args); arg; arg = TREE_CHAIN (arg), idx++) + { + tree val = TREE_VALUE (arg); + if (TREE_CODE (val) == INTEGER_CST) + { + int arg_idx = TREE_INT_CST_LOW (val); + bool is_data = arg_idx != -1; + if (arg_idx == -1) + { + arg_idx = idx; + } + (*args->callback_args)[idx] = {arg_idx, is_data}; + } + else + { + gcc_checking_assert (0); + } + } +} + /* Compute jump function for all arguments of callsite CS and insert the information in the jump_functions array in the ipa_edge_args corresponding to this callsite. */ -static void calc_callback_args_idx(cgraph_edge * e) { - gcc_checking_assert(e->callback); - ipa_edge_args *args = ipa_edge_args_sum->get_create (e); - int argn = 1; - vec_safe_grow_cleared (args->callback_args, argn, true); - (*args->callback_args)[0] = {1, true}; - for (int i = 1; i < argn; i++) { - (*args->callback_args)[i] = {i, false}; - } -} - static void ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, struct cgraph_edge *cs) @@ -2438,13 +2467,13 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, { tree pointee = TREE_OPERAND (arg, 0); if (TREE_CODE (pointee) == FUNCTION_DECL - && lookup_attribute ("callback", DECL_ATTRIBUTES (pointee)) + && lookup_attribute ("callback", DECL_ATTRIBUTES (cs->callee->decl)) && !cs->callback) { cgraph_node *kernel_node = cgraph_node::get_create (pointee); gcc_checking_assert (!callback_edge); callback_edge = cs->make_callback (kernel_node); - calc_callback_args_idx (callback_edge); + calc_callback_args_idx (cs, callback_edge); } } } @@ -2513,16 +2542,17 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, for (i = 0; i < cb_summary->callback_args->length (); i++) { cb_arg_info cb = (*cb_summary->callback_args)[i]; - ipa_copy_ith_jump_func (cs, cb.idx, callback_edge, i); + class ipa_jump_func * src = ipa_get_ith_jump_func(args, cb.idx); + class ipa_jump_func * dst = ipa_get_ith_jump_func(cb_summary, i); + ipa_duplicate_jump_function(cs, callback_edge, src, dst); if (cb.is_data_arg) { - class ipa_jump_func *jfunc = ipa_get_ith_jump_func (args, cb.idx); unsigned j; - for (j = 0; jfunc->agg.items && (j < jfunc->agg.items->length ()); + for (j = 0; src->agg.items && (j < src->agg.items->length ()); j++) { - if ((*jfunc->agg.items)[j].jftype == IPA_JF_PASS_THROUGH) - (*jfunc->agg.items)[j].value.pass_through.agg_preserved + if ((*src->agg.items)[j].jftype == IPA_JF_PASS_THROUGH) + (*src->agg.items)[j].value.pass_through.agg_preserved = true; } } @@ -4554,111 +4584,6 @@ ipa_edge_args_sum_t::remove (cgraph_edge *cs, ipa_edge_args *args) } } -void -ipa_copy_ith_jump_func (class cgraph_edge *src, unsigned src_idx, - class cgraph_edge *dst, unsigned dst_idx) -{ - class ipa_edge_args *src_args = ipa_edge_args_sum->get (src); - class ipa_edge_args *dst_args = ipa_edge_args_sum->get (dst); - - - if (dst_idx >= vec_safe_length (dst_args->jump_functions)) - { - vec_safe_grow_cleared (dst_args->jump_functions, dst_idx + 1, true); - } - - struct ipa_jump_func *src_jf = ipa_get_ith_jump_func (src_args, src_idx); - struct ipa_jump_func *dst_jf = ipa_get_ith_jump_func (dst_args, dst_idx); - - ::new (dst_jf) ipa_jump_func (*src_jf); - - dst_jf->agg.items = vec_safe_copy (src_jf->agg.items); - dst_jf->m_vr = src_jf->m_vr; - - if (src_jf->type == IPA_JF_CONST) - { - struct ipa_cst_ref_desc *src_rdesc = jfunc_rdesc_usable (src_jf); - - if (!src_rdesc) - dst_jf->value.constant.rdesc = NULL; - else if (src->caller == dst->caller) - { - /* Creation of a speculative edge. If the source edge is the one - grabbing a reference, we must create a new (duplicate) - reference description. Otherwise they refer to the same - description corresponding to a reference taken in a function - src->caller is inlined to. In that case we just must - increment the refcount. */ - if (src_rdesc->cs == src) - { - symtab_node *n = symtab_node_for_jfunc (src_jf); - gcc_checking_assert (n); - ipa_ref *ref - = src->caller->find_reference (n, src->call_stmt, - src->lto_stmt_uid, IPA_REF_ADDR); - gcc_checking_assert (ref); - dst->caller->clone_reference (ref, ref->stmt); - - ipa_cst_ref_desc *dst_rdesc = ipa_refdesc_pool.allocate (); - dst_rdesc->cs = dst; - dst_rdesc->refcount = src_rdesc->refcount; - dst_rdesc->next_duplicate = NULL; - dst_jf->value.constant.rdesc = dst_rdesc; - } - else - { - src_rdesc->refcount++; - dst_jf->value.constant.rdesc = src_rdesc; - } - } - else if (src_rdesc->cs == src) - { - struct ipa_cst_ref_desc *dst_rdesc = ipa_refdesc_pool.allocate (); - dst_rdesc->cs = dst; - dst_rdesc->refcount = src_rdesc->refcount; - dst_rdesc->next_duplicate = src_rdesc->next_duplicate; - src_rdesc->next_duplicate = dst_rdesc; - dst_jf->value.constant.rdesc = dst_rdesc; - } - else - { - struct ipa_cst_ref_desc *dst_rdesc; - /* This can happen during inlining, when a JFUNC can refer to a - reference taken in a function up in the tree of inline clones. - We need to find the duplicate that refers to our tree of - inline clones. */ - - gcc_assert (dst->caller->inlined_to); - for (dst_rdesc = src_rdesc->next_duplicate; dst_rdesc; - dst_rdesc = dst_rdesc->next_duplicate) - { - struct cgraph_node *top; - top = dst_rdesc->cs->caller->inlined_to - ? dst_rdesc->cs->caller->inlined_to - : dst_rdesc->cs->caller; - if (dst->caller->inlined_to == top) - break; - } - gcc_assert (dst_rdesc); - dst_jf->value.constant.rdesc = dst_rdesc; - } - } - else if (dst_jf->type == IPA_JF_PASS_THROUGH && src->caller == dst->caller) - { - struct cgraph_node *inline_root - = dst->caller->inlined_to ? dst->caller->inlined_to : dst->caller; - ipa_node_params *root_info = ipa_node_params_sum->get (inline_root); - int idx = ipa_get_jf_pass_through_formal_id (dst_jf); - - int c = ipa_get_controlled_uses (root_info, idx); - if (c != IPA_UNDESCRIBED_USE) - { - c++; - ipa_set_controlled_uses (root_info, idx, c); - } - } -} - /* Method invoked when an edge is duplicated. Copy ipa_edge_args and adjust reference count data strucutres accordingly. */ static void diff --git a/gcc/omp-builtins.def b/gcc/omp-builtins.def index c70e077063b7..46a68668d894 100644 --- a/gcc/omp-builtins.def +++ b/gcc/omp-builtins.def @@ -399,7 +399,7 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_DOACROSS_ULL_POST, "GOMP_doacross_ull_post", DEF_GOMP_BUILTIN (BUILT_IN_GOMP_DOACROSS_ULL_WAIT, "GOMP_doacross_ull_wait", BT_FN_VOID_ULL_VAR, ATTR_NOTHROW_LEAF_LIST) DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL, "GOMP_parallel", - BT_FN_VOID_OMPFN_PTR_UINT_UINT, ATTR_NOTHROW_LIST) + BT_FN_VOID_OMPFN_PTR_UINT_UINT, ATTR_NOTHROW_CALLBACK_GOMP_LIST) DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_REDUCTIONS, "GOMP_parallel_reductions", BT_FN_UINT_OMPFN_PTR_UINT_UINT, ATTR_NOTHROW_LIST)