blob: f52c1d095ff69f60fb94348aaa010a6457df011d [file]
! { dg-do run { target offload_device_nvptx } }
! { dg-additional-options "-O0 -foffload=nvptx-none" }
!
! FIXME: Enable testing for AMD GCN once implemented
!
! The following code works if
! - either 'target teams' runs in sequence order (this seems to happen on the
! host for 'target teams' but not for 'teams')
! - or, when teams run concurrently, if 'cnt' and 'local_cnt' are 'groupprivate'.
!
! The latter is check by this testcase.
!
! On nvptx, such memory is called 'shared' and it turns out that the address
! is the same for all teams. However, the value check only succeeds if it is
! indeed shared! The produced nvptx assembly is:
! .shared .align 4 .u32 local_cnt$1[1];
! .visible .shared .align 4 .u32 __m_MOD_cnt[1];
!
module m
use iso_c_binding
use omp_lib
implicit none
integer :: cnt ! Note that no initializer is permitted!
common /one/ cnt
!$omp declare target local(/one/) device_type(nohost)
!$omp groupprivate(/one/) device_type(nohost)
contains
integer(c_ptrdiff_t) function addr()
addr = loc(cnt)
end
integer function f_global(first)
!$omp declare target enter(f_global) device_type(nohost)
logical, value, intent(in) :: first
if (first) then
!$omp atomic write
cnt = 0
end if
!$omp atomic update
cnt = cnt + (omp_get_team_num () + 1);
!$omp atomic read
f_global = cnt
end
integer function f_local(first)
!$omp declare target enter(f_local) device_type(nohost)
logical, value, intent(in) :: first
integer :: local_cnt
common /two/ local_cnt
!$omp groupprivate(/two/) device_type(nohost)
if (first) then
!$omp atomic write
local_cnt = 5
end if
!$omp atomic update
local_cnt = local_cnt + 2*(omp_get_team_num () + 1);
!$omp atomic read
f_local = local_cnt
end
end module m
program main
use m
implicit none
integer :: team_global(16), team_local(16), j, num_teams
integer(c_ptrdiff_t) :: addrs(16)
! !$omp teams num_teams(16)
!$omp target teams num_teams(16) map(from: team_global, team_local, num_teams) device_type(nohost)
block
!$omp parallel if(.false.)
block
integer :: i
real, volatile :: x
x = 3.3
i = f_global(.true.)
i = f_local(.true.)
addrs(1+omp_get_team_num()) = addr()
x = sin(x)
team_global(1+omp_get_team_num()) = f_global(.false.)
team_local(1+omp_get_team_num()) = f_local(.false.)
if (omp_get_team_num() == 0) &
num_teams = omp_get_num_teams ()
end block
end block
if (num_teams /= 16) error stop "num teams error"
do j = 1, 16
if (team_global(j) /= j*2 .or. team_local(j) /= 5+j*4) then
print '(i2,": ", 4(i6, " "), g0, " ", g0, " - ", z16)', j,&
team_global(j), team_local(j), j*2, 5+j*4, &
team_global(j)==j*2, team_local(j)==5+j*4, addrs(j)
error stop "invalid value"
end if
end do
end