]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Add OpenACC Fortran support for deviceptr and variable in common blocks
authorJulian Brown <julian@codesourcery.com>
Tue, 12 Feb 2019 22:32:34 +0000 (14:32 -0800)
committerKwok Cheung Yeung <kcy@codesourcery.com>
Tue, 21 Jun 2022 13:11:07 +0000 (14:11 +0100)
2018-06-29  Cesar Philippidis  <cesar@codesourcery.com>
    James Norris  <jnorris@codesourcery.com>

gcc/fortran/
* openmp.cc (gfc_match_omp_map_clause): Re-write handling of the
deviceptr clause.  Add new common_blocks argument.  Propagate it to
gfc_match_omp_variable_list.
(gfc_match_omp_clauses): Update calls to gfc_match_omp_map_clauses.
(resolve_positive_int_expr): Promote the warning to an error.
(check_array_not_assumed): Remove pointer check.
(resolve_oacc_nested_loops): Error on do concurrent loops.
* trans-openmp.cc (gfc_omp_finish_clause): Don't create pointer data
mappings for deviceptr clauses.
(gfc_trans_omp_clauses): Likewise.

gcc/
* gimplify.cc (enum gimplify_omp_var_data): Add GOVD_DEVICETPR.
(oacc_default_clause): Privatize fortran common blocks.
(omp_notice_variable): Add GOVD_DEVICEPTR attribute when appropriate.
Defer the expansion of DECL_VALUE_EXPR for common block decls.
(gimplify_scan_omp_clauses): Add GOVD_DEVICEPTR attribute when
appropriate.
(gimplify_adjust_omp_clauses_1): Set GOMP_MAP_FORCE_DEVICEPTR for
implicit deviceptr mappings.

gcc/testsuite/
* c-c++-common/goacc/deviceptr-4.c: Update.
* gfortran.dg/goacc/loop-2-kernels-tile.f95: Update.
* gfortran.dg/goacc/loop-2-parallel-tile.f95: Update.
* gfortran.dg/goacc/sie.f95: Update.
* gfortran.dg/goacc/tile-1.f90: Update.
* gfortran.dg/gomp/pr77516.f90: Update.

libgomp/
* oacc-parallel.c (GOACC_parallel_keyed): Handle Fortran deviceptr
clause.
(GOACC_data_start): Likewise.
* testsuite/libgomp.oacc-fortran/deviceptr-1.f90: New test.

15 files changed:
gcc/ChangeLog.omp
gcc/fortran/ChangeLog.omp
gcc/fortran/openmp.cc
gcc/fortran/trans-openmp.cc
gcc/gimplify.cc
gcc/testsuite/ChangeLog.omp
gcc/testsuite/c-c++-common/goacc/deviceptr-4.c
gcc/testsuite/gfortran.dg/goacc/loop-2-kernels-tile.f95
gcc/testsuite/gfortran.dg/goacc/loop-2-parallel-tile.f95
gcc/testsuite/gfortran.dg/goacc/sie.f95
gcc/testsuite/gfortran.dg/goacc/tile-1.f90
gcc/testsuite/gfortran.dg/gomp/pr77516.f90
libgomp/ChangeLog.omp
libgomp/oacc-parallel.c
libgomp/testsuite/libgomp.oacc-fortran/deviceptr-1.f90 [new file with mode: 0644]

index eed10a545ddbe35537e1e12075d7e8457bf05bf5..30b4ab9005e371f1d64b938cc30b62054fdec3c5 100644 (file)
@@ -1,3 +1,13 @@
+2018-06-29  Cesar Philippidis  <cesar@codesourcery.com>
+           James Norris  <jnorris@codesourcery.com>
+
+       * gimplify.cc (enum gimplify_omp_var_data): Add GOVD_DEVICETPR.
+       (omp_notice_variable): Add GOVD_DEVICEPTR attribute when appropriate.
+       (gimplify_scan_omp_clauses): Add GOVD_DEVICEPTR attribute when
+       appropriate.
+       (gimplify_adjust_omp_clauses_1): Set GOMP_MAP_FORCE_DEVICEPTR for
+       implicit deviceptr mappings.
+
 2020-04-19  Chung-Lin Tang  <cltang@codesourcery.com>
 
        PR other/76739
index b742e1bfe350aaba1f42e5623b24f00660a17840..379b2aee1498f71d0b65b68f9b6f8ce8fe9859e1 100644 (file)
@@ -1,3 +1,9 @@
+2018-06-29  Cesar Philippidis  <cesar@codesourcery.com>
+           James Norris  <jnorris@codesourcery.com>
+
+       * openmp.cc (resolve_positive_int_expr): Promote the warning to an
+       error.
+
 2020-04-19  Chung-Lin Tang  <cltang@codesourcery.com>
 
        PR other/76739
index 714148138c22468d10acb303aaeb2c9d374cc640..838fe2fc95dde9bc8ca3a33c269c68d5b21bc463 100644 (file)
@@ -6071,8 +6071,8 @@ resolve_positive_int_expr (gfc_expr *expr, const char *clause)
   if (expr->expr_type == EXPR_CONSTANT
       && expr->ts.type == BT_INTEGER
       && mpz_sgn (expr->value.integer) <= 0)
-    gfc_warning (0, "INTEGER expression of %s clause at %L must be positive",
-                clause, &expr->where);
+    gfc_error ("INTEGER expression of %s clause at %L must be positive",
+              clause, &expr->where);
 }
 
 static void
index 43d59abe9e098a35ce76fbb65aa51491dff2e1ce..436694ca1519acb77f3b438145c8dd51a60b8702 100644 (file)
@@ -1501,6 +1501,9 @@ gfc_omp_finish_clause (tree c, gimple_seq *pre_p, bool openacc)
       return;
     }
 
+  if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_DEVICEPTR)
+    return;
+
   tree c2 = NULL_TREE, c3 = NULL_TREE, c4 = NULL_TREE;
   tree present = gfc_omp_check_optional_argument (decl, true);
   if (POINTER_TYPE_P (TREE_TYPE (decl)))
@@ -3103,6 +3106,12 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
                      OMP_CLAUSE_SIZE (node3) = size_int (0);
                      goto finalize_map_clause;
                    }
+                 else 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)
index 8daa5526e99ca2c1f21687afb89046dfc3d2bf83..e654031429969694d6a7faf177edf4a03e33c708 100644 (file)
@@ -132,6 +132,9 @@ enum gimplify_omp_var_data
   /* Flag for GOVD_FIRSTPRIVATE: OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT.  */
   GOVD_FIRSTPRIVATE_IMPLICIT = 0x8000000,
 
+  /* Flag for OpenACC deviceptrs.  */
+  GOVD_DEVICEPTR = (1<<24),
+
   GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
                           | GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR
                           | GOVD_LOCAL)
@@ -7864,6 +7867,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;
@@ -10286,6 +10290,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;
 
          if ((code == OMP_TARGET
               || code == OMP_TARGET_DATA
@@ -11243,7 +11249,8 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
                       | GOVD_MAP_FORCE
                       | GOVD_MAP_FORCE_PRESENT
                       | GOVD_MAP_ALLOC_ONLY
-                      | GOVD_MAP_FROM_ONLY))
+                      | GOVD_MAP_FROM_ONLY
+                      | GOVD_DEVICEPTR))
        {
        case 0:
          kind = GOMP_MAP_TOFROM;
@@ -11266,6 +11273,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 ();
        }
index 64bb0cb2e5ce2aeb29187bb763b75fc9447d97bd..75d810faac551385a1f20a2c0ffe90d8f6b900a5 100644 (file)
@@ -1,3 +1,13 @@
+2018-06-29  Cesar Philippidis  <cesar@codesourcery.com>
+           James Norris  <jnorris@codesourcery.com>
+
+       * c-c++-common/goacc/deviceptr-4.c: Update.
+       * gfortran.dg/goacc/loop-2-kernels-tile.f95: Update.
+       * gfortran.dg/goacc/loop-2-parallel-tile.f95: Update.
+       * gfortran.dg/goacc/sie.f95: Update.
+       * gfortran.dg/goacc/tile-1.f90: Update.
+       * gfortran.dg/gomp/pr77516.f90: Update.
+
 2020-04-19  Chung-Lin Tang  <cltang@codesourcery.com>
 
        PR other/76739
index db1b91633a6f8e66d0d551e81a817f6ca466d341..79a51620db944d853456bd661cc1a81830c538d9 100644 (file)
@@ -8,4 +8,4 @@ subr (int *a)
   a[0] += 1.0;
 }
 
-/* { dg-final { scan-tree-dump-times "#pragma omp target oacc_parallel.*map\\(tofrom:a" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "#pragma omp target oacc_parallel.*map\\(force_deviceptr:a" 1 "gimple" } } */
index afc8a278cacd5f0c8960641ede5eb551eb02cf8f..65425159a2c906da7399da701e83cd300bc43336 100644 (file)
@@ -29,7 +29,7 @@ program test
       DO j = 1,10
       ENDDO
     ENDDO
-    !$acc loop tile(-1) ! { dg-warning "must be positive" }
+    !$acc loop tile(-1) ! { dg-error "must be positive" }
     do i = 1,10
     enddo
     !$acc loop tile(i) ! { dg-error "constant expression" }
@@ -82,7 +82,7 @@ program test
     DO j = 1,10
     ENDDO
   ENDDO
-  !$acc kernels loop tile(-1) ! { dg-warning "must be positive" }
+  !$acc kernels loop tile(-1) ! { dg-error "must be positive" }
   do i = 1,10
   enddo
   !$acc kernels loop tile(i) ! { dg-error "constant expression" }
index 4bfca748f75ebe7ed57b62ee1113a58057b08b52..dae8f6674865c5c3b02ac4f898522e1e7f9e56c3 100644 (file)
@@ -20,7 +20,7 @@ program test
       DO j = 1,10
       ENDDO
     ENDDO
-    !$acc loop tile(-1) ! { dg-warning "must be positive" }
+    !$acc loop tile(-1) ! { dg-error "must be positive" }
     do i = 1,10
     enddo
     !$acc loop tile(i) ! { dg-error "constant expression" }
@@ -73,7 +73,7 @@ program test
     DO j = 1,10
     ENDDO
   ENDDO
-  !$acc parallel loop tile(-1) ! { dg-warning "must be positive" }
+  !$acc parallel loop tile(-1) ! { dg-error "must be positive" }
   do i = 1,10
   enddo
   !$acc parallel loop tile(i) ! { dg-error "constant expression" }
index 5982d5d229faccfc3927fc457bc63d737932ae24..f393cf29dd47dbf6a9d4af8350532631c1cbd997 100644 (file)
@@ -78,10 +78,10 @@ program test
   !$acc parallel num_gangs(i+1)
   !$acc end parallel
 
-  !$acc parallel num_gangs(-1) ! { dg-warning "must be positive" }
+  !$acc parallel num_gangs(-1) ! { dg-error "must be positive" }
   !$acc end parallel
 
-  !$acc parallel num_gangs(0) ! { dg-warning "must be positive" }
+  !$acc parallel num_gangs(0) ! { dg-error "must be positive" }
   !$acc end parallel
 
   !$acc parallel num_gangs() ! { dg-error "Invalid character in name" }
@@ -106,10 +106,10 @@ program test
   !$acc kernels num_gangs(i+1)
   !$acc end kernels
 
-  !$acc kernels num_gangs(-1) ! { dg-warning "must be positive" }
+  !$acc kernels num_gangs(-1) ! { dg-error "must be positive" }
   !$acc end kernels
 
-  !$acc kernels num_gangs(0) ! { dg-warning "must be positive" }
+  !$acc kernels num_gangs(0) ! { dg-error "must be positive" }
   !$acc end kernels
 
   !$acc kernels num_gangs() ! { dg-error "Invalid character in name" }
@@ -135,10 +135,10 @@ program test
   !$acc parallel num_workers(i+1)
   !$acc end parallel
 
-  !$acc parallel num_workers(-1) ! { dg-warning "must be positive" }
+  !$acc parallel num_workers(-1) ! { dg-error "must be positive" }
   !$acc end parallel
 
-  !$acc parallel num_workers(0) ! { dg-warning "must be positive" }
+  !$acc parallel num_workers(0) ! { dg-error "must be positive" }
   !$acc end parallel
 
   !$acc parallel num_workers() ! { dg-error "Invalid expression after 'num_workers\\('" }
@@ -163,10 +163,10 @@ program test
   !$acc kernels num_workers(i+1)
   !$acc end kernels
 
-  !$acc kernels num_workers(-1) ! { dg-warning "must be positive" }
+  !$acc kernels num_workers(-1) ! { dg-error "must be positive" }
   !$acc end kernels
 
-  !$acc kernels num_workers(0) ! { dg-warning "must be positive" }
+  !$acc kernels num_workers(0) ! { dg-error "must be positive" }
   !$acc end kernels
 
   !$acc kernels num_workers() ! { dg-error "Invalid expression after 'num_workers\\('" }
@@ -192,10 +192,10 @@ program test
   !$acc parallel vector_length(i+1)
   !$acc end parallel
 
-  !$acc parallel vector_length(-1) ! { dg-warning "must be positive" }
+  !$acc parallel vector_length(-1) ! { dg-error "must be positive" }
   !$acc end parallel
 
-  !$acc parallel vector_length(0) ! { dg-warning "must be positive" }
+  !$acc parallel vector_length(0) ! { dg-error "must be positive" }
   !$acc end parallel
 
   !$acc parallel vector_length() ! { dg-error "Invalid expression after 'vector_length\\('" }
@@ -220,10 +220,10 @@ program test
   !$acc kernels vector_length(i+1)
   !$acc end kernels
 
-  !$acc kernels vector_length(-1) ! { dg-warning "must be positive" }
+  !$acc kernels vector_length(-1) ! { dg-error "must be positive" }
   !$acc end kernels
 
-  !$acc kernels vector_length(0) ! { dg-warning "must be positive" }
+  !$acc kernels vector_length(0) ! { dg-error "must be positive" }
   !$acc end kernels
 
   !$acc kernels vector_length() ! { dg-error "Invalid expression after 'vector_length\\('" }
@@ -250,10 +250,10 @@ program test
   !$acc loop gang(i+1)
   do i = 1,10
   enddo
-  !$acc loop gang(-1) ! { dg-warning "must be positive" }
+  !$acc loop gang(-1) ! { dg-error "must be positive" }
   do i = 1,10
   enddo
-  !$acc loop gang(0) ! { dg-warning "must be positive" }
+  !$acc loop gang(0) ! { dg-error "must be positive" }
   do i = 1,10
   enddo
   !$acc loop gang() ! { dg-error "Invalid character in name" }
@@ -282,10 +282,10 @@ program test
   !$acc loop worker(i+1)
   do i = 1,10
   enddo
-  !$acc loop worker(-1) ! { dg-warning "must be positive" }
+  !$acc loop worker(-1) ! { dg-error "must be positive" }
   do i = 1,10
   enddo
-  !$acc loop worker(0) ! { dg-warning "must be positive" }
+  !$acc loop worker(0) ! { dg-error "must be positive" }
   do i = 1,10
   enddo
   !$acc loop worker() ! { dg-error "Invalid character in name" }
@@ -314,10 +314,10 @@ program test
   !$acc loop vector(i+1)
   do i = 1,10
   enddo
-  !$acc loop vector(-1) ! { dg-warning "must be positive" }
+  !$acc loop vector(-1) ! { dg-error "must be positive" }
   do i = 1,10
   enddo
-  !$acc loop vector(0) ! { dg-warning "must be positive" }
+  !$acc loop vector(0) ! { dg-error "must be positive" }
   do i = 1,10
   enddo
   !$acc loop vector() ! { dg-error "Invalid character in name" }
index f609b127df987adc99048728ee119e7ee0b7043f..9ef752110877d90594db434599f86c7895ff1a7b 100644 (file)
@@ -44,17 +44,17 @@ subroutine parloop
   do i = 1, n
   end do
 
-  !$acc parallel loop tile(-3) ! { dg-warning "must be positive" }
+  !$acc parallel loop tile(-3) ! { dg-error "must be positive" }
   do i = 1, n
   end do
 
-  !$acc parallel loop tile(10, -3) ! { dg-warning "must be positive" }
+  !$acc parallel loop tile(10, -3) ! { dg-error "must be positive" }
   do i = 1, n
      do j = 1, n
      end do
   end do
 
-  !$acc parallel loop tile(-100, 10, 5) ! { dg-warning "must be positive" }
+  !$acc parallel loop tile(-100, 10, 5) ! { dg-error "must be positive" }
   do i = 1, n
      do j = 1, n
         do k = 1, n
@@ -114,7 +114,7 @@ subroutine par
      end do
   end do
 
-  !$acc loop tile(-2) ! { dg-warning "must be positive" }
+  !$acc loop tile(-2) ! { dg-error "must be positive" }
   do i = 1, n
   end do
 
@@ -195,7 +195,7 @@ subroutine kern
      end do
   end do
 
-  !$acc loop tile(-2) ! { dg-warning "must be positive" }
+  !$acc loop tile(-2) ! { dg-error "must be positive" }
   do i = 1, n
   end do
 
@@ -295,17 +295,17 @@ subroutine kernsloop
   do i = 1, n
   end do
 
-  !$acc kernels loop tile(-3) ! { dg-warning "must be positive" }
+  !$acc kernels loop tile(-3) ! { dg-error "must be positive" }
   do i = 1, n
   end do
 
-  !$acc kernels loop tile(10, -3) ! { dg-warning "must be positive" }
+  !$acc kernels loop tile(10, -3) ! { dg-error "must be positive" }
   do i = 1, n
      do j = 1, n
      end do
   end do
 
-  !$acc kernels loop tile(-100, 10, 5) ! { dg-warning "must be positive" }
+  !$acc kernels loop tile(-100, 10, 5) ! { dg-error "must be positive" }
   do i = 1, n
      do j = 1, n
         do k = 1, n
index 9c0a95b9f79a18b0b868a70225dfeee9c4bad886..3ac3f5562d0a52afbffa8d61ef634ecb538f6481 100644 (file)
@@ -4,7 +4,7 @@
 program pr77516
    integer :: i, x
    x = 0
-!$omp simd safelen(0) reduction(+:x)   ! { dg-warning "must be positive" }
+!$omp simd safelen(0) reduction(+:x)   ! { dg-error "must be positive" }
    do i = 1, 8
       x = x + 1
    end do
index 2769eb88dad686ad5a698456e73dffecdd1db1d3..fc784d92160c62e31f99625b5ab76a7d05e4da4f 100644 (file)
@@ -1,3 +1,11 @@
+2018-06-29  Cesar Philippidis  <cesar@codesourcery.com>
+           James Norris  <jnorris@codesourcery.com>
+
+       * oacc-parallel.c (GOACC_parallel_keyed): Handle Fortran deviceptr
+       clause.
+       (GOACC_data_start): Likewise.
+       * testsuite/libgomp.oacc-fortran/deviceptr-1.f90: New test.
+
 2019-02-12  Julian Brown <julian@codesourcery.com>
 
        * oacc-cuda.c (acc_set_cuda_stream): Return 0 on error/invalid
index 83be56310f95c7f6b0c984b6eeea4ef2cba3609e..0cc087c765649d080ed0627ed410b28d6f88252b 100644 (file)
@@ -625,6 +625,8 @@ GOACC_data_start (int flags_m, size_t mapnum,
   if (profiling_p)
     goacc_profiling_dispatch (&prof_info, &enter_data_event_info, &api_info);
 
+  handle_ftn_pointers (mapnum, hostaddrs, sizes, kinds);
+
   /* Host fallback or 'do nothing'.  */
   if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
       || (flags & GOACC_FLAG_HOST_FALLBACK))
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/deviceptr-1.f90 b/libgomp/testsuite/libgomp.oacc-fortran/deviceptr-1.f90
new file mode 100644 (file)
index 0000000..276a172
--- /dev/null
@@ -0,0 +1,197 @@
+! { dg-do run }
+
+! Test the deviceptr clause with various directives
+! and in combination with other directives where
+! the deviceptr variable is implied.
+
+subroutine subr1 (a, b)
+  implicit none
+  integer, parameter :: N = 8
+  integer :: a(N)
+  integer :: b(N)
+  integer :: i = 0
+
+  !$acc data deviceptr (a)
+
+  !$acc parallel copy (b)
+    do i = 1, N
+      a(i) = i * 2
+      b(i) = a(i)
+    end do
+  !$acc end parallel
+
+  !$acc end data
+
+end subroutine
+
+subroutine subr2 (a, b)
+  implicit none
+  integer, parameter :: N = 8
+  integer :: a(N)
+  !$acc declare deviceptr (a)
+  integer :: b(N)
+  integer :: i = 0
+
+  !$acc parallel copy (b)
+    do i = 1, N
+      a(i) = i * 4
+      b(i) = a(i)
+    end do
+  !$acc end parallel
+
+end subroutine
+
+subroutine subr3 (a, b)
+  implicit none
+  integer, parameter :: N = 8
+  integer :: a(N)
+  !$acc declare deviceptr (a)
+  integer :: b(N)
+  integer :: i = 0
+
+  !$acc kernels copy (b)
+    do i = 1, N
+      a(i) = i * 8
+      b(i) = a(i)
+    end do
+  !$acc end kernels
+
+end subroutine
+
+subroutine subr4 (a, b)
+  implicit none
+  integer, parameter :: N = 8
+  integer :: a(N)
+  integer :: b(N)
+  integer :: i = 0
+
+  !$acc parallel deviceptr (a) copy (b)
+    do i = 1, N
+      a(i) = i * 16
+      b(i) = a(i)
+    end do
+  !$acc end parallel
+
+end subroutine
+
+subroutine subr5 (a, b)
+  implicit none
+  integer, parameter :: N = 8
+  integer :: a(N)
+  integer :: b(N)
+  integer :: i = 0
+
+  !$acc kernels deviceptr (a) copy (b)
+    do i = 1, N
+      a(i) = i * 32
+      b(i) = a(i)
+    end do
+  !$acc end kernels
+
+end subroutine
+
+subroutine subr6 (a, b)
+  implicit none
+  integer, parameter :: N = 8
+  integer :: a(N)
+  integer :: b(N)
+  integer :: i = 0
+
+  !$acc parallel deviceptr (a) copy (b)
+    do i = 1, N
+      b(i) = i
+    end do
+  !$acc end parallel
+
+end subroutine
+
+subroutine subr7 (a, b)
+  implicit none
+  integer, parameter :: N = 8
+  integer :: a(N)
+  integer :: b(N)
+  integer :: i = 0
+
+  !$acc data deviceptr (a)
+
+  !$acc parallel copy (b)
+    do i = 1, N
+      a(i) = i * 2
+      b(i) = a(i)
+    end do
+  !$acc end parallel
+
+  !$acc parallel copy (b)
+    do i = 1, N
+      a(i) = b(i) * 2
+      b(i) = a(i)
+    end do
+  !$acc end parallel
+
+  !$acc end data
+
+end subroutine
+
+program main
+  use iso_c_binding, only: c_ptr, c_f_pointer
+  implicit none
+  type (c_ptr) :: cp
+  integer, parameter :: N = 8
+  integer, pointer :: fp(:)
+  integer :: i = 0
+  integer :: b(N)
+
+  interface
+    function acc_malloc (s) bind (C)
+      use iso_c_binding, only: c_ptr, c_size_t
+      integer (c_size_t), value :: s
+      type (c_ptr) :: acc_malloc
+    end function
+  end interface
+
+  cp = acc_malloc (N * sizeof (fp(N)))
+  call c_f_pointer (cp, fp, [N])
+
+  call subr1 (fp, b)
+
+  do i = 1, N
+    if (b(i) .ne. i * 2) call abort
+  end do
+
+  call subr2 (fp, b)
+
+  do i = 1, N
+    if (b(i) .ne. i * 4) call abort
+  end do
+
+  call subr3 (fp, b)
+
+  do i = 1, N
+    if (b(i) .ne. i * 8) call abort
+  end do
+
+  call subr4 (fp, b)
+
+  do i = 1, N
+    if (b(i) .ne. i * 16) call abort
+  end do
+
+  call subr5 (fp, b)
+
+  do i = 1, N
+    if (b(i) .ne. i * 32) call abort
+  end do
+
+  call subr6 (fp, b)
+
+  do i = 1, N
+    if (b(i) .ne. i) call abort
+  end do
+
+  call subr7 (fp, b)
+
+  do i = 1, N
+    if (b(i) .ne. i * 4) call abort
+  end do
+
+end program main