[PATCH 5/7] Fortran: Add send_to_remote [PR107635] Refactor to use send_to_remote instead of the slow send_by_ref.
gcc/fortran/ChangeLog: PR fortran/107635 * gfortran.h (enum gfc_isym_id): Add SENDGET-isym. * gfortran.texi: Add documentation for send_to_remote. * resolve.cc (gfc_resolve_code): No longer generate send_by_ref when allocatable coarray (component) is on the lhs. * rewrite.cc (move_coarray_ref): Move the coarray reference out of the given one. Especially when there is a regular array ref. (fixup_comp_refs): Move components refs to a derived type where the codim has been removed, aka a new type. (split_expr_at_caf_ref): Correctly split the reference chain. (remove_caf_ref): Simplify. (create_get_callback): Fix some deficiencies. (create_allocated_callback): Adapt to new signature of split. (create_send_callback): New function. (rewrite_caf_send): Rewrite a call to caf_send to caf_send_to_remote. (coindexed_code_callback): Treat caf_send and caf_sendget correctly. * trans-decl.cc (gfc_build_builtin_function_decls): Add caf_send_to_remote decl. * trans-intrinsic.cc (conv_caf_func_index): Ensure the static variables created are not in a block-scope. (conv_caf_send_to_remote): Translate caf_send_to_remote calls. (conv_caf_send): Renamed to conv_caf_sendget. (conv_caf_sendget): Renamed from conv_caf_send. (gfc_conv_intrinsic_subroutine): Branch correctly for conv_caf_send and sendget. * trans.h: Correct decl. libgfortran/ChangeLog: * caf/libcaf.h: Add/Correct prototypes for caf_get_from_remote, caf_send_to_remote. * caf/single.c (struct accessor_hash_t): Rename accessor_t to getter_t. (_gfortran_caf_register_accessor): Use new name of getter_t. (_gfortran_caf_send_to_remote): New function for sending data to coarray on a remote image. gcc/testsuite/ChangeLog: * gfortran.dg/coarray/send_char_array_1.f90: Extend test to catch more cases. * gfortran.dg/coarray_42.f90: Invert tests use, because no longer a send is needed when local memory in a coarray is allocated. -- Andre Vehreschild * Email: vehre ad gmx dot de
From 43f8d8fdbdde62b09851bc6b82c883794d57645e Mon Sep 17 00:00:00 2001 From: Andre Vehreschild <ve...@gcc.gnu.org> Date: Wed, 29 Jan 2025 12:42:18 +0100 Subject: [PATCH 5/7] Fortran: Add send_to_remote [PR107635] Refactor to use send_to_remote instead of the slow send_by_ref. gcc/fortran/ChangeLog: PR fortran/107635 * gfortran.h (enum gfc_isym_id): Add SENDGET-isym. * gfortran.texi: Add documentation for send_to_remote. * resolve.cc (gfc_resolve_code): No longer generate send_by_ref when allocatable coarray (component) is on the lhs. * rewrite.cc (move_coarray_ref): Move the coarray reference out of the given one. Especially when there is a regular array ref. (fixup_comp_refs): Move components refs to a derived type where the codim has been removed, aka a new type. (split_expr_at_caf_ref): Correctly split the reference chain. (remove_caf_ref): Simplify. (create_get_callback): Fix some deficiencies. (create_allocated_callback): Adapt to new signature of split. (create_send_callback): New function. (rewrite_caf_send): Rewrite a call to caf_send to caf_send_to_remote. (coindexed_code_callback): Treat caf_send and caf_sendget correctly. * trans-decl.cc (gfc_build_builtin_function_decls): Add caf_send_to_remote decl. * trans-intrinsic.cc (conv_caf_func_index): Ensure the static variables created are not in a block-scope. (conv_caf_send_to_remote): Translate caf_send_to_remote calls. (conv_caf_send): Renamed to conv_caf_sendget. (conv_caf_sendget): Renamed from conv_caf_send. (gfc_conv_intrinsic_subroutine): Branch correctly for conv_caf_send and sendget. * trans.h: Correct decl. libgfortran/ChangeLog: * caf/libcaf.h: Add/Correct prototypes for caf_get_from_remote, caf_send_to_remote. * caf/single.c (struct accessor_hash_t): Rename accessor_t to getter_t. (_gfortran_caf_register_accessor): Use new name of getter_t. (_gfortran_caf_send_to_remote): New function for sending data to coarray on a remote image. gcc/testsuite/ChangeLog: * gfortran.dg/coarray/send_char_array_1.f90: Extend test to catch more cases. * gfortran.dg/coarray_42.f90: Invert tests use, because no longer a send is needed when local memory in a coarray is allocated. --- gcc/fortran/gfortran.h | 1 + gcc/fortran/gfortran.texi | 69 +++ gcc/fortran/resolve.cc | 3 +- gcc/fortran/rewrite.cc | 402 +++++++++++++++--- gcc/fortran/trans-decl.cc | 10 + gcc/fortran/trans-intrinsic.cc | 209 ++++++++- gcc/fortran/trans.h | 9 +- .../gfortran.dg/coarray/send_char_array_1.f90 | 13 +- gcc/testsuite/gfortran.dg/coarray_42.f90 | 4 +- libgfortran/caf/libcaf.h | 12 +- libgfortran/caf/single.c | 57 ++- 11 files changed, 706 insertions(+), 83 deletions(-) diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index c9bac84c16b..43ac59db807 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -458,6 +458,7 @@ enum gfc_isym_id GFC_ISYM_CAF_GET, GFC_ISYM_CAF_IS_PRESENT_ON_REMOTE, GFC_ISYM_CAF_SEND, + GFC_ISYM_CAF_SENDGET, GFC_ISYM_CEILING, GFC_ISYM_CHAR, GFC_ISYM_CHDIR, diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi index 32558e6b803..6bd63fcb4f4 100644 --- a/gcc/fortran/gfortran.texi +++ b/gcc/fortran/gfortran.texi @@ -4212,6 +4212,7 @@ future implementation of teams. It is about to change without further notice. * _gfortran_caf_get_by_ref:: Getting data from a remote image using enhanced references * _gfortran_caf_get_from_remote:: Getting data from a remote image using a remote side accessor * _gfortran_caf_is_present_on_remote:: Check that a coarray or a part of it is allocated on the remote image +* _gfortran_caf_send_to_remote:: Send data to a remote image using a remote side accessor to store it * _gfortran_caf_sendget_by_ref:: Sending data between remote images using enhanced references * _gfortran_caf_lock:: Locking a lock variable * _gfortran_caf_unlock:: Unlocking a lock variable @@ -5083,6 +5084,74 @@ structure. @end table +@node _gfortran_caf_send_to_remote +@subsection @code{_gfortran_caf_send_to_remote} --- Send data to a remote image using a remote side accessor to store it +@cindex Coarray, _gfortran_caf_send_to_remote + +@table @asis +@item @emph{Description}: +Called to send a scalar, an array section or a whole array to a remote image +identified by the @var{image_index}. The call modifies the memory of the remote +image. + +@item @emph{Syntax}: +@code{void _gfortran_caf_send_to_remote (caf_token_t token, +gfc_descriptor_t *opt_dst_desc, const size_t *opt_dst_charlen, +const int image_index, const size_t src_size, const void *src_data, +size_t *opt_src_charlen, const gfc_descriptor_t *opt_src_desc, +const int setter_index, void *add_data, const size_t add_data_size, int *stat, +caf_team_t *team, int *team_number)} + +@item @emph{Arguments}: +@multitable @columnfractions .15 .70 +@item @var{token} @tab intent(in) An opaque pointer identifying the coarray. +@item @var{opt_dst_desc} @tab intent(inout) A pointer to the descriptor when +the object identified by @var{token} is an array with a descriptor. The +parameter needs to be set to @code{NULL}, when @var{token} identifies a scalar +or is an array without a descriptor. +@item @var{opt_dst_charlen} @tab intent(in) When the object to send is a char +array with deferred length, then this parameter needs to be set to point to its +length. Else the parameter needs to be set to @code{NULL}. +@item @var{image_index} @tab intent(in) The ID of the remote image; must be a +positive number. @code{this_image ()} is valid. +@item @var{src_size} @tab intent(in) The size of data expected to be transferred +to the remote image. If the data type to get is a string or string array, +then this needs to be set to the byte size of each character, i.e. @code{4} for +a @code{CHARACTER (KIND=4)} string. The length of the string is then given +in @code{opt_src_charlen} (also for string arrays). +@item @var{src_data} @tab intent(in) A pointer the data to be send to the remote +image. When a descriptor is provided in @code{opt_src_desc} then this parameter +can be ignored by the library implementing the coarray functionality. +@item @var{opt_src_charlen} @tab intent(in) When a char array is send, this +parameter is set to its length. +@item @var{opt_src_desc} @tab intent(in) When a descriptor array is send, then +this parameter gives the handle. +@item @var{setter_index} @tab intent(in) The index of the accessor to execute +as returned by @code{_gfortran_caf_get_remote_function_index ()}. +@item @var{add_data} @tab intent(inout) Additional data needed in the accessor. +I.e., when an array reference uses a local variable @var{v}, it is transported +in this structure and all references in the accessor are rewritten to access the +member. The data in the structure of @var{add_data} may be changed by the +accessor, but these changes are lost to the calling Fortran program. +@item @var{add_data_size} @tab intent(in) The size of the @var{add_data} +structure. +@item @var{stat} @tab intent(out) When non-@code{NULL} give the result of the +operation, i.e., zero on success and non-zero on error. When @code{NULL} and an +error occurs, then an error message is printed and the program is terminated. +@item @var{team} @tab intent(in) The opaque team handle as returned by +@code{FORM TEAM}. Unused at the moment. +@item @var{team_number} @tab intent(in) The number of the team this access is +to be part of. Unused at the moment. +@end multitable + +@item @emph{NOTES} +It is permitted to have @code{image_index} equal the current image; the memory +to send the data to and the memory to read for the data may (partially) overlap. +The implementation has to take care that it handles this case, e.g. using +@code{memmove} which handles (partially) overlapping memory. +@end table + + @node _gfortran_caf_sendget_by_ref @subsection @code{_gfortran_caf_sendget_by_ref} --- Sending data between remote images using enhanced references on both sides @cindex Coarray, _gfortran_caf_sendget_by_ref diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc index 8ea54666254..8df9d0beb8b 100644 --- a/gcc/fortran/resolve.cc +++ b/gcc/fortran/resolve.cc @@ -13343,8 +13343,7 @@ start: break; if (flag_coarray == GFC_FCOARRAY_LIB - && (gfc_is_coindexed (code->expr1) - || caf_possible_reallocate (code->expr1))) + && gfc_is_coindexed (code->expr1)) { /* Insert a GFC_ISYM_CAF_SEND intrinsic, when the LHS is a coindexed variable. */ diff --git a/gcc/fortran/rewrite.cc b/gcc/fortran/rewrite.cc index e8e791e8ada..380c64242e8 100644 --- a/gcc/fortran/rewrite.cc +++ b/gcc/fortran/rewrite.cc @@ -242,25 +242,125 @@ convert_coarray_class_to_derived_type (gfc_symbol *base, gfc_namespace *ns) base->attr.pointer = 0; // Ensure, that it is no pointer. } +static void +move_coarray_ref (gfc_ref **from, gfc_expr *expr) +{ + int i; + gfc_ref *to = expr->ref; + for (; to && to->next; to = to->next) + ; + + if (!to) + { + expr->ref = gfc_get_ref (); + to = expr->ref; + to->type = REF_ARRAY; + } + gcc_assert (to->type == REF_ARRAY); + to->u.ar.as = gfc_copy_array_spec ((*from)->u.ar.as); + to->u.ar.codimen = (*from)->u.ar.codimen; + to->u.ar.dimen = (*from)->u.ar.dimen; + to->u.ar.type = AR_FULL; + to->u.ar.stat = (*from)->u.ar.stat; + (*from)->u.ar.stat = nullptr; + to->u.ar.team = (*from)->u.ar.team; + (*from)->u.ar.team = nullptr; + for (i = 0; i < to->u.ar.dimen; ++i) + { + to->u.ar.start[i] = nullptr; + to->u.ar.end[i] = nullptr; + to->u.ar.stride[i] = nullptr; + } + for (i = (*from)->u.ar.dimen; i < (*from)->u.ar.dimen + (*from)->u.ar.codimen; + ++i) + { + to->u.ar.dimen_type[i] = (*from)->u.ar.dimen_type[i]; + to->u.ar.start[i] = (*from)->u.ar.start[i]; + (*from)->u.ar.start[i] = nullptr; + to->u.ar.end[i] = (*from)->u.ar.end[i]; + (*from)->u.ar.end[i] = nullptr; + to->u.ar.stride[i] = (*from)->u.ar.stride[i]; + (*from)->u.ar.stride[i] = nullptr; + } + (*from)->u.ar.codimen = 0; + if ((*from)->u.ar.dimen == 0) + { + gfc_ref *nref = (*from)->next; + (*from)->next = nullptr; + gfc_free_ref_list (*from); + *from = nref; + } +} + +static void +fixup_comp_refs (gfc_expr *expr) +{ + gfc_symbol *type = expr->symtree->n.sym->ts.type == BT_DERIVED + ? expr->symtree->n.sym->ts.u.derived + : (expr->symtree->n.sym->ts.type == BT_CLASS + ? CLASS_DATA (expr->symtree->n.sym)->ts.u.derived + : nullptr); + if (!type) + return; + gfc_ref **pref = &(expr->ref); + for (gfc_ref *ref = expr->ref; ref && type;) + { + switch (ref->type) + { + case REF_COMPONENT: + gfc_find_component (type, ref->u.c.component->name, false, true, + pref); + if (!*pref) + { + /* This happens when there were errors previously. Just don't + crash. */ + ref = nullptr; + break; + } + (*pref)->next = ref->next; + ref->next = NULL; + gfc_free_ref_list (ref); + ref = (*pref)->next; + type = (*pref)->u.c.component->ts.type == BT_DERIVED + ? (*pref)->u.c.component->ts.u.derived + : ((*pref)->u.c.component->ts.type == BT_CLASS + ? CLASS_DATA ((*pref)->u.c.component)->ts.u.derived + : nullptr); + pref = &(*pref)->next; + break; + case REF_ARRAY: + pref = &ref->next; + ref = ref->next; + break; + default: + gcc_unreachable (); + break; + } + } +} + static void split_expr_at_caf_ref (gfc_expr *expr, gfc_namespace *ns, - gfc_expr **post_caf_ref_expr) + gfc_expr **post_caf_ref_expr, bool for_send) { gfc_ref *caf_ref = NULL; gfc_symtree *st; gfc_symbol *base; + gfc_typespec *caf_ts; bool created; gcc_assert (expr->expr_type == EXPR_VARIABLE); + caf_ts = &expr->symtree->n.sym->ts; if (!expr->symtree->n.sym->attr.codimension) { /* The coarray is in some component. Find it. */ caf_ref = expr->ref; while (caf_ref) { - if (caf_ref->type == REF_COMPONENT - && caf_ref->u.c.component->attr.codimension) + if (caf_ref->type == REF_ARRAY && caf_ref->u.ar.codimen != 0) break; + if (caf_ref->type == REF_COMPONENT) + caf_ts = &caf_ref->u.c.component->ts; caf_ref = caf_ref->next; } } @@ -271,7 +371,7 @@ split_expr_at_caf_ref (gfc_expr *expr, gfc_namespace *ns, st->n.sym->attr.flavor = FL_PARAMETER; st->n.sym->attr.dummy = 1; st->n.sym->attr.intent = INTENT_IN; - st->n.sym->ts = caf_ref ? caf_ref->u.c.sym->ts : expr->symtree->n.sym->ts; + st->n.sym->ts = *caf_ts; *post_caf_ref_expr = gfc_get_variable_expr (st); (*post_caf_ref_expr)->where = expr->where; @@ -279,7 +379,12 @@ split_expr_at_caf_ref (gfc_expr *expr, gfc_namespace *ns, if (!caf_ref) { - (*post_caf_ref_expr)->ref = gfc_copy_ref (expr->ref); + (*post_caf_ref_expr)->ref = gfc_get_ref (); + *(*post_caf_ref_expr)->ref = *expr->ref; + expr->ref = nullptr; + move_coarray_ref (&(*post_caf_ref_expr)->ref, expr); + fixup_comp_refs (expr); + if (expr->symtree->n.sym->attr.dimension) { base->as = gfc_copy_array_spec (expr->symtree->n.sym->as); @@ -292,34 +397,39 @@ split_expr_at_caf_ref (gfc_expr *expr, gfc_namespace *ns, } else { - (*post_caf_ref_expr)->ref = gfc_copy_ref (caf_ref->next); - if (caf_ref->u.c.component->attr.dimension) + (*post_caf_ref_expr)->ref = gfc_get_ref (); + *(*post_caf_ref_expr)->ref = *caf_ref; + caf_ref->next = nullptr; + move_coarray_ref (&(*post_caf_ref_expr)->ref, expr); + fixup_comp_refs (expr); + + if (caf_ref && caf_ref->u.ar.dimen) { - base->as = gfc_copy_array_spec (caf_ref->u.c.component->as); + base->as = gfc_copy_array_spec (caf_ref->u.ar.as); base->as->corank = 0; base->attr.dimension = 1; - base->attr.allocatable = caf_ref->u.c.component->attr.allocatable; - base->attr.pointer = caf_ref->u.c.component->attr.pointer; + base->attr.allocatable = caf_ref->u.ar.as->type != AS_EXPLICIT; } - base->ts = caf_ref->u.c.component->ts; + base->ts = *caf_ts; } (*post_caf_ref_expr)->ts = expr->ts; if (base->ts.type == BT_CHARACTER) { base->ts.u.cl = gfc_get_charlen (); - *base->ts.u.cl = *(caf_ref ? caf_ref->u.c.component->ts.u.cl - : expr->symtree->n.sym->ts.u.cl); + *base->ts.u.cl = *(caf_ts->u.cl); base->ts.deferred = 1; base->ts.u.cl->length = nullptr; } - - if (base->ts.type == BT_DERIVED) + else if (base->ts.type == BT_DERIVED) remove_coarray_from_derived_type (base, ns); else if (base->ts.type == BT_CLASS) convert_coarray_class_to_derived_type (base, ns); - gfc_expression_rank (expr); gfc_expression_rank (*post_caf_ref_expr); + if (for_send) + gfc_expression_rank (expr); + else + expr->rank = (*post_caf_ref_expr)->rank; } static void add_caf_get_from_remote (gfc_expr *e); @@ -647,18 +757,16 @@ create_caf_add_data_parameter_type (gfc_expr *expr, gfc_namespace *ns, static void remove_caf_ref (gfc_expr *expr, const bool conv_to_this_image_cafref = false) { - gfc_ref *ref = expr->ref, **pref = &expr->ref; + gfc_ref *ref = expr->ref; while (ref && (ref->type != REF_ARRAY || ref->u.ar.codimen == 0)) { ref = ref->next; - pref = &ref->next; } if (ref && ref->type == REF_ARRAY && ref->u.ar.codimen != 0) { if (ref->u.ar.dimen != 0) { ref->u.ar.codimen = 0; - pref = &ref->next; ref = ref->next; } else @@ -675,21 +783,10 @@ remove_caf_ref (gfc_expr *expr, const bool conv_to_this_image_cafref = false) ref->next = NULL; gfc_free_ref_list (ref); ref = expr->ref; - pref = &expr->ref; } } } - if (ref && ref->type == REF_COMPONENT) - { - gfc_find_component (expr->symtree->n.sym->ts.u.derived, - ref->u.c.component->name, false, true, pref); - if (*pref && *pref != ref) - { - (*pref)->next = ref->next; - ref->next = NULL; - gfc_free_ref_list (ref); - } - } + fixup_comp_refs (expr); } static gfc_expr * @@ -719,7 +816,7 @@ create_get_callback (gfc_expr *expr) mname = expr->symtree->n.sym->module; else mname = "main"; - name = xasprintf ("_caf_rget_%s_%s_%d", mname, tname, ++caf_sym_cnt); + name = xasprintf ("_caf_accessor_%s_%s_%d", mname, tname, ++caf_sym_cnt); gfc_get_symbol (name, ns, &extproc); extproc->declared_at = expr->where; gfc_set_sym_referenced (extproc); @@ -744,7 +841,7 @@ create_get_callback (gfc_expr *expr) gfc_commit_symbol (proc); free (name); - split_expr_at_caf_ref (expr, sub_ns, &post_caf_ref_expr); + split_expr_at_caf_ref (expr, sub_ns, &post_caf_ref_expr, false); if (ns->proc_name->attr.flavor == FL_MODULE) proc->module = ns->proc_name->name; @@ -809,8 +906,7 @@ create_get_callback (gfc_expr *expr) { buffer->ts.u.cl = gfc_get_charlen (); *buffer->ts.u.cl = *expr->ts.u.cl; - buffer->ts.deferred = 1; - buffer->ts.u.cl->length = nullptr; + buffer->ts.u.cl->length = gfc_copy_expr (expr->ts.u.cl->length); } gfc_commit_symbol (buffer); @@ -857,7 +953,7 @@ create_get_callback (gfc_expr *expr) remove_caf_ref (post_caf_ref_expr); get_data->ts.u.derived = create_caf_add_data_parameter_type (code->expr2, ns, get_data); - if (code->expr2->rank == 0) + if (code->expr2->rank == 0 && code->expr2->ts.type != BT_CHARACTER) code->expr2 = gfc_build_intrinsic_call (ns, GFC_ISYM_C_LOC, "C_LOC", gfc_current_locus, 1, code->expr2); @@ -994,7 +1090,7 @@ create_allocated_callback (gfc_expr *expr) free (name); split_expr_at_caf_ref (expr->value.function.actual->expr, sub_ns, - &post_caf_ref_expr); + &post_caf_ref_expr, true); if (ns->proc_name->attr.flavor == FL_MODULE) proc->module = ns->proc_name->name; @@ -1086,10 +1182,198 @@ rewrite_caf_allocated (gfc_expr **e) "caf_is_present_on_remote", (*e)->where, 3, *e, present_hash_expr, present_fn_expr); gfc_add_caf_accessor (present_hash_expr, present_fn_expr); - wrapper->ts = (*e)->ts; *e = wrapper; } +static gfc_expr * +create_send_callback (gfc_expr *expr, gfc_expr *rhs) +{ + gfc_namespace *ns; + gfc_symbol *extproc, *proc, *buffer, *base, *send_data, *caller_image; + char tname[GFC_MAX_SYMBOL_LEN + 1]; + char *name; + const char *mname; + gfc_expr *cb, *post_caf_ref_expr; + gfc_code *code; + gfc_code *backup_caf_accessor_prepend = caf_accessor_prepend; + caf_accessor_prepend = nullptr; + + /* Find the top-level namespace. */ + for (ns = gfc_current_ns; ns->parent; ns = ns->parent) + ; + + if (expr->expr_type == EXPR_VARIABLE) + strcpy (tname, expr->symtree->name); + else + strcpy (tname, "dummy"); + if (expr->symtree->n.sym->module) + mname = expr->symtree->n.sym->module; + else + mname = "main"; + name = xasprintf ("_caf_accessor_%s_%s_%d", mname, tname, ++caf_sym_cnt); + gfc_get_symbol (name, ns, &extproc); + extproc->declared_at = expr->where; + gfc_set_sym_referenced (extproc); + ++extproc->refs; + gfc_commit_symbol (extproc); + + /* Set up namespace. */ + gfc_namespace *sub_ns = gfc_get_namespace (ns, 0); + sub_ns->sibling = ns->contained; + ns->contained = sub_ns; + sub_ns->resolved = 1; + /* Set up procedure symbol. */ + gfc_find_symbol (name, sub_ns, 1, &proc); + sub_ns->proc_name = proc; + proc->attr.if_source = IFSRC_DECL; + proc->attr.access = ACCESS_PUBLIC; + gfc_add_subroutine (&proc->attr, name, NULL); + proc->attr.host_assoc = 1; + proc->attr.always_explicit = 1; + ++proc->refs; + proc->declared_at = expr->where; + gfc_commit_symbol (proc); + free (name); + + split_expr_at_caf_ref (expr, sub_ns, &post_caf_ref_expr, true); + + if (ns->proc_name->attr.flavor == FL_MODULE) + proc->module = ns->proc_name->name; + gfc_set_sym_referenced (proc); + /* Set up formal arguments. */ + gfc_formal_arglist **argptr = &proc->formal; +#define ADD_ARG(name, nsym, stype, skind, sintent) \ + gfc_get_symbol (name, sub_ns, &nsym); \ + nsym->ts.type = stype; \ + nsym->ts.kind = skind; \ + nsym->attr.flavor = FL_PARAMETER; \ + nsym->attr.dummy = 1; \ + nsym->attr.intent = sintent; \ + nsym->declared_at = expr->where; \ + gfc_set_sym_referenced (nsym); \ + *argptr = gfc_get_formal_arglist (); \ + (*argptr)->sym = nsym; \ + argptr = &(*argptr)->next + + name = xasprintf ("add_send_data_%s_%s_%d", mname, tname, caf_sym_cnt); + ADD_ARG (name, send_data, BT_DERIVED, 0, INTENT_IN); + gfc_commit_symbol (send_data); + free (name); + + ADD_ARG ("caller_image", caller_image, BT_INTEGER, gfc_default_integer_kind, + INTENT_IN); + gfc_commit_symbol (caller_image); + + // ADD_ARG (expr->symtree->name, base, BT_VOID, INTENT_IN); + base = post_caf_ref_expr->symtree->n.sym; + base->attr.intent = INTENT_INOUT; + gfc_set_sym_referenced (base); + gfc_commit_symbol (base); + *argptr = gfc_get_formal_arglist (); + (*argptr)->sym = base; + argptr = &(*argptr)->next; + gfc_commit_symbol (base); + + ADD_ARG ("buffer", buffer, rhs->ts.type, rhs->ts.kind, INTENT_IN); + buffer->ts = rhs->ts; + if (rhs->rank) + { + buffer->as = gfc_get_array_spec (); + buffer->as->rank = rhs->rank; + buffer->as->type = AS_DEFERRED; + buffer->attr.allocatable = 1; + buffer->attr.dimension = 1; + } + if (buffer->ts.type == BT_CHARACTER) + { + buffer->ts.u.cl = gfc_get_charlen (); + *buffer->ts.u.cl = *rhs->ts.u.cl; + buffer->ts.deferred = 1; + buffer->ts.u.cl->length = gfc_copy_expr (rhs->ts.u.cl->length); + } + gfc_commit_symbol (buffer); +#undef ADD_ARG + + /* Set up code. */ + /* Code: base = buffer; */ + code = sub_ns->code = gfc_get_code (EXEC_ASSIGN); + code->loc = expr->where; + code->expr1 = post_caf_ref_expr; + if (code->expr1->ts.type == BT_CHARACTER + && code->expr1->ts.kind != buffer->ts.kind) + { + bool converted; + code->expr2 = gfc_lval_expr_from_sym (buffer); + converted = gfc_convert_chartype (code->expr2, &code->expr1->ts); + gcc_assert (converted); + } + else if (code->expr1->ts.type != buffer->ts.type) + { + bool converted; + code->expr2 = gfc_lval_expr_from_sym (buffer); + converted = gfc_convert_type_warn (code->expr2, &code->expr1->ts, 0, 0, + buffer->attr.dimension); + gcc_assert (converted); + } + else + code->expr2 = gfc_lval_expr_from_sym (buffer); + remove_caf_ref (post_caf_ref_expr); + send_data->ts.u.derived + = create_caf_add_data_parameter_type (code->expr1, ns, send_data); + + cb = gfc_lval_expr_from_sym (extproc); + cb->ts.interface = extproc; + + if (caf_accessor_prepend) + { + gfc_code *c = caf_accessor_prepend; + /* Find last in chain. */ + for (; c->next; c = c->next) + ; + c->next = sub_ns->code; + sub_ns->code = caf_accessor_prepend; + } + caf_accessor_prepend = backup_caf_accessor_prepend; + return cb; +} + +static void +rewrite_caf_send (gfc_code *c) +{ + gfc_expr *send_to_remote_expr, *send_to_remote_hash_expr, *lhs, *rhs; + gfc_actual_arglist *arg = c->ext.actual; + + lhs = arg->expr; + arg = arg->next; + rhs = arg->expr; + /* Detect an already rewritten caf_send. */ + if (arg->next && arg->next->expr->expr_type == EXPR_CONSTANT + && arg->next->next && arg->next->next->expr->expr_type == EXPR_VARIABLE) + return; + + if (gfc_is_coindexed (rhs)) + { + c->resolved_isym->id = GFC_ISYM_CAF_SENDGET; + return; + } + + send_to_remote_expr = create_send_callback (lhs, rhs); + send_to_remote_hash_expr = gfc_get_expr (); + send_to_remote_hash_expr->expr_type = EXPR_CONSTANT; + send_to_remote_hash_expr->ts.type = BT_INTEGER; + send_to_remote_hash_expr->ts.kind = gfc_default_integer_kind; + send_to_remote_hash_expr->where = lhs->where; + mpz_init_set_ui (send_to_remote_hash_expr->value.integer, + gfc_hash_value (send_to_remote_expr->symtree->n.sym)); + arg->next = gfc_get_actual_arglist (); + arg = arg->next; + arg->expr = send_to_remote_hash_expr; + arg->next = gfc_get_actual_arglist (); + arg = arg->next; + arg->expr = send_to_remote_expr; + gfc_add_caf_accessor (send_to_remote_hash_expr, send_to_remote_expr); +} + static int coindexed_expr_callback (gfc_expr **e, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) @@ -1158,20 +1442,34 @@ coindexed_code_callback (gfc_code **c, int *walk_subtrees, *walk_subtrees = 0; break; case EXEC_CALL: - *walk_subtrees - = !((*c)->resolved_isym - && ((*c)->resolved_isym->id == GFC_ISYM_CAF_SEND - || (*c)->resolved_isym->id == GFC_ISYM_ATOMIC_ADD - || (*c)->resolved_isym->id == GFC_ISYM_ATOMIC_AND - || (*c)->resolved_isym->id == GFC_ISYM_ATOMIC_CAS - || (*c)->resolved_isym->id == GFC_ISYM_ATOMIC_DEF - || (*c)->resolved_isym->id == GFC_ISYM_ATOMIC_FETCH_ADD - || (*c)->resolved_isym->id == GFC_ISYM_ATOMIC_FETCH_AND - || (*c)->resolved_isym->id == GFC_ISYM_ATOMIC_FETCH_OR - || (*c)->resolved_isym->id == GFC_ISYM_ATOMIC_FETCH_XOR - || (*c)->resolved_isym->id == GFC_ISYM_ATOMIC_OR - || (*c)->resolved_isym->id == GFC_ISYM_ATOMIC_REF - || (*c)->resolved_isym->id == GFC_ISYM_ATOMIC_XOR)); + *walk_subtrees = 1; + if ((*c)->resolved_isym) + switch ((*c)->resolved_isym->id) + { + case GFC_ISYM_CAF_SEND: + rewrite_caf_send (*c); + *walk_subtrees = 0; + break; + case GFC_ISYM_CAF_SENDGET: + // rewrite_caf_sendget (*c); + *walk_subtrees = 0; + break; + case GFC_ISYM_ATOMIC_ADD: + case GFC_ISYM_ATOMIC_AND: + case GFC_ISYM_ATOMIC_CAS: + case GFC_ISYM_ATOMIC_DEF: + case GFC_ISYM_ATOMIC_FETCH_ADD: + case GFC_ISYM_ATOMIC_FETCH_AND: + case GFC_ISYM_ATOMIC_FETCH_OR: + case GFC_ISYM_ATOMIC_FETCH_XOR: + case GFC_ISYM_ATOMIC_OR: + case GFC_ISYM_ATOMIC_REF: + case GFC_ISYM_ATOMIC_XOR: + *walk_subtrees = 0; + break; + default: + break; + } break; default: *walk_subtrees = 1; diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc index c03096b1a90..427ad2b84a4 100644 --- a/gcc/fortran/trans-decl.cc +++ b/gcc/fortran/trans-decl.cc @@ -148,6 +148,7 @@ tree gfor_fndecl_caf_register_accessor; tree gfor_fndecl_caf_register_accessors_finish; tree gfor_fndecl_caf_get_remote_function_index; tree gfor_fndecl_caf_get_from_remote; +tree gfor_fndecl_caf_send_to_remote; tree gfor_fndecl_caf_sync_all; tree gfor_fndecl_caf_sync_memory; @@ -4136,6 +4137,15 @@ gfc_build_builtin_function_decls (void) boolean_type_node, integer_type_node, pvoid_type_node, size_type_node, pint_type, pvoid_type_node, pint_type); + gfor_fndecl_caf_send_to_remote + = gfc_build_library_function_decl_with_spec ( + get_identifier (PREFIX ("caf_send_to_remote")), + ". r r r r r r r r r w r w r r ", void_type_node, 14, pvoid_type_node, + pvoid_type_node, psize_type, integer_type_node, size_type_node, + ppvoid_type_node, psize_type, pvoid_type_node, integer_type_node, + pvoid_type_node, size_type_node, pint_type, pvoid_type_node, + pint_type); + gfor_fndecl_caf_sync_all = gfc_build_library_function_decl_with_spec ( get_identifier (PREFIX("caf_sync_all")), ". w w . ", void_type_node, 3, pint_type, pchar_type_node, size_type_node); diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc index 472acfa81ca..19286f7a0ae 100644 --- a/gcc/fortran/trans-intrinsic.cc +++ b/gcc/fortran/trans-intrinsic.cc @@ -1681,6 +1681,11 @@ conv_caf_func_index (stmtblock_t *block, gfc_namespace *ns, const char *pat, tree func_index_tree; stmtblock_t blk; + /* Need to get namespace where static variables are possible. */ + while (ns && ns->proc_name && ns->proc_name->attr.flavor == FL_LABEL) + ns = ns->parent; + gcc_assert (ns); + name = xasprintf (pat, caf_call_cnt); gcc_assert (!gfc_get_sym_tree (name, ns, &index_st, false)); free (name); @@ -2006,6 +2011,198 @@ gfc_conv_intrinsic_caf_is_present_remote (gfc_se *se, gfc_expr *e) add_data_tree, add_data_size)); } +static tree +conv_caf_send_to_remote (gfc_code *code) +{ + gfc_expr *lhs_expr, *rhs_expr, *lhs_hash, *receiver_fn_expr, *tmp_stat, + *tmp_team; + gfc_symbol *add_data_sym; + gfc_se lhs_se, rhs_se; + stmtblock_t block; + gfc_namespace *ns; + tree caf_decl, token, rhs_size, image_index, tmp, rhs_data; + tree lhs_stat, lhs_team, opt_lhs_charlen, opt_rhs_charlen; + tree opt_lhs_desc = NULL_TREE, opt_rhs_desc = NULL_TREE; + tree receiver_fn_index_tree, add_data_tree, add_data_size; + + gcc_assert (flag_coarray == GFC_FCOARRAY_LIB); + gcc_assert (code->resolved_isym->id == GFC_ISYM_CAF_SEND); + + lhs_expr = code->ext.actual->expr; + rhs_expr = code->ext.actual->next->expr; + lhs_hash = code->ext.actual->next->next->expr; + receiver_fn_expr = code->ext.actual->next->next->next->expr; + add_data_sym = receiver_fn_expr->symtree->n.sym->formal->sym; + + ns = lhs_expr->expr_type == EXPR_VARIABLE + && !lhs_expr->symtree->n.sym->attr.associate_var + ? lhs_expr->symtree->n.sym->ns + : gfc_current_ns; + + gfc_init_block (&block); + + lhs_stat = null_pointer_node; + lhs_team = null_pointer_node; + + /* LHS. */ + gfc_init_se (&lhs_se, NULL); + caf_decl = gfc_get_tree_for_caf_expr (lhs_expr); + if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE) + caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl); + if (lhs_expr->rank == 0) + { + if (lhs_expr->ts.type == BT_CHARACTER) + { + gfc_conv_string_length (lhs_expr->ts.u.cl, lhs_expr, &block); + lhs_se.string_length = lhs_expr->ts.u.cl->backend_decl; + opt_lhs_charlen = gfc_build_addr_expr ( + NULL_TREE, gfc_trans_force_lval (&block, lhs_se.string_length)); + } + else + opt_lhs_charlen = build_zero_cst (build_pointer_type (size_type_node)); + opt_lhs_desc = null_pointer_node; + } + else + { + gfc_conv_expr_descriptor (&lhs_se, lhs_expr); + gfc_add_block_to_block (&block, &lhs_se.pre); + opt_lhs_desc = lhs_se.expr; + if (lhs_expr->ts.type == BT_CHARACTER) + opt_lhs_charlen = gfc_build_addr_expr ( + NULL_TREE, gfc_trans_force_lval (&block, lhs_se.string_length)); + else + opt_lhs_charlen = build_zero_cst (build_pointer_type (size_type_node)); + if (!TYPE_LANG_SPECIFIC (TREE_TYPE (caf_decl))->rank + || GFC_ARRAY_TYPE_P (TREE_TYPE (caf_decl))) + opt_lhs_desc = null_pointer_node; + else + opt_lhs_desc + = gfc_build_addr_expr (NULL_TREE, + gfc_trans_force_lval (&block, opt_lhs_desc)); + } + + /* Obtain token, offset and image index for the LHS. */ + image_index = gfc_caf_get_image_index (&block, lhs_expr, caf_decl); + gfc_get_caf_token_offset (&lhs_se, &token, NULL, caf_decl, NULL, lhs_expr); + + /* RHS. */ + gfc_init_se (&rhs_se, NULL); + if (rhs_expr->rank == 0) + { + gfc_conv_expr (&rhs_se, rhs_expr); + gfc_add_block_to_block (&block, &rhs_se.pre); + opt_rhs_desc = null_pointer_node; + if (rhs_expr->ts.type == BT_CHARACTER) + { + rhs_data + = rhs_expr->expr_type == EXPR_CONSTANT + ? gfc_build_addr_expr (NULL_TREE, + gfc_trans_force_lval (&block, + rhs_se.expr)) + : rhs_se.expr; + opt_rhs_charlen = gfc_build_addr_expr ( + NULL_TREE, gfc_trans_force_lval (&block, rhs_se.string_length)); + rhs_size = build_int_cstu (size_type_node, rhs_expr->ts.kind); + } + else + { + rhs_data + = gfc_build_addr_expr (NULL_TREE, + gfc_trans_force_lval (&block, rhs_se.expr)); + opt_rhs_charlen + = build_zero_cst (build_pointer_type (size_type_node)); + rhs_size = rhs_se.expr->typed.type->type_common.size_unit; + } + } + else + { + rhs_se.force_tmp = rhs_expr->shape == NULL + || !gfc_is_simply_contiguous (rhs_expr, false, false); + gfc_conv_expr_descriptor (&rhs_se, rhs_expr); + gfc_add_block_to_block (&block, &rhs_se.pre); + opt_rhs_desc = rhs_se.expr; + if (rhs_expr->ts.type == BT_CHARACTER) + { + opt_rhs_charlen = gfc_build_addr_expr ( + NULL_TREE, gfc_trans_force_lval (&block, rhs_se.string_length)); + rhs_size = build_int_cstu (size_type_node, rhs_expr->ts.kind); + } + else + { + opt_rhs_charlen + = build_zero_cst (build_pointer_type (size_type_node)); + rhs_size = fold_build2 ( + MULT_EXPR, size_type_node, + fold_convert (size_type_node, + rhs_expr->shape + ? conv_shape_to_cst (rhs_expr) + : gfc_conv_descriptor_size (rhs_se.expr, + rhs_expr->rank)), + fold_convert (size_type_node, + gfc_conv_descriptor_span_get (rhs_se.expr))); + } + + rhs_data = gfc_build_addr_expr ( + NULL_TREE, gfc_trans_force_lval (&block, gfc_conv_descriptor_data_get ( + opt_rhs_desc))); + opt_rhs_desc = gfc_build_addr_expr (NULL_TREE, opt_rhs_desc); + } + gfc_add_block_to_block (&block, &rhs_se.pre); + + tmp_stat = gfc_find_stat_co (lhs_expr); + + if (tmp_stat) + { + gfc_se stat_se; + gfc_init_se (&stat_se, NULL); + gfc_conv_expr_reference (&stat_se, tmp_stat); + lhs_stat = stat_se.expr; + gfc_add_block_to_block (&block, &stat_se.pre); + gfc_add_block_to_block (&block, &stat_se.post); + } + + tmp_team = gfc_find_team_co (lhs_expr); + + if (tmp_team) + { + gfc_se team_se; + gfc_init_se (&team_se, NULL); + gfc_conv_expr_reference (&team_se, tmp_team); + lhs_team = team_se.expr; + gfc_add_block_to_block (&block, &team_se.pre); + gfc_add_block_to_block (&block, &team_se.post); + } + + receiver_fn_index_tree + = conv_caf_func_index (&block, ns, "__caf_send_to_remote_fn_index_%d", + lhs_hash); + add_data_tree + = conv_caf_add_call_data (&block, ns, "__caf_send_to_remote_add_data_%d", + add_data_sym, &add_data_size); + ++caf_call_cnt; + + tmp + = build_call_expr_loc (input_location, gfor_fndecl_caf_send_to_remote, 14, + token, opt_lhs_desc, opt_lhs_charlen, image_index, + rhs_size, rhs_data, opt_rhs_charlen, opt_rhs_desc, + receiver_fn_index_tree, add_data_tree, add_data_size, + lhs_stat, lhs_team, null_pointer_node); + + gfc_add_expr_to_block (&block, tmp); + gfc_add_block_to_block (&block, &lhs_se.post); + gfc_add_block_to_block (&block, &rhs_se.post); + + /* It guarantees memory consistency within the same segment. */ + tmp = gfc_build_string_const (strlen ("memory") + 1, "memory"); + tmp = build5_loc (input_location, ASM_EXPR, void_type_node, + gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE, + tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE); + ASM_VOLATILE_P (tmp) = 1; + gfc_add_expr_to_block (&block, tmp); + + return gfc_finish_block (&block); +} + static bool has_ref_after_cafref (gfc_expr *expr) { @@ -2015,10 +2212,11 @@ has_ref_after_cafref (gfc_expr *expr) return false; } -/* Send data to a remote coarray. */ +/* Send-get data to a remote coarray. */ static tree -conv_caf_send (gfc_code *code) { +conv_caf_sendget (gfc_code *code) +{ gfc_expr *lhs_expr, *rhs_expr, *tmp_stat, *tmp_team; gfc_se lhs_se, rhs_se; stmtblock_t block; @@ -2461,7 +2659,6 @@ conv_caf_send (gfc_code *code) { return gfc_finish_block (&block); } - static void trans_this_image (gfc_se * se, gfc_expr *expr) { @@ -13843,7 +14040,11 @@ gfc_conv_intrinsic_subroutine (gfc_code *code) break; case GFC_ISYM_CAF_SEND: - res = conv_caf_send (code); + res = conv_caf_send_to_remote (code); + break; + + case GFC_ISYM_CAF_SENDGET: + res = conv_caf_sendget (code); break; case GFC_ISYM_CO_BROADCAST: diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index c0a621df55d..8b76a277c07 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -892,10 +892,11 @@ extern GTY(()) tree gfor_fndecl_caf_send_by_ref; extern GTY(()) tree gfor_fndecl_caf_sendget_by_ref; // Deprecate end -extern GTY (()) tree gfor_fndecl_caf_register_accessor; -extern GTY (()) tree gfor_fndecl_caf_register_accessors_finish; -extern GTY (()) tree gfor_fndecl_caf_get_remote_function_index; -extern GTY (()) tree gfor_fndecl_caf_get_from_remote; +extern GTY(()) tree gfor_fndecl_caf_register_accessor; +extern GTY(()) tree gfor_fndecl_caf_register_accessors_finish; +extern GTY(()) tree gfor_fndecl_caf_get_remote_function_index; +extern GTY(()) tree gfor_fndecl_caf_get_from_remote; +extern GTY(()) tree gfor_fndecl_caf_send_to_remote; extern GTY(()) tree gfor_fndecl_caf_sync_all; extern GTY(()) tree gfor_fndecl_caf_sync_memory; diff --git a/gcc/testsuite/gfortran.dg/coarray/send_char_array_1.f90 b/gcc/testsuite/gfortran.dg/coarray/send_char_array_1.f90 index b3caf80b1ad..65e3afd1732 100644 --- a/gcc/testsuite/gfortran.dg/coarray/send_char_array_1.f90 +++ b/gcc/testsuite/gfortran.dg/coarray/send_char_array_1.f90 @@ -39,16 +39,21 @@ program send_convert_char_array co_str_k1_arr(:)[this_image()] = str_k1_arr if (any(co_str_k1_arr /= ['abc ', 'EFG ', 'klm ', 'NOP '])) STOP 5 - - co_str_k4_arr(:)[this_image()] = [4_'abc', 4_'EFG', 4_'klm', 4_'NOP']! str_k4_arr - if (any(co_str_k4_arr /= [4_'abc ', 4_'EFG ', 4_'klm ', 4_'NOP '])) STOP 6 + co_str_k4_arr(:)[this_image()] = str_k4_arr + if (any(co_str_k4_arr /= [4_'abc ', 4_'EFG ', 4_'klm ', 4_'NOP '])) STOP 6 + co_str_k4_arr(:)[this_image()] = str_k1_arr if (any(co_str_k4_arr /= [ 4_'abc ', 4_'EFG ', 4_'klm ', 4_'NOP '])) STOP 7 co_str_k1_arr(:)[this_image()] = str_k4_arr if (any(co_str_k1_arr /= ['abc ', 'EFG ', 'klm ', 'NOP '])) STOP 8 + co_str_k1_arr(:)[this_image()] = ['abc', 'EFG', 'klm', 'NOP'] + if (any(co_str_k1_arr /= ['abc ', 'EFG ', 'klm ', 'NOP '])) STOP 9 + + co_str_k4_arr(:)[this_image()] = [4_'abc', 4_'EFG', 4_'klm', 4_'NOP'] + if (any(co_str_k4_arr /= [4_'abc ', 4_'EFG ', 4_'klm ', 4_'NOP '])) STOP 10 + end program send_convert_char_array -! vim:ts=2:sts=2:sw=2: diff --git a/gcc/testsuite/gfortran.dg/coarray_42.f90 b/gcc/testsuite/gfortran.dg/coarray_42.f90 index 982f5d12381..e99cc9e5f70 100644 --- a/gcc/testsuite/gfortran.dg/coarray_42.f90 +++ b/gcc/testsuite/gfortran.dg/coarray_42.f90 @@ -11,11 +11,11 @@ program Jac allocate(D[2,2,*]) allocate(D%endsi(2), source = 0) - ! Lhs may be reallocate, so caf_send_by_ref needs to be used. + ! Lhs may be reallocate. Due to new communication pattern no send. D%endsi = D%n if (any(D%endsi /= [ 64, 64])) error stop deallocate(D) end program -! { dg-final { scan-tree-dump-times "caf_send_by_ref" 1 "original" } } +! { dg-final { scan-tree-dump-not "caf_send" "original" } } diff --git a/libgfortran/caf/libcaf.h b/libgfortran/caf/libcaf.h index a29047d4b23..0af1813bbd5 100644 --- a/libgfortran/caf/libcaf.h +++ b/libgfortran/caf/libcaf.h @@ -246,13 +246,21 @@ void _gfortran_caf_get_from_remote ( caf_token_t token, const gfc_descriptor_t *opt_src_desc, const size_t *opt_src_charlen, const int image_index, const size_t dst_size, void **dst_data, size_t *opt_dst_charlen, gfc_descriptor_t *opt_dst_desc, - const bool may_realloc_dst, const int getter_index, void *get_data, - const size_t get_data_size, int *stat, caf_team_t *team, int *team_number); + const bool may_realloc_dst, const int accessor_index, void *add_data, + const size_t add_data_size, int *stat, caf_team_t *team, int *team_number); int32_t _gfortran_caf_is_present_on_remote (caf_token_t token, int, int, void *add_data, const size_t add_data_size); +void _gfortran_caf_send_to_remote ( + caf_token_t token, gfc_descriptor_t *opt_dst_desc, + const size_t *opt_dst_charlen, const int image_index, const size_t src_size, + const void *src_data, const size_t *opt_src_charlen, + const gfc_descriptor_t *opt_src_desc, const int accessor_index, + void *add_data, const size_t add_data_size, int *stat, caf_team_t *team, + int *team_number); + void _gfortran_caf_atomic_define (caf_token_t, size_t, int, void *, int *, int, int); void _gfortran_caf_atomic_ref (caf_token_t, size_t, int, void *, int *, diff --git a/libgfortran/caf/single.c b/libgfortran/caf/single.c index 66d3bf93e1d..625e1a71148 100644 --- a/libgfortran/caf/single.c +++ b/libgfortran/caf/single.c @@ -57,19 +57,22 @@ typedef struct caf_single_token *caf_single_token_t; /* Global variables. */ caf_static_t *caf_static_list = NULL; -typedef void (*accessor_t) (void *, const int *, void **, int32_t *, void *, - caf_token_t, const size_t, size_t *, - const size_t *); +typedef void (*getter_t) (void *, const int *, void **, int32_t *, void *, + caf_token_t, const size_t, size_t *, const size_t *); typedef void (*is_present_t) (void *, const int *, int32_t *, void *, caf_single_token_t, const size_t); +typedef void (*receiver_t) (void *, const int *, void *, const void *, + caf_token_t, const size_t, const size_t *, + const size_t *); struct accessor_hash_t { int hash; int pad; union { - accessor_t accessor; + getter_t getter; is_present_t is_present; + receiver_t receiver; } u; }; @@ -2862,7 +2865,7 @@ _gfortran_caf_sendget_by_ref (caf_token_t dst_token, int dst_image_index, } void -_gfortran_caf_register_accessor (const int hash, accessor_t accessor) +_gfortran_caf_register_accessor (const int hash, getter_t accessor) { if (accessor_hash_table_state == AHT_UNINITIALIZED) { @@ -2881,7 +2884,7 @@ _gfortran_caf_register_accessor (const int hash, accessor_t accessor) accessor_hash_table_state = AHT_OPEN; } accessor_hash_table[aht_size].hash = hash; - accessor_hash_table[aht_size].u.accessor = accessor; + accessor_hash_table[aht_size].u.getter = accessor; ++aht_size; } @@ -2929,8 +2932,8 @@ _gfortran_caf_get_from_remote ( const size_t *opt_src_charlen, const int image_index, const size_t dst_size __attribute__ ((unused)), void **dst_data, size_t *opt_dst_charlen, gfc_descriptor_t *opt_dst_desc, - const bool may_realloc_dst, const int getter_index, void *get_data, - const size_t get_data_size __attribute__ ((unused)), int *stat, + const bool may_realloc_dst, const int getter_index, void *add_data, + const size_t add_data_size __attribute__ ((unused)), int *stat, caf_team_t *team __attribute__ ((unused)), int *team_number __attribute__ ((unused))) { @@ -2940,7 +2943,7 @@ _gfortran_caf_get_from_remote ( void *dst_ptr = opt_dst_desc ? (void *)opt_dst_desc : dst_data; void *old_dst_data_ptr = NULL; struct caf_single_token cb_token; - cb_token.memptr = get_data; + cb_token.memptr = add_data; cb_token.desc = NULL; cb_token.owning_memory = false; @@ -2953,10 +2956,10 @@ _gfortran_caf_get_from_remote ( opt_dst_desc->base_addr = NULL; } - accessor_hash_table[getter_index].u.accessor (get_data, &image_index, dst_ptr, - &free_buffer, src_ptr, - &cb_token, 0, opt_dst_charlen, - opt_src_charlen); + accessor_hash_table[getter_index].u.getter (add_data, &image_index, dst_ptr, + &free_buffer, src_ptr, &cb_token, + 0, opt_dst_charlen, + opt_src_charlen); if (opt_dst_desc && old_dst_data_ptr && !may_realloc_dst && opt_dst_desc->base_addr != old_dst_data_ptr) { @@ -2992,6 +2995,34 @@ _gfortran_caf_is_present_on_remote (caf_token_t token, const int image_index, return result; } +void +_gfortran_caf_send_to_remote ( + caf_token_t token, gfc_descriptor_t *opt_dst_desc, + const size_t *opt_dst_charlen, const int image_index, + const size_t src_size __attribute__ ((unused)), const void *src_data, + const size_t *opt_src_charlen, const gfc_descriptor_t *opt_src_desc, + const int accessor_index, void *add_data, + const size_t add_data_size __attribute__ ((unused)), int *stat, + caf_team_t *team __attribute__ ((unused)), + int *team_number __attribute__ ((unused))) +{ + caf_single_token_t single_token = TOKEN (token); + void *dst_ptr = opt_dst_desc ? (void *) opt_dst_desc : single_token->memptr; + const void *src_ptr = opt_src_desc ? (void *) opt_src_desc : src_data; + struct caf_single_token cb_token; + cb_token.memptr = add_data; + cb_token.desc = NULL; + cb_token.owning_memory = false; + + if (stat) + *stat = 0; + + accessor_hash_table[accessor_index].u.receiver (add_data, &image_index, + dst_ptr, src_ptr, &cb_token, + 0, opt_dst_charlen, + opt_src_charlen); +} + void _gfortran_caf_atomic_define (caf_token_t token, size_t offset, int image_index __attribute__ ((unused)), -- 2.48.1