Hello Thomas, hi all,

updated version. Changes:
* Incorporate Thomas's changes
* Add no_create clause to newly added 'acc serial'
* Renamed (G)OMP_MAP_NO_ALLOC to (G)OMP_MAP_IF_PRESENT as proposed
* Make no_create.c effective by adding 'has_firstprivate = true;' to target.c.*

(* If one tries to access c or e in the no_create-3.{c,f90} run-time test case, plugin-nvidia rightly complains (illegal memory access), using the created 'b' or 'd' works as tested by the test case. This feature seems to be also broken on the OG9 branch.)

Bootstrapped and regtested without offloading and with nvptx offloading.
OK?

Tobias

PS: Remaining bits of the OG9 patch, which are not included are the following. I think those are all attach/detach features: a test case for "no_create(s.y…)" (i.e. the struct component-ref; libgomp/testsuite/libgomp.oacc-c-c++-common/nocreate-{3,4}.c) and some 'do_detach = false' in libgomp/target.c. Cf. openacc-gcc-9 /…-8 branch patch is commit 8e74c2ec2b90819c995444370e742864a685209f of Dec 20, 2018. It has been posted as https://gcc.gnu.org/ml/gcc-patches/2018-12/msg01418.html


On 11/6/19 1:42 PM, Thomas Schwinge wrote:
Hi Tobias!

On 2019-11-06T00:47:05+0100, I wrote:
--- a/libgomp/testsuite/libgomp.oacc-fortran/common-block-2.f90
+++ b/libgomp/testsuite/libgomp.oacc-fortran/common-block-2.f90
@@ -76,7 +76,9 @@ program main
!$acc enter data create(b) - !$acc parallel loop pcopy(b)
+  !$acc parallel loop &
+  !$acc   no_create(b) ! ... here means 'present(b)'.
+  !TODO But we get: "libgomp: cuStreamSynchronize error: an illegal memory access 
was encountered".
    do i = 1, n
       b(i) = i
    end do
Either I'm completely confused -- always possible ;-) -- or there's
something wrong; see the two attached test cases, not actually related to
Fortran common blocks at all.  If such a basic usage of the 'no_create'
clause doesn't work...?  So, again..., seems that my suspicion was right
that this patch doesn't have sufficient test coverage at all.  Or, I'm
completely confused -- we still have that option, too.  ;-\


Grüße
  Thomas


Add OpenACC 2.6 `no_create' clause support

The clause makes any device code use the local memory address for each
of the variables specified unless the given variable is already present
on the current device.

2019-11-15  Julian Brown  <jul...@codesourcery.com>
	    Maciej W. Rozycki  <ma...@codesourcery.com>
	    Tobias Burnus  <tob...@codesourcery.com>
	    Thomas Schwinge  <tho...@codesourcery.com>

	gcc/
	* omp-low.c (lower_omp_target): Support GOMP_MAP_NO_ALLOC.
	* tree-pretty-print.c (dump_omp_clause): Likewise.

	gcc/c-family/
	* c-pragma.h (pragma_omp_clause): Add
	PRAGMA_OACC_CLAUSE_NO_CREATE.

	gcc/c/
	* c-parser.c (c_parser_omp_clause_name): Support no_create.
	(c_parser_oacc_data_clause): Likewise.
	(c_parser_oacc_all_clauses): Likewise.
	(OACC_DATA_CLAUSE_MASK, OACC_KERNELS_CLAUSE_MASK)
	(OACC_PARALLEL_CLAUSE_MASK, OACC_SERIAL_CLAUSE_MASK): Add
	PRAGMA_OACC_CLAUSE_NO_CREATE.
	* c-typeck.c (handle_omp_array_sections): Support
	GOMP_MAP_NO_ALLOC.

	gcc/cp/
	* parser.c (cp_parser_omp_clause_name): Support no_create.
	(cp_parser_oacc_data_clause): Likewise.
	(cp_parser_oacc_all_clauses): Likewise.
	(OACC_DATA_CLAUSE_MASK, OACC_KERNELS_CLAUSE_MASK)
	(OACC_PARALLEL_CLAUSE_MASK): Add PRAGMA_OACC_CLAUSE_NO_CREATE.
	* semantics.c (handle_omp_array_sections): Support no_create.

	gcc/fortran/
	* gfortran.h (gfc_omp_map_op): Add OMP_MAP_NO_ALLOC.
	* openmp.c (omp_mask2): Add OMP_CLAUSE_NO_CREATE.
	(gfc_match_omp_clauses): Support no_create.
	(OACC_PARALLEL_CLAUSES, OACC_KERNELS_CLAUSES)
	(OACC_DATA_CLAUSES): Add OMP_CLAUSE_NO_CREATE.
	* trans-openmp.c (gfc_trans_omp_clauses_1): Support
	OMP_MAP_NO_ALLOC.

	gcc/testsuite/
	* gfortran.dg/goacc/common-block-1.f90: Add no_create-clause tests.
	* gfortran.dg/goacc/common-block-1.f90: Likewise.
	* gfortran.dg/goacc/data-clauses.f95: Likewise.
	* gfortran.dg/goacc/data-tree.f95: Likewise.
	* gfortran.dg/goacc/kernels-tree.f95: Likewise.
	* gfortran.dg/goacc/parallel-tree.f95: Likewise.

	include/
	* gomp-constants.h (gomp_map_kind): Support GOMP_MAP_NO_ALLOC.

	libgomp/
	* target.c (gomp_map_vars_async): Support GOMP_MAP_NO_ALLOC.
	* testsuite/libgomp.oacc-c-c++-common/nocreate-1.c: New test.
	* testsuite/libgomp.oacc-c-c++-common/nocreate-2.c: New test.
	* testsuite/libgomp.oacc-c-c++-common/nocreate-3.c: New test.
	* testsuite/libgomp.oacc-fortran/nocreate-1.f90: New test.
	* testsuite/libgomp.oacc-fortran/nocreate-2.f90: New test.
	* testsuite/libgomp.oacc-fortran/nocreate-3.f90: New test.

 gcc/c-family/c-pragma.h                            |  1 +
 gcc/c/c-parser.c                                   | 20 +++++-
 gcc/c/c-typeck.c                                   |  1 +
 gcc/cp/parser.c                                    | 22 ++++++-
 gcc/cp/semantics.c                                 |  1 +
 gcc/fortran/gfortran.h                             |  1 +
 gcc/fortran/openmp.c                               | 28 +++++----
 gcc/fortran/trans-openmp.c                         |  3 +
 gcc/omp-low.c                                      |  2 +
 gcc/testsuite/gfortran.dg/goacc/common-block-1.f90 |  3 +
 gcc/testsuite/gfortran.dg/goacc/common-block-2.f90 |  3 +
 gcc/testsuite/gfortran.dg/goacc/data-clauses.f95   | 21 +++++++
 gcc/testsuite/gfortran.dg/goacc/data-tree.f95      |  3 +-
 gcc/testsuite/gfortran.dg/goacc/kernels-tree.f95   |  3 +-
 gcc/testsuite/gfortran.dg/goacc/parallel-tree.f95  |  3 +-
 gcc/tree-pretty-print.c                            |  3 +
 include/gomp-constants.h                           |  2 +
 libgomp/target.c                                   | 50 +++++++++++++++
 .../libgomp.oacc-c-c++-common/no_create-1.c        | 40 ++++++++++++
 .../libgomp.oacc-c-c++-common/no_create-2.c        | 28 +++++++++
 .../libgomp.oacc-c-c++-common/no_create-3.c        | 24 ++++++++
 .../testsuite/libgomp.oacc-fortran/no_create-1.f90 | 35 +++++++++++
 .../testsuite/libgomp.oacc-fortran/no_create-2.f90 | 71 ++++++++++++++++++++++
 .../testsuite/libgomp.oacc-fortran/no_create-3.f90 | 21 +++++++
 24 files changed, 370 insertions(+), 19 deletions(-)

diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index bfe681bb430..3754c5fda45 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -154,6 +154,7 @@ enum pragma_omp_clause {
   PRAGMA_OACC_CLAUSE_GANG,
   PRAGMA_OACC_CLAUSE_HOST,
   PRAGMA_OACC_CLAUSE_INDEPENDENT,
+  PRAGMA_OACC_CLAUSE_NO_CREATE,
   PRAGMA_OACC_CLAUSE_NUM_GANGS,
   PRAGMA_OACC_CLAUSE_NUM_WORKERS,
   PRAGMA_OACC_CLAUSE_PRESENT,
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 5b290bf7567..d93c7b6316f 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -12457,7 +12457,9 @@ c_parser_omp_clause_name (c_parser *parser)
 	    result = PRAGMA_OMP_CLAUSE_MERGEABLE;
 	  break;
 	case 'n':
-	  if (!strcmp ("nogroup", p))
+	  if (!strcmp ("no_create", p))
+	    result = PRAGMA_OACC_CLAUSE_NO_CREATE;
+	  else if (!strcmp ("nogroup", p))
 	    result = PRAGMA_OMP_CLAUSE_NOGROUP;
 	  else if (!strcmp ("nontemporal", p))
 	    result = PRAGMA_OMP_CLAUSE_NONTEMPORAL;
@@ -12920,7 +12922,10 @@ c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
    copyout ( variable-list )
    create ( variable-list )
    delete ( variable-list )
-   present ( variable-list ) */
+   present ( variable-list )
+
+   OpenACC 2.6:
+   no_create ( variable-list ) */
 
 static tree
 c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind,
@@ -12956,6 +12961,9 @@ c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind,
     case PRAGMA_OACC_CLAUSE_LINK:
       kind = GOMP_MAP_LINK;
       break;
+    case PRAGMA_OACC_CLAUSE_NO_CREATE:
+      kind = GOMP_MAP_IF_PRESENT;
+      break;
     case PRAGMA_OACC_CLAUSE_PRESENT:
       kind = GOMP_MAP_FORCE_PRESENT;
       break;
@@ -15754,6 +15762,10 @@ c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask,
 	  clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
 	  c_name = "link";
 	  break;
+	case PRAGMA_OACC_CLAUSE_NO_CREATE:
+	  clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
+	  c_name = "no_create";
+	  break;
 	case PRAGMA_OACC_CLAUSE_NUM_GANGS:
 	  clauses = c_parser_oacc_single_int_clause (parser,
 						     OMP_CLAUSE_NUM_GANGS,
@@ -16222,6 +16234,7 @@ c_parser_oacc_cache (location_t loc, c_parser *parser)
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF)			\
+	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT))
 
 static tree
@@ -16554,6 +16567,7 @@ c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF)			\
+	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT)		\
@@ -16569,6 +16583,7 @@ c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF)			\
+	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE)	\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS)		\
@@ -16587,6 +16602,7 @@ c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF)			\
+	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE)	\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT)		\
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 5f74a3b28d9..0f04e153ea7 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -13422,6 +13422,7 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
 	switch (OMP_CLAUSE_MAP_KIND (c))
 	  {
 	  case GOMP_MAP_ALLOC:
+	  case GOMP_MAP_IF_PRESENT:
 	  case GOMP_MAP_TO:
 	  case GOMP_MAP_FROM:
 	  case GOMP_MAP_TOFROM:
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c473e7fd92f..07685c8c389 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -33100,7 +33100,9 @@ cp_parser_omp_clause_name (cp_parser *parser)
 	    result = PRAGMA_OMP_CLAUSE_MERGEABLE;
 	  break;
 	case 'n':
-	  if (!strcmp ("nogroup", p))
+	  if (!strcmp ("no_create", p))
+	    result = PRAGMA_OACC_CLAUSE_NO_CREATE;
+	  else if (!strcmp ("nogroup", p))
 	    result = PRAGMA_OMP_CLAUSE_NOGROUP;
 	  else if (!strcmp ("nontemporal", p))
 	    result = PRAGMA_OMP_CLAUSE_NONTEMPORAL;
@@ -33466,7 +33468,10 @@ cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list)
    copyout ( variable-list )
    create ( variable-list )
    delete ( variable-list )
-   present ( variable-list ) */
+   present ( variable-list )
+
+   OpenACC 2.6:
+   no_create ( variable-list ) */
 
 static tree
 cp_parser_oacc_data_clause (cp_parser *parser, pragma_omp_clause c_kind,
@@ -33502,6 +33507,9 @@ cp_parser_oacc_data_clause (cp_parser *parser, pragma_omp_clause c_kind,
     case PRAGMA_OACC_CLAUSE_LINK:
       kind = GOMP_MAP_LINK;
       break;
+    case PRAGMA_OACC_CLAUSE_NO_CREATE:
+      kind = GOMP_MAP_IF_PRESENT;
+      break;
     case PRAGMA_OACC_CLAUSE_PRESENT:
       kind = GOMP_MAP_FORCE_PRESENT;
       break;
@@ -36064,6 +36072,10 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
 	  clauses = cp_parser_oacc_data_clause (parser, c_kind, clauses);
 	  c_name = "link";
 	  break;
+	case PRAGMA_OACC_CLAUSE_NO_CREATE:
+	  clauses = cp_parser_oacc_data_clause (parser, c_kind, clauses);
+	  c_name = "no_create";
+	  break;
 	case PRAGMA_OACC_CLAUSE_NUM_GANGS:
 	  code = OMP_CLAUSE_NUM_GANGS;
 	  c_name = "num_gangs";
@@ -39869,6 +39881,7 @@ cp_parser_oacc_cache (cp_parser *parser, cp_token *pragma_tok)
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF)			\
+	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) )
 
 static tree
@@ -40190,6 +40203,7 @@ cp_parser_oacc_loop (cp_parser *parser, cp_token *pragma_tok, char *p_name,
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF)			\
+	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT)		\
@@ -40204,8 +40218,9 @@ cp_parser_oacc_loop (cp_parser *parser, cp_token *pragma_tok, char *p_name,
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR)		\
-	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE)       	\
+	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE)	\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF)			\
+	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT)		\
@@ -40223,6 +40238,7 @@ cp_parser_oacc_loop (cp_parser *parser, cp_token *pragma_tok, char *p_name,
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF)			\
+	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE)	\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT)		\
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0ce73af5bc6..5a23b37a201 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5300,6 +5300,7 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
 	    switch (OMP_CLAUSE_MAP_KIND (c))
 	      {
 	      case GOMP_MAP_ALLOC:
+	      case GOMP_MAP_IF_PRESENT:
 	      case GOMP_MAP_TO:
 	      case GOMP_MAP_FROM:
 	      case GOMP_MAP_TOFROM:
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index e962db59bc5..3b473854f06 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1192,6 +1192,7 @@ enum gfc_omp_depend_op
 enum gfc_omp_map_op
 {
   OMP_MAP_ALLOC,
+  OMP_MAP_IF_PRESENT,
   OMP_MAP_TO,
   OMP_MAP_FROM,
   OMP_MAP_TOFROM,
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index dc0521b40f0..576003d7ff8 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -807,6 +807,7 @@ enum omp_mask2
   OMP_CLAUSE_COPY,
   OMP_CLAUSE_COPYOUT,
   OMP_CLAUSE_CREATE,
+  OMP_CLAUSE_NO_CREATE,
   OMP_CLAUSE_PRESENT,
   OMP_CLAUSE_DEVICEPTR,
   OMP_CLAUSE_GANG,
@@ -1445,6 +1446,11 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	    }
 	  break;
 	case 'n':
+	  if ((mask & OMP_CLAUSE_NO_CREATE)
+	      && gfc_match ("no_create ( ") == MATCH_YES
+	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+					   OMP_MAP_IF_PRESENT, true))
+	    continue;
 	  if ((mask & OMP_CLAUSE_NOGROUP)
 	      && !c->nogroup
 	      && gfc_match ("nogroup") == MATCH_YES)
@@ -1955,25 +1961,25 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS	      \
    | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_REDUCTION \
    | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT		      \
-   | OMP_CLAUSE_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_DEVICEPTR	      \
-   | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULT	      \
-   | OMP_CLAUSE_WAIT)
+   | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT	      \
+   | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE      \
+   | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT)
 #define OACC_KERNELS_CLAUSES \
   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS	      \
    | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_DEVICEPTR \
    | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT		      \
-   | OMP_CLAUSE_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_DEFAULT	      \
-   | OMP_CLAUSE_WAIT)
+   | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT	      \
+   | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT)
 #define OACC_SERIAL_CLAUSES \
   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_REDUCTION	      \
    | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT		      \
-   | OMP_CLAUSE_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_DEVICEPTR	      \
-   | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULT	      \
-   | OMP_CLAUSE_WAIT)
+   | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT	      \
+   | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE      \
+   | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT)
 #define OACC_DATA_CLAUSES \
   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICEPTR  | OMP_CLAUSE_COPY	      \
    | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE		      \
-   | OMP_CLAUSE_PRESENT)
+   | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT)
 #define OACC_LOOP_CLAUSES \
   (omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER	      \
    | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT	      \
@@ -2509,7 +2515,7 @@ cleanup:
 #define OMP_TASKLOOP_CLAUSES \
   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE		\
    | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF		\
-   | OMP_CLAUSE_DEFAULT	| OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL		\
+   | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL		\
    | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_GRAINSIZE	\
    | OMP_CLAUSE_NUM_TASKS | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_NOGROUP)
 #define OMP_TARGET_CLAUSES \
@@ -2531,7 +2537,7 @@ cleanup:
    | OMP_CLAUSE_FROM | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
 #define OMP_TEAMS_CLAUSES \
   (omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT		\
-   | OMP_CLAUSE_DEFAULT	| OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE	\
+   | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE	\
    | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION)
 #define OMP_DISTRIBUTE_CLAUSES \
   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE		\
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index d9dfcabc65e..6c1b1b0aa0e 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -2431,6 +2431,9 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
 		case OMP_MAP_ALLOC:
 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALLOC);
 		  break;
+		case OMP_MAP_IF_PRESENT:
+		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_IF_PRESENT);
+		  break;
 		case OMP_MAP_TO:
 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TO);
 		  break;
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 3e470afe32b..700a9352b1b 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -11431,6 +11431,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 	  case GOMP_MAP_STRUCT:
 	  case GOMP_MAP_ALWAYS_POINTER:
 	    break;
+	  case GOMP_MAP_IF_PRESENT:
 	  case GOMP_MAP_FORCE_ALLOC:
 	  case GOMP_MAP_FORCE_TO:
 	  case GOMP_MAP_FORCE_FROM:
@@ -11841,6 +11842,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 		  switch (tkind)
 		    {
 		    case GOMP_MAP_ALLOC:
+		    case GOMP_MAP_IF_PRESENT:
 		    case GOMP_MAP_TO:
 		    case GOMP_MAP_FROM:
 		    case GOMP_MAP_TOFROM:
diff --git a/gcc/testsuite/gfortran.dg/goacc/common-block-1.f90 b/gcc/testsuite/gfortran.dg/goacc/common-block-1.f90
index 228637f5883..6df5aa65e70 100644
--- a/gcc/testsuite/gfortran.dg/goacc/common-block-1.f90
+++ b/gcc/testsuite/gfortran.dg/goacc/common-block-1.f90
@@ -51,6 +51,9 @@ program test
   !$acc data pcopyout(/blockA/, /blockB/, e, v)
   !$acc end data
 
+  !$acc data no_create(/blockA/, /blockB/, e, v)
+  !$acc end data
+
   !$acc parallel private(/blockA/, /blockB/, e, v)
   !$acc end parallel
 
diff --git a/gcc/testsuite/gfortran.dg/goacc/common-block-2.f90 b/gcc/testsuite/gfortran.dg/goacc/common-block-2.f90
index 5d49f6195b8..30c87a91f36 100644
--- a/gcc/testsuite/gfortran.dg/goacc/common-block-2.f90
+++ b/gcc/testsuite/gfortran.dg/goacc/common-block-2.f90
@@ -39,6 +39,9 @@ program test
   !$acc data pcopyout(/blockA/, /blockB/, e, v, a) ! { dg-error "Symbol .a. present on multiple clauses" }
   !$acc end data
 
+  !$acc data no_create(/blockA/, /blockB/, e, v, a) ! { dg-error "Symbol .a. present on multiple clauses" }
+  !$acc end data
+
   !$acc parallel private(/blockA/, /blockB/, e, v, a) ! { dg-error "Symbol .a. present on multiple clauses" }
   !$acc end parallel
 
diff --git a/gcc/testsuite/gfortran.dg/goacc/data-clauses.f95 b/gcc/testsuite/gfortran.dg/goacc/data-clauses.f95
index b94214e8b63..30930a0cf1c 100644
--- a/gcc/testsuite/gfortran.dg/goacc/data-clauses.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/data-clauses.f95
@@ -111,6 +111,27 @@ contains
   !$acc end data
 
 
+  !$acc parallel no_create (tip) ! { dg-error "POINTER" }
+  !$acc end parallel
+  !$acc parallel no_create (tia) ! { dg-error "ALLOCATABLE" }
+  !$acc end parallel
+  !$acc parallel deviceptr (i) no_create (i) ! { dg-error "multiple clauses" }
+  !$acc end parallel
+  !$acc parallel copy (i) no_create (i) ! { dg-error "multiple clauses" }
+  !$acc end parallel
+  !$acc parallel copyin (i) no_create (i) ! { dg-error "multiple clauses" }
+  !$acc end parallel
+  !$acc parallel copyout (i) no_create (i) ! { dg-error "multiple clauses" }
+  !$acc end parallel
+
+  !$acc parallel no_create (i, c, r, ia, ca, ra, asa, rp, ti, vi, aa)
+  !$acc end parallel
+  !$acc kernels no_create (i, c, r, ia, ca, ra, asa, rp, ti, vi, aa)
+  !$acc end kernels
+  !$acc data no_create (i, c, r, ia, ca, ra, asa, rp, ti, vi, aa)
+  !$acc end data
+
+
   !$acc parallel present (tip) ! { dg-error "POINTER" }
   !$acc end parallel
   !$acc parallel present (tia) ! { dg-error "ALLOCATABLE" }
diff --git a/gcc/testsuite/gfortran.dg/goacc/data-tree.f95 b/gcc/testsuite/gfortran.dg/goacc/data-tree.f95
index f16d62cce69..454417d6a05 100644
--- a/gcc/testsuite/gfortran.dg/goacc/data-tree.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/data-tree.f95
@@ -7,6 +7,7 @@ program test
   logical :: l = .true.
 
   !$acc data if(l) copy(i), copyin(j), copyout(k), create(m) &
+  !$acc no_create(n) &
   !$acc present(o), pcopy(p), pcopyin(r), pcopyout(s), pcreate(t) &
   !$acc deviceptr(u)
   !$acc end data
@@ -19,7 +20,7 @@ end program test
 ! { dg-final { scan-tree-dump-times "map\\(to:j\\)" 1 "original" } } 
 ! { dg-final { scan-tree-dump-times "map\\(from:k\\)" 1 "original" } } 
 ! { dg-final { scan-tree-dump-times "map\\(alloc:m\\)" 1 "original" } } 
-
+! { dg-final { scan-tree-dump-times "map\\(no_alloc:n\\)" 1 "original" } } 
 ! { dg-final { scan-tree-dump-times "map\\(force_present:o\\)" 1 "original" } } 
 ! { dg-final { scan-tree-dump-times "map\\(tofrom:p\\)" 1 "original" } } 
 ! { dg-final { scan-tree-dump-times "map\\(to:r\\)" 1 "original" } } 
diff --git a/gcc/testsuite/gfortran.dg/goacc/kernels-tree.f95 b/gcc/testsuite/gfortran.dg/goacc/kernels-tree.f95
index a70f1e737bd..5583ffb4d04 100644
--- a/gcc/testsuite/gfortran.dg/goacc/kernels-tree.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/kernels-tree.f95
@@ -8,6 +8,7 @@ program test
 
   !$acc kernels if(l) async num_gangs(i) num_workers(i) vector_length(i) &
   !$acc copy(i), copyin(j), copyout(k), create(m) &
+  !$acc no_create(n) &
   !$acc present(o), pcopy(p), pcopyin(r), pcopyout(s), pcreate(t) &
   !$acc deviceptr(u)
   !$acc end kernels
@@ -25,7 +26,7 @@ end program test
 ! { dg-final { scan-tree-dump-times "map\\(to:j\\)" 1 "original" } } 
 ! { dg-final { scan-tree-dump-times "map\\(from:k\\)" 1 "original" } } 
 ! { dg-final { scan-tree-dump-times "map\\(alloc:m\\)" 1 "original" } } 
-
+! { dg-final { scan-tree-dump-times "map\\(no_alloc:n\\)" 1 "original" } } 
 ! { dg-final { scan-tree-dump-times "map\\(force_present:o\\)" 1 "original" } } 
 ! { dg-final { scan-tree-dump-times "map\\(tofrom:p\\)" 1 "original" } } 
 ! { dg-final { scan-tree-dump-times "map\\(to:r\\)" 1 "original" } } 
diff --git a/gcc/testsuite/gfortran.dg/goacc/parallel-tree.f95 b/gcc/testsuite/gfortran.dg/goacc/parallel-tree.f95
index 2697bb79e7f..e33653bdd78 100644
--- a/gcc/testsuite/gfortran.dg/goacc/parallel-tree.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/parallel-tree.f95
@@ -9,6 +9,7 @@ program test
 
   !$acc parallel if(l) async num_gangs(i) num_workers(i) vector_length(i) &
   !$acc reduction(max:q), copy(i), copyin(j), copyout(k), create(m) &
+  !$acc no_create(n) &
   !$acc present(o), pcopy(p), pcopyin(r), pcopyout(s), pcreate(t) &
   !$acc deviceptr(u), private(v), firstprivate(w)
   !$acc end parallel
@@ -28,7 +29,7 @@ end program test
 ! { dg-final { scan-tree-dump-times "map\\(to:j\\)" 1 "original" } } 
 ! { dg-final { scan-tree-dump-times "map\\(from:k\\)" 1 "original" } } 
 ! { dg-final { scan-tree-dump-times "map\\(alloc:m\\)" 1 "original" } } 
-
+! { dg-final { scan-tree-dump-times "map\\(no_alloc:n\\)" 1 "original" } } 
 ! { dg-final { scan-tree-dump-times "map\\(force_present:o\\)" 1 "original" } } 
 ! { dg-final { scan-tree-dump-times "map\\(tofrom:p\\)" 1 "original" } } 
 ! { dg-final { scan-tree-dump-times "map\\(to:r\\)" 1 "original" } } 
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 1cf7a912133..603617358ae 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -788,6 +788,9 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
 	case GOMP_MAP_POINTER:
 	  pp_string (pp, "alloc");
 	  break;
+	case GOMP_MAP_IF_PRESENT:
+	  pp_string (pp, "no_alloc");
+	  break;
 	case GOMP_MAP_TO:
 	case GOMP_MAP_TO_PSET:
 	  pp_string (pp, "to");
diff --git a/include/gomp-constants.h b/include/gomp-constants.h
index 9e356cdfeec..79c5de38db5 100644
--- a/include/gomp-constants.h
+++ b/include/gomp-constants.h
@@ -75,6 +75,8 @@ enum gomp_map_kind
     GOMP_MAP_DEVICE_RESIDENT =		(GOMP_MAP_FLAG_SPECIAL_1 | 1),
     /* OpenACC link.  */
     GOMP_MAP_LINK =			(GOMP_MAP_FLAG_SPECIAL_1 | 2),
+    /* Use device data if present, fall back to host address otherwise.  */
+    GOMP_MAP_IF_PRESENT =			(GOMP_MAP_FLAG_SPECIAL_1 | 3),
     /* Do not map, copy bits for firstprivate instead.  */
     GOMP_MAP_FIRSTPRIVATE =		(GOMP_MAP_FLAG_SPECIAL | 0),
     /* Similarly, but store the value in the pointer rather than
diff --git a/libgomp/target.c b/libgomp/target.c
index 84d6daa76ca..467ebc0772b 100644
--- a/libgomp/target.c
+++ b/libgomp/target.c
@@ -667,6 +667,13 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
 	  has_firstprivate = true;
 	  continue;
 	}
+      else if ((kind & typemask) == GOMP_MAP_IF_PRESENT)
+	{
+	  tgt->list[i].key = NULL;
+	  tgt->list[i].offset = 0;
+	  has_firstprivate = true;
+	  continue;
+	}
       cur_node.host_start = (uintptr_t) hostaddrs[i];
       if (!GOMP_MAP_POINTER_P (kind & typemask))
 	cur_node.host_end = cur_node.host_start + sizes[i];
@@ -892,6 +899,49 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
 		cur_node.tgt_offset = n->tgt->tgt_start + n->tgt_offset
 				      + cur_node.host_start - n->host_start;
 		continue;
+	      case GOMP_MAP_IF_PRESENT:
+		{
+		  cur_node.host_start = (uintptr_t) hostaddrs[i];
+		  cur_node.host_end = cur_node.host_start + sizes[i];
+		  splay_tree_key n = splay_tree_lookup (mem_map, &cur_node);
+		  if (n != NULL)
+		    {
+		      tgt->list[i].key = n;
+		      tgt->list[i].offset = cur_node.host_start - n->host_start;
+		      tgt->list[i].length = n->host_end - n->host_start;
+		      tgt->list[i].copy_from = false;
+		      tgt->list[i].always_copy_from = false;
+		      n->refcount++;
+		    }
+		  else
+		    {
+		      tgt->list[i].key = NULL;
+		      tgt->list[i].offset = OFFSET_INLINED;
+		      tgt->list[i].length = sizes[i];
+		      tgt->list[i].copy_from = false;
+		      tgt->list[i].always_copy_from = false;
+		      if (i + 1 < mapnum)
+			{
+			  int kind2 = get_kind (short_mapkind, kinds, i + 1);
+			  switch (kind2 & typemask)
+			    {
+			    case GOMP_MAP_POINTER:
+			      /* The data is not present but we have an attach
+				 or pointer clause next.  Skip over it.  */
+			      i++;
+			      tgt->list[i].key = NULL;
+			      tgt->list[i].offset = OFFSET_INLINED;
+			      tgt->list[i].length = sizes[i];
+			      tgt->list[i].copy_from = false;
+			      tgt->list[i].always_copy_from = false;
+			      break;
+			    default:
+			      break;
+			    }
+			}
+		    }
+		  continue;
+		}
 	      default:
 		break;
 	      }
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/no_create-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/no_create-1.c
new file mode 100644
index 00000000000..c7a1bd9c015
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/no_create-1.c
@@ -0,0 +1,40 @@
+/* Test no_create clause when data is present on the device.  */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <openacc.h>
+
+#define N 128
+
+int
+main (int argc, char *argv[])
+{
+  int *arr = (int *) malloc (N * sizeof (*arr));
+  int *devptr;
+
+  acc_copyin (arr, N * sizeof (*arr));
+
+  #pragma acc parallel no_create(arr[0:N]) copyout(devptr)
+  {
+    devptr = &arr[2];
+  }
+
+#if !ACC_MEM_SHARED
+  if (acc_hostptr (devptr) != (void *) &arr[2])
+    __builtin_abort ();
+#endif
+
+  acc_delete (arr, N * sizeof (*arr));
+
+#if ACC_MEM_SHARED
+  if (&arr[2] != devptr)
+    __builtin_abort ();
+#else
+  if (&arr[2] == devptr)
+    __builtin_abort ();
+#endif
+
+  free (arr);
+
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/no_create-2.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/no_create-2.c
new file mode 100644
index 00000000000..2964a40b217
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/no_create-2.c
@@ -0,0 +1,28 @@
+/* Test no_create clause when data is not present on the device.  */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#define N 128
+
+int
+main (int argc, char *argv[])
+{
+  int *arr = (int *) malloc (N * sizeof (*arr));
+  int *devptr;
+
+  #pragma acc data no_create(arr[0:N])
+  {
+    #pragma acc parallel copyout(devptr)
+    {
+      devptr = &arr[2];
+    }
+  }
+
+  if (devptr != &arr[2])
+    __builtin_abort ();
+
+  free (arr);
+
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/no_create-3.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/no_create-3.c
new file mode 100644
index 00000000000..418ff216612
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/no_create-3.c
@@ -0,0 +1,24 @@
+#include <float.h>  /* For FLT_EPSILON. */
+#include <math.h>  /* For fabs.  */
+#include <stdlib.h>  /* For abort.  */
+
+int main()
+{
+#define N 100
+  float b[N];
+  float c[N];
+
+#pragma acc enter data create(b)
+
+#pragma acc parallel loop no_create(b) no_create(c)
+  for (int i = 0; i < N; ++i)
+    b[i] = i;
+
+#pragma acc exit data copyout(b)
+
+  for (int i = 0; i < N; ++i)
+    if (fabs (b[i] - i) > 10.0*FLT_EPSILON)
+      abort ();
+
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/no_create-1.f90 b/libgomp/testsuite/libgomp.oacc-fortran/no_create-1.f90
new file mode 100644
index 00000000000..ca9611b777c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/no_create-1.f90
@@ -0,0 +1,35 @@
+! { dg-do run }
+
+! Test no_create clause with data construct when data is present/not present.
+
+program nocreate
+  use openacc
+  implicit none
+  logical :: shared_memory
+  integer, parameter :: n = 512
+  integer :: myarr(n)
+  integer i
+
+  shared_memory = .false.
+  !$acc kernels copyin (shared_memory)
+  shared_memory = .true.
+  !$acc end kernels
+
+  do i = 1, n
+    myarr(i) = 0
+  end do
+
+  !$acc data no_create (myarr)
+  if (acc_is_present (myarr) .neqv. shared_memory) stop 1
+  !$acc end data
+
+  !$acc enter data copyin (myarr)
+  !$acc data no_create (myarr)
+  if (acc_is_present (myarr) .eqv. .false.) stop 2
+  !$acc end data
+  !$acc exit data copyout (myarr)
+
+  do i = 1, n
+    if (myarr(i) .ne. 0) stop 3
+  end do
+end program nocreate
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/no_create-2.f90 b/libgomp/testsuite/libgomp.oacc-fortran/no_create-2.f90
new file mode 100644
index 00000000000..16227b8ae22
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/no_create-2.f90
@@ -0,0 +1,71 @@
+! { dg-do run }
+
+! Test no_create clause with data/parallel constructs.
+
+program nocreate
+  use openacc
+  implicit none
+  logical :: shared_memory
+  integer, parameter :: n = 512
+  integer :: myarr(n)
+  integer i
+
+  shared_memory = .false.
+  !$acc kernels copyin (shared_memory)
+  shared_memory = .true.
+  !$acc end kernels
+
+  do i = 1, n
+    myarr(i) = 0
+  end do
+
+  call do_on_target(myarr, n)
+
+  do i = 1, n
+    if (shared_memory) then
+      if (myarr(i) .ne. i * 2) stop 1
+    else
+      if (myarr(i) .ne. i) stop 2
+    end if
+  end do
+
+  do i = 1, n
+    myarr(i) = 0
+  end do
+
+  !$acc enter data copyin(myarr)
+  call do_on_target(myarr, n)
+  !$acc exit data copyout(myarr)
+
+  do i = 1, n
+    if (myarr(i) .ne. i * 2) stop 3
+  end do
+end program nocreate
+
+subroutine do_on_target (arr, n)
+  use openacc
+  implicit none
+  integer :: n, arr(n)
+  integer :: i
+
+!$acc data no_create (arr)
+
+if (acc_is_present(arr)) then
+  ! The no_create clause is meant for partially shared-memory machines.  This
+  ! test is written to work on non-shared-memory machines, though this is not
+  ! necessarily a useful way to use the no_create clause in practice.
+
+  !$acc parallel loop no_create (arr)
+  do i = 1, n
+    arr(i) = i * 2
+  end do
+  !$acc end parallel loop
+else
+  do i = 1, n
+    arr(i) = i
+  end do
+end if
+
+!$acc end data
+
+end subroutine do_on_target
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/no_create-3.f90 b/libgomp/testsuite/libgomp.oacc-fortran/no_create-3.f90
new file mode 100644
index 00000000000..739e8356581
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/no_create-3.f90
@@ -0,0 +1,21 @@
+! { dg-do run }
+
+program main
+  implicit none
+  integer i
+  integer, parameter :: n = 100
+  real*4 b(n), c(n)
+  real :: d(n), e(n)
+  common /BLOCK/ d, e
+
+  !$acc enter data create(b) create(d)
+  !$acc parallel loop no_create(b) no_create(c) no_create(/BLOCK/)
+  do i = 1, n
+     b(i) = i
+     d(i) = -i
+  end do
+  !$acc end parallel loop
+  !$acc exit data copyout(b) copyout(d)
+  if (any(abs(b - [(real(i), i = 1, n)]) > 10*epsilon(b))) stop 1
+  if (any(abs(d - [(real(-i), i = 1, n)]) > 10*epsilon(d))) stop 2
+end program main

Reply via email to