openacc: Allow strided arrays in update directives
authorJulian Brown <julian@codesourcery.com>
Tue, 2 Feb 2021 11:44:34 +0000 (03:44 -0800)
committerJulian Brown <julian@codesourcery.com>
Thu, 4 Feb 2021 23:06:22 +0000 (15:06 -0800)
OpenACC 3.0 ("2.14.4. Update Directive") states:

  Noncontiguous subarrays may appear. It is implementation-specific
  whether noncontiguous regions are updated by using one transfer for
  each contiguous subregion, or whether the non-contiguous data is
  packed, transferred once, and unpacked, or whether one or more larger
  subarrays (no larger than the smallest contiguous region that contains
  the specified subarray) are updated.

This patch relaxes some conditions in the Fortran front-end so that
strided accesses are permitted for update directives.

gcc/fortran/
* openmp.c (resolve_omp_clauses): Omit OpenACC update in
contiguity check and stride-specified error.

gcc/testsuite/
* gfortran.dg/goacc/array-with-dt-2.f90: New test.

libgomp/
* testsuite/libgomp.oacc-fortran/array-stride-dt-1.f90: New test.

gcc/fortran/openmp.c
gcc/testsuite/gfortran.dg/goacc/array-with-dt-2.f90 [new file with mode: 0644]
libgomp/testsuite/libgomp.oacc-fortran/array-stride-dt-1.f90 [new file with mode: 0644]

index aab17f0589f6e44708ecd1f2acc27fb4303b17f7..797f6c86b62049e436d45fc6c05007458c04098a 100644 (file)
@@ -5192,7 +5192,8 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
                           array isn't contiguous.  An expression such as
                           arr(-n:n,-n:n) could be contiguous even if it looks
                           like it may not be.  */
-                       if (list != OMP_LIST_CACHE
+                       if (code->op != EXEC_OACC_UPDATE
+                           && list != OMP_LIST_CACHE
                            && list != OMP_LIST_DEPEND
                            && !gfc_is_simply_contiguous (n->expr, false, true)
                            && gfc_is_not_contiguous (n->expr))
@@ -5230,7 +5231,7 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
                        int i;
                        gfc_array_ref *ar = &array_ref->u.ar;
                        for (i = 0; i < ar->dimen; i++)
-                         if (ar->stride[i])
+                         if (ar->stride[i] && code->op != EXEC_OACC_UPDATE)
                            {
                              gfc_error ("Stride should not be specified for "
                                         "array section in %s clause at %L",
diff --git a/gcc/testsuite/gfortran.dg/goacc/array-with-dt-2.f90 b/gcc/testsuite/gfortran.dg/goacc/array-with-dt-2.f90
new file mode 100644 (file)
index 0000000..807580d
--- /dev/null
@@ -0,0 +1,10 @@
+type t
+   integer, allocatable :: A(:,:)
+end type t
+
+type(t), allocatable :: b(:)
+
+!$acc update host(b(::2))
+!$acc update host(b(1)%A(::3,::4))
+end
+
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/array-stride-dt-1.f90 b/libgomp/testsuite/libgomp.oacc-fortran/array-stride-dt-1.f90
new file mode 100644 (file)
index 0000000..f04d76d
--- /dev/null
@@ -0,0 +1,44 @@
+! { dg-do run }
+
+type t
+   integer, allocatable :: A(:,:)
+end type t
+
+type(t), allocatable :: b(:)
+
+integer :: i
+
+allocate(b(1:20))
+do i=1,20
+  allocate(b(i)%A(1:20,1:20))
+end do
+
+do i=1,20
+  b(i)%A(:,:) = 0
+end do
+
+!$acc enter data copyin(b)
+do i=1,20
+  !$acc enter data copyin(b(i)%A)
+end do
+
+b(1)%A(:,:) = 5
+
+!$acc update device(b(::2))
+!$acc update device(b(1)%A(::3,::4))
+
+do i=1,20
+  !$acc exit data copyout(b(i)%A)
+end do
+!$acc exit data copyout(b)
+
+! This is necessarily conservative because the "update" is allowed to copy
+! e.g. the whole of the containing block for a discontinuous update.
+! Try to ensure that the update covers a sufficient portion of the array.
+
+if (any(b(1)%A(::3,::4) .ne. 5)) stop 1
+do i=2,20
+  if (any(b(i)%A(:,:) .ne. 0)) stop 2
+end do
+
+end