This patch teaches both the Fortran FE and the gimplifier how to only
utilize one data mapping for OpenACC deviceptr clauses. Before, the
Fortran FE would create three (one for the dereferenced pointer data,
one for the array descriptor, and another for a firstprivate pointer)
and gimplifier would create two (one for the dereferenced pointer data,
and another for a pointer). Additionally, this patch teaches the
gimplifer to propagate the deviceptr clause to OpenACC parallel and
kernels nested inside OpenACC data regions. E.g.

  !$acc data deviceptr (a)
  !$acc parallel loop
  do ...
  enddo
  !$acc end data

Before this patch, variable 'a' would be implicitly assigned a copy data
clause. Now the gimplifier assigns a deviceptr clause to it.

In addition to XPASS'ing devicetpr-1.f90, this patch resolves a couple
of regressions that Thomas encountered while rebasing the og7 patches on
top of GCC 8. Specifically, the new libgomp gomp_copy_host2dev
optimization creates a copy of the data mapping arguments to a host
buffer so the multiple adjacent data mappings can be uploaded to the
accelerator using a single device host2dev copy. Naturally, this fails
when the runtime tries to deference deviceptrs because those pointers
may not be valid on the host.

I've applied this patch to og7, and I'll backport the gomp_copy_host2dev
enhancements to og7 in a followup patch. It was tempting to remove the
XFAIL from deviceptr-1.f90, but the test case still fails on at least
one legacy driver.

Cesar
2018-05-07  Cesar Philippidis  <ce...@codesourcery.com>

	gcc/fortran/
	* trans-openmp.c (gfc_omp_finish_clause): Don't create pointer data
	mappings for deviceptr clauses.
	(gfc_trans_omp_clauses_1): Likewise.

	gcc/
	* gimplify.c (enum gimplify_omp_var_data): Add GOVD_DEVICETPR.
	(omp_notice_variable): Add GOVD_DEVICEPTR attribute when appropriate.
	(gimplify_scan_omp_clauses): Likewise.
	(gimplify_adjust_omp_clauses_1): Set GOMP_MAP_FORCE_DEVICEPTR for
	implicit deviceptr mappings.


diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index ef828e8ac06..1a8fb3461ef 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -1069,6 +1069,8 @@ gfc_omp_finish_clause (tree c, gimple_seq *pre_p)
 #endif
 
   tree c2 = NULL_TREE, c3 = NULL_TREE, c4 = NULL_TREE;
+  if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_DEVICEPTR)
+    return;
   if (POINTER_TYPE_P (TREE_TYPE (decl)))
     {
       if (!gfc_omp_privatize_by_reference (decl)
@@ -2159,6 +2161,12 @@ gfc_trans_omp_clauses_1 (stmtblock_t *block, gfc_omp_clauses *clauses,
 			   || n->expr->ref->u.ar.type == AR_FULL))
 		{
 		  if (POINTER_TYPE_P (TREE_TYPE (decl))
+		      && n->u.map_op == OMP_MAP_FORCE_DEVICEPTR)
+		    {
+		      OMP_CLAUSE_DECL (node) = decl;
+		      goto finalize_map_clause;
+		    }
+		  else if (POINTER_TYPE_P (TREE_TYPE (decl))
 		      && (gfc_omp_privatize_by_reference (decl)
 			  || GFC_DECL_GET_SCALAR_POINTER (decl)
 			  || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
@@ -2168,9 +2176,7 @@ gfc_trans_omp_clauses_1 (stmtblock_t *block, gfc_omp_clauses *clauses,
 		    {
 		      tree orig_decl = decl;
 		      enum gomp_map_kind gmk = GOMP_MAP_FIRSTPRIVATE_POINTER;
-		      if (n->u.map_op == OMP_MAP_FORCE_DEVICEPTR)
-			gmk = GOMP_MAP_POINTER;
-		      else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
+		      if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
 			       && (n->sym->attr.oacc_declare_create)
 			       && clauses->update_allocatable)
 			gmk = GOMP_MAP_ALWAYS_POINTER;
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 44c03ab8310..458e9ade797 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -105,6 +105,9 @@ enum gimplify_omp_var_data
   /* Flag for GOVD_MAP, copy to/from private storage inside offloaded region.  */
   GOVD_MAP_PRIVATE = 1048576,
 
+  /* Flag for OpenACC deviceptrs.  */
+  GOVD_DEVICEPTR = (1<<21),
+
   GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
 			   | GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR
 			   | GOVD_LOCAL)
@@ -7209,6 +7212,7 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
 		        error ("variable %qE declared in enclosing "
 			       "%<host_data%> region", DECL_NAME (decl));
 		      nflags |= GOVD_MAP;
+		      nflags |= (n2->value & GOVD_DEVICEPTR);
 		      if (octx->region_type == ORT_ACC_DATA
 			  && (n2->value & GOVD_MAP_0LEN_ARRAY))
 			nflags |= GOVD_MAP_0LEN_ARRAY;
@@ -8250,6 +8254,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
 	  if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
 	      || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM)
 	    flags |= GOVD_MAP_ALWAYS_TO;
+	  else if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_DEVICEPTR)
+	    flags |= GOVD_DEVICEPTR;
 	  goto do_add;
 
 	case OMP_CLAUSE_DEPEND:
@@ -8927,7 +8933,8 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
       /* Not all combinations of these GOVD_MAP flags are actually valid.  */
       switch (flags & (GOVD_MAP_TO_ONLY
 		       | GOVD_MAP_FORCE
-		       | GOVD_MAP_FORCE_PRESENT))
+		       | GOVD_MAP_FORCE_PRESENT
+		       | GOVD_DEVICEPTR))
 	{
 	case 0:
 	  kind = GOMP_MAP_TOFROM;
@@ -8944,6 +8951,9 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
 	case GOVD_MAP_FORCE_PRESENT:
 	  kind = GOMP_MAP_FORCE_PRESENT;
 	  break;
+	case GOVD_DEVICEPTR:
+	  kind = GOMP_MAP_FORCE_DEVICEPTR;
+	  break;
 	default:
 	  gcc_unreachable ();
 	}

Reply via email to