This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gomp4] Properly handle allocatable scalars in acc update.


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  <cesar@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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]