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 (); }