This patch fixes a bug I introduced while adding support for allocatable scalars back in April. Before, gfc_trans_oacc_executable_directive would indiscriminately promote all GOMP_MAP_FIRSTPRIVATE_POINTER data mappings to GOMP_MAP_ALWAYS_POINTER, because for allocatable scalars the runtime needs to update the on-device values of both the data being pointed to and the pointer itself. The problem with this is that the allocatable scalar bit isn't propagated across subroutine calls. Clearly this indiscriminate update behavior is wrong because the pointer of dummy arguments may not get mapped onto the accelerator.
In this patch, I introduced a new acc_update bit inside the gfc_omp_clauses struct to represent when allocatable scalars need special treatment. As it stands, gfc_trans_omp_clauses_1 already has too many arguments, so I thought this approach would be better. Now gfc_trans_omp_clauses_1 can handle the allocatable scalar update directly. I've applied this patch to gomp-4_0-branch. Cesar
2017-06-08 Cesar Philippidis <ce...@codesourcery.com> gcc/fortran/ * gfortran.h gfc_omp_clauses: Add update_allocatable. * trans-openmp.c (gfc_trans_omp_clauses_1): Set update_allocatable bit in clauses. Remove GOMP_MAP_FIRSTPRIVATE_POINTER data map promotions for acc update. (gfc_trans_oacc_executable_directive): Use GOMP_MAP_ALWAYS_POINTER for allocatable scalar data clauses inside acc update directives. libgomp/ * testsuite/libgomp.oacc-fortran/allocatable-array-1.f90: New test. diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 8ca9f8a..0290efe 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -1318,7 +1318,7 @@ typedef struct gfc_omp_clauses gfc_expr_list *tile_list; unsigned async:1, gang:1, worker:1, vector:1, seq:1, independent:1; unsigned wait:1, par_auto:1, gang_static:1, nohost:1, acc_collapse:1, bind:1; - unsigned if_present:1, finalize:1; + unsigned if_present:1, finalize:1, update_allocatable:1; locus loc; char bind_name[GFC_MAX_SYMBOL_LEN+1]; } diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c index d5e2250..ca41903 100644 --- a/gcc/fortran/trans-openmp.c +++ b/gcc/fortran/trans-openmp.c @@ -2133,6 +2133,10 @@ gfc_trans_omp_clauses_1 (stmtblock_t *block, gfc_omp_clauses *clauses, 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) + && (n->sym->attr.oacc_declare_create) + && clauses->update_allocatable) + gmk = GOMP_MAP_ALWAYS_POINTER; node4 = build_omp_clause (input_location, OMP_CLAUSE_MAP); OMP_CLAUSE_SET_MAP_KIND (node4, gmk); @@ -3323,12 +3327,14 @@ gfc_trans_oacc_executable_directive (gfc_code *code) { stmtblock_t block; tree stmt, oacc_clauses; + gfc_omp_clauses *clauses = code->ext.omp_clauses; enum tree_code construct_code; switch (code->op) { case EXEC_OACC_UPDATE: construct_code = OACC_UPDATE; + clauses->update_allocatable = 1; break; case EXEC_OACC_ENTER_DATA: construct_code = OACC_ENTER_DATA; @@ -3344,20 +3350,7 @@ gfc_trans_oacc_executable_directive (gfc_code *code) } gfc_start_block (&block); - oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses, - code->loc); - - /* Promote GOMP_MAP_FIRSTPRIVATE_POINTER to GOMP_MAP_ALWAYS_POINTER for - variables inside OpenACC update directives. */ - if (code->op == EXEC_OACC_UPDATE) - for (tree c = oacc_clauses; c; c = OMP_CLAUSE_CHAIN (c)) - { - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP - && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER) - OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_POINTER); - } - - + oacc_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc); stmt = build1_loc (input_location, construct_code, void_type_node, oacc_clauses); gfc_add_expr_to_block (&block, stmt); diff --git a/libgomp/testsuite/libgomp.oacc-fortran/allocatable-array-1.f90 b/libgomp/testsuite/libgomp.oacc-fortran/allocatable-array-1.f90 new file mode 100644 index 0000000..4fc7b02 --- /dev/null +++ b/libgomp/testsuite/libgomp.oacc-fortran/allocatable-array-1.f90 @@ -0,0 +1,28 @@ +! Ensure that dummy arguments of allocatable arrays don't cause +! "libgomp: [...] is not mapped" errors. + +program main + integer, parameter :: n = 40 + integer, allocatable :: ar(:,:,:) + integer :: i + + allocate (ar(1:n,0:n-1,0:n-1)) + !$acc enter data copyin (ar) + + !$acc update host (ar) + + !$acc update device (ar) + + call update_ar (ar, n) + + !$acc exit data copyout (ar) +end program main + +subroutine update_ar (ar, n) + integer :: n + integer, dimension (1:n,0:n-1,0:n-1) :: ar + + !$acc update host (ar) + + !$acc update device (ar) +end subroutine update_ar