1! { dg-do run }
2! { dg-require-effective-target offload_device_nonshared_as } */
3
4module target_test
5  implicit none (type, external)
6  integer, parameter :: N = 40
7  integer :: sum
8  integer :: var1 = 1
9  integer :: var2 = 2
10
11  !$omp declare target to(D)
12  integer :: D(N) = 0
13contains
14  subroutine enter_data (X)
15    integer :: X(:)
16    !$omp target enter data map(to: var1, var2, X) map(alloc: sum)
17  end subroutine enter_data
18
19  subroutine exit_data_0 (D)
20    integer :: D(N)
21    !$omp target exit data map(delete: D)
22  end subroutine exit_data_0
23
24  subroutine exit_data_1 ()
25    !$omp target exit data map(from: var1)
26  end subroutine exit_data_1
27
28  subroutine exit_data_2 (X)
29    integer :: X(N)
30    !$omp target exit data map(from: var2) map(release: X, sum)
31  end subroutine exit_data_2
32
33  subroutine exit_data_3 (p, idx)
34    integer :: p(:)
35    integer, value :: idx
36    !$omp target exit data map(from: p(idx))
37  end subroutine exit_data_3
38
39  subroutine test_nested ()
40    integer :: X, Y, Z
41    X = 0
42    Y = 0
43    Z = 0
44
45    !$omp target data map(from: X, Y, Z)
46      !$omp target data map(from: X, Y, Z)
47        !$omp target map(from: X, Y, Z)
48          X = 1337
49          Y = 1337
50          Z = 1337
51        !$omp end target
52        if (X /= 0) stop 11
53        if (Y /= 0) stop 12
54        if (Z /= 0) stop 13
55
56        !$omp target exit data map(from: X) map(release: Y)
57        if (X /= 0) stop 14
58        if (Y /= 0) stop 15
59
60        !$omp target exit data map(release: Y) map(delete: Z)
61        if (Y /= 0) stop 16
62        if (Z /= 0) stop 17
63      !$omp end target data
64      if (X /= 1337) stop 18
65      if (Y /= 0) stop 19
66      if (Z /= 0) stop 20
67
68      !$omp target map(from: X)
69        X = 2448
70      !$omp end target
71      if (X /= 2448) stop 21
72      if (Y /= 0) stop 22
73      if (Z /= 0) stop 23
74
75      X = 4896
76    !$omp end target data
77    if (X /= 4896) stop 24
78    if (Y /= 0) stop 25
79    if (Z /= 0) stop 26
80  end subroutine test_nested
81end module target_test
82
83program main
84  use target_test
85  implicit none (type, external)
86
87  integer, allocatable :: X(:)
88  integer, pointer, contiguous :: Y(:)
89
90
91  allocate(X(N), Y(N))
92  X(10) = 10
93  Y(20) = 20
94  call enter_data (X)
95
96  call exit_data_0 (D)  ! This should have no effect on D.
97
98  !$omp target map(alloc: var1, var2, X) map(to: Y) map(always, from: sum)
99    var1 = var1 + X(10)
100    var2 = var2 + Y(20)
101    sum = var1 + var2
102    D(sum) = D(sum) + 1
103  !$omp end target
104
105  if (var1 /= 1) stop 1
106  if (var2 /= 2) stop 2
107  if (sum /= 33) stop 3
108
109  call exit_data_1 ()
110  if (var1 /= 11) stop 4
111  if (var2 /= 2) stop 5
112
113  ! Increase refcount of already mapped X(1:N).
114  !$omp target enter data map(alloc: X(16:17))
115
116  call exit_data_2 (X)
117  if (var2 /= 22) stop 6
118
119  call exit_data_3 (X, 5) ! Unmap X(1:N).
120
121  deallocate (X, Y)
122
123  call test_nested ()
124end program main
125