public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 0/4] [og8] Add support for Fortran optional arguments in OpenACC
@ 2019-01-30 22:19 Kwok Cheung Yeung
  2019-01-30 22:22 ` [PATCH 1/4] [og8] Allow NULL for update directives in OpenACC 2.6 Kwok Cheung Yeung
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Kwok Cheung Yeung @ 2019-01-30 22:19 UTC (permalink / raw)
  To: gcc-patches; +Cc: thomas, clm

This patch series adds support for the use of Fortran optional arguments 
in OpenACC constructs as specified by the OpenACC 2.6 standard.

I will shortly commit these to openacc-gcc-8-branch if there are no 
objections.

Kwok

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/4] [og8] Allow NULL for update directives in OpenACC 2.6
  2019-01-30 22:19 [PATCH 0/4] [og8] Add support for Fortran optional arguments in OpenACC Kwok Cheung Yeung
@ 2019-01-30 22:22 ` Kwok Cheung Yeung
  2019-01-31 17:17   ` Thomas Schwinge
  2019-01-30 22:24 ` [PATCH 2/4] [og8] Calculate correct size for optional arguments used in the firstprivate clause Kwok Cheung Yeung
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Kwok Cheung Yeung @ 2019-01-30 22:22 UTC (permalink / raw)
  To: gcc-patches; +Cc: thomas, clm

A non-present passed-by-reference Fortran optional argument is 
represented by a null pointer.  When passed to an update directive, it 
should be ignored as variable mappings are not created for null 
pointers.  This should be safe as it is not possible to change a 
non-present argument into a present one (or vice-versa) in Fortran.

	libgomp/
	* oacc-mem.c (update_dev_host): Return early if the host address
	is NULL.

Reviewed-by: Julian Brown <julian@codesourcery.com>
Reviewed-by: Thomas Schwinge <thomas@codesourcery.com>
---
  libgomp/ChangeLog.openacc | 5 +++++
  libgomp/oacc-mem.c        | 6 ++++++
  2 files changed, 11 insertions(+)

diff --git a/libgomp/ChangeLog.openacc b/libgomp/ChangeLog.openacc
index a9a30d2..69bd1ee 100644
--- a/libgomp/ChangeLog.openacc
+++ b/libgomp/ChangeLog.openacc
@@ -1,3 +1,8 @@
+2019-01-30  Kwok Cheung Yeung  <kcy@codesourcery.com>
+
+	* oacc-mem.c (update_dev_host): Return early if the host address
+	is NULL.
+
  2019-01-30  Andrew Jenner  <andrew@codesourcery.com>

  	* testsuite/libgomp.fortan/fortran.exp (lang_link_flags): Add
diff --git a/libgomp/oacc-mem.c b/libgomp/oacc-mem.c
index 9b70820..74d7ce9 100644
--- a/libgomp/oacc-mem.c
+++ b/libgomp/oacc-mem.c
@@ -819,6 +819,12 @@ update_dev_host (int is_dev, void *h, size_t s, int 
async)
    if (acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
      return;

+  /* Fortran optional arguments that are non-present result in a
+     null host address here.  This can safely be ignored as it is
+     not possible to 'update' a non-present optional argument.  */
+  if (h == NULL)
+    return;
+
    gomp_mutex_lock (&acc_dev->lock);

    acc_prof_info prof_info;
-- 
2.8.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 2/4] [og8] Calculate correct size for optional arguments used in the firstprivate clause
  2019-01-30 22:19 [PATCH 0/4] [og8] Add support for Fortran optional arguments in OpenACC Kwok Cheung Yeung
  2019-01-30 22:22 ` [PATCH 1/4] [og8] Allow NULL for update directives in OpenACC 2.6 Kwok Cheung Yeung
@ 2019-01-30 22:24 ` Kwok Cheung Yeung
  2019-01-30 22:25 ` [PATCH 3/4] [og8] Add support for allocatable arrays as optional arguments Kwok Cheung Yeung
  2019-01-30 22:37 ` [PATCH 4/4] [og8] Add tests for Fortran optional arguments in OpenACC 2.6 Kwok Cheung Yeung
  3 siblings, 0 replies; 8+ messages in thread
From: Kwok Cheung Yeung @ 2019-01-30 22:24 UTC (permalink / raw)
  To: gcc-patches; +Cc: thomas, clm

The lowering for firstprivate uses the pointer size rather than the size
of the referenced object when passed an optional argument.  This patch
detects optional arguments as a special case and treats them as 
reference types.

	gcc/
	* omp-general.c (omp_is_optional_argument): New.
	* omp-general.h (omp_is_optional_argument): New.
	* omp-low.c (lower_omp_target): Use size of referenced object when
	optional argument used as argument to firstprivate.
---
  gcc/ChangeLog.openacc | 7 +++++++
  gcc/omp-general.c     | 9 +++++++++
  gcc/omp-general.h     | 1 +
  gcc/omp-low.c         | 3 ++-
  4 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/gcc/ChangeLog.openacc b/gcc/ChangeLog.openacc
index 744cf02..04d18c0 100644
--- a/gcc/ChangeLog.openacc
+++ b/gcc/ChangeLog.openacc
@@ -1,3 +1,10 @@
+2019-01-30  Kwok Cheung Yeung  <kcy@codesourcery.com>
+
+	* omp-general.c (omp_is_optional_argument): New.
+	* omp-general.h (omp_is_optional_argument): New.
+	* omp-low.c (lower_omp_target): Use size of referenced object when
+	optional argument used as argument to firstprivate.
+
  2019-01-30  Thomas Schwinge  <thomas@codesourcery.com>

  	* doc/invoke.texi (C Language Options): List "-fopenacc-dim".
diff --git a/gcc/omp-general.c b/gcc/omp-general.c
index 1897f00..dd37c46 100644
--- a/gcc/omp-general.c
+++ b/gcc/omp-general.c
@@ -46,6 +46,15 @@ omp_find_clause (tree clauses, enum omp_clause_code kind)
    return NULL_TREE;
  }

+/* Return true if DECL is a Fortran optional argument.  */
+
+bool
+omp_is_optional_argument (tree decl)
+{
+  return TREE_CODE (decl) == PARM_DECL && DECL_BY_REFERENCE (decl)
+	 && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE;
+}
+
  /* Return true if DECL is a reference type.  */

  bool
diff --git a/gcc/omp-general.h b/gcc/omp-general.h
index b704427..c5e7446 100644
--- a/gcc/omp-general.h
+++ b/gcc/omp-general.h
@@ -72,6 +72,7 @@ struct omp_for_data
  #define OACC_FN_ATTRIB "oacc function"

  extern tree omp_find_clause (tree clauses, enum omp_clause_code kind);
+extern bool omp_is_optional_argument (tree decl);
  extern bool omp_is_reference (tree decl);
  extern void omp_adjust_for_condition (location_t loc, enum tree_code 
*cond_code,
  				      tree *n2);
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index f48002e..ef71704 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -8749,7 +8749,8 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, 
omp_context *ctx)
  		else
  		  {
  		    s = TREE_TYPE (ovar);
-		    if (TREE_CODE (s) == REFERENCE_TYPE)
+		    if (TREE_CODE (s) == REFERENCE_TYPE
+			|| omp_is_optional_argument (ovar))
  		      s = TREE_TYPE (s);
  		    s = TYPE_SIZE_UNIT (s);
  		  }
-- 
2.8.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 3/4] [og8] Add support for allocatable arrays as optional arguments
  2019-01-30 22:19 [PATCH 0/4] [og8] Add support for Fortran optional arguments in OpenACC Kwok Cheung Yeung
  2019-01-30 22:22 ` [PATCH 1/4] [og8] Allow NULL for update directives in OpenACC 2.6 Kwok Cheung Yeung
  2019-01-30 22:24 ` [PATCH 2/4] [og8] Calculate correct size for optional arguments used in the firstprivate clause Kwok Cheung Yeung
@ 2019-01-30 22:25 ` Kwok Cheung Yeung
  2019-01-30 22:37 ` [PATCH 4/4] [og8] Add tests for Fortran optional arguments in OpenACC 2.6 Kwok Cheung Yeung
  3 siblings, 0 replies; 8+ messages in thread
From: Kwok Cheung Yeung @ 2019-01-30 22:25 UTC (permalink / raw)
  To: gcc-patches; +Cc: thomas, clm

This patch allows allocatable arrays to be used as Fortran optional 
arguments.  When an optional argument is detected, the Fortran front-end 
now generates extra code to test if the argument is null. If so, it sets 
the size of the array contents to zero, and the pointers to data to 
null.  This prevents libgomp from trying to copy non-existant data, and 
preserves the null pointer used by PRESENT to detect non-present arguments.

	gcc/fortran/
	* trans-openmp.c (gfc_build_conditional_assign): New.
	(gfc_build_conditional_assign_expr): New.
	(gfc_omp_finish_clause): Add conditionals to set the clause
	declaration to null and size to zero if the declaration is a
	non-present optional argument.
	(gfc_trans_omp_clauses_1): Likewise.

Reviewed-by: Chung-Lin Tang <cltang@codesourcery.com>
---
  gcc/fortran/ChangeLog.openacc |   9 +++
  gcc/fortran/trans-openmp.c    | 164 
+++++++++++++++++++++++++++++++++++-------
  2 files changed, 147 insertions(+), 26 deletions(-)

diff --git a/gcc/fortran/ChangeLog.openacc b/gcc/fortran/ChangeLog.openacc
index 05462a0..dba098b 100644
--- a/gcc/fortran/ChangeLog.openacc
+++ b/gcc/fortran/ChangeLog.openacc
@@ -1,3 +1,12 @@
+2019-01-30  Kwok Cheung Yeung  <kcy@codesourcery.com>
+
+	* trans-openmp.c (gfc_build_conditional_assign): New.
+	(gfc_build_conditional_assign_expr): New.
+	(gfc_omp_finish_clause): Add conditionals to set the clause
+	declaration to null and size to zero if the declaration is a
+	non-present optional argument.
+	(gfc_trans_omp_clauses_1): Likewise.
+
  2019-01-29  Gergö Barany  <gergo@codesourcery.com>

  	* trans-openmp.c (gfc_privatize_nodesc_array_clauses): Renamed from
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 5a444c3..6b20271 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -1042,6 +1042,62 @@ gfc_omp_clause_dtor (tree clause, tree decl)
    return tem;
  }

+/* Build a conditional expression in BLOCK.  If COND_VAL is not
+   null, then the block THEN_B is executed, otherwise ELSE_VAL
+   is assigned to VAL.  */
+
+static void
+gfc_build_conditional_assign (stmtblock_t *block,
+			      tree val,
+			      tree cond_val,
+			      tree then_b,
+			      tree else_val)
+{
+  stmtblock_t cond_block;
+  tree cond, else_b;
+  tree val_ty = TREE_TYPE (val);
+
+  gfc_init_block (&cond_block);
+  gfc_add_modify (&cond_block, val, fold_convert (val_ty, else_val));
+  else_b = gfc_finish_block (&cond_block);
+  cond = fold_convert (pvoid_type_node, cond_val);
+  cond = fold_build2_loc (input_location, NE_EXPR,
+			  logical_type_node,
+			  cond, null_pointer_node);
+  gfc_add_expr_to_block (block,
+			 build3_loc (input_location,
+				     COND_EXPR,
+				     void_type_node,
+				     cond, then_b,
+				     else_b));
+}
+
+/* Build a conditional expression in BLOCK, returning a temporary
+   variable containing the result.  If COND_VAL is not null, then
+   THEN_VAL will be assigned to the variable, otherwise ELSE_VAL
+   is assigned.
+ */
+
+static tree
+gfc_build_conditional_assign_expr (stmtblock_t *block,
+				   tree cond_val,
+				   tree then_val,
+				   tree else_val)
+{
+  tree val;
+  tree val_ty = TREE_TYPE (then_val);
+  stmtblock_t cond_block;
+
+  val = create_tmp_var (val_ty);
+
+  gfc_init_block (&cond_block);
+  gfc_add_modify (&cond_block, val, then_val);
+  tree then_b = gfc_finish_block (&cond_block);
+
+  gfc_build_conditional_assign (block, val, cond_val, then_b, else_val);
+
+  return val;
+}

  void
  gfc_omp_finish_clause (tree c, gimple_seq *pre_p)
@@ -1107,16 +1163,45 @@ gfc_omp_finish_clause (tree c, gimple_seq *pre_p)
        stmtblock_t block;
        gfc_start_block (&block);
        tree type = TREE_TYPE (decl);
-      tree ptr = gfc_conv_descriptor_data_get (decl);
+      bool optional_arg_p =
+	      TREE_CODE (decl) == INDIRECT_REF
+	      && TREE_CODE (TREE_OPERAND (decl, 0)) == PARM_DECL
+	      && DECL_BY_REFERENCE (TREE_OPERAND (decl, 0))
+	      && TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0))) == POINTER_TYPE;
+      tree ptr;
+
+      if (optional_arg_p)
+	ptr = gfc_build_conditional_assign_expr (
+		&block,
+		TREE_OPERAND (decl, 0),
+		gfc_conv_descriptor_data_get (decl),
+		null_pointer_node);
+      else
+	ptr = gfc_conv_descriptor_data_get (decl);
        ptr = build_fold_indirect_ref (ptr);
        OMP_CLAUSE_DECL (c) = ptr;
        c2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
        OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_TO_PSET);
-      OMP_CLAUSE_DECL (c2) = decl;
+      if (optional_arg_p)
+	{
+	  ptr = create_tmp_var (TREE_TYPE (TREE_OPERAND (decl, 0)));
+	  gfc_add_modify (&block, ptr, TREE_OPERAND (decl, 0));
+
+	  OMP_CLAUSE_DECL (c2) = build_fold_indirect_ref (ptr);
+	}
+      else
+	OMP_CLAUSE_DECL (c2) = decl;
        OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (type);
        c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
        OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_POINTER);
-      OMP_CLAUSE_DECL (c3) = gfc_conv_descriptor_data_get (decl);
+      if (optional_arg_p)
+	OMP_CLAUSE_DECL (c3) = gfc_build_conditional_assign_expr (
+		&block,
+		TREE_OPERAND (decl, 0),
+		gfc_conv_descriptor_data_get (decl),
+		null_pointer_node);
+      else
+	OMP_CLAUSE_DECL (c3) = gfc_conv_descriptor_data_get (decl);
        OMP_CLAUSE_SIZE (c3) = size_int (0);
        tree size = create_tmp_var (gfc_array_index_type);
        tree elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
@@ -1147,6 +1232,27 @@ gfc_omp_finish_clause (tree c, gimple_seq *pre_p)
  						     void_type_node, cond,
  						     then_b, else_b));
  	}
+      else if (optional_arg_p)
+	{
+	  stmtblock_t cond_block;
+	  tree then_b;
+
+	  gfc_init_block (&cond_block);
+	  gfc_add_modify (&cond_block, size,
+			  gfc_full_array_size (&cond_block, decl,
+					       GFC_TYPE_ARRAY_RANK (type)));
+	  gfc_add_modify (&cond_block, size,
+			  fold_build2 (MULT_EXPR, gfc_array_index_type,
+				       size, elemsz));
+	  then_b = gfc_finish_block (&cond_block);
+
+	  gfc_build_conditional_assign (
+		  &block,
+		  size,
+		  TREE_OPERAND (decl, 0),
+		  then_b,
+		  build_int_cst (gfc_array_index_type, 0));
+	}
        else
  	{
  	  gfc_add_modify (&block, size,
@@ -2197,7 +2303,17 @@ gfc_trans_omp_clauses_1 (stmtblock_t *block, 
gfc_omp_clauses *clauses,
  		      && n->u.map_op != OMP_MAP_DETACH)
  		    {
  		      tree type = TREE_TYPE (decl);
-		      tree ptr = gfc_conv_descriptor_data_get (decl);
+		      tree ptr;
+
+		      if (sym_attr->optional)
+			ptr = gfc_build_conditional_assign_expr (
+				block,
+				TREE_OPERAND (decl, 0),
+				gfc_conv_descriptor_data_get (decl),
+				null_pointer_node);
+		      else
+			ptr = gfc_conv_descriptor_data_get (decl);
+
  		      ptr = build_fold_indirect_ref (ptr);
  		      OMP_CLAUSE_DECL (node) = ptr;
  		      node2 = build_omp_clause (input_location,
@@ -2216,34 +2332,30 @@ gfc_trans_omp_clauses_1 (stmtblock_t *block, 
gfc_omp_clauses *clauses,

  		      /* We have to check for n->sym->attr.dimension because
  			 of scalar coarrays.  */
-		      if (sym_attr->pointer && sym_attr->dimension)
+		      if ((sym_attr->pointer || sym_attr->optional)
+			  && sym_attr->dimension)
  			{
  			  stmtblock_t cond_block;
  			  tree size
  			    = gfc_create_var (gfc_array_index_type, NULL);
-			  tree tem, then_b, else_b, zero, cond;
+			  tree cond = sym_attr->optional
+			      ? TREE_OPERAND (decl, 0)
+			      : gfc_conv_descriptor_data_get (decl);

  			  gfc_init_block (&cond_block);
-			  tem
-			    = gfc_full_array_size (&cond_block, decl,
-						   GFC_TYPE_ARRAY_RANK (type));
-			  gfc_add_modify (&cond_block, size, tem);
-			  then_b = gfc_finish_block (&cond_block);
-			  gfc_init_block (&cond_block);
-			  zero = build_int_cst (gfc_array_index_type, 0);
-			  gfc_add_modify (&cond_block, size, zero);
-			  else_b = gfc_finish_block (&cond_block);
-			  tem = gfc_conv_descriptor_data_get (decl);
-			  tem = fold_convert (pvoid_type_node, tem);
-			  cond = fold_build2_loc (input_location, NE_EXPR,
-						  logical_type_node,
-						  tem, null_pointer_node);
-			  gfc_add_expr_to_block (block,
-						 build3_loc (input_location,
-							     COND_EXPR,
-							     void_type_node,
-							     cond, then_b,
-							     else_b));
+			  gfc_add_modify (&cond_block, size,
+					  gfc_full_array_size (
+					      &cond_block, decl,
+					      GFC_TYPE_ARRAY_RANK (type)));
+			  tree then_b = gfc_finish_block (&cond_block);
+
+			  gfc_build_conditional_assign (
+				  block,
+				  size,
+				  cond,
+				  then_b,
+				  build_int_cst (gfc_array_index_type, 0));
+
  			  OMP_CLAUSE_SIZE (node) = size;
  			}
  		      else if (sym_attr->dimension)
-- 
2.8.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 4/4] [og8] Add tests for Fortran optional arguments in OpenACC 2.6
  2019-01-30 22:19 [PATCH 0/4] [og8] Add support for Fortran optional arguments in OpenACC Kwok Cheung Yeung
                   ` (2 preceding siblings ...)
  2019-01-30 22:25 ` [PATCH 3/4] [og8] Add support for allocatable arrays as optional arguments Kwok Cheung Yeung
@ 2019-01-30 22:37 ` Kwok Cheung Yeung
  2019-01-31 17:23   ` Thomas Schwinge
  3 siblings, 1 reply; 8+ messages in thread
From: Kwok Cheung Yeung @ 2019-01-30 22:37 UTC (permalink / raw)
  To: gcc-patches; +Cc: thomas, clm

	libgomp/
	* testsuite/libgomp.oacc-fortran/optional-cache.f95
	* testsuite/libgomp.oacc-fortran/optional-data-copyin-by-value.f90
	* testsuite/libgomp.oacc-fortran/optional-data-copyin.f90
	* testsuite/libgomp.oacc-fortran/optional-data-copyout.f90
	* testsuite/libgomp.oacc-fortran/optional-data-enter-exit.f90
	* testsuite/libgomp.oacc-fortran/optional-declare.f90
	* testsuite/libgomp.oacc-fortran/optional-firstprivate.f90
	* testsuite/libgomp.oacc-fortran/optional-host_data.f90
	* testsuite/libgomp.oacc-fortran/optional-nested-calls.f90
	* testsuite/libgomp.oacc-fortran/optional-private.f90
	* testsuite/libgomp.oacc-fortran/optional-reduction.f90
	* testsuite/libgomp.oacc-fortran/optional-update-device.f90
	* testsuite/libgomp.oacc-fortran/optional-update-host.f90

Reviewed-by: Julian Brown <julian@codesourcery.com>
Reviewed-by: Thomas Schwinge <thomas@codesourcery.com>
---
  libgomp/ChangeLog.openacc                          |  16 +++
  .../libgomp.oacc-fortran/optional-cache.f95        |  23 ++++
  .../optional-data-copyin-by-value.f90              |  29 +++++
  .../libgomp.oacc-fortran/optional-data-copyin.f90  | 140 
+++++++++++++++++++++
  .../libgomp.oacc-fortran/optional-data-copyout.f90 |  96 ++++++++++++++
  .../optional-data-enter-exit.f90                   |  91 ++++++++++++++
  .../libgomp.oacc-fortran/optional-declare.f90      |  87 +++++++++++++
  .../libgomp.oacc-fortran/optional-firstprivate.f90 | 112 +++++++++++++++++
  .../libgomp.oacc-fortran/optional-host_data.f90    |  37 ++++++
  .../libgomp.oacc-fortran/optional-nested-calls.f90 | 135 
++++++++++++++++++++
  .../libgomp.oacc-fortran/optional-private.f90      | 118 +++++++++++++++++
  .../libgomp.oacc-fortran/optional-reduction.f90    |  69 ++++++++++
  .../optional-update-device.f90                     | 121 
++++++++++++++++++
  .../libgomp.oacc-fortran/optional-update-host.f90  | 115 +++++++++++++++++
  14 files changed, 1189 insertions(+)
  create mode 100644 
libgomp/testsuite/libgomp.oacc-fortran/optional-cache.f95
  create mode 100644 
libgomp/testsuite/libgomp.oacc-fortran/optional-data-copyin-by-value.f90
  create mode 100644 
libgomp/testsuite/libgomp.oacc-fortran/optional-data-copyin.f90
  create mode 100644 
libgomp/testsuite/libgomp.oacc-fortran/optional-data-copyout.f90
  create mode 100644 
libgomp/testsuite/libgomp.oacc-fortran/optional-data-enter-exit.f90
  create mode 100644 
libgomp/testsuite/libgomp.oacc-fortran/optional-declare.f90
  create mode 100644 
libgomp/testsuite/libgomp.oacc-fortran/optional-firstprivate.f90
  create mode 100644 
libgomp/testsuite/libgomp.oacc-fortran/optional-host_data.f90
  create mode 100644 
libgomp/testsuite/libgomp.oacc-fortran/optional-nested-calls.f90
  create mode 100644 
libgomp/testsuite/libgomp.oacc-fortran/optional-private.f90
  create mode 100644 
libgomp/testsuite/libgomp.oacc-fortran/optional-reduction.f90
  create mode 100644 
libgomp/testsuite/libgomp.oacc-fortran/optional-update-device.f90
  create mode 100644 
libgomp/testsuite/libgomp.oacc-fortran/optional-update-host.f90

diff --git a/libgomp/ChangeLog.openacc b/libgomp/ChangeLog.openacc
index 69bd1ee..421e0c0 100644
--- a/libgomp/ChangeLog.openacc
+++ b/libgomp/ChangeLog.openacc
@@ -1,5 +1,21 @@
  2019-01-30  Kwok Cheung Yeung  <kcy@codesourcery.com>

+	* testsuite/libgomp.oacc-fortran/optional-cache.f95
+	* testsuite/libgomp.oacc-fortran/optional-data-copyin-by-value.f90
+	* testsuite/libgomp.oacc-fortran/optional-data-copyin.f90
+	* testsuite/libgomp.oacc-fortran/optional-data-copyout.f90
+	* testsuite/libgomp.oacc-fortran/optional-data-enter-exit.f90
+	* testsuite/libgomp.oacc-fortran/optional-declare.f90
+	* testsuite/libgomp.oacc-fortran/optional-firstprivate.f90
+	* testsuite/libgomp.oacc-fortran/optional-host_data.f90
+	* testsuite/libgomp.oacc-fortran/optional-nested-calls.f90
+	* testsuite/libgomp.oacc-fortran/optional-private.f90
+	* testsuite/libgomp.oacc-fortran/optional-reduction.f90
+	* testsuite/libgomp.oacc-fortran/optional-update-device.f90
+	* testsuite/libgomp.oacc-fortran/optional-update-host.f90
+
+2019-01-30  Kwok Cheung Yeung  <kcy@codesourcery.com>
+
  	* oacc-mem.c (update_dev_host): Return early if the host address
  	is NULL.

diff --git a/libgomp/testsuite/libgomp.oacc-fortran/optional-cache.f95 
b/libgomp/testsuite/libgomp.oacc-fortran/optional-cache.f95
new file mode 100644
index 0000000..d828497
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/optional-cache.f95
@@ -0,0 +1,23 @@
+! Test that the cache directives work with optional arguments.  The effect
+! of giving a non-present argument to the cache directive is not tested as
+! it is undefined.  The test is based on gfortran.dg/goacc/cache-1.f95.
+
+! { dg-additional-options "-std=f2008" }
+
+program cache_test
+  implicit none
+  integer :: d(10), e(5,13)
+
+  call do_test(d, e)
+contains
+  subroutine do_test(d, e)
+    integer, optional :: d(10), e(5,13)
+    integer :: i
+    do concurrent (i=1:5)
+      !$acc cache (d(1:3))
+      !$acc cache (d(i:i+2))
+      !$acc cache (e(1:3,2:4))
+      !$acc cache (e(i:i+2,i+1:i+3))
+    enddo
+  end
+end
diff --git 
a/libgomp/testsuite/libgomp.oacc-fortran/optional-data-copyin-by-value.f90 
b/libgomp/testsuite/libgomp.oacc-fortran/optional-data-copyin-by-value.f90
new file mode 100644
index 0000000..5cadeed
--- /dev/null
+++ 
b/libgomp/testsuite/libgomp.oacc-fortran/optional-data-copyin-by-value.f90
@@ -0,0 +1,29 @@
+! Test OpenACC data regions with optional arguments passed by value.
+
+! { dg-do run }
+
+program test
+  implicit none
+
+  integer :: res
+
+  if (foo(27) .ne. 27) stop 1
+  if (foo(16, 18) .ne. 288) stop 1
+contains
+  function foo(x, y)
+    integer, value :: x
+    integer, value, optional :: y
+    integer :: res, foo
+
+    !$acc data copyin(x, y) copyout(res)
+    !$acc parallel
+    res = x
+    if (present(y)) then
+      res = res * y
+    end if
+    !$acc end parallel
+    !$acc end data
+
+    foo = res
+  end function foo
+end program test
diff --git 
a/libgomp/testsuite/libgomp.oacc-fortran/optional-data-copyin.f90 
b/libgomp/testsuite/libgomp.oacc-fortran/optional-data-copyin.f90
new file mode 100644
index 0000000..a30908d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/optional-data-copyin.f90
@@ -0,0 +1,140 @@
+! Test OpenACC data regions with a copy-in of optional arguments.
+
+! { dg-do run }
+
+program test
+  implicit none
+
+  integer, parameter :: n = 64
+  integer :: i
+  integer :: a_int, b_int, c_int, res_int
+  integer :: a_arr(n), b_arr(n), c_arr(n), res_arr(n)
+  integer, allocatable :: a_alloc(:), b_alloc(:), c_alloc(:), res_alloc(:)
+
+  a_int = 7
+  b_int = 3
+  c_int = 11
+
+  call test_int(res_int, a_int)
+  if (res_int .ne. a_int) stop 1
+
+  call test_int(res_int, a_int, b_int)
+  if (res_int .ne. a_int * b_int) stop 2
+
+  call test_int(res_int, a_int, b_int, c_int)
+  if (res_int .ne. a_int * b_int + c_int) stop 3
+
+  do i = 1, n
+    a_arr(i) = i
+    b_arr(i) = n - i + 1
+    c_arr(i) = i * 3
+  end do
+
+  call test_array(res_arr, a_arr)
+  do i = 1, n
+    if (res_arr(i) .ne. a_arr(i)) stop 4
+  end do
+
+  call test_array(res_arr, a_arr, b_arr)
+  do i = 1, n
+    if (res_arr(i) .ne. a_arr(i) * b_arr(i)) stop 5
+  end do
+
+  call test_array(res_arr, a_arr, b_arr, c_arr)
+  do i = 1, n
+    if (res_arr(i) .ne. a_arr(i) * b_arr(i) + c_arr(i)) stop 6
+  end do
+
+  allocate (a_alloc(n))
+  allocate (b_alloc(n))
+  allocate (c_alloc(n))
+  allocate (res_alloc(n))
+
+  do i = 1, n
+    a_alloc(i) = i
+    b_alloc(i) = n - i + 1
+    c_alloc(i) = i * 3
+  end do
+
+  call test_allocatable(res_alloc, a_alloc)
+  do i = 1, n
+    if (res_alloc(i) .ne. a_alloc(i)) stop 7
+  end do
+
+  call test_allocatable(res_alloc, a_alloc, b_alloc)
+  do i = 1, n
+    if (res_alloc(i) .ne. a_alloc(i) * b_alloc(i)) stop 8
+  end do
+
+  call test_allocatable(res_alloc, a_alloc, b_alloc, c_alloc)
+  do i = 1, n
+    if (res_alloc(i) .ne. a_alloc(i) * b_alloc(i) + c_alloc(i)) stop 9
+  end do
+
+  deallocate (a_alloc)
+  deallocate (b_alloc)
+  deallocate (c_alloc)
+  deallocate (res_alloc)
+contains
+  subroutine test_int(res, a, b, c)
+    integer :: res
+    integer :: a
+    integer, optional :: b, c
+
+    !$acc data copyin(a, b, c) copyout(res)
+    !$acc parallel
+    res = a
+
+    if (present(b)) res = res * b
+
+    if (present(c)) res = res + c
+    !$acc end parallel
+    !$acc end data
+  end subroutine test_int
+
+  subroutine test_array(res, a, b, c)
+    integer :: res(n)
+    integer :: a(n)
+    integer, optional :: b(n), c(n)
+
+    !$acc data copyin(a, b, c) copyout(res)
+    !$acc parallel loop
+    do i = 1, n
+      res(i) = a(i)
+    end do
+
+    !$acc parallel loop
+    do i = 1, n
+      if (present(b)) res(i) = res(i) * b(i)
+    end do
+
+    !$acc parallel loop
+    do i = 1, n
+      if (present(c)) res(i) = res(i) + c(i)
+    end do
+    !$acc end data
+  end subroutine test_array
+
+  subroutine test_allocatable(res, a, b, c)
+    integer, allocatable :: res(:)
+    integer, allocatable  :: a(:)
+    integer, allocatable, optional :: b(:), c(:)
+
+    !$acc data copyin(a, b, c) copyout(res)
+    !$acc parallel loop
+    do i = 1, n
+      res(i) = a(i)
+    end do
+
+    !$acc parallel loop
+    do i = 1, n
+      if (present(b)) res(i) = res(i) * b(i)
+    end do
+
+    !$acc parallel loop
+    do i = 1, n
+      if (present(c)) res(i) = res(i) + c(i)
+    end do
+    !$acc end data
+  end subroutine test_allocatable
+end program test
diff --git 
a/libgomp/testsuite/libgomp.oacc-fortran/optional-data-copyout.f90 
b/libgomp/testsuite/libgomp.oacc-fortran/optional-data-copyout.f90
new file mode 100644
index 0000000..feaa31f
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/optional-data-copyout.f90
@@ -0,0 +1,96 @@
+! Test OpenACC data regions with a copy-out of optional arguments.
+
+! { dg-do run }
+
+program test
+  implicit none
+
+  integer, parameter :: n = 64
+  integer :: i
+  integer :: a_int, b_int, res_int
+  integer :: a_arr(n), b_arr(n), res_arr(n)
+  integer, allocatable :: a_alloc(:), b_alloc(:), res_alloc(:)
+
+  res_int = 0
+
+  call test_int(a_int, b_int)
+  if (res_int .ne. 0) stop 1
+
+  call test_int(a_int, b_int, res_int)
+  if (res_int .ne. a_int * b_int) stop 2
+
+  res_arr(:) = 0
+  do i = 1, n
+    a_arr(i) = i
+    b_arr(i) = n - i + 1
+  end do
+
+  call test_array(a_arr, b_arr)
+  do i = 1, n
+    if (res_arr(i) .ne. 0) stop 3
+  end do
+
+  call test_array(a_arr, b_arr, res_arr)
+  do i = 1, n
+    if (res_arr(i) .ne. a_arr(i) * b_arr(i)) stop 4
+  end do
+
+  allocate (a_alloc(n))
+  allocate (b_alloc(n))
+  allocate (res_alloc(n))
+
+  res_alloc(:) = 0
+  do i = 1, n
+    a_alloc(i) = i
+    b_alloc(i) = n - i + 1
+  end do
+
+  call test_allocatable(a_alloc, b_alloc)
+  do i = 1, n
+    if (res_alloc(i) .ne. 0) stop 5
+  end do
+
+  call test_allocatable(a_alloc, b_alloc, res_alloc)
+  do i = 1, n
+    if (res_alloc(i) .ne. a_alloc(i) * b_alloc(i)) stop 6
+  end do
+
+  deallocate (a_alloc)
+  deallocate (b_alloc)
+  deallocate (res_alloc)
+contains
+  subroutine test_int(a, b, res)
+    integer :: a, b
+    integer, optional :: res
+
+    !$acc data copyin(a, b) copyout(res)
+    !$acc parallel
+    if (present(res)) res = a * b
+    !$acc end parallel
+    !$acc end data
+  end subroutine test_int
+
+  subroutine test_array(a, b, res)
+    integer :: a(n), b(n)
+    integer, optional :: res(n)
+
+    !$acc data copyin(a, b) copyout(res)
+    !$acc parallel loop
+    do i = 1, n
+      if (present(res)) res(i) = a(i) * b(i)
+    end do
+    !$acc end data
+  end subroutine test_array
+
+  subroutine test_allocatable(a, b, res)
+    integer, allocatable :: a(:), b(:)
+    integer, allocatable, optional :: res(:)
+
+    !$acc data copyin(a, b) copyout(res)
+    !$acc parallel loop
+    do i = 1, n
+      if (present(res)) res(i) = a(i) * b(i)
+    end do
+    !$acc end data
+  end subroutine test_allocatable
+end program test
diff --git 
a/libgomp/testsuite/libgomp.oacc-fortran/optional-data-enter-exit.f90 
b/libgomp/testsuite/libgomp.oacc-fortran/optional-data-enter-exit.f90
new file mode 100644
index 0000000..9ed0f75
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/optional-data-enter-exit.f90
@@ -0,0 +1,91 @@
+! Test OpenACC unstructured enter data/exit data regions with optional
+! arguments.
+
+! { dg-do run }
+
+program test
+  implicit none
+
+  integer, parameter :: n = 64
+  integer :: a(n), b(n), c(n), res(n)
+  integer :: x, y, z, r, i
+
+  do i = 1, n
+    a(i) = i
+    b(i) = n - i + 1
+    c(i) = i * 3
+  end do
+
+  res = test_array(a)
+  do i = 1, n
+    if (res(i) .ne. a(i)) stop 1
+  end do
+
+  res = test_array(a, b)
+  do i = 1, n
+    if (res(i) .ne. a(i) * b(i)) stop 2
+  end do
+
+  res = test_array(a, b, c)
+  do i = 1, n
+    if (res(i) .ne. a(i) * b(i) + c(i)) stop 3
+  end do
+
+  x = 7
+  y = 3
+  z = 11
+
+  r = test_int(x)
+  if (r .ne. x) stop 4
+
+  r = test_int(x, y)
+  if (r .ne. x * y) stop 5
+
+  r = test_int(x, y, z)
+  if (r .ne. x * y + z) stop 6
+contains
+  function test_array(a, b, c)
+    integer :: a(n)
+    integer, optional :: b(n), c(n)
+    integer :: test_array(n), res(n)
+
+    !$acc enter data copyin(a, b, c) create(res)
+    !$acc parallel loop
+    do i = 1, n
+      res(i) = a(i)
+    end do
+
+    !$acc parallel loop
+    do i = 1, n
+      if (present(b)) then
+        res(i) = res(i) * b(i)
+      end if
+    end do
+
+    !$acc parallel loop
+    do i = 1, n
+      if (present(c)) then
+        res(i) = res(i) + c(i)
+      end if
+    end do
+    !$acc exit data copyout(res) delete(a, b, c)
+
+    test_array = res
+  end function test_array
+
+  function test_int(a, b, c)
+    integer :: a
+    integer, optional :: b, c
+    integer :: test_int, res
+
+    !$acc enter data copyin(a, b, c) create(res)
+    !$acc parallel present(a, b, c, res)
+    res = a
+    if (present(b)) res = res * b
+    if (present(c)) res = res + c
+    !$acc end parallel
+    !$acc exit data copyout(res) delete(a, b, c)
+
+    test_int = res
+  end function test_int
+end program test
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/optional-declare.f90 
b/libgomp/testsuite/libgomp.oacc-fortran/optional-declare.f90
new file mode 100644
index 0000000..074e5a2
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/optional-declare.f90
@@ -0,0 +1,87 @@
+! Test OpenACC declare directives with optional arguments.
+
+! { dg-do run }
+
+program test
+  implicit none
+
+  integer, parameter :: n = 64
+  integer :: i
+  integer :: a_int, b_int, c_int, res_int
+  integer :: a_arr(n), b_arr(n), c_arr(n), res_arr(n)
+
+  a_int = 7
+  b_int = 3
+  c_int = 11
+
+  call test_int(res_int, a_int)
+  if (res_int .ne. a_int) stop 1
+
+  call test_int(res_int, a_int, b_int)
+  if (res_int .ne. a_int * b_int) stop 2
+
+  call test_int(res_int, a_int, b_int, c_int)
+  if (res_int .ne. a_int * b_int + c_int) stop 3
+
+  do i = 1, n
+    a_arr(i) = i
+    b_arr(i) = n - i + 1
+    c_arr(i) = i * 3
+  end do
+
+  call test_array(res_arr, a_arr)
+  do i = 1, n
+    if (res_arr(i) .ne. a_arr(i)) stop 4
+  end do
+
+  call test_array(res_arr, a_arr, b_arr)
+  do i = 1, n
+    if (res_arr(i) .ne. a_arr(i) * b_arr(i)) stop 5
+  end do
+
+  call test_array(res_arr, a_arr, b_arr, c_arr)
+  do i = 1, n
+    if (res_arr(i) .ne. a_arr(i) * b_arr(i) + c_arr(i)) stop 6
+  end do
+contains
+  subroutine test_int(res, a, b, c)
+    integer :: a
+    integer, optional :: b, c
+    !$acc declare present_or_copyin(a, b, c)
+    integer :: res
+    !$acc declare present_or_copyout(res)
+
+    !$acc parallel
+    res = a
+    if (present(b)) res = res * b
+    if (present(c)) res = res + c
+    !$acc end parallel
+  end subroutine test_int
+
+  subroutine test_array(res, a, b, c)
+    integer :: a(n)
+    integer, optional :: b(n), c(n)
+    !$acc declare present_or_copyin(a, b, c)
+    integer :: res(n)
+    !$acc declare present_or_copyout(res)
+
+    !$acc parallel loop
+    do i = 1, n
+      res(i) = a(i)
+    end do
+
+    !$acc parallel loop
+    do i = 1, n
+      if (present(b)) then
+        res(i) = res(i) * b(i)
+      end if
+    end do
+
+    !$acc parallel loop
+    do i = 1, n
+      if (present(c)) then
+        res(i) = res(i) + c(i)
+      end if
+    end do
+  end subroutine test_array
+end program test
diff --git 
a/libgomp/testsuite/libgomp.oacc-fortran/optional-firstprivate.f90 
b/libgomp/testsuite/libgomp.oacc-fortran/optional-firstprivate.f90
new file mode 100644
index 0000000..693e611
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/optional-firstprivate.f90
@@ -0,0 +1,112 @@
+! Test that optional arguments work in firstprivate clauses.  The effect of
+! non-present arguments in firstprivate clauses is undefined, and is not
+! tested for.
+
+! { dg-do run }
+
+program test_firstprivate
+  implicit none
+  integer, parameter :: n = 64
+
+  integer :: i, j
+  integer :: a_int, b_int, c_int, res_int
+  integer :: a_arr(n), b_arr(n), c_arr(n), res_arr(n)
+  integer, allocatable :: a_alloc(:), b_alloc(:), c_alloc(:), res_alloc(:)
+
+  a_int = 14
+  b_int = 5
+  c_int = 12
+
+  call test_int(res_int, a_int, b_int, c_int)
+  if (res_int .ne. a_int * b_int + c_int) stop 1
+
+  do i = 1, n
+    a_arr(i) = i
+    b_arr(i) = n - i + 1
+    c_arr(i) = i * 3
+  end do
+
+  call test_array(res_arr, a_arr, b_arr, c_arr)
+  do i = 1, n
+    if (res_arr(i) .ne. a_arr(i) * b_arr(i) + c_arr(i)) stop 2
+  end do
+
+  allocate(a_alloc(n))
+  allocate(b_alloc(n))
+  allocate(c_alloc(n))
+  allocate(res_alloc(n))
+
+  do i = 1, n
+    a_arr(i) = i
+    b_arr(i) = n - i + 1
+    c_arr(i) = i * 3
+  end do
+
+  call test_allocatable(res_alloc, a_alloc, b_alloc, c_alloc)
+  do i = 1, n
+    if (res_alloc(i) .ne. a_alloc(i) * b_alloc(i) + c_alloc(i)) stop 2
+  end do
+
+  deallocate(a_alloc)
+  deallocate(b_alloc)
+  deallocate(c_alloc)
+  deallocate(res_alloc)
+contains
+  subroutine test_int(res, a, b, c)
+    integer :: a
+    integer, optional :: b, c
+    integer :: res
+
+    !$acc parallel firstprivate(a, b, c) copyout(res)
+    res = a
+    if (present(b)) res = res * b
+    if (present(c)) res = res + c
+    !$acc end parallel
+  end subroutine test_int
+
+  subroutine test_array(res, a, b, c)
+    integer :: a(n)
+    integer, optional :: b(n), c(n)
+    integer :: res(n)
+
+    !$acc data copyin(a, b, c) copyout(res)
+    !$acc parallel loop firstprivate(a)
+    do i = 1, n
+      res(i) = a(i)
+    end do
+
+    !$acc parallel loop firstprivate(b)
+    do i = 1, n
+      if (present(b)) res(i) = res(i) * b(i)
+    end do
+
+    !$acc parallel loop firstprivate(c)
+    do i = 1, n
+      if (present(c)) res(i) = res(i) + c(i)
+    end do
+    !$acc end data
+  end subroutine test_array
+
+  subroutine test_allocatable(res, a, b, c)
+    integer, allocatable :: a(:)
+    integer, allocatable, optional :: b(:), c(:)
+    integer, allocatable :: res(:)
+
+    !$acc data copyin(a, b, c) copyout(res)
+    !$acc parallel loop firstprivate(a)
+    do i = 1, n
+      res(i) = a(i)
+    end do
+
+    !$acc parallel loop firstprivate(b)
+    do i = 1, n
+      if (present(b)) res(i) = res(i) * b(i)
+    end do
+
+    !$acc parallel loop firstprivate(c)
+    do i = 1, n
+      if (present(c)) res(i) = res(i) + c(i)
+    end do
+    !$acc end data
+  end subroutine test_allocatable
+end program test_firstprivate
diff --git 
a/libgomp/testsuite/libgomp.oacc-fortran/optional-host_data.f90 
b/libgomp/testsuite/libgomp.oacc-fortran/optional-host_data.f90
new file mode 100644
index 0000000..5c80f8c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/optional-host_data.f90
@@ -0,0 +1,37 @@
+! Test the host_data construct with optional arguments.
+! Based on host_data-1.f90.
+
+! { dg-do run }
+! { dg-additional-options "-cpp" }
+
+program test
+  implicit none
+
+  integer, target :: i
+  integer, pointer :: ip, iph
+
+  ! Assign the same targets
+  ip => i
+  iph => i
+
+  call foo(iph)
+  call foo(iph, ip)
+contains
+  subroutine foo(iph, ip)
+    integer, pointer :: iph
+    integer, pointer, optional :: ip
+
+    !$acc data copyin(i)
+    !$acc host_data use_device(ip)
+
+    ! Test how the pointers compare inside a host_data construct
+#if ACC_MEM_SHARED
+    if (present(ip) .and. .not. associated(ip, iph)) STOP 1
+#else
+    if (present(ip) .and. associated(ip, iph)) STOP 2
+#endif
+
+    !$acc end host_data
+    !$acc end data
+  end subroutine foo
+end program test
diff --git 
a/libgomp/testsuite/libgomp.oacc-fortran/optional-nested-calls.f90 
b/libgomp/testsuite/libgomp.oacc-fortran/optional-nested-calls.f90
new file mode 100644
index 0000000..279139f
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/optional-nested-calls.f90
@@ -0,0 +1,135 @@
+! Test propagation of optional arguments from within an OpenACC 
parallel region.
+
+! { dg-do run }
+
+program test
+  implicit none
+
+  integer, parameter :: n = 64
+  integer :: i
+  integer :: res_int
+  integer :: a_arr(n), b_arr(n), res_arr(n)
+  integer, allocatable :: a_alloc(:), b_alloc(:), res_alloc(:)
+
+  call test_int_caller(res_int, 5)
+  if (res_int .ne. 10) stop 1
+
+  call test_int_caller(res_int, 2, 3)
+  if (res_int .ne. 11) stop 2
+
+  do i = 1, n
+    a_arr(i) = i
+    b_arr(i) = n - i + 1
+  end do
+
+  call test_array_caller(res_arr, a_arr)
+  do i = 1, n
+    if (res_arr(i) .ne. 2 * a_arr(i)) stop 3
+  end do
+
+  call test_array_caller(res_arr, a_arr, b_arr)
+  do i = 1, n
+    if (res_arr(i) .ne. a_arr(i) * b_arr(i) + a_arr(i) + b_arr(i)) stop 4
+  end do
+
+  allocate(a_alloc(n))
+  allocate(b_alloc(n))
+  allocate(res_alloc(n))
+
+  do i = 1, n
+    a_alloc(i) = i
+    b_alloc(i) = n - i + 1
+  end do
+
+  call test_array_caller(res_arr, a_arr)
+  do i = 1, n
+    if (res_arr(i) .ne. 2 * a_alloc(i)) stop 5
+  end do
+
+  call test_array_caller(res_arr, a_arr, b_arr)
+  do i = 1, n
+    if (res_arr(i) .ne. a_arr(i) * b_alloc(i) + a_alloc(i) + 
b_alloc(i)) stop 6
+  end do
+
+  deallocate(a_alloc)
+  deallocate(b_alloc)
+  deallocate(res_alloc)
+contains
+  subroutine test_int_caller(res, a, b)
+    integer :: res, a
+    integer, optional :: b
+
+    !$acc data copyin(a, b) copyout (res)
+    !$acc parallel
+    res = a
+    if (present(b)) res = res * b
+    call test_int_callee(res, a, b)
+    !$acc end parallel
+    !$acc end data
+  end subroutine test_int_caller
+
+  subroutine test_int_callee(res, a, b)
+    !$acc routine seq
+    integer :: res, a
+    integer, optional :: b
+
+    res = res + a
+    if (present(b)) res = res + b
+  end subroutine test_int_callee
+
+  subroutine test_array_caller(res, a, b)
+    integer :: res(n), a(n), i
+    integer, optional :: b(n)
+
+    !$acc data copyin(a, b) copyout(res)
+    !$acc parallel
+    !$acc loop seq
+    do i = 1, n
+      res(i) = a(i)
+      if (present(b)) res(i) = res(i) * b(i)
+    end do
+    call test_array_callee(res, a, b)
+    !$acc end parallel
+    !$acc end data
+  end subroutine test_array_caller
+
+  subroutine test_array_callee(res, a, b)
+    !$acc routine seq
+    integer :: res(n), a(n), i
+    integer, optional :: b(n)
+
+    do i = 1, n
+      res(i) = res(i) + a(i)
+      if (present(b)) res(i) = res(i) + b(i)
+    end do
+  end subroutine test_array_callee
+
+  subroutine test_allocatable_caller(res, a, b)
+    integer :: i
+    integer, allocatable :: res(:), a(:)
+    integer, allocatable, optional :: b(:)
+
+    !$acc data copyin(a, b) copyout(res)
+    !$acc parallel
+    !$acc loop seq
+    do i = 1, n
+      res(i) = a(i)
+      if (present(b)) res(i) = res(i) * b(i)
+    end do
+    call test_array_callee(res, a, b)
+    !$acc end parallel
+    !$acc end data
+  end subroutine test_allocatable_caller
+
+  subroutine test_allocatable_callee(res, a, b)
+    !$acc routine seq
+    integer :: i
+    integer, allocatable :: res(:), a(:)
+    integer, allocatable, optional :: b(:)
+
+    do i = 1, n
+      res(i) = res(i) + a(i)
+      if (present(b)) res(i) = res(i) + b(i)
+    end do
+  end subroutine test_allocatable_callee
+end program test
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/optional-private.f90 
b/libgomp/testsuite/libgomp.oacc-fortran/optional-private.f90
new file mode 100644
index 0000000..6bc91b7
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/optional-private.f90
@@ -0,0 +1,118 @@
+! Test that optional arguments work in private clauses.  The effect of
+! non-present arguments in private clauses is undefined, and is not tested
+! for.  The tests are based on those in private-variables.f90.
+
+! { dg-do run }
+
+program main
+  implicit none
+
+  type vec3
+     integer x, y, z, attr(13)
+  end type vec3
+  integer :: x
+  type(vec3) :: pt
+  integer :: arr(2)
+
+  call t1(x)
+  call t2(pt)
+  call t3(arr)
+contains
+
+  ! Test of gang-private variables declared on loop directive.
+
+  subroutine t1(x)
+    integer, optional :: x
+    integer :: i, arr(32)
+
+    do i = 1, 32
+       arr(i) = i
+    end do
+
+    !$acc parallel copy(arr) num_gangs(32) num_workers(8) vector_length(32)
+    ! { dg-warning "region is worker partitioned but does not contain 
worker partitioned code" "worker" { target *-*-* } 32 }
+    ! { dg-warning "region is vector partitioned but does not contain 
vector partitioned code" "vector" { target *-*-* } 32 }
+    !$acc loop gang private(x)
+    do i = 1, 32
+       x = i * 2;
+       arr(i) = arr(i) + x
+    end do
+    !$acc end parallel
+
+    do i = 1, 32
+       if (arr(i) .ne. i * 3) STOP 1
+    end do
+  end subroutine t1
+
+
+  ! Test of gang-private addressable variable declared on loop 
directive, with
+  ! broadcasting to partitioned workers.
+
+  subroutine t2(pt)
+    integer i, j, arr(0:32*32)
+    type(vec3), optional :: pt
+
+    do i = 0, 32*32-1
+       arr(i) = i
+    end do
+
+    !$acc parallel copy(arr) num_gangs(32) num_workers(8) vector_length(32)
+    ! { dg-warning "region is worker partitioned but does not contain 
worker partitioned code" "worker" { target *-*-* } 59 }
+    !$acc loop gang private(pt)
+    do i = 0, 31
+       pt%x = i
+       pt%y = i * 2
+       pt%z = i * 4
+       pt%attr(5) = i * 6
+
+       !$acc loop vector
+       do j = 0, 31
+          arr(i * 32 + j) = arr(i * 32 + j) + pt%x + pt%y + pt%z + 
pt%attr(5);
+       end do
+    end do
+    !$acc end parallel
+
+    do i = 0, 32 * 32 - 1
+       if (arr(i) .ne. i + (i / 32) * 13) STOP 2
+    end do
+  end subroutine t2
+
+  ! Test of vector-private variables declared on loop directive. Array 
type.
+
+  subroutine t3(pt)
+    integer, optional :: pt(2)
+    integer :: i, j, k, idx, arr(0:32*32*32)
+
+    do i = 0, 32*32*32-1
+       arr(i) = i
+    end do
+
+    !$acc parallel copy(arr) num_gangs(32) num_workers(8) vector_length(32)
+    !$acc loop gang
+    do i = 0, 31
+       !$acc loop worker
+       do j = 0, 31
+          !$acc loop vector private(pt)
+          do k = 0, 31
+             pt(1) = ieor(i, j * 3)
+             pt(2) = ior(i, j * 5)
+             arr(i * 1024 + j * 32 + k) = arr(i * 1024 + j * 32 + k) + 
pt(1) * k
+             arr(i * 1024 + j * 32 + k) = arr(i * 1024 + j * 32 + k) + 
pt(2) * k
+          end do
+       end do
+    end do
+    !$acc end parallel
+
+    do i = 0, 32 - 1
+       do j = 0, 32 -1
+          do k = 0, 32 - 1
+             idx = i * 1024 + j * 32 + k
+             if (arr(idx) .ne. idx + ieor(i, j * 3) * k + ior(i, j * 5) 
* k) then
+                STOP 3
+             end if
+          end do
+       end do
+    end do
+  end subroutine t3
+
+end program main
diff --git 
a/libgomp/testsuite/libgomp.oacc-fortran/optional-reduction.f90 
b/libgomp/testsuite/libgomp.oacc-fortran/optional-reduction.f90
new file mode 100644
index 0000000..b76db3e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/optional-reduction.f90
@@ -0,0 +1,69 @@
+! Test optional arguments in reduction clauses.  The effect of
+! non-present arguments in reduction clauses is undefined, and is not 
tested
+! for.  The tests are based on those in reduction-1.f90.
+
+! { dg-do run }
+! { dg-additional-options "-w" }
+
+program optional_reduction
+  implicit none
+
+  integer :: rg, rw, rv, rc
+
+  rg = 0
+  rw = 0
+  rv = 0
+  rc = 0
+
+  call do_test(rg, rw, rv, rc)
+contains
+  subroutine do_test(rg, rw, rv, rc)
+    integer, parameter     :: n = 10, ng = 8, nw = 4, vl = 32
+    integer, optional      :: rg, rw, rv, rc
+    integer                :: i, vresult
+    integer, dimension (n) :: array
+
+    vresult = 0
+    do i = 1, n
+       array(i) = i
+    end do
+
+    !$acc parallel num_gangs(ng) copy(rg)
+    !$acc loop reduction(+:rg) gang
+    do i = 1, n
+       rg = rg + array(i)
+    end do
+    !$acc end parallel
+
+    !$acc parallel num_workers(nw) copy(rw)
+    !$acc loop reduction(+:rw) worker
+    do i = 1, n
+       rw = rw + array(i)
+    end do
+    !$acc end parallel
+
+    !$acc parallel vector_length(vl) copy(rv)
+    !$acc loop reduction(+:rv) vector
+    do i = 1, n
+       rv = rv + array(i)
+    end do
+    !$acc end parallel
+
+    !$acc parallel num_gangs(ng) num_workers(nw) vector_length(vl) copy(rc)
+    !$acc loop reduction(+:rc) gang worker vector
+    do i = 1, n
+       rc = rc + array(i)
+    end do
+    !$acc end parallel
+
+    ! Verify the results
+    do i = 1, n
+       vresult = vresult + array(i)
+    end do
+
+    if (rg .ne. vresult) STOP 1
+    if (rw .ne. vresult) STOP 2
+    if (rv .ne. vresult) STOP 3
+    if (rc .ne. vresult) STOP 4
+  end subroutine do_test
+end program optional_reduction
diff --git 
a/libgomp/testsuite/libgomp.oacc-fortran/optional-update-device.f90 
b/libgomp/testsuite/libgomp.oacc-fortran/optional-update-device.f90
new file mode 100644
index 0000000..57f6900
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/optional-update-device.f90
@@ -0,0 +1,121 @@
+! Test OpenACC update to device with an optional argument.
+
+! { dg-do run }
+
+program optional_update_device
+  implicit none
+
+  integer, parameter :: n = 64
+  integer :: i
+  integer :: a_int, b_int, res_int
+  integer :: a_arr(n), b_arr(n), res_arr(n)
+  integer, allocatable :: a_alloc(:), b_alloc(:), res_alloc(:)
+
+  a_int = 5
+  b_int = 11
+
+  call test_int(res_int, a_int)
+  if (res_int .ne. a_int) stop 1
+
+  call test_int(res_int, a_int, b_int)
+  if (res_int .ne. a_int * b_int) stop 2
+
+  res_arr(:) = 0
+  do i = 1, n
+    a_arr(i) = i
+    b_arr(i) = n - i + 1
+  end do
+
+  call test_array(res_arr, a_arr)
+  do i = 1, n
+    if (res_arr(i) .ne. a_arr(i)) stop 3
+  end do
+
+  call test_array(res_arr, a_arr, b_arr)
+  do i = 1, n
+    if (res_arr(i) .ne. a_arr(i) * b_arr(i)) stop 4
+  end do
+
+  allocate (a_alloc(n))
+  allocate (b_alloc(n))
+  allocate (res_alloc(n))
+
+  res_alloc(:) = 0
+  do i = 1, n
+    a_alloc(i) = i
+    b_alloc(i) = n - i + 1
+  end do
+
+  call test_allocatable(res_alloc, a_alloc)
+  do i = 1, n
+    if (res_alloc(i) .ne. a_alloc(i)) stop 5
+  end do
+
+  call test_allocatable(res_alloc, a_alloc, b_alloc)
+  do i = 1, n
+    if (res_alloc(i) .ne. a_alloc(i) * b_alloc(i)) stop 6
+  end do
+
+  deallocate (a_alloc)
+  deallocate (b_alloc)
+  deallocate (res_alloc)
+contains
+  subroutine test_int(res, a, b)
+    integer :: res
+    integer :: a
+    integer, optional :: b
+
+    !$acc data create(a, b, res)
+    !$acc update device(a, b)
+    !$acc parallel
+    res = a
+    if (present(b)) res = res * b
+    !$acc end parallel
+    !$acc update self(res)
+    !$acc end data
+  end subroutine test_int
+
+  subroutine test_array(res, a, b)
+    integer :: res(n)
+    integer :: a(n)
+    integer, optional :: b(n)
+
+    !$acc data create(a, b, res)
+    !$acc update device(a, b)
+    !$acc parallel loop
+    do i = 1, n
+      res(i) = a(i)
+    end do
+
+    !$acc parallel loop
+    do i = 1, n
+      if (present(b)) then
+        res(i) = res(i) * b(i)
+      end if
+    end do
+    !$acc update self(res)
+    !$acc end data
+  end subroutine test_array
+
+  subroutine test_allocatable(res, a, b)
+    integer, allocatable :: res(:)
+    integer, allocatable :: a(:)
+    integer, allocatable, optional :: b(:)
+
+    !$acc data create(a, b, res)
+    !$acc update device(a, b)
+    !$acc parallel loop
+    do i = 1, n
+      res(i) = a(i)
+    end do
+
+    !$acc parallel loop
+    do i = 1, n
+      if (present(b)) then
+        res(i) = res(i) * b(i)
+      end if
+    end do
+    !$acc update self(res)
+    !$acc end data
+  end subroutine test_allocatable
+end program optional_update_device
diff --git 
a/libgomp/testsuite/libgomp.oacc-fortran/optional-update-host.f90 
b/libgomp/testsuite/libgomp.oacc-fortran/optional-update-host.f90
new file mode 100644
index 0000000..0f3a903
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/optional-update-host.f90
@@ -0,0 +1,115 @@
+! Test OpenACC update to host with an optional argument.
+
+! { dg-do run }
+
+program optional_update_host
+  implicit none
+
+  integer, parameter :: n = 64
+  integer :: i
+  integer :: a_int, b_int, res_int
+  integer :: a_arr(n), b_arr(n), res_arr(n)
+  integer, allocatable :: a_alloc(:), b_alloc(:), res_alloc(:)
+
+  a_int = 5
+  b_int = 11
+  res_int = 0
+
+  call test_int(a_int, b_int)
+  if (res_int .ne. 0) stop 1
+
+  call test_int(a_int, b_int, res_int)
+  if (res_int .ne. a_int * b_int) stop 2
+
+  res_arr(:) = 0
+  do i = 1, n
+    a_arr(i) = i
+    b_arr(i) = n - i + 1
+  end do
+
+  call test_array(a_arr, b_arr)
+  do i = 1, n
+    if (res_arr(i) .ne. 0) stop 1
+  end do
+
+  call test_array(a_arr, b_arr, res_arr)
+  do i = 1, n
+    if (res_arr(i) .ne. a_arr(i) * b_arr(i)) stop 2
+  end do
+
+  allocate(a_alloc(n))
+  allocate(b_alloc(n))
+  allocate(res_alloc(n))
+
+  res_alloc(:) = 0
+  do i = 1, n
+    a_alloc(i) = i
+    b_alloc(i) = n - i + 1
+  end do
+
+  call test_allocatable(a_alloc, b_alloc)
+  do i = 1, n
+    if (res_alloc(i) .ne. 0) stop 1
+  end do
+
+  call test_allocatable(a_alloc, b_alloc, res_alloc)
+  do i = 1, n
+    if (res_alloc(i) .ne. a_alloc(i) * b_alloc(i)) stop 2
+  end do
+
+  deallocate(a_alloc)
+  deallocate(b_alloc)
+  deallocate(res_alloc)
+contains
+  subroutine test_int(a, b, res)
+    integer :: a, b
+    integer, optional :: res
+
+    !$acc data create(a, b, res)
+    !$acc update device(a, b)
+    !$acc parallel
+    if (present(res)) res = a
+    if (present(res)) res = res * b
+    !$acc end parallel
+    !$acc update self(res)
+    !$acc end data
+  end subroutine test_int
+
+  subroutine test_array(a, b, res)
+    integer :: a(n), b(n)
+    integer, optional :: res(n)
+
+    !$acc data create(a, b, res)
+    !$acc update device(a, b)
+    !$acc parallel loop
+    do i = 1, n
+      if (present(res)) res(i) = a(i)
+    end do
+
+    !$acc parallel loop
+    do i = 1, n
+      if (present(res)) res(i) = res(i) * b(i)
+    end do
+    !$acc update self(res)
+    !$acc end data
+  end subroutine test_array
+
+  subroutine test_allocatable(a, b, res)
+    integer, allocatable :: a(:), b(:)
+    integer, allocatable, optional :: res(:)
+
+    !$acc data create(a, b, res)
+    !$acc update device(a, b)
+    !$acc parallel loop
+    do i = 1, n
+      if (present(res)) res(i) = a(i)
+    end do
+
+    !$acc parallel loop
+    do i = 1, n
+      if (present(res)) res(i) = res(i) * b(i)
+    end do
+    !$acc update self(res)
+    !$acc end data
+  end subroutine test_allocatable
+end program optional_update_host
-- 
2.8.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/4] [og8] Allow NULL for update directives in OpenACC 2.6
  2019-01-30 22:22 ` [PATCH 1/4] [og8] Allow NULL for update directives in OpenACC 2.6 Kwok Cheung Yeung
@ 2019-01-31 17:17   ` Thomas Schwinge
  0 siblings, 0 replies; 8+ messages in thread
From: Thomas Schwinge @ 2019-01-31 17:17 UTC (permalink / raw)
  To: Kwok Cheung Yeung, gcc-patches; +Cc: clm

[-- Attachment #1: Type: text/plain, Size: 2167 bytes --]

Hi Kwok!

On Wed, 30 Jan 2019 22:18:43 +0000, Kwok Cheung Yeung <kcy@codesourcery.com> wrote:
> A non-present passed-by-reference Fortran optional argument is 
> represented by a null pointer.  When passed to an update directive, it 
> should be ignored as variable mappings are not created for null 
> pointers.  This should be safe as it is not possible to change a 
> non-present argument into a present one (or vice-versa) in Fortran.
> 
> 	libgomp/
> 	* oacc-mem.c (update_dev_host): Return early if the host address
> 	is NULL.
> 
> Reviewed-by: Julian Brown <julian@codesourcery.com>
> Reviewed-by: Thomas Schwinge <thomas@codesourcery.com>

As I'd mentioned a few weeks ago internally, this change:

> --- a/libgomp/oacc-mem.c
> +++ b/libgomp/oacc-mem.c
> @@ -819,6 +819,12 @@ update_dev_host (int is_dev, void *h, size_t s, int 
> async)
>     if (acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
>       return;
> 
> +  /* Fortran optional arguments that are non-present result in a
> +     null host address here.  This can safely be ignored as it is
> +     not possible to 'update' a non-present optional argument.  */
> +  if (h == NULL)
> +    return;

... doesn't just affect the Fortran "update" directive but also the C/C++
one, and the "acc_update_device", "acc_update_self" runtime library
functions, and thus invalidates the C/C++
"libgomp.oacc-c-c++-common/lib-43.c", and
"libgomp.oacc-c-c++-common/lib-47.c" test cases, so these will have to be
adjusted (that is, removed).  I pushed the attached to
openacc-gcc-8-branch in commit 745d3a19c63ec9c1de3f44e0dd5ee3ff126e2828
"Remove libgomp.oacc-c-c++-common/lib-43.c,
libgomp.oacc-c-c++-common/lib-47.c".

For avoidance of doubt: I'm not objecting to your code change.  On
contrary, I do have an issue open to verify whether a host-NULL should
actually be accepted in even more places, as a no-op.  But we'll have to
review/adjust/test all the code, not just "update_dev_host".  (That's for
later, of course.)

A (very) quick check with the PGI compiler shows that they're also
handling such NULL pointers as no-ops.


Grüße
 Thomas



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Remove-libgomp.oacc-c-c-common-lib-43.c-libgomp.oacc.patch --]
[-- Type: text/x-diff, Size: 3673 bytes --]

From 745d3a19c63ec9c1de3f44e0dd5ee3ff126e2828 Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>
Date: Thu, 31 Jan 2019 18:08:09 +0100
Subject: [PATCH] Remove libgomp.oacc-c-c++-common/lib-43.c,
 libgomp.oacc-c-c++-common/lib-47.c

They're invalid after commit 550afd2b2b47091f43780f0fbf5ead87f73d9b1e "[og8]
Allow NULL for update directives in OpenACC 2.6".

	libgomp/
	* testsuite/libgomp.oacc-c-c++-common/lib-43.c: Remove.
	* testsuite/libgomp.oacc-c-c++-common/lib-47.c: Likewise.
---
 libgomp/ChangeLog.openacc                     |  3 ++
 .../libgomp.oacc-c-c++-common/lib-43.c        | 51 -------------------
 .../libgomp.oacc-c-c++-common/lib-47.c        | 49 ------------------
 3 files changed, 3 insertions(+), 100 deletions(-)
 delete mode 100644 libgomp/testsuite/libgomp.oacc-c-c++-common/lib-43.c
 delete mode 100644 libgomp/testsuite/libgomp.oacc-c-c++-common/lib-47.c

diff --git a/libgomp/ChangeLog.openacc b/libgomp/ChangeLog.openacc
index d558f0df97b..edb7d3f76eb 100644
--- a/libgomp/ChangeLog.openacc
+++ b/libgomp/ChangeLog.openacc
@@ -1,5 +1,8 @@
 2019-01-31  Thomas Schwinge  <thomas@codesourcery.com>
 
+	* testsuite/libgomp.oacc-c-c++-common/lib-43.c: Remove.
+	* testsuite/libgomp.oacc-c-c++-common/lib-47.c: Likewise.
+
 	* testsuite/libgomp.oacc-c-c++-common/avoid-offloading-1.c:
 	Update.
 	* testsuite/libgomp.oacc-c-c++-common/avoid-offloading-2.c:
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/lib-43.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/lib-43.c
deleted file mode 100644
index 5db29124e9e..00000000000
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/lib-43.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/* Exercise acc_update_device with a NULL data address on nvidia targets.  */
-
-/* { dg-do run { target openacc_nvidia_accel_selected } } */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <openacc.h>
-
-int
-main (int argc, char **argv)
-{
-  const int N = 256;
-  int i;
-  unsigned char *h;
-  void *d;
-
-  h = (unsigned char *) malloc (N);
-
-  for (i = 0; i < N; i++)
-    {
-      h[i] = i;
-    }
-
-  d = acc_copyin (h, N);
-  if (!d)
-    abort ();
-
-  for (i = 0; i < N; i++)
-    {
-      h[i] = 0xab;
-    }
-
-  fprintf (stderr, "CheCKpOInT\n");
-  acc_update_device (0, N);
-
-  acc_copyout (h, N);
-
-  for (i = 0; i < N; i++)
-    {
-      if (h[i] != 0xab)
-	abort ();
-    }
-
-  free (h);
-
-  return 0;
-}
-
-/* { dg-output "CheCKpOInT(\n|\r\n|\r).*" } */
-/* { dg-output "\\\[\[^\n\r]*,256\\\] is not mapped" } */
-/* { dg-shouldfail "" } */
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/lib-47.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/lib-47.c
deleted file mode 100644
index c2140429cb1..00000000000
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/lib-47.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Exercise acc_update_self with a NULL data mapping on nvidia targets.  */
-
-/* { dg-do run { target openacc_nvidia_accel_selected } } */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <openacc.h>
-
-int
-main (int argc, char **argv)
-{
-  const int N = 256;
-  int i;
-  unsigned char *h;
-  void *d;
-
-  h = (unsigned char *) malloc (N);
-
-  for (i = 0; i < N; i++)
-    {
-      h[i] = i;
-    }
-
-  d = acc_copyin (h, N);
-  if (!d)
-    abort ();
-
-  memset (&h[0], 0, N);
-
-  fprintf (stderr, "CheCKpOInT\n");
-  acc_update_self (0, N);
-
-  for (i = 0; i < N; i++)
-    {
-      if (h[i] != i)
-	abort ();
-    }
-
-  acc_delete (h, N);
-
-  free (h);
-
-  return 0;
-}
-
-/* { dg-output "CheCKpOInT(\n|\r\n|\r).*" } */
-/* { dg-output "\\\[\[^\n\r]*,256\\\] is not mapped" } */
-/* { dg-shouldfail "" } */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 4/4] [og8] Add tests for Fortran optional arguments in OpenACC 2.6
  2019-01-30 22:37 ` [PATCH 4/4] [og8] Add tests for Fortran optional arguments in OpenACC 2.6 Kwok Cheung Yeung
@ 2019-01-31 17:23   ` Thomas Schwinge
  2019-01-31 17:32     ` Kwok Cheung Yeung
  0 siblings, 1 reply; 8+ messages in thread
From: Thomas Schwinge @ 2019-01-31 17:23 UTC (permalink / raw)
  To: Kwok Cheung Yeung; +Cc: clm, gcc-patches

Hi Kwok!

On Wed, 30 Jan 2019 22:24:48 +0000, Kwok Cheung Yeung <kcy@codesourcery.com> wrote:
> diff --git 
> a/libgomp/testsuite/libgomp.oacc-fortran/optional-host_data.f90 
> b/libgomp/testsuite/libgomp.oacc-fortran/optional-host_data.f90
> new file mode 100644

I'm seeing this one fail at run time: "libgomp: use_device_ptr pointer
wasn't mapped".  Is this expected (and should thus be XFAILed), or
unexpected?


Grüße
 Thomas


> --- /dev/null
> +++ b/libgomp/testsuite/libgomp.oacc-fortran/optional-host_data.f90
> @@ -0,0 +1,37 @@
> +! Test the host_data construct with optional arguments.
> +! Based on host_data-1.f90.
> +
> +! { dg-do run }
> +! { dg-additional-options "-cpp" }
> +
> +program test
> +  implicit none
> +
> +  integer, target :: i
> +  integer, pointer :: ip, iph
> +
> +  ! Assign the same targets
> +  ip => i
> +  iph => i
> +
> +  call foo(iph)
> +  call foo(iph, ip)
> +contains
> +  subroutine foo(iph, ip)
> +    integer, pointer :: iph
> +    integer, pointer, optional :: ip
> +
> +    !$acc data copyin(i)
> +    !$acc host_data use_device(ip)
> +
> +    ! Test how the pointers compare inside a host_data construct
> +#if ACC_MEM_SHARED
> +    if (present(ip) .and. .not. associated(ip, iph)) STOP 1
> +#else
> +    if (present(ip) .and. associated(ip, iph)) STOP 2
> +#endif
> +
> +    !$acc end host_data
> +    !$acc end data
> +  end subroutine foo
> +end program test

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 4/4] [og8] Add tests for Fortran optional arguments in OpenACC 2.6
  2019-01-31 17:23   ` Thomas Schwinge
@ 2019-01-31 17:32     ` Kwok Cheung Yeung
  0 siblings, 0 replies; 8+ messages in thread
From: Kwok Cheung Yeung @ 2019-01-31 17:32 UTC (permalink / raw)
  To: Thomas Schwinge; +Cc: clm, gcc-patches

The use_device_ptr patch (which needed reviewing) is needed for that 
test. I bundled all the new tests into one commit, but forgot to exclude 
that particular test. I will post and push that patch a little later.

Kwok

On 31/01/2019 5:20 pm, Thomas Schwinge wrote:
> Hi Kwok!
> 
> On Wed, 30 Jan 2019 22:24:48 +0000, Kwok Cheung Yeung <kcy@codesourcery.com> wrote:
>> diff --git
>> a/libgomp/testsuite/libgomp.oacc-fortran/optional-host_data.f90
>> b/libgomp/testsuite/libgomp.oacc-fortran/optional-host_data.f90
>> new file mode 100644
> 
> I'm seeing this one fail at run time: "libgomp: use_device_ptr pointer
> wasn't mapped".  Is this expected (and should thus be XFAILed), or
> unexpected?
> 
> 
> Grüße
>   Thomas
> 
> 
>> --- /dev/null
>> +++ b/libgomp/testsuite/libgomp.oacc-fortran/optional-host_data.f90
>> @@ -0,0 +1,37 @@
>> +! Test the host_data construct with optional arguments.
>> +! Based on host_data-1.f90.
>> +
>> +! { dg-do run }
>> +! { dg-additional-options "-cpp" }
>> +
>> +program test
>> +  implicit none
>> +
>> +  integer, target :: i
>> +  integer, pointer :: ip, iph
>> +
>> +  ! Assign the same targets
>> +  ip => i
>> +  iph => i
>> +
>> +  call foo(iph)
>> +  call foo(iph, ip)
>> +contains
>> +  subroutine foo(iph, ip)
>> +    integer, pointer :: iph
>> +    integer, pointer, optional :: ip
>> +
>> +    !$acc data copyin(i)
>> +    !$acc host_data use_device(ip)
>> +
>> +    ! Test how the pointers compare inside a host_data construct
>> +#if ACC_MEM_SHARED
>> +    if (present(ip) .and. .not. associated(ip, iph)) STOP 1
>> +#else
>> +    if (present(ip) .and. associated(ip, iph)) STOP 2
>> +#endif
>> +
>> +    !$acc end host_data
>> +    !$acc end data
>> +  end subroutine foo
>> +end program test

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2019-01-31 17:28 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-30 22:19 [PATCH 0/4] [og8] Add support for Fortran optional arguments in OpenACC Kwok Cheung Yeung
2019-01-30 22:22 ` [PATCH 1/4] [og8] Allow NULL for update directives in OpenACC 2.6 Kwok Cheung Yeung
2019-01-31 17:17   ` Thomas Schwinge
2019-01-30 22:24 ` [PATCH 2/4] [og8] Calculate correct size for optional arguments used in the firstprivate clause Kwok Cheung Yeung
2019-01-30 22:25 ` [PATCH 3/4] [og8] Add support for allocatable arrays as optional arguments Kwok Cheung Yeung
2019-01-30 22:37 ` [PATCH 4/4] [og8] Add tests for Fortran optional arguments in OpenACC 2.6 Kwok Cheung Yeung
2019-01-31 17:23   ` Thomas Schwinge
2019-01-31 17:32     ` Kwok Cheung Yeung

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).