diff mbox series

[12/14] OpenACC: "declare create" fixes wrt. "allocatable" variables

Message ID 8c5fc0e8a53e228dbf299ba1ee824bf8fbcc06c8.1687201316.git.julian@codesourcery.com
State New
Headers show
Series OpenMP/OpenACC: map clause and OMP gimplify rework | expand

Commit Message

Julian Brown June 19, 2023, 9:17 p.m. UTC
This patch fixes a case revealed by the previous patch where a synthetic
"acc data" region created for a "declare create" variable could interact
strangely with lexical inheritance behaviour.  In fact, it doesn't seem
right to create the "acc data" region for allocatable variables at all
-- doing so means that a data region is likely to be created for an
unallocated variable.

The fix is not to add such variables to the synthetic "acc data" region
at all, and defer to the code that performs "enter data"/"exit data"
for them when allocated/deallocated on the host instead. Then, "declare
create" variables are implicitly turned into "present" clauses on in-scope
offload regions.

2023-06-16  Julian Brown  <julian@codesourcery.com>

gcc/fortran/
	* trans-openmp.cc (gfc_omp_finish_clause): Handle "declare create" for
	scalar allocatable variables.
	(gfc_trans_omp_clauses): Don't include allocatable vars in synthetic
	"acc data" region created for "declare create" variables.  Mark such
	variables with the "oacc declare create" attribute instead.  Don't
	create ALWAYS_POINTER mapping for target-to-host updates of declare
	create variables.
	(gfc_trans_oacc_declare): Handle empty clause list.

gcc/
	* gimplify.cc (gimplify_adjust_omp_clauses_1): Handle "oacc declare
	create" attribute.

libgomp/
	* testsuite/libgomp.oacc-fortran/declare-create-1.f90: New test.
	* testsuite/libgomp.oacc-fortran/declare-create-2.f90: New test.
	* testsuite/libgomp.oacc-fortran/declare-create-3.f90: New test.
---
 gcc/fortran/trans-openmp.cc                   | 45 ++++++++++++++++---
 gcc/gimplify.cc                               |  8 ++++
 .../libgomp.oacc-fortran/declare-create-1.f90 | 21 +++++++++
 .../libgomp.oacc-fortran/declare-create-2.f90 | 25 +++++++++++
 .../libgomp.oacc-fortran/declare-create-3.f90 | 25 +++++++++++
 5 files changed, 119 insertions(+), 5 deletions(-)
 create mode 100644 libgomp/testsuite/libgomp.oacc-fortran/declare-create-1.f90
 create mode 100644 libgomp/testsuite/libgomp.oacc-fortran/declare-create-2.f90
 create mode 100644 libgomp/testsuite/libgomp.oacc-fortran/declare-create-3.f90
diff mbox series

Patch

diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index 1a14d2bc068..819d79cda28 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -1619,7 +1619,16 @@  gfc_omp_finish_clause (tree c, gimple_seq *pre_p, bool openacc)
       orig_decl = decl;
 
       c4 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
-      OMP_CLAUSE_SET_MAP_KIND (c4, GOMP_MAP_POINTER);
+      if (openacc
+	  && GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
+	  && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_PRESENT)
+	/* This allows "declare create" to work for scalar allocatables.  The
+	   resulting mapping nodes are:
+	     force_present(*var) firstprivate_pointer(var)
+	   which is the same as an explicit "present" clause gives.  */
+	OMP_CLAUSE_SET_MAP_KIND (c4, GOMP_MAP_FIRSTPRIVATE_POINTER);
+      else
+	OMP_CLAUSE_SET_MAP_KIND (c4, GOMP_MAP_POINTER);
       OMP_CLAUSE_DECL (c4) = decl;
       OMP_CLAUSE_SIZE (c4) = size_int (0);
       decl = build_fold_indirect_ref (decl);
@@ -4588,6 +4597,29 @@  gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
 	      if (!n->sym->attr.referenced)
 		continue;
 
+	      /* We do not want to include allocatable vars in a synthetic
+		 "acc data" region created for "!$acc declare create" vars.
+		 Such variables are handled by augmenting allocate/deallocate
+		 statements elsewhere (with
+		 "acc enter data declare_allocate(...)", etc.).  */
+	      if (op == EXEC_OACC_DECLARE
+		  && n->u.map_op == OMP_MAP_ALLOC
+		  && n->sym->attr.allocatable
+		  && n->sym->attr.oacc_declare_create)
+		{
+		  tree tree_var = gfc_get_symbol_decl (n->sym);
+		  if (!lookup_attribute ("oacc declare create",
+					 DECL_ATTRIBUTES (tree_var)))
+		    DECL_ATTRIBUTES (tree_var)
+		      = tree_cons (get_identifier ("oacc declare create"),
+				   NULL_TREE, DECL_ATTRIBUTES (tree_var));
+		  /* We might need to turn what would normally be a
+		     "firstprivate" mapping into a "present" mapping.  For the
+		     latter, we need the decl to be addressable.  */
+		  TREE_ADDRESSABLE (tree_var) = 1;
+		  continue;
+		}
+
 	      bool always_modifier = false;
 	      tree node = build_omp_clause (input_location, OMP_CLAUSE_MAP);
 	      tree node2 = NULL_TREE;
@@ -4780,7 +4812,8 @@  gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
 		      tree orig_decl = decl;
 		      enum gomp_map_kind gmk = GOMP_MAP_POINTER;
 		      if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
-			  && n->sym->attr.oacc_declare_create)
+			  && n->sym->attr.oacc_declare_create
+			  && n->u.map_op != OMP_MAP_FORCE_FROM)
 			{
 			  if (clauses->update_allocatable)
 			    gmk = GOMP_MAP_ALWAYS_POINTER;
@@ -9846,10 +9879,12 @@  gfc_trans_oacc_declare (gfc_code *code)
   gfc_start_block (&block);
 
   oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.oacc_declare->clauses,
-					code->loc, false, true);
+					code->loc, false, true,
+					EXEC_OACC_DECLARE);
   stmt = gfc_trans_omp_code (code->block->next, true);
-  stmt = build2_loc (input_location, construct_code, void_type_node, stmt,
-		     oacc_clauses);
+  if (oacc_clauses)
+    stmt = build2_loc (input_location, construct_code, void_type_node, stmt,
+		       oacc_clauses);
   gfc_add_expr_to_block (&block, stmt);
 
   return gfc_finish_block (&block);
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 55befa4d3c1..0706f130ebb 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -13215,6 +13215,8 @@  gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
 		g->have_offload = true;
 	    }
 	}
+      if (lookup_attribute ("oacc declare create", DECL_ATTRIBUTES (decl)))
+	flags |= GOVD_MAP_FORCE_PRESENT;
     }
   else if (flags & GOVD_SHARED)
     {
@@ -13254,6 +13256,12 @@  gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
 		 "%<target%> construct", decl);
 	  return 0;
 	}
+      if (lookup_attribute ("oacc declare create", DECL_ATTRIBUTES (decl)))
+	{
+	  code = OMP_CLAUSE_MAP;
+	  flags &= ~GOVD_FIRSTPRIVATE;
+	  flags |= GOVD_MAP | GOVD_MAP_FORCE_PRESENT;
+	}
     }
   else if (flags & GOVD_LASTPRIVATE)
     code = OMP_CLAUSE_LASTPRIVATE;
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/declare-create-1.f90 b/libgomp/testsuite/libgomp.oacc-fortran/declare-create-1.f90
new file mode 100644
index 00000000000..9e7e60f1440
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/declare-create-1.f90
@@ -0,0 +1,21 @@ 
+! { dg-do run }
+
+module m
+integer :: mint
+!$acc declare create (mint)
+end module m
+
+program p
+use m
+
+mint = 0
+
+!$acc serial
+mint = 5
+!$acc end serial
+
+!$acc update host(mint)
+
+if (mint.ne.5) stop 1
+
+end program p
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/declare-create-2.f90 b/libgomp/testsuite/libgomp.oacc-fortran/declare-create-2.f90
new file mode 100644
index 00000000000..675f6902775
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/declare-create-2.f90
@@ -0,0 +1,25 @@ 
+! { dg-do run }
+
+module m
+integer, allocatable :: mint
+!$acc declare create (mint)
+end module m
+
+program p
+use m
+
+allocate(mint)
+
+mint = 0
+
+!$acc serial
+mint = 5
+!$acc end serial
+
+!$acc update host(mint)
+
+if (mint.ne.5) stop 1
+
+deallocate(mint)
+
+end program p
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/declare-create-3.f90 b/libgomp/testsuite/libgomp.oacc-fortran/declare-create-3.f90
new file mode 100644
index 00000000000..16651cb1f5e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/declare-create-3.f90
@@ -0,0 +1,25 @@ 
+! { dg-do run }
+
+module m
+integer, allocatable :: mint(:)
+!$acc declare create (mint)
+end module m
+
+program p
+use m
+
+allocate(mint(1:20))
+
+mint = 0
+
+!$acc serial
+mint = 5
+!$acc end serial
+
+!$acc update host(mint)
+
+if (any(mint.ne.5)) stop 1
+
+deallocate(mint)
+
+end program p