public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/omp/gcc-10] [PATCH] OpenMP/Fortran: Fix (re)mapping of allocatable/pointer arrays [PR96668]
@ 2020-09-15  8:44 Tobias Burnus
  0 siblings, 0 replies; only message in thread
From: Tobias Burnus @ 2020-09-15  8:44 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:a93cc85210334f821e2c269336a155ecde1612cb

commit a93cc85210334f821e2c269336a155ecde1612cb
Author: Tobias Burnus <tobias@codesourcery.com>
Date:   Tue Sep 15 10:42:55 2020 +0200

    [PATCH] OpenMP/Fortran: Fix (re)mapping of allocatable/pointer arrays [PR96668]
    
    gcc/cp/ChangeLog:
    
            PR fortran/96668
            * cp-gimplify.c (cxx_omp_finish_clause): Add bool openacc arg.
            * cp-tree.h (cxx_omp_finish_clause): Likewise
            * semantics.c (handle_omp_for_class_iterator): Update call.
    
    gcc/fortran/ChangeLog:
    
            PR fortran/96668
            * trans.h (gfc_omp_finish_clause): Add bool openacc arg.
            * trans-openmp.c (gfc_omp_finish_clause): Ditto. Use
            GOMP_MAP_ALWAYS_POINTER with PSET for pointers.
            (gfc_trans_omp_clauses): Like the latter and also if the always
            modifier is used.
    
    gcc/ChangeLog:
    
            PR fortran/96668
            * gimplify.c (gimplify_omp_for): Add 'bool openacc' argument;
            update omp_finish_clause calls.
            (gimplify_adjust_omp_clauses_1, gimplify_adjust_omp_clauses,
            gimplify_expr, gimplify_omp_loop): Update omp_finish_clause
            and/or gimplify_for calls.
            * langhooks-def.h (lhd_omp_finish_clause): Add bool openacc arg.
            * langhooks.c (lhd_omp_finish_clause): Likewise.
            * langhooks.h (lhd_omp_finish_clause): Likewise.
            * omp-low.c (scan_sharing_clauses): Keep GOMP_MAP_TO_PSET cause for
            'declare target' vars.
    
    include/ChangeLog:
    
            PR fortran/96668
            * gomp-constants.h (GOMP_MAP_ALWAYS_POINTER_P): Define.
    
    libgomp/ChangeLog:
    
            PR fortran/96668
            * libgomp.h (struct target_var_desc): Add has_null_ptr_assoc member.
            * target.c (gomp_map_vars_existing): Add always_to_flag flag.
            (gomp_map_vars_existing): Update call to it.
            (gomp_map_fields_existing): Likewise
            (gomp_map_vars_internal): Update PSET handling such that if a nullptr is
            now allocated or if GOMP_MAP_POINTER is used PSET is updated and pointer
            remapped.
            (GOMP_target_enter_exit_data): Hanlde GOMP_MAP_ALWAYS_POINTER like
            GOMP_MAP_POINTER.
            * testsuite/libgomp.fortran/map-alloc-ptr-1.f90: New test.
            * testsuite/libgomp.fortran/map-alloc-ptr-2.f90: New test.
    
    (cherry picked from commit 972da557463ec946a31577294764a186b9821012)

Diff:
---
 gcc/ChangeLog.omp                                  |  17 ++
 gcc/cp/ChangeLog.omp                               |  10 ++
 gcc/cp/cp-gimplify.c                               |   2 +-
 gcc/cp/cp-tree.h                                   |   2 +-
 gcc/cp/semantics.c                                 |   4 +-
 gcc/fortran/ChangeLog.omp                          |  12 ++
 gcc/fortran/trans-openmp.c                         |  31 +++-
 gcc/fortran/trans.h                                |   2 +-
 gcc/gimplify.c                                     |  25 ++-
 gcc/langhooks-def.h                                |   2 +-
 gcc/langhooks.c                                    |   2 +-
 gcc/langhooks.h                                    |   2 +-
 gcc/omp-low.c                                      |   1 +
 include/ChangeLog.omp                              |   8 +
 include/gomp-constants.h                           |   3 +
 libgomp/ChangeLog.omp                              |  18 ++
 libgomp/libgomp.h                                  |   3 +
 libgomp/target.c                                   | 188 ++++++++++++++++-----
 .../testsuite/libgomp.fortran/map-alloc-ptr-1.f90  | 114 +++++++++++++
 .../testsuite/libgomp.fortran/map-alloc-ptr-2.f90  |  86 ++++++++++
 20 files changed, 472 insertions(+), 60 deletions(-)

diff --git a/gcc/ChangeLog.omp b/gcc/ChangeLog.omp
index 7d556677609..a36afa93836 100644
--- a/gcc/ChangeLog.omp
+++ b/gcc/ChangeLog.omp
@@ -1,3 +1,20 @@
+2020-09-15  Tobias Burnus  <tobias@codesourcery.com>
+
+	Backport from mainline
+	2020-09-15  Tobias Burnus  <tobias@codesourcery.com>
+
+	PR fortran/96668
+	* gimplify.c (gimplify_omp_for): Add 'bool openacc' argument;
+	update omp_finish_clause calls.
+	(gimplify_adjust_omp_clauses_1, gimplify_adjust_omp_clauses,
+	gimplify_expr, gimplify_omp_loop): Update omp_finish_clause
+	and/or gimplify_for calls.
+	* langhooks-def.h (lhd_omp_finish_clause): Add bool openacc arg.
+	* langhooks.c (lhd_omp_finish_clause): Likewise.
+	* langhooks.h (lhd_omp_finish_clause): Likewise.
+	* omp-low.c (scan_sharing_clauses): Keep GOMP_MAP_TO_PSET cause for
+	'declare target' vars.
+
 2020-09-11  Tobias Burnus  <tobias@codesourcery.com>
 
 	Backport from mainline
diff --git a/gcc/cp/ChangeLog.omp b/gcc/cp/ChangeLog.omp
index 4f9c3390058..31515f31264 100644
--- a/gcc/cp/ChangeLog.omp
+++ b/gcc/cp/ChangeLog.omp
@@ -1,3 +1,13 @@
+2020-09-15  Tobias Burnus  <tobias@codesourcery.com>
+
+	Backport from mainline
+	2020-09-15  Tobias Burnus  <tobias@codesourcery.com>
+
+	PR fortran/96668
+	* cp-gimplify.c (cxx_omp_finish_clause): Add bool openacc arg.
+	* cp-tree.h (cxx_omp_finish_clause): Likewise
+	* semantics.c (handle_omp_for_class_iterator): Update call.
+
 2020-09-01  Tobias Burnus  <tobias@codesourcery.com>
 
 	Backport from mainline
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index cc6eb2be3af..c12c50775e5 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -2015,7 +2015,7 @@ cxx_omp_predetermined_sharing (tree decl)
 /* Finalize an implicitly determined clause.  */
 
 void
-cxx_omp_finish_clause (tree c, gimple_seq *)
+cxx_omp_finish_clause (tree c, gimple_seq *, bool /* openacc */)
 {
   tree decl, inner_type;
   bool make_shared = false;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1c03b927f0a..b58248c71b7 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7746,7 +7746,7 @@ extern tree cxx_omp_clause_default_ctor		(tree, tree, tree);
 extern tree cxx_omp_clause_copy_ctor		(tree, tree, tree);
 extern tree cxx_omp_clause_assign_op		(tree, tree, tree);
 extern tree cxx_omp_clause_dtor			(tree, tree);
-extern void cxx_omp_finish_clause		(tree, gimple_seq *);
+extern void cxx_omp_finish_clause		(tree, gimple_seq *, bool);
 extern bool cxx_omp_privatize_by_reference	(const_tree);
 extern bool cxx_omp_disregard_value_expr	(tree, bool);
 extern void cp_fold_function			(tree);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 9596a87d651..7c2871eedb9 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -8785,7 +8785,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
 	{
 	  tree ivc = build_omp_clause (locus, OMP_CLAUSE_FIRSTPRIVATE);
 	  OMP_CLAUSE_DECL (ivc) = iter;
-	  cxx_omp_finish_clause (ivc, NULL);
+	  cxx_omp_finish_clause (ivc, NULL, false);
 	  OMP_CLAUSE_CHAIN (ivc) = clauses;
 	  clauses = ivc;
 	}
@@ -8817,7 +8817,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
 	  OMP_CLAUSE_CODE (loop_iv_seen) = OMP_CLAUSE_FIRSTPRIVATE;
 	}
       if (OMP_CLAUSE_CODE (loop_iv_seen) == OMP_CLAUSE_FIRSTPRIVATE)
-	cxx_omp_finish_clause (loop_iv_seen, NULL);
+	cxx_omp_finish_clause (loop_iv_seen, NULL, false);
     }
 
   orig_pre_body = *pre_body;
diff --git a/gcc/fortran/ChangeLog.omp b/gcc/fortran/ChangeLog.omp
index 986eb7d31f2..c547f71a054 100644
--- a/gcc/fortran/ChangeLog.omp
+++ b/gcc/fortran/ChangeLog.omp
@@ -1,3 +1,15 @@
+2020-09-15  Tobias Burnus  <tobias@codesourcery.com>
+
+	Backport from mainline
+	2020-09-15  Tobias Burnus  <tobias@codesourcery.com>
+
+	PR fortran/96668
+	* trans.h (gfc_omp_finish_clause): Add bool openacc arg.
+	* trans-openmp.c (gfc_omp_finish_clause): Ditto. Use
+	GOMP_MAP_ALWAYS_POINTER with PSET for pointers.
+	(gfc_trans_omp_clauses): Like the latter and also if the always
+	modifier is used.
+
 2020-09-09  Tobias Burnus  <tobias@codesourcery.com>
 
 	Backport from mainline
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index d1a0bd2a682..877b0fe380a 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -1257,7 +1257,7 @@ gfc_build_cond_assign_expr (stmtblock_t *block, tree cond_val,
 }
 
 void
-gfc_omp_finish_clause (tree c, gimple_seq *pre_p)
+gfc_omp_finish_clause (tree c, gimple_seq *pre_p, bool openacc)
 {
   if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
     return;
@@ -1349,6 +1349,16 @@ gfc_omp_finish_clause (tree c, gimple_seq *pre_p)
       tree type = TREE_TYPE (decl);
       tree ptr = gfc_conv_descriptor_data_get (decl);
 
+      /* OpenMP: automatically map pointer targets with the pointer;
+	 hence, always update the descriptor/pointer itself.
+	 NOTE: This also remaps the pointer for allocatable arrays with
+	 'target' attribute which also don't have the 'restrict' qualifier.  */
+      bool always_modifier = false;
+
+      if (!openacc
+	  && !(TYPE_QUALS (TREE_TYPE (ptr)) & TYPE_QUAL_RESTRICT))
+	always_modifier = true;
+
       if (present)
 	ptr = gfc_build_cond_assign_expr (&block, present, ptr,
 					  null_pointer_node);
@@ -1368,7 +1378,8 @@ gfc_omp_finish_clause (tree c, gimple_seq *pre_p)
 	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_SET_MAP_KIND (c3, always_modifier ? GOMP_MAP_ALWAYS_POINTER
+						   : GOMP_MAP_POINTER);
       if (present)
 	{
 	  ptr = gfc_conv_descriptor_data_get (decl);
@@ -2540,11 +2551,19 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
 	      if (!n->sym->attr.referenced)
 		continue;
 
+	      bool always_modifier = false;
 	      tree node = build_omp_clause (input_location, OMP_CLAUSE_MAP);
 	      tree node2 = NULL_TREE;
 	      tree node3 = NULL_TREE;
 	      tree node4 = NULL_TREE;
 
+	      /* OpenMP: automatically map pointer targets with the pointer;
+		 hence, always update the descriptor/pointer itself.  */
+	      if (!openacc
+		  && ((n->expr == NULL && n->sym->attr.pointer)
+		      || (n->expr && gfc_expr_attr (n->expr).pointer)))
+		always_modifier = true;
+
 	      switch (n->u.map_op)
 		{
 		case OMP_MAP_ALLOC:
@@ -2566,12 +2585,15 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TOFROM);
 		  break;
 		case OMP_MAP_ALWAYS_TO:
+		  always_modifier = true;
 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TO);
 		  break;
 		case OMP_MAP_ALWAYS_FROM:
+		  always_modifier = true;
 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_FROM);
 		  break;
 		case OMP_MAP_ALWAYS_TOFROM:
+		  always_modifier = true;
 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TOFROM);
 		  break;
 		case OMP_MAP_RELEASE:
@@ -2735,7 +2757,10 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
 		      OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
 		      node3 = build_omp_clause (input_location,
 						OMP_CLAUSE_MAP);
-		      OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER);
+		      OMP_CLAUSE_SET_MAP_KIND (node3,
+					       always_modifier
+					       ? GOMP_MAP_ALWAYS_POINTER
+					       : GOMP_MAP_POINTER);
 		      if (present)
 			{
 			  ptr = gfc_conv_descriptor_data_get (decl);
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 2627da3abdd..cc7be35d839 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -809,7 +809,7 @@ tree gfc_omp_clause_copy_ctor (tree, tree, tree);
 tree gfc_omp_clause_assign_op (tree, tree, tree);
 tree gfc_omp_clause_linear_ctor (tree, tree, tree, tree);
 tree gfc_omp_clause_dtor (tree, tree);
-void gfc_omp_finish_clause (tree, gimple_seq *);
+void gfc_omp_finish_clause (tree, gimple_seq *, bool);
 bool gfc_omp_scalar_p (tree);
 bool gfc_omp_disregard_value_expr (tree, bool);
 bool gfc_omp_private_debug_clause (tree, bool);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 9484117a8bc..8cf2a681d80 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -10330,7 +10330,8 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
       OMP_CLAUSE_CHAIN (clause) = nc;
       struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
       gimplify_omp_ctxp = ctx->outer_context;
-      lang_hooks.decls.omp_finish_clause (nc, pre_p);
+      lang_hooks.decls.omp_finish_clause (nc, pre_p,
+					  (ctx->region_type & ORT_ACC) != 0);
       gimplify_omp_ctxp = ctx;
     }
   *list_p = clause;
@@ -10338,7 +10339,8 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
   gimplify_omp_ctxp = ctx->outer_context;
   gomp_map_kind kind = (code == OMP_CLAUSE_MAP) ? OMP_CLAUSE_MAP_KIND (clause)
 						: (gomp_map_kind) GOMP_MAP_LAST;
-  lang_hooks.decls.omp_finish_clause (clause, pre_p);
+  lang_hooks.decls.omp_finish_clause (clause, pre_p,
+				      (ctx->region_type & ORT_ACC) != 0);
   /* Allow OpenACC to have implicit assumed-size arrays via FORCE_PRESENT,
      which should work as long as the array has previously been mapped
      explicitly on the target (e.g. by "enter data").  Raise an error for
@@ -10762,7 +10764,9 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
 		  OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_TOFROM);
 		  OMP_CLAUSE_DECL (nc) = decl;
 		  OMP_CLAUSE_CHAIN (c) = nc;
-		  lang_hooks.decls.omp_finish_clause (nc, pre_p);
+		  lang_hooks.decls.omp_finish_clause (nc, pre_p,
+						      (ctx->region_type
+						       & ORT_ACC) != 0);
 		  while (1)
 		    {
 		      OMP_CLAUSE_MAP_IN_REDUCTION (nc) = 1;
@@ -11323,6 +11327,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
   int i;
   bitmap has_decl_expr = NULL;
   enum omp_region_type ort = ORT_WORKSHARE;
+  bool openacc = TREE_CODE (*expr_p) == OACC_LOOP;
 
   orig_for_stmt = for_stmt = *expr_p;
 
@@ -11430,7 +11435,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
 		OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
 		OMP_FOR_CLAUSES (for_stmt) = c;
 		OMP_CLAUSE_CODE (*pc) = OMP_CLAUSE_FIRSTPRIVATE;
-		lang_hooks.decls.omp_finish_clause (*pc, pre_p);
+		lang_hooks.decls.omp_finish_clause (*pc, pre_p, openacc);
 	      }
 	    else
 	      {
@@ -11442,7 +11447,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
 		OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (*pc);
 		OMP_CLAUSE_CHAIN (c) = *pc;
 		*pc = c;
-		lang_hooks.decls.omp_finish_clause (*pc, pre_p);
+		lang_hooks.decls.omp_finish_clause (*pc, pre_p, openacc);
 	      }
 	    tree c = build_omp_clause (UNKNOWN_LOCATION,
 				       OMP_CLAUSE_FIRSTPRIVATE);
@@ -12382,7 +12387,8 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
 		  = build_omp_clause (OMP_CLAUSE_LOCATION (c),
 				      OMP_CLAUSE_FIRSTPRIVATE);
 		OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
-		lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL);
+		lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL,
+						    openacc);
 		gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
 		*gforo_clauses_ptr = c;
 		gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
@@ -12421,7 +12427,8 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
 		  = build_omp_clause (OMP_CLAUSE_LOCATION (c),
 				      OMP_CLAUSE_FIRSTPRIVATE);
 		OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
-		lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL);
+		lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL,
+						    openacc);
 		gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
 		OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c) = 1;
 		*gforo_clauses_ptr = build_omp_clause (OMP_CLAUSE_LOCATION (c),
@@ -12774,7 +12781,7 @@ gimplify_omp_loop (tree *expr_p, gimple_seq *pre_p)
 		*pc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
 					OMP_CLAUSE_FIRSTPRIVATE);
 		OMP_CLAUSE_DECL (*pc) = OMP_CLAUSE_DECL (c);
-		lang_hooks.decls.omp_finish_clause (*pc, NULL);
+		lang_hooks.decls.omp_finish_clause (*pc, NULL, false);
 		pc = &OMP_CLAUSE_CHAIN (*pc);
 	      }
 	    *pc = copy_node (c);
@@ -12785,7 +12792,7 @@ gimplify_omp_loop (tree *expr_p, gimple_seq *pre_p)
 		if (pass != last)
 		  OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (*pc) = 1;
 		else
-		  lang_hooks.decls.omp_finish_clause (*pc, NULL);
+		  lang_hooks.decls.omp_finish_clause (*pc, NULL, false);
 		OMP_CLAUSE_LASTPRIVATE_LOOP_IV (*pc) = 0;
 	      }
 	    pc = &OMP_CLAUSE_CHAIN (*pc);
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index 82aeb653085..e27fb717ac5 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -80,7 +80,7 @@ extern bool lhd_handle_option (size_t, const char *, HOST_WIDE_INT, int,
 extern int lhd_gimplify_expr (tree *, gimple_seq *, gimple_seq *);
 extern enum omp_clause_default_kind lhd_omp_predetermined_sharing (tree);
 extern tree lhd_omp_assignment (tree, tree, tree);
-extern void lhd_omp_finish_clause (tree, gimple_seq *);
+extern void lhd_omp_finish_clause (tree, gimple_seq *, bool);
 struct gimplify_omp_ctx;
 extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *,
 					       tree);
diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index 5e3216da631..80efed02458 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -597,7 +597,7 @@ lhd_omp_assignment (tree clause ATTRIBUTE_UNUSED, tree dst, tree src)
 /* Finalize clause C.  */
 
 void
-lhd_omp_finish_clause (tree, gimple_seq *)
+lhd_omp_finish_clause (tree, gimple_seq *, bool)
 {
 }
 
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 83069a9cf7f..0d208f7d31a 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -290,7 +290,7 @@ struct lang_hooks_for_decls
   tree (*omp_clause_dtor) (tree clause, tree decl);
 
   /* Do language specific checking on an implicitly determined clause.  */
-  void (*omp_finish_clause) (tree clause, gimple_seq *pre_p);
+  void (*omp_finish_clause) (tree clause, gimple_seq *pre_p, bool);
 
   /* Return true if DECL is a scalar variable (for the purpose of
      implicit firstprivatization).  */
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 5269d31bdfc..a740c6e4146 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -1558,6 +1558,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx,
 	      && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_TO
 	      && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_FROM
 	      && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_TOFROM
+	      && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_TO_PSET
 	      && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
 	      && varpool_node::get_create (decl)->offloadable
 	      && !lookup_attribute ("omp declare target link",
diff --git a/include/ChangeLog.omp b/include/ChangeLog.omp
index 13c1a1644d2..3e1bdd5e922 100644
--- a/include/ChangeLog.omp
+++ b/include/ChangeLog.omp
@@ -1,3 +1,11 @@
+2020-09-15  Tobias Burnus  <tobias@codesourcery.com>
+
+	Backport from mainline
+	2020-09-15  Tobias Burnus  <tobias@codesourcery.com>
+
+	PR fortran/96668
+	* gomp-constants.h (GOMP_MAP_ALWAYS_POINTER_P): Define.
+
 2018-10-04  Cesar Philippidis  <cesar@codesourcery.com>
             Julian Brown  <julian@codesourcery.com>
 
diff --git a/include/gomp-constants.h b/include/gomp-constants.h
index 02a4c429adf..f2d15f65b67 100644
--- a/include/gomp-constants.h
+++ b/include/gomp-constants.h
@@ -197,6 +197,9 @@ enum gomp_map_kind
   (!((X) & GOMP_MAP_FLAG_SPECIAL) \
    && ((X) & GOMP_MAP_FLAG_FROM))
 
+#define GOMP_MAP_ALWAYS_POINTER_P(X) \
+  ((X) == GOMP_MAP_ALWAYS_POINTER)
+
 #define GOMP_MAP_POINTER_P(X) \
   ((X) == GOMP_MAP_POINTER)
 
diff --git a/libgomp/ChangeLog.omp b/libgomp/ChangeLog.omp
index 6b7c71c58be..3e57a6cff39 100644
--- a/libgomp/ChangeLog.omp
+++ b/libgomp/ChangeLog.omp
@@ -1,3 +1,21 @@
+2020-09-15  Tobias Burnus  <tobias@codesourcery.com>
+
+	Backport from mainline
+	2020-09-15  Tobias Burnus  <tobias@codesourcery.com>
+
+	PR fortran/96668
+	* libgomp.h (struct target_var_desc): Add has_null_ptr_assoc member.
+	* target.c (gomp_map_vars_existing): Add always_to_flag flag.
+	(gomp_map_vars_existing): Update call to it.
+	(gomp_map_fields_existing): Likewise
+	(gomp_map_vars_internal): Update PSET handling such that if a nullptr is
+	now allocated or if GOMP_MAP_POINTER is used PSET is updated and pointer
+	remapped.
+	(GOMP_target_enter_exit_data): Hanlde GOMP_MAP_ALWAYS_POINTER like
+	GOMP_MAP_POINTER.
+	* testsuite/libgomp.fortran/map-alloc-ptr-1.f90: New test.
+	* testsuite/libgomp.fortran/map-alloc-ptr-2.f90: New test.
+
 2020-09-14  Tobias Burnus  <tobias@codesourcery.com>
 
 	Backport from mainline
diff --git a/libgomp/libgomp.h b/libgomp/libgomp.h
index 9d7899aa38e..d37fcb84b0c 100644
--- a/libgomp/libgomp.h
+++ b/libgomp/libgomp.h
@@ -954,6 +954,9 @@ struct target_var_desc {
   bool always_copy_from;
   /* True if this is for OpenACC 'attach'.  */
   bool is_attach;
+  /* If GOMP_MAP_TO_PSET had a NULL pointer; used for Fortran descriptors,
+     which were initially unallocated.  */
+  bool has_null_ptr_assoc;
   /* Relative offset against key host_start.  */
   uintptr_t offset;
   /* Actual length.  */
diff --git a/libgomp/target.c b/libgomp/target.c
index a1558a2711a..03b65786fdd 100644
--- a/libgomp/target.c
+++ b/libgomp/target.c
@@ -360,7 +360,8 @@ static inline void
 gomp_map_vars_existing (struct gomp_device_descr *devicep,
 			struct goacc_asyncqueue *aq, splay_tree_key oldn,
 			splay_tree_key newn, struct target_var_desc *tgt_var,
-			unsigned char kind, struct gomp_coalesce_buf *cbuf)
+			unsigned char kind, bool always_to_flag,
+			struct gomp_coalesce_buf *cbuf)
 {
   assert (kind != GOMP_MAP_ATTACH);
 
@@ -382,7 +383,7 @@ gomp_map_vars_existing (struct gomp_device_descr *devicep,
 		  (void *) oldn->host_start, (void *) oldn->host_end);
     }
 
-  if (GOMP_MAP_ALWAYS_TO_P (kind))
+  if (GOMP_MAP_ALWAYS_TO_P (kind) || always_to_flag)
     gomp_copy_host2dev (devicep, aq,
 			(void *) (oldn->tgt->tgt_start + oldn->tgt_offset
 				  + newn->host_start - oldn->host_start),
@@ -462,8 +463,8 @@ gomp_map_fields_existing (struct target_mem_desc *tgt,
       && n2->tgt == n->tgt
       && n2->host_start - n->host_start == n2->tgt_offset - n->tgt_offset)
     {
-      gomp_map_vars_existing (devicep, aq, n2, &cur_node,
-			      &tgt->list[i], kind & typemask, cbuf);
+      gomp_map_vars_existing (devicep, aq, n2, &cur_node, &tgt->list[i],
+			      kind & typemask, false, cbuf);
       return;
     }
   if (sizes[i] == 0)
@@ -478,8 +479,8 @@ gomp_map_fields_existing (struct target_mem_desc *tgt,
 	      && n2->host_start - n->host_start
 		 == n2->tgt_offset - n->tgt_offset)
 	    {
-	      gomp_map_vars_existing (devicep, aq, n2, &cur_node,
-				      &tgt->list[i], kind & typemask, cbuf);
+	      gomp_map_vars_existing (devicep, aq, n2, &cur_node, &tgt->list[i],
+				      kind & typemask, false, cbuf);
 	      return;
 	    }
 	}
@@ -491,7 +492,7 @@ gomp_map_fields_existing (struct target_mem_desc *tgt,
 	  && n2->host_start - n->host_start == n2->tgt_offset - n->tgt_offset)
 	{
 	  gomp_map_vars_existing (devicep, aq, n2, &cur_node, &tgt->list[i],
-				  kind & typemask, cbuf);
+				  kind & typemask, false, cbuf);
 	  return;
 	}
     }
@@ -668,6 +669,7 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
   size_t i, tgt_align, tgt_size, not_found_cnt = 0;
   size_t nca_data_row_num = (nca_info ? nca_info->num_data_rows : 0);
   bool has_firstprivate = false;
+  bool has_always_ptrset = false;
   const int rshift = short_mapkind ? 8 : 3;
   const int typemask = short_mapkind ? 0xff : 0x7;
   struct splay_tree_s *mem_map = &devicep->mem_map;
@@ -880,8 +882,55 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
       else
 	n = splay_tree_lookup (mem_map, &cur_node);
       if (n && n->refcount != REFCOUNT_LINK)
-	gomp_map_vars_existing (devicep, aq, n, &cur_node, &tgt->list[i],
-				kind & typemask, NULL);
+	{
+	  int always_to_cnt = 0;
+	  if ((kind & typemask) == GOMP_MAP_TO_PSET)
+	    {
+	      bool has_nullptr;
+	      size_t j;
+	      for (j = 0; j < n->tgt->list_count; j++)
+		if (n->tgt->list[j].key == n)
+		  {
+		    has_nullptr = n->tgt->list[j].has_null_ptr_assoc;
+		    break;
+		  }
+	      if (n->tgt->list_count == 0)
+		{
+		  /* 'declare target'; assume has_nullptr; it could also be
+		     statically assigned pointer, but that it should be to
+		     the equivalent variable on the host.  */
+		  assert (n->refcount == REFCOUNT_INFINITY);
+		  has_nullptr = true;
+		}
+	      else
+		assert (j < n->tgt->list_count);
+	      /* Re-map the data if there is an 'always' modifier or if it a
+		 null pointer was there and non a nonnull has been found; that
+		 permits transparent re-mapping for Fortran array descriptors
+		 which were previously mapped unallocated.  */
+	      for (j = i + 1; j < mapnum; j++)
+		{
+		  int ptr_kind = get_kind (short_mapkind, kinds, j) & typemask;
+		  if (!GOMP_MAP_ALWAYS_POINTER_P (ptr_kind)
+		      && (!has_nullptr
+			  || !GOMP_MAP_POINTER_P (ptr_kind)
+			  || *(void **) hostaddrs[j] == NULL))
+		    break;
+		  else if ((uintptr_t) hostaddrs[j] < cur_node.host_start
+			   || ((uintptr_t) hostaddrs[j] + sizeof (void *)
+			       > cur_node.host_end))
+		    break;
+		  else
+		    {
+		      has_always_ptrset = true;
+		      ++always_to_cnt;
+		    }
+		}
+	    }
+	  gomp_map_vars_existing (devicep, aq, n, &cur_node, &tgt->list[i],
+				  kind & typemask, always_to_cnt > 0, NULL);
+	  i += always_to_cnt;
+	}
       else
 	{
 	  tgt->list[i].key = NULL;
@@ -913,9 +962,11 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
 	  if ((kind & typemask) == GOMP_MAP_TO_PSET)
 	    {
 	      size_t j;
+	      int kind;
 	      for (j = i + 1; j < mapnum; j++)
-		if (!GOMP_MAP_POINTER_P (get_kind (short_mapkind, kinds, j)
-					 & typemask))
+		if (!GOMP_MAP_POINTER_P ((kind = (get_kind (short_mapkind,
+						  kinds, j)) & typemask))
+		    && !GOMP_MAP_ALWAYS_POINTER_P (kind))
 		  break;
 		else if ((uintptr_t) hostaddrs[j] < cur_node.host_start
 			 || ((uintptr_t) hostaddrs[j] + sizeof (void *)
@@ -954,7 +1005,7 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
 		{
 		  assert (n->refcount != REFCOUNT_LINK);
 		  gomp_map_vars_existing (devicep, aq, n, &cur_node, row_desc,
-					  kind & typemask,
+					  kind & typemask, false,
 					  /* TODO: cbuf? */ NULL);
 		}
 	      else
@@ -1021,7 +1072,7 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
     tgt_size = mapnum * sizeof (void *);
 
   tgt->array = NULL;
-  if (not_found_cnt || has_firstprivate)
+  if (not_found_cnt || has_firstprivate || has_always_ptrset)
     {
       if (not_found_cnt)
 	tgt->array = gomp_malloc (not_found_cnt * sizeof (*tgt->array));
@@ -1030,7 +1081,58 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
       uintptr_t field_tgt_base = 0;
 
       for (i = 0; i < mapnum; i++)
-	if (tgt->list[i].key == NULL)
+	if (has_always_ptrset
+	    && tgt->list[i].key
+	    && (get_kind (short_mapkind, kinds, i) & typemask)
+	       == GOMP_MAP_TO_PSET)
+	  {
+	    splay_tree_key k = tgt->list[i].key;
+	    bool has_nullptr;
+	    size_t j;
+	    for (j = 0; j < k->tgt->list_count; j++)
+	      if (k->tgt->list[j].key == k)
+		{
+		  has_nullptr = k->tgt->list[j].has_null_ptr_assoc;
+		  break;
+		}
+	    if (k->tgt->list_count == 0)
+	      has_nullptr = true;
+	    else
+	      assert (j < k->tgt->list_count);
+
+	    tgt->list[i].has_null_ptr_assoc = false;
+	    for (j = i + 1; j < mapnum; j++)
+	      {
+		int ptr_kind = get_kind (short_mapkind, kinds, j) & typemask;
+		if (!GOMP_MAP_ALWAYS_POINTER_P (ptr_kind)
+		    && (!has_nullptr
+			|| !GOMP_MAP_POINTER_P (ptr_kind)
+			|| *(void **) hostaddrs[j] == NULL))
+		  break;
+		else if ((uintptr_t) hostaddrs[j] < k->host_start
+			 || ((uintptr_t) hostaddrs[j] + sizeof (void *)
+			     > k->host_end))
+		  break;
+		else
+		  {
+		    if (*(void **) hostaddrs[j] == NULL)
+		      tgt->list[i].has_null_ptr_assoc = true;
+		    tgt->list[j].key = k;
+		    tgt->list[j].copy_from = false;
+		    tgt->list[j].always_copy_from = false;
+		    tgt->list[j].is_attach = false;
+		    if (k->refcount != REFCOUNT_INFINITY)
+		      k->refcount++;
+		    gomp_map_pointer (k->tgt, aq,
+				      (uintptr_t) *(void **) hostaddrs[j],
+				      k->tgt_offset + ((uintptr_t) hostaddrs[j]
+						       - k->host_start),
+				      sizes[j], cbufp);
+		  }
+	      }
+	    i = j - 1;
+	  }
+	else if (tgt->list[i].key == NULL)
 	  {
 	    int kind = get_kind (short_mapkind, kinds, i);
 	    if (hostaddrs[i] == NULL)
@@ -1198,7 +1300,7 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
 	    splay_tree_key n = splay_tree_lookup (mem_map, k);
 	    if (n && n->refcount != REFCOUNT_LINK)
 	      gomp_map_vars_existing (devicep, aq, n, k, &tgt->list[i],
-				      kind & typemask, cbufp);
+				      kind & typemask, false, cbufp);
 	    else
 	      {
 		k->aux = NULL;
@@ -1272,32 +1374,37 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
 					(void *) k->host_start,
 					k->host_end - k->host_start, false,
 					cbufp);
+		    tgt->list[i].has_null_ptr_assoc = false;
 
 		    for (j = i + 1; j < mapnum; j++)
-		      if (!GOMP_MAP_POINTER_P (get_kind (short_mapkind, kinds,
-							 j)
-					       & typemask))
-			break;
-		      else if ((uintptr_t) hostaddrs[j] < k->host_start
-			       || ((uintptr_t) hostaddrs[j] + sizeof (void *)
-				   > k->host_end))
-			break;
-		      else
-			{
-			  tgt->list[j].key = k;
-			  tgt->list[j].copy_from = false;
-			  tgt->list[j].always_copy_from = false;
-			  tgt->list[j].is_attach = false;
-			  if (k->refcount != REFCOUNT_INFINITY)
-			    k->refcount++;
-			  gomp_map_pointer (tgt, aq,
-					    (uintptr_t) *(void **) hostaddrs[j],
-					    k->tgt_offset
-					    + ((uintptr_t) hostaddrs[j]
-					       - k->host_start),
-					    sizes[j], cbufp);
-			  i++;
+		      {
+			int ptr_kind = (get_kind (short_mapkind, kinds, j)
+					& typemask);
+			if (!GOMP_MAP_POINTER_P (ptr_kind)
+			    && !GOMP_MAP_ALWAYS_POINTER_P (ptr_kind))
+			  break;
+			else if ((uintptr_t) hostaddrs[j] < k->host_start
+				 || ((uintptr_t) hostaddrs[j] + sizeof (void *)
+				     > k->host_end))
+			  break;
+			else
+			  {
+			    tgt->list[j].key = k;
+			    tgt->list[j].copy_from = false;
+			    tgt->list[j].always_copy_from = false;
+			    tgt->list[j].is_attach = false;
+			    tgt->list[i].has_null_ptr_assoc |= !(*(void **) hostaddrs[j]);
+			    if (k->refcount != REFCOUNT_INFINITY)
+			      k->refcount++;
+			    gomp_map_pointer (tgt, aq,
+					      (uintptr_t) *(void **) hostaddrs[j],
+					      k->tgt_offset
+					      + ((uintptr_t) hostaddrs[j]
+						 - k->host_start),
+					      sizes[j], cbufp);
+			  }
 			}
+		    i = j - 1;
 		    break;
 		  case GOMP_MAP_FORCE_PRESENT:
 		    {
@@ -1380,7 +1487,7 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
 		    {
 		      assert (k->refcount != REFCOUNT_LINK);
 		      gomp_map_vars_existing (devicep, aq, k, &cur_node, row_desc,
-					      kind & typemask,
+					      kind & typemask, false,
 					      cbufp);
 		    }
 		  else
@@ -2669,7 +2776,8 @@ GOMP_target_enter_exit_data (int device, size_t mapnum, void **hostaddrs,
       else if ((kinds[i] & 0xff) == GOMP_MAP_TO_PSET)
 	{
 	  for (j = i + 1; j < mapnum; j++)
-	    if (!GOMP_MAP_POINTER_P (get_kind (true, kinds, j) & 0xff))
+	    if (!GOMP_MAP_POINTER_P (get_kind (true, kinds, j) & 0xff)
+		&& !GOMP_MAP_ALWAYS_POINTER_P (get_kind (true, kinds, j) & 0xff))
 	      break;
 	  gomp_map_vars (devicep, j-i, &hostaddrs[i], NULL, &sizes[i],
 			 &kinds[i], true, GOMP_MAP_VARS_ENTER_DATA);
diff --git a/libgomp/testsuite/libgomp.fortran/map-alloc-ptr-1.f90 b/libgomp/testsuite/libgomp.fortran/map-alloc-ptr-1.f90
new file mode 100644
index 00000000000..a1ff1d6d1e5
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/map-alloc-ptr-1.f90
@@ -0,0 +1,114 @@
+! { dg-do run }
+! 
+! PR fortran/96668
+
+implicit none
+  integer, pointer :: p1(:), p2(:), p3(:)
+  integer, allocatable :: a1(:), a2(:)
+  p1 => null()
+  p3 => null()
+
+  !$omp target enter data map(to:p3)
+
+  !$omp target data map(a1, a2, p1)
+     !$omp target
+       if (allocated (a1)) stop 1
+       if (allocated (a2)) stop 1
+       if (associated (p1)) stop 1
+       if (associated (p3)) stop 1
+     !$omp end target
+
+     allocate (a1, source=[10,11,12,13,14])
+     allocate (a2, source=[10,11,12,13,14])
+     allocate (p1, source=[9,8,7,6,5,4])
+     allocate (p3, source=[4,5,6])
+     p2 => p1
+
+     !$omp target enter data map(to:p3)
+
+     ! allocatable, TR9 requires 'always' modifier:
+     !$omp target map(always, tofrom: a1)
+       if (.not. allocated(a1)) stop 2
+       if (size(a1) /= 5) stop 3
+       if (any (a1 /= [10,11,12,13,14])) stop 5
+       a1(:) = [101, 102, 103, 104, 105]
+     !$omp end target
+
+     ! allocatable, extension (OpenMP 6.0?): without 'always'
+     !$omp target
+       if (.not. allocated(a2)) stop 2
+       if (size(a2) /= 5) stop 3
+       if (any (a2 /= [10,11,12,13,14])) stop 5
+       a2(:) = [101, 102, 103, 104, 105]
+     !$omp end target
+
+     ! pointer: target is automatically mapped
+     ! without requiring an explicit mapping or even the always modifier
+     !$omp target  !! map(always, tofrom: p1)
+       if (.not. associated(p1)) stop 7
+       if (size(p1) /= 6) stop 8
+       if (any (p1 /= [9,8,7,6,5,4])) stop 10
+       p1(:) = [-1, -2, -3, -4, -5, -6]
+     !$omp end target
+
+     !$omp target  !! map(always, tofrom: p3)
+       if (.not. associated(p3)) stop 7
+       if (size(p3) /= 3) stop 8
+       if (any (p3 /= [4,5,6])) stop 10
+       p3(:) = [23,24,25]
+     !$omp end target
+
+     if (any (p1 /= [-1, -2, -3, -4, -5, -6])) stop 141
+
+  !$omp target exit data map(from:p3)
+  !$omp target exit data map(from:p3)
+     if (any (p3 /= [23,24,25])) stop 141
+
+     allocate (p1, source=[99,88,77,66,55,44,33])
+
+     !$omp target  ! And this also should work
+       if (.not. associated(p1)) stop 7
+       if (size(p1) /= 7) stop 8
+       if (any (p1 /= [99,88,77,66,55,44,33])) stop 10
+       p1(:) = [-11, -22, -33, -44, -55, -66, -77]
+     !$omp end target
+  !$omp end target data
+
+  if (any (a1 /= [101, 102, 103, 104, 105])) stop 12
+  if (any (a2 /= [101, 102, 103, 104, 105])) stop 12
+
+  if (any (p1 /= [-11, -22, -33, -44, -55, -66, -77])) stop 142
+  if (any (p2 /= [-1, -2, -3, -4, -5, -6])) stop 143
+
+
+  block
+    integer, pointer :: tmp(:), tmp2(:), tmp3(:)
+    tmp => p1
+    tmp2 => p2
+    tmp3 => p3
+    !$omp target enter data map(to:p3)
+
+    !$omp target data map(to: p1, p2)
+      p1 => null ()
+      p2 => null ()
+      p3 => null ()
+      !$omp target map(always, tofrom: p1)
+        if (associated (p1)) stop 22
+      !$omp end target
+      if (associated (p1)) stop 22
+
+      !$omp target
+        if (associated (p2)) stop 22
+      !$omp end target
+      if (associated (p2)) stop 22
+
+      !$omp target
+        if (associated (p3)) stop 22
+      !$omp end target
+      if (associated (p3)) stop 22
+    !$omp end target data
+    !$omp target exit data map(from:p3)
+    deallocate(tmp, tmp2, tmp3) 
+  end block
+  deallocate(a1, a2)
+end
diff --git a/libgomp/testsuite/libgomp.fortran/map-alloc-ptr-2.f90 b/libgomp/testsuite/libgomp.fortran/map-alloc-ptr-2.f90
new file mode 100644
index 00000000000..c69a9bf44ad
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/map-alloc-ptr-2.f90
@@ -0,0 +1,86 @@
+! { dg-do run }
+! 
+! PR fortran/96668
+
+module m
+  implicit none
+  integer, pointer :: p1(:) => null(), p3(:) => null()
+  integer, allocatable :: a1(:), a2(:)
+  !$omp declare target to(a1, a2, p1, p3)
+end module m
+
+use m
+implicit none
+  integer, pointer :: p2(:)
+
+  !$omp target
+    if (allocated (a1)) stop 1
+    if (allocated (a2)) stop 1
+    if (associated (p1)) stop 1
+    if (associated (p3)) stop 1
+  !$omp end target
+
+  allocate (a1, source=[10,11,12,13,14])
+  allocate (a2, source=[10,11,12,13,14])
+  allocate (p1, source=[9,8,7,6,5,4])
+  allocate (p3, source=[4,5,6])
+  p2 => p1
+
+  !$omp target enter data map(to:p3)
+
+  ! allocatable, TR9 requires 'always' modifier:
+  !$omp target map(always, tofrom: a1)
+    if (.not. allocated(a1)) stop 2
+    if (size(a1) /= 5) stop 3
+    if (any (a1 /= [10,11,12,13,14])) stop 5
+    a1(:) = [101, 102, 103, 104, 105]
+  !$omp end target
+
+  ! allocatable, extension (OpenMP 6.0?): without 'always'
+  !$omp target
+    if (.not. allocated(a2)) stop 2
+    if (size(a2) /= 5) stop 3
+    if (any (a2 /= [10,11,12,13,14])) stop 5
+    a2(:) = [101, 102, 103, 104, 105]
+  !$omp end target
+
+  ! pointer: target is automatically mapped
+  ! without requiring an explicit mapping or even the always modifier
+  !$omp target  !! map(always, tofrom: p1)
+    if (.not. associated(p1)) stop 7
+    if (size(p1) /= 6) stop 8
+    if (any (p1 /= [9,8,7,6,5,4])) stop 10
+    p1(:) = [-1, -2, -3, -4, -5, -6]
+  !$omp end target
+
+  !$omp target  !! map(always, tofrom: p3)
+    if (.not. associated(p3)) stop 7
+    if (size(p3) /= 3) stop 8
+    if (any (p3 /= [4,5,6])) stop 10
+    p3(:) = [23,24,25]
+  !$omp end target
+
+  !$omp target update from(p1)
+  if (any (p1 /= [-1, -2, -3, -4, -5, -6])) stop 141
+
+  !$omp target exit data map(always, from:p3)
+  if (any (p3 /= [23,24,25])) stop 141
+
+  allocate (p1, source=[99,88,77,66,55,44,33])
+
+  !$omp target  ! And this also should work
+    if (.not. associated(p1)) stop 7
+    if (size(p1) /= 7) stop 8
+    if (any (p1 /= [99,88,77,66,55,44,33])) stop 10
+    p1(:) = [-11, -22, -33, -44, -55, -66, -77]
+  !$omp end target
+  !$omp target update from(p1)
+
+  if (any (a1 /= [101, 102, 103, 104, 105])) stop 12
+  if (any (a2 /= [101, 102, 103, 104, 105])) stop 12
+
+  if (any (p1 /= [-11, -22, -33, -44, -55, -66, -77])) stop 142
+  if (any (p2 /= [-1, -2, -3, -4, -5, -6])) stop 143
+
+  deallocate(a1, a2, p1, p2, p3)
+end


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-09-15  8:44 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-15  8:44 [gcc/devel/omp/gcc-10] [PATCH] OpenMP/Fortran: Fix (re)mapping of allocatable/pointer arrays [PR96668] Tobias Burnus

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).