[PATCH 4/7] Fortran: Add caf_is_present_on_remote. [PR107635]

Replace caf_is_present by caf_is_present_on_remote which is using a
dedicated callback for each object to test on the remote image.

gcc/fortran/ChangeLog:

        PR fortran/107635

        * gfortran.h (enum gfc_isym_id): Add caf_is_present_on_remote
        id.
        * gfortran.texi: Add documentation for caf_is_present_on_remote.
        * intrinsic.cc (add_functions): Add caf_is_present_on_remote
        symbol.
        * rewrite.cc (create_allocated_callback): Add creating remote
        side procedure for checking allocation status of coarray.
        (rewrite_caf_allocated): Rewrite ALLOCATED on coarray to use caf
        routine.
        (coindexed_expr_callback): Exempt caf_is_present_on_remote from
        being rewritten again.
        * trans-decl.cc (gfc_build_builtin_function_decls): Define
        interface of caf_is_present_on_remote.
        * trans-intrinsic.cc (gfc_conv_intrinsic_caf_is_present_remote):
        Translate caf_is_present_on_remote.
        (trans_caf_is_present): Remove.
        (caf_this_image_ref): Remove.
        (gfc_conv_allocated): Take out coarray treatment, because that
        is rewritten to caf_is_present_on_remote now.
        (gfc_conv_intrinsic_function): Handle caf_is_present_on_remote
        calls.
        * trans.h: Add symbol for caf_is_present_on_remote and remove
        old one.

libgfortran/ChangeLog:

        * caf/libcaf.h (_gfortran_caf_is_present_on_remote): Add new
        function.
        (_gfortran_caf_is_present): Remove deprecated one.
        * caf/single.c (struct accessor_hash_t): Add function ptr access
        for remote side call.
        (_gfortran_caf_is_present_on_remote): Added.
        (_gfortran_caf_is_present): Removed.

gcc/testsuite/ChangeLog:

        * gfortran.dg/coarray/coarray_allocated.f90: Adapt to new method
        of checking on remote image.
        * gfortran.dg/coarray_lib_alloc_4.f90: Same.

--
Andre Vehreschild * Email: vehre ad gmx dot de
From ca929ce62d0f07b274113a20a5900d525526d25e Mon Sep 17 00:00:00 2001
From: Andre Vehreschild <ve...@gcc.gnu.org>
Date: Wed, 22 Jan 2025 15:12:29 +0100
Subject: [PATCH 4/7] Fortran: Add caf_is_present_on_remote. [PR107635]

Replace caf_is_present by caf_is_present_on_remote which is using a
dedicated callback for each object to test on the remote image.

gcc/fortran/ChangeLog:

	PR fortran/107635

	* gfortran.h (enum gfc_isym_id): Add caf_is_present_on_remote
	id.
	* gfortran.texi: Add documentation for caf_is_present_on_remote.
	* intrinsic.cc (add_functions): Add caf_is_present_on_remote
	symbol.
	* rewrite.cc (create_allocated_callback): Add creating remote
	side procedure for checking allocation status of coarray.
	(rewrite_caf_allocated): Rewrite ALLOCATED on coarray to use caf
	routine.
	(coindexed_expr_callback): Exempt caf_is_present_on_remote from
	being rewritten again.
	* trans-decl.cc (gfc_build_builtin_function_decls): Define
	interface of caf_is_present_on_remote.
	* trans-intrinsic.cc (gfc_conv_intrinsic_caf_is_present_remote):
	Translate caf_is_present_on_remote.
	(trans_caf_is_present): Remove.
	(caf_this_image_ref): Remove.
	(gfc_conv_allocated): Take out coarray treatment, because that
	is rewritten to caf_is_present_on_remote now.
	(gfc_conv_intrinsic_function): Handle caf_is_present_on_remote
	calls.
	* trans.h: Add symbol for caf_is_present_on_remote and remove
	old one.

libgfortran/ChangeLog:

	* caf/libcaf.h (_gfortran_caf_is_present_on_remote): Add new
	function.
	(_gfortran_caf_is_present): Remove deprecated one.
	* caf/single.c (struct accessor_hash_t): Add function ptr access
	for remote side call.
	(_gfortran_caf_is_present_on_remote): Added.
	(_gfortran_caf_is_present): Removed.

gcc/testsuite/ChangeLog:

	* gfortran.dg/coarray/coarray_allocated.f90: Adapt to new method
	of checking on remote image.
	* gfortran.dg/coarray_lib_alloc_4.f90: Same.
---
 gcc/fortran/gfortran.h                        |   1 +
 gcc/fortran/gfortran.texi                     |  34 ++++
 gcc/fortran/intrinsic.cc                      |   7 +
 gcc/fortran/rewrite.cc                        | 157 ++++++++++++++++++
 gcc/fortran/trans-decl.cc                     |  11 +-
 gcc/fortran/trans-intrinsic.cc                | 136 +++++++--------
 gcc/fortran/trans.h                           |   2 +-
 .../gfortran.dg/coarray/coarray_allocated.f90 |  16 +-
 .../gfortran.dg/coarray_lib_alloc_4.f90       |   2 +-
 libgfortran/caf/libcaf.h                      |   5 +-
 libgfortran/caf/single.c                      | 126 +++-----------
 11 files changed, 297 insertions(+), 200 deletions(-)

diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 00dcc06bd4b..c9bac84c16b 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -456,6 +456,7 @@ enum gfc_isym_id
   GFC_ISYM_BLT,
   GFC_ISYM_BTEST,
   GFC_ISYM_CAF_GET,
+  GFC_ISYM_CAF_IS_PRESENT_ON_REMOTE,
   GFC_ISYM_CAF_SEND,
   GFC_ISYM_CEILING,
   GFC_ISYM_CHAR,
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index 4c3802e307a..32558e6b803 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -4211,6 +4211,7 @@ future implementation of teams.  It is about to change without further notice.
 * _gfortran_caf_send_by_ref:: Sending data from a local image to a remote image using enhanced references
 * _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_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
@@ -5049,6 +5050,39 @@ implementation has to take care that it handles this case, e.g. using
 @end table


+@node _gfortran_caf_is_present_on_remote
+@subsection @code{_gfortran_caf_is_present_on_remote} --- Check that a coarray or a part of it is allocated on the remote image
+@cindex Coarray, _gfortran_caf_is_present_on_remote
+
+@table @asis
+@item @emph{Description}:
+Check if an allocatable coarray or a component of a derived type coarray is
+allocated on the remote image identified by the @var{image_index}.  The check
+is done by calling routine on the remote side.
+
+@item @emph{Syntax}:
+@code{int32_t _gfortran_caf_is_present_on_remote (caf_token_t token,
+const int image_index, const int is_present_index, void *add_data,
+const size_t add_data_size)}
+
+@item @emph{Arguments}:
+@multitable @columnfractions .15 .70
+@item @var{token} @tab intent(in)  An opaque pointer identifying the coarray.
+@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{is_present_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.
+@end multitable
+@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/intrinsic.cc b/gcc/fortran/intrinsic.cc
index dc60d98d51b..99d5abcb9d5 100644
--- a/gcc/fortran/intrinsic.cc
+++ b/gcc/fortran/intrinsic.cc
@@ -3521,6 +3521,13 @@ add_functions (void)
 	     BT_REAL, dr, GFC_STD_GNU, NULL, NULL, NULL,
 	     x, BT_REAL, dr, REQUIRED);
   make_from_module();
+
+  add_sym_3 (GFC_PREFIX ("caf_is_present_on_remote"),
+	     GFC_ISYM_CAF_IS_PRESENT_ON_REMOTE, CLASS_IMPURE, ACTUAL_NO,
+	     BT_LOGICAL, dl, GFC_STD_GNU, NULL, NULL, NULL, ca, BT_VOID, di,
+	     REQUIRED, val, BT_INTEGER, di, REQUIRED, i, BT_INTEGER, di,
+	     REQUIRED);
+  make_from_module ();
 }


diff --git a/gcc/fortran/rewrite.cc b/gcc/fortran/rewrite.cc
index 3caa65c40fd..e8e791e8ada 100644
--- a/gcc/fortran/rewrite.cc
+++ b/gcc/fortran/rewrite.cc
@@ -942,6 +942,154 @@ add_caf_get_from_remote (gfc_expr *e)
   free (wrapper);
 }

+static gfc_expr *
+create_allocated_callback (gfc_expr *expr)
+{
+  gfc_namespace *ns;
+  gfc_symbol *extproc, *proc, *result, *base, *add_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;
+  gfc_expr swp;
+
+  /* Find the top-level namespace.  */
+  for (ns = gfc_current_ns; ns->parent; ns = ns->parent)
+    ;
+
+  if (expr->value.function.actual->expr->expr_type == EXPR_VARIABLE)
+    strcpy (tname, expr->value.function.actual->expr->symtree->name);
+  else
+    strcpy (tname, "dummy");
+  if (expr->value.function.actual->expr->symtree->n.sym->module)
+    mname = expr->value.function.actual->expr->symtree->n.sym->module;
+  else
+    mname = "main";
+  name = xasprintf ("_caf_present_%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->declared_at = expr->where;
+  ++proc->refs;
+  gfc_commit_symbol (proc);
+  free (name);
+
+  split_expr_at_caf_ref (expr->value.function.actual->expr, sub_ns,
+			 &post_caf_ref_expr);
+
+  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_data_%s_%s_%d", mname, tname, ++caf_sym_cnt);
+  ADD_ARG (name, add_data, BT_DERIVED, 0, INTENT_IN);
+  gfc_commit_symbol (add_data);
+  free (name);
+  ADD_ARG ("caller_image", caller_image, BT_INTEGER, gfc_default_integer_kind,
+	   INTENT_IN);
+  gfc_commit_symbol (caller_image);
+
+  ADD_ARG ("result", result, BT_LOGICAL, gfc_default_logical_kind, INTENT_OUT);
+  gfc_commit_symbol (result);
+
+  // ADD_ARG (expr->symtree->name, base, BT_VOID, INTENT_IN);
+  base = post_caf_ref_expr->symtree->n.sym;
+  gfc_set_sym_referenced (base);
+  gfc_commit_symbol (base);
+  *argptr = gfc_get_formal_arglist ();
+  (*argptr)->sym = base;
+  argptr = &(*argptr)->next;
+  gfc_commit_symbol (base);
+#undef ADD_ARG
+
+  /* Set up code.  */
+  /* Code: result = post_caf_ref_expr;  */
+  code = sub_ns->code = gfc_get_code (EXEC_ASSIGN);
+  code->loc = expr->where;
+  code->expr1 = gfc_lval_expr_from_sym (result);
+  swp = *expr;
+  *expr = *swp.value.function.actual->expr;
+  swp.value.function.actual->expr = nullptr;
+  code->expr2 = gfc_copy_expr (&swp);
+  code->expr2->value.function.actual->expr = post_caf_ref_expr;
+
+  remove_caf_ref (code->expr2->value.function.actual->expr, true);
+  add_data->ts.u.derived
+    = create_caf_add_data_parameter_type (post_caf_ref_expr, ns, add_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_allocated (gfc_expr **e)
+{
+  gfc_expr *present_fn_expr, *present_hash_expr, *wrapper;
+
+  present_fn_expr = create_allocated_callback (*e);
+
+  present_hash_expr = gfc_get_expr ();
+  present_hash_expr->expr_type = EXPR_CONSTANT;
+  present_hash_expr->ts.type = BT_INTEGER;
+  present_hash_expr->ts.kind = gfc_default_integer_kind;
+  present_hash_expr->where = (*e)->where;
+  mpz_init_set_ui (present_hash_expr->value.integer,
+		   gfc_hash_value (present_fn_expr->symtree->n.sym));
+  wrapper
+    = gfc_build_intrinsic_call (gfc_current_ns,
+				GFC_ISYM_CAF_IS_PRESENT_ON_REMOTE,
+				"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 int
 coindexed_expr_callback (gfc_expr **e, int *walk_subtrees,
 			 void *data ATTRIBUTE_UNUSED)
@@ -963,7 +1111,16 @@ coindexed_expr_callback (gfc_expr **e, int *walk_subtrees,
       if ((*e)->value.function.isym)
 	switch ((*e)->value.function.isym->id)
 	  {
+	  case GFC_ISYM_ALLOCATED:
+	    if ((*e)->value.function.actual->expr
+		&& gfc_is_coindexed ((*e)->value.function.actual->expr))
+	      {
+		rewrite_caf_allocated (e);
+		*walk_subtrees = 0;
+	      }
+	    break;
 	  case GFC_ISYM_CAF_GET:
+	  case GFC_ISYM_CAF_IS_PRESENT_ON_REMOTE:
 	    *walk_subtrees = 0;
 	    break;
 	  default:
diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc
index c22ecb4641e..c03096b1a90 100644
--- a/gcc/fortran/trans-decl.cc
+++ b/gcc/fortran/trans-decl.cc
@@ -180,7 +180,7 @@ tree gfor_fndecl_co_max;
 tree gfor_fndecl_co_min;
 tree gfor_fndecl_co_reduce;
 tree gfor_fndecl_co_sum;
-tree gfor_fndecl_caf_is_present;
+tree gfor_fndecl_caf_is_present_on_remote;
 tree gfor_fndecl_caf_random_init;


@@ -4302,10 +4302,11 @@ gfc_build_builtin_function_decls (void)
 	void_type_node, 5, pvoid_type_node, integer_type_node,
 	pint_type, pchar_type_node, size_type_node);

-      gfor_fndecl_caf_is_present = gfc_build_library_function_decl_with_spec (
-	get_identifier (PREFIX("caf_is_present")), ". r . r ",
-	integer_type_node, 3, pvoid_type_node, integer_type_node,
-	pvoid_type_node);
+      gfor_fndecl_caf_is_present_on_remote
+	= gfc_build_library_function_decl_with_spec (
+	  get_identifier (PREFIX ("caf_is_present_on_remote")), ". r r r r r ",
+	  integer_type_node, 5, pvoid_type_node, integer_type_node,
+	  integer_type_node, pvoid_type_node, size_type_node);

       gfor_fndecl_caf_random_init = gfc_build_library_function_decl (
 	    get_identifier (PREFIX("caf_random_init")),
diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index 1a28bfa7a58..472acfa81ca 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -1966,6 +1966,46 @@ gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs,
   return;
 }

+/* Generate call to caf_is_present_on_remote for allocated (coarrary[...])
+   calls.  */
+
+static void
+gfc_conv_intrinsic_caf_is_present_remote (gfc_se *se, gfc_expr *e)
+{
+  gfc_expr *caf_expr, *hash, *present_fn;
+  gfc_symbol *add_data_sym;
+  tree fn_index, add_data_tree, add_data_size, caf_decl, image_index, token;
+
+  gcc_assert (e->expr_type == EXPR_FUNCTION
+	      && e->value.function.isym->id
+		   == GFC_ISYM_CAF_IS_PRESENT_ON_REMOTE);
+  caf_expr = e->value.function.actual->expr;
+  hash = e->value.function.actual->next->expr;
+  present_fn = e->value.function.actual->next->next->expr;
+  add_data_sym = present_fn->symtree->n.sym->formal->sym;
+
+  fn_index = conv_caf_func_index (&se->pre, gfc_current_ns,
+				  "__caf_present_on_remote_fn_index_%d", hash);
+  add_data_tree = conv_caf_add_call_data (&se->pre, gfc_current_ns,
+					  "__caf_present_on_remote_add_data_%d",
+					  add_data_sym, &add_data_size);
+  ++caf_call_cnt;
+
+  caf_decl = gfc_get_tree_for_caf_expr (caf_expr);
+  if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
+    caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
+
+  image_index = gfc_caf_get_image_index (&se->pre, caf_expr, caf_decl);
+  gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL, caf_expr);
+
+  se->expr
+    = fold_convert (logical_type_node,
+		    build_call_expr_loc (input_location,
+					 gfor_fndecl_caf_is_present_on_remote,
+					 5, token, image_index, fn_index,
+					 add_data_tree, add_data_size));
+}
+
 static bool
 has_ref_after_cafref (gfc_expr *expr)
 {
@@ -9498,42 +9538,6 @@ scalar_transfer:
 }


-/* Generate a call to caf_is_present.  */
-
-static tree
-trans_caf_is_present (gfc_se *se, gfc_expr *expr)
-{
-  tree caf_reference, caf_decl, token, image_index;
-
-  /* Compile the reference chain.  */
-  caf_reference = conv_expr_ref_to_caf_ref (&se->pre, expr);
-  gcc_assert (caf_reference != NULL_TREE);
-
-  caf_decl = gfc_get_tree_for_caf_expr (expr);
-  if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
-    caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
-  image_index = gfc_caf_get_image_index (&se->pre, expr, caf_decl);
-  gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
-			    expr);
-
-  return build_call_expr_loc (input_location, gfor_fndecl_caf_is_present,
-			      3, token, image_index, caf_reference);
-}
-
-
-/* Test whether this ref-chain refs this image only.  */
-
-static bool
-caf_this_image_ref (gfc_ref *ref)
-{
-  for ( ; ref; ref = ref->next)
-    if (ref->type == REF_ARRAY && ref->u.ar.codimen)
-      return ref->u.ar.dimen_type[ref->u.ar.dimen] == DIMEN_THIS_IMAGE;
-
-  return false;
-}
-
-
 /* Generate code for the ALLOCATED intrinsic.
    Generate inline code that directly check the address of the argument.  */

@@ -9542,7 +9546,6 @@ gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
 {
   gfc_se arg1se;
   tree tmp;
-  bool coindexed_caf_comp = false;
   gfc_expr *e = expr->value.function.actual->expr;

   gfc_init_se (&arg1se, NULL);
@@ -9557,53 +9560,26 @@ gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
 	gfc_add_data_component (e);
     }

-  /* When 'e' references an allocatable component in a coarray, then call
-     the caf-library function caf_is_present ().  */
-  if (flag_coarray == GFC_FCOARRAY_LIB && e->expr_type == EXPR_FUNCTION
-      && e->value.function.isym
-      && e->value.function.isym->id == GFC_ISYM_CAF_GET)
+  gcc_assert (flag_coarray != GFC_FCOARRAY_LIB || !gfc_is_coindexed (e));
+
+  if (e->rank == 0)
     {
-      e = e->value.function.actual->expr;
-      if (gfc_expr_attr (e).codimension)
-	{
-	  /* Last partref is the coindexed coarray. As coarrays are collectively
-	     (de)allocated, the allocation status must be the same as the one of
-	     the local allocation.  Convert to local access. */
-	  for (gfc_ref *ref = e->ref; ref; ref = ref->next)
-	    if (ref->type == REF_ARRAY && ref->u.ar.codimen)
-	      {
-		for (int i = ref->u.ar.dimen;
-		     i < ref->u.ar.dimen + ref->u.ar.codimen; ++i)
-		ref->u.ar.dimen_type[i] = DIMEN_THIS_IMAGE;
-		break;
-	      }
-	}
-      else if (!caf_this_image_ref (e->ref))
-	coindexed_caf_comp = true;
+      /* Allocatable scalar.  */
+      arg1se.want_pointer = 1;
+      gfc_conv_expr (&arg1se, e);
+      tmp = arg1se.expr;
     }
-  if (coindexed_caf_comp)
-    tmp = trans_caf_is_present (se, e);
   else
     {
-      if (e->rank == 0)
-	{
-	  /* Allocatable scalar.  */
-	  arg1se.want_pointer = 1;
-	  gfc_conv_expr (&arg1se, e);
-	  tmp = arg1se.expr;
-	}
-      else
-	{
-	  /* Allocatable array.  */
-	  arg1se.descriptor_only = 1;
-	  gfc_conv_expr_descriptor (&arg1se, e);
-	  tmp = gfc_conv_descriptor_data_get (arg1se.expr);
-	}
-
-      tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
-			     fold_convert (TREE_TYPE (tmp), null_pointer_node));
+      /* Allocatable array.  */
+      arg1se.descriptor_only = 1;
+      gfc_conv_expr_descriptor (&arg1se, e);
+      tmp = gfc_conv_descriptor_data_get (arg1se.expr);
     }

+  tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
+			 fold_convert (TREE_TYPE (tmp), null_pointer_node));
+
   /* Components of pointer array references sometimes come back with a pre block.  */
   if (arg1se.pre.head)
     gfc_add_block_to_block (&se->pre, &arg1se.pre);
@@ -11718,6 +11694,10 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
       gfc_conv_intrinsic_caf_get (se, expr, NULL_TREE, false, NULL);
       break;

+    case GFC_ISYM_CAF_IS_PRESENT_ON_REMOTE:
+      gfc_conv_intrinsic_caf_is_present_remote (se, expr);
+      break;
+
     case GFC_ISYM_CMPLX:
       gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
       break;
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 57e2794ddee..c0a621df55d 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -928,7 +928,7 @@ extern GTY(()) tree gfor_fndecl_co_max;
 extern GTY(()) tree gfor_fndecl_co_min;
 extern GTY(()) tree gfor_fndecl_co_reduce;
 extern GTY(()) tree gfor_fndecl_co_sum;
-extern GTY(()) tree gfor_fndecl_caf_is_present;
+extern GTY(()) tree gfor_fndecl_caf_is_present_on_remote;

 /* Math functions.  Many other math functions are handled in
    trans-intrinsic.cc.  */
diff --git a/gcc/testsuite/gfortran.dg/coarray/coarray_allocated.f90 b/gcc/testsuite/gfortran.dg/coarray/coarray_allocated.f90
index a423d1f126e..27db0e8d8ce 100644
--- a/gcc/testsuite/gfortran.dg/coarray/coarray_allocated.f90
+++ b/gcc/testsuite/gfortran.dg/coarray/coarray_allocated.f90
@@ -30,7 +30,7 @@ program p
   if (.not. allocated (a[1])) stop 7
   if (.not. allocated (c%x[1,2,3])) stop 8

-  ! Dellocate collectively
+  ! Deallocate collectively
   deallocate(a)
   deallocate(c%x)

@@ -40,16 +40,6 @@ program p
   if (allocated (c%x[1,2,3])) stop 12
 end

-! twice == 0 for .not. allocated' (coindexed vs. not)
-! four times != for allocated (before alloc after dealloc, coindexed and not)
-
-! There are also == 0 and != 0 for (de)allocate checks with -fcoarray=single but those
-! aren't prefixed by '(integer(kind=4) *)'
-
-! { dg-final { scan-tree-dump-times "\\(integer\\(kind=4\\) \\*\\) a.data != 0B" 4 "original" } }
-! { dg-final { scan-tree-dump-times "\\(integer\\(kind=4\\) \\*\\) c.x.data != 0B" 4 "original" } }
-! { dg-final { scan-tree-dump-times "\\(integer\\(kind=4\\) \\*\\) a.data == 0B" 2 "original" } }
-! { dg-final { scan-tree-dump-times "\\(integer\\(kind=4\\) \\*\\) c.x.data == 0B" 2 "original" } }
-
 ! Expected: always local access and never a call to _gfortran_caf_get
-! { dg-final { scan-tree-dump-not "caf_get" "original" } }
+! { dg-final { scan-tree-dump-not "caf_get " "original" } }
+! { dg-final { scan-tree-dump-not "caf_get_by_" "original" } }
diff --git a/gcc/testsuite/gfortran.dg/coarray_lib_alloc_4.f90 b/gcc/testsuite/gfortran.dg/coarray_lib_alloc_4.f90
index d695faa9eaf..e79ee442be8 100644
--- a/gcc/testsuite/gfortran.dg/coarray_lib_alloc_4.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_lib_alloc_4.f90
@@ -38,7 +38,7 @@ program test_caf_alloc
   deallocate(xx)
 end

-! { dg-final { scan-tree-dump-times "_gfortran_caf_is_present \\(xx\\.token, \\(integer\\(kind=4\\)\\) \\(2 - xx\\.dim\\\[0\\\]\\.lbound\\), &caf_ref\\.\[0-9\]+\\)|_gfortran_caf_is_present \\(xx\\.token, 2 - xx\\.dim\\\[0\\\]\\.lbound, &caf_ref\\.\[0-9\]+\\)" 10 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_is_present_on_remote" 10 "original" } }
 ! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(\[0-9\]+, 1, &xx\\.token, \\(void \\*\\) &xx, 0B, 0B, 0\\)" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(\[0-9\]+, 7" 2 "original" } }
 ! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(\[0-9\]+, 8" 2 "original" } }
diff --git a/libgfortran/caf/libcaf.h b/libgfortran/caf/libcaf.h
index 4f41f5dcb67..a29047d4b23 100644
--- a/libgfortran/caf/libcaf.h
+++ b/libgfortran/caf/libcaf.h
@@ -249,6 +249,9 @@ void _gfortran_caf_get_from_remote (
   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);

+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_atomic_define (caf_token_t, size_t, int, void *, int *,
 				  int, int);
@@ -272,8 +275,6 @@ void _gfortran_caf_stopped_images (gfc_descriptor_t *,
 				   caf_team_t * __attribute__ ((unused)),
 				   int *);

-int _gfortran_caf_is_present (caf_token_t, int, caf_reference_t *);
-
 void _gfortran_caf_random_init (bool, bool);

 #endif  /* LIBCAF_H  */
diff --git a/libgfortran/caf/single.c b/libgfortran/caf/single.c
index 573da1b85bf..66d3bf93e1d 100644
--- a/libgfortran/caf/single.c
+++ b/libgfortran/caf/single.c
@@ -60,6 +60,8 @@ 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 (*is_present_t) (void *, const int *, int32_t *, void *,
+			      caf_single_token_t, const size_t);
 struct accessor_hash_t
 {
   int hash;
@@ -67,6 +69,7 @@ struct accessor_hash_t
   union
   {
     accessor_t accessor;
+    is_present_t is_present;
   } u;
 };

@@ -2966,6 +2969,29 @@ _gfortran_caf_get_from_remote (
     }
 }

+int32_t
+_gfortran_caf_is_present_on_remote (caf_token_t token, const int image_index,
+				    const int present_index, void *add_data,
+				    const size_t add_data_size
+				    __attribute__ ((unused)))
+{
+  /* Unregistered tokens are always not present.  */
+  if (!token)
+    return 0;
+
+  caf_single_token_t single_token = TOKEN (token);
+  int32_t result;
+  struct caf_single_token cb_token = {add_data, NULL, false};
+
+
+  accessor_hash_table[present_index].u.is_present (add_data, &image_index,
+						   &result,
+						   single_token->memptr,
+						   &cb_token, 0);
+
+  return result;
+}
+
 void
 _gfortran_caf_atomic_define (caf_token_t token, size_t offset,
 			     int image_index __attribute__ ((unused)),
@@ -3174,106 +3200,6 @@ _gfortran_caf_unlock (caf_token_t token, size_t index,
   _gfortran_caf_error_stop_str (msg, strlen (msg), false);
 }

-int
-_gfortran_caf_is_present (caf_token_t token,
-			  int image_index __attribute__ ((unused)),
-			  caf_reference_t *refs)
-{
-  const char arraddressingnotallowed[] = "libcaf_single::caf_is_present(): "
-				   "only scalar indexes allowed.\n";
-  const char unknownreftype[] = "libcaf_single::caf_get_by_ref(): "
-				"unknown reference type.\n";
-  const char unknownarrreftype[] = "libcaf_single::caf_get_by_ref(): "
-				   "unknown array reference type.\n";
-  size_t i;
-  caf_single_token_t single_token = TOKEN (token);
-  void *memptr = single_token->memptr;
-  gfc_descriptor_t *src = single_token->desc;
-  caf_reference_t *riter = refs;
-
-  while (riter)
-    {
-      switch (riter->type)
-	{
-	case CAF_REF_COMPONENT:
-	  if (riter->u.c.caf_token_offset)
-	    {
-	      single_token = *(caf_single_token_t*)
-					 (memptr + riter->u.c.caf_token_offset);
-	      memptr = single_token->memptr;
-	      src = single_token->desc;
-	    }
-	  else
-	    {
-	      memptr += riter->u.c.offset;
-	      src = (gfc_descriptor_t *)memptr;
-	    }
-	  break;
-	case CAF_REF_ARRAY:
-	  for (i = 0; riter->u.a.mode[i] != CAF_ARR_REF_NONE; ++i)
-	    {
-	      switch (riter->u.a.mode[i])
-		{
-		case CAF_ARR_REF_SINGLE:
-		  memptr += (riter->u.a.dim[i].s.start
-			     - GFC_DIMENSION_LBOUND (src->dim[i]))
-		      * GFC_DIMENSION_STRIDE (src->dim[i])
-		      * riter->item_size;
-		  break;
-		case CAF_ARR_REF_FULL:
-		  /* A full array ref is allowed on the last reference only.  */
-		  if (riter->next == NULL)
-		    break;
-		  /* else fall through reporting an error.  */
-		  /* FALLTHROUGH */
-		case CAF_ARR_REF_VECTOR:
-		case CAF_ARR_REF_RANGE:
-		case CAF_ARR_REF_OPEN_END:
-		case CAF_ARR_REF_OPEN_START:
-		  caf_internal_error (arraddressingnotallowed, 0, NULL, 0);
-		  return 0;
-		default:
-		  caf_internal_error (unknownarrreftype, 0, NULL, 0);
-		  return 0;
-		}
-	    }
-	  break;
-	case CAF_REF_STATIC_ARRAY:
-	  for (i = 0; riter->u.a.mode[i] != CAF_ARR_REF_NONE; ++i)
-	    {
-	      switch (riter->u.a.mode[i])
-		{
-		case CAF_ARR_REF_SINGLE:
-		  memptr += riter->u.a.dim[i].s.start
-		      * riter->u.a.dim[i].s.stride
-		      * riter->item_size;
-		  break;
-		case CAF_ARR_REF_FULL:
-		  /* A full array ref is allowed on the last reference only.  */
-		  if (riter->next == NULL)
-		    break;
-		  /* else fall through reporting an error.  */
-		  /* FALLTHROUGH */
-		case CAF_ARR_REF_VECTOR:
-		case CAF_ARR_REF_RANGE:
-		case CAF_ARR_REF_OPEN_END:
-		case CAF_ARR_REF_OPEN_START:
-		  caf_internal_error (arraddressingnotallowed, 0, NULL, 0);
-		  return 0;
-		default:
-		  caf_internal_error (unknownarrreftype, 0, NULL, 0);
-		  return 0;
-		}
-	    }
-	  break;
-	default:
-	  caf_internal_error (unknownreftype, 0, NULL, 0);
-	  return 0;
-	}
-      riter = riter->next;
-    }
-  return memptr != NULL;
-}

 /* Reference the libraries implementation.  */
 extern void _gfortran_random_init (int32_t, int32_t, int32_t);
--
2.48.1

Reply via email to