aboutsummaryrefslogtreecommitdiff
path: root/libgomp/testsuite/libgomp.fortran/use_device_ptr-optional-3.f90
blob: b06a88415b47f9cbd684ec607d294fd52c64cf85 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
! { dg-do run }
! Check whether absent optional arguments are properly
! handled with use_device_{addr,ptr}.
program main
  use iso_c_binding, only: c_ptr, c_loc, c_associated, c_f_pointer
  implicit none (type, external)

  integer, target :: u
  integer, target :: v
  integer, target :: w
  integer, target :: x(4)
  integer, target, allocatable :: y
  integer, target, allocatable :: z(:)
  type(c_ptr), target :: cptr
  type(c_ptr), target :: cptr_in
  integer :: dummy

  u = 42
  v = 5
  w = 7
  x = [3,4,6,2]
  y = 88
  z = [1,2,3]

  !$omp target enter data map(to:u)
  !$omp target data map(to:dummy) use_device_addr(u)
   cptr_in = c_loc(u) ! Has to be outside 'foo' due to 'intent(in)'
  !$omp end target data

  call foo (u, v, w, x, y, z, cptr, cptr_in)
  deallocate (y, z)
contains
  subroutine foo (u, v, w, x, y, z, cptr, cptr_in)
    integer, target, optional, value :: v
    integer, target, optional :: u, w
    integer, target, optional :: x(:)
    integer, target, optional, allocatable :: y
    integer, target, optional, allocatable :: z(:)
    type(c_ptr), target, optional, value :: cptr
    type(c_ptr), target, optional, value, intent(in) :: cptr_in
    integer :: d

    type(c_ptr) :: p_u, p_v, p_w, p_x, p_y, p_z, p_cptr, p_cptr_in

    !$omp target enter data map(to:w, x, y, z)
    !$omp target data map(dummy) use_device_addr(x)
      cptr = c_loc(x)
    !$omp end target data

    ! Need to map per-VALUE arguments, if present
    if (present(v)) then
      !$omp target enter data map(to:v)
    else
      stop 1
    end if
    if (present(cptr)) then
      !$omp target enter data map(to:cptr)
    else
      stop 2
    end if
    if (present(cptr_in)) then
      !$omp target enter data map(to:cptr_in)
    else
      stop 3
    end if

    !$omp target data map(d) use_device_addr(u, v, w, x, y, z)
    !$omp target data map(d) use_device_addr(cptr, cptr_in)
      if (.not. present(u)) stop 10
      if (.not. present(v)) stop 11
      if (.not. present(w)) stop 12
      if (.not. present(x)) stop 13
      if (.not. present(y)) stop 14
      if (.not. present(z)) stop 15
      if (.not. present(cptr)) stop 16
      if (.not. present(cptr_in)) stop 17
      p_u = c_loc(u)
      p_v = c_loc(v)
      p_w = c_loc(w)
      p_x = c_loc(x)
      p_y = c_loc(y)
      p_z = c_loc(z)
      p_cptr = c_loc(cptr)
      p_cptr_in = c_loc(cptr_in)
    !$omp end target data
    !$omp end target data
    call check(p_u, p_v, p_w, p_x, p_y, p_z, p_cptr, p_cptr_in, size(x), size(z))
  end subroutine foo

  subroutine check(p_u, p_v, p_w, p_x, p_y, p_z, p_cptr, p_cptr_in, Nx, Nz)
    type(c_ptr), value :: p_u, p_v, p_w, p_x, p_y, p_z, p_cptr, p_cptr_in
    integer, value :: Nx, Nz
    integer, pointer :: c_u(:), c_v(:), c_w(:), c_x(:), c_y(:), c_z(:)
    type(c_ptr), pointer :: c_cptr(:), c_cptr_in(:)

    ! As is_device_ptr does not handle scalars, we map them to a size-1 array
    call c_f_pointer(p_u, c_u, shape=[1])
    call c_f_pointer(p_v, c_v, shape=[1])
    call c_f_pointer(p_w, c_w, shape=[1])
    call c_f_pointer(p_x, c_x, shape=[Nx])
    call c_f_pointer(p_y, c_y, shape=[1])
    call c_f_pointer(p_z, c_z, shape=[Nz])
    call c_f_pointer(p_cptr, c_cptr, shape=[1])
    call c_f_pointer(p_cptr_in, c_cptr_in, shape=[1])
    call run_target(c_u, c_v, c_w, c_x, c_y, c_z, c_cptr, c_cptr_in, Nx, Nz)
  end subroutine check

  subroutine run_target(c_u, c_v, c_w, c_x, c_y, c_z, c_cptr, c_cptr_in, Nx, Nz)
    integer, target :: c_u(:), c_v(:), c_w(:), c_x(:), c_y(:), c_z(:)
    type(c_ptr) :: c_cptr(:), c_cptr_in(:)
    integer, value :: Nx, Nz
    !$omp target is_device_ptr(c_u, c_v, c_w, c_x, c_y, c_z, c_cptr, c_cptr_in) map(to:Nx, Nz)
      call target_fn(c_u(1), c_v(1), c_w(1), c_x, c_y(1), c_z, c_cptr(1), c_cptr_in(1), Nx, Nz)
    !$omp end target
  end subroutine run_target

  subroutine target_fn(c_u, c_v, c_w, c_x, c_y, c_z, c_cptr, c_cptr_in, Nx, Nz)
    !$omp declare target
    integer, target :: c_u, c_v, c_w, c_x(:), c_y, c_z(:)
    type(c_ptr), value :: c_cptr, c_cptr_in
    integer, value :: Nx, Nz
    integer, pointer :: u, x(:)
    if (c_u /= 42) stop 30
    if (c_v /= 5) stop 31
    if (c_w /= 7) stop 32
    if (Nx /= 4) stop 33
    if (any (c_x /= [3,4,6,2])) stop 34
    if (c_y /= 88) stop 35
    if (Nz /= 3) stop 36
    if (any (c_z /= [1,2,3])) stop 37
    if (.not. c_associated (c_cptr)) stop 38
    if (.not. c_associated (c_cptr_in)) stop 39
    if (.not. c_associated (c_cptr, c_loc(c_x))) stop 40
    if (.not. c_associated (c_cptr_in, c_loc(c_u))) stop 41
    call c_f_pointer(c_cptr_in, u)
    call c_f_pointer(c_cptr, x, shape=[Nx])
    if (u /= c_u .or. u /= 42)  stop 42
    if (any (x /= c_x))  stop 43
    if (any (x /= [3,4,6,2]))  stop 44
  end subroutine target_fn
end program main