I also wanted to add another reproducer. Not sure if this is the same issue or related. I compile all codes with:
mpif90 -stdpar=gpu -O3 -o small_reproducer small_reproducer.F90 -gpu=mem:separate -mp=gpu -Minfo=accel
Reproducer 1: do concurrent … reduce inside omp target fails
module stubs
use iso_fortran_env
integer, parameter :: r_typ = REAL64
contains
pure subroutine f1(n, x)
integer, intent(in) :: n
real(r_typ), dimension(n), intent(in) :: x
real(r_typ) :: a
a = 0._r_typ
end subroutine f1
pure subroutine f2(x, y)
real(r_typ), intent(in) :: x, y
real(r_typ) :: p
if (x.eq.0._r_typ) then
if (y.ge.0._r_typ) then
p = 2
else
p = -2
end if
end if
end subroutine f2
end module
subroutine run
use iso_fortran_env
use stubs
implicit none
integer :: i, m, n
real(r_typ) :: a, b
real(r_typ), allocatable :: arr(:)
real(r_typ) :: out
m = 4
n = 1
out = 0._r_typ
allocate(arr(m))
arr(1) = 1._r_typ
!$omp target enter data map(to: arr)
!$omp target map(tofrom: out)
do concurrent (i = 1: n) reduce(+:out)
call f1(m, arr)
a = 1._r_typ
b = 1._r_typ
call f2(a, b)
out = out + a + b
enddo
!$omp end target
write(*,'(a,es12.4)') 'out (from device) = ', out
deallocate(arr)
end subroutine run
program main
call run
end program main
Error
NVFORTRAN-S-0155-Compiler failed to translate accelerator region (see -Minfo messages): Unknown variable reference (small_reproducer.F90: 41)
run:
41, Generating NVIDIA GPU code
41, Loop parallelized across CUDA thread blocks, CUDA threads(32) blockidx%x threadidx%x
Generating reduction(+:out)
NVFORTRAN-F-0704-Compilation aborted due to previous errors. (small_reproducer.F90)
NVFORTRAN/x86-64 Linux 26.1-0: compilation aborted
Workarounds I found:
- Add an extra “use” of the mapped array inside the region (e.g., create a dummy tmp and touch arr), then it compiles:
module stubs
use iso_fortran_env
integer, parameter :: r_typ = REAL64
contains
pure subroutine f1(n, x)
integer, intent(in) :: n
real(r_typ), dimension(n), intent(in) :: x
real(r_typ) :: a
a = 0._r_typ
end subroutine f1
pure subroutine f2(x, y)
real(r_typ), intent(in) :: x, y
real(r_typ) :: p
if (x.eq.0._r_typ) then
if (y.ge.0._r_typ) then
p = 2
else
p = -2
end if
end if
end subroutine f2
end module
subroutine run
use iso_fortran_env
use stubs
implicit none
integer :: i, m, n
real(r_typ) :: a, b
real(r_typ), allocatable :: arr(:), tmp(:)
real(r_typ) :: out
m = 4
n = 1
out = 0._r_typ
allocate(arr(m))
allocate(tmp(m))
arr(1) = 1._r_typ
!$omp target enter data map(to: arr)
!$omp target map(tofrom: out)
do concurrent (i = 1: n) reduce(+:out)
tmp = arr(m)
call f1(m, arr)
a = 1._r_typ
b = 1._r_typ
call f2(a, b)
out = out + a + b
enddo
!$omp end target
write(*,'(a,es12.4)') 'out (from device) = ', out
deallocate(tmp, arr)
end subroutine run
program main
call run
end program main
- Or remove the tofrom map, then it compiles.
module stubs
use iso_fortran_env
integer, parameter :: r_typ = REAL64
contains
pure subroutine f1(n, x)
integer, intent(in) :: n
real(r_typ), dimension(n), intent(in) :: x
real(r_typ) :: a
a = 0._r_typ
end subroutine f1
pure subroutine f2(x, y)
real(r_typ), intent(in) :: x, y
real(r_typ) :: p
if (x.eq.0._r_typ) then
if (y.ge.0._r_typ) then
p = 2
else
p = -2
end if
end if
end subroutine f2
end module
subroutine run
use iso_fortran_env
use stubs
implicit none
integer :: i, m, n
real(r_typ) :: a, b
real(r_typ), allocatable :: arr(:)
m = 4
n = 1
allocate(arr(m))
arr(1) = 1._r_typ
!$omp target enter data map(to: arr)
do concurrent (i = 1: n)
call f1(m, arr)
a = 1._r_typ
b = 1._r_typ
call f2(a, b)
enddo
deallocate(arr)
end subroutine run
program main
call run
end program main
Reproducer 2: OpenMP target teams distribute parallel do + nested if in pure routine fails
If I replace the do concurrent with OpenMP teams/distribute/parallel-do, I see a different failure:
module stubs
use iso_fortran_env
integer, parameter :: r_typ = REAL64
contains
pure subroutine f1(n, x)
integer, intent(in) :: n
real(r_typ), dimension(n), intent(in) :: x
real(r_typ) :: a
a = 0._r_typ
end subroutine f1
pure subroutine f2(x, y)
real(r_typ), intent(in) :: x, y
real(r_typ) :: p
if (x.eq.0._r_typ) then
if (y.ge.0._r_typ) then
p = 2
else
p = -2
end if
end if
end subroutine f2
end module
subroutine run
use iso_fortran_env
use stubs
implicit none
integer :: i, m, n
real(r_typ) :: a, b
real(r_typ), allocatable :: arr(:)
m = 4
n = 1
allocate(arr(m))
arr(1) = 1._r_typ
!$omp target teams distribute parallel do &
!$omp map(to: arr, m, n) &
!$omp private(i, a, b)
do i = 1, n
call f1(m, arr)
a = 1._r_typ
b = 1._r_typ
call f2(a, b)
enddo
deallocate(arr)
end subroutine run
program main
call run
end program main
Error:
f1:
5, Generating acc routine seq
Generating NVIDIA GPU code
NVFORTRAN-W-0155-Compiler failed to translate accelerator region (see -Minfo messages): Missing branch target block (small_reproducer.F90: 11)
f2:
11, Generating acc routine seq
Generating NVIDIA GPU code
NVFORTRAN-F-0704-Compilation aborted due to previous errors. (small_reproducer.F90)
NVFORTRAN/x86-64 Linux 26.1-0: compilation aborted
However, rewriting f2 to a branchless form using merge() makes it compile:
module stubs
use iso_fortran_env
integer, parameter :: r_typ = REAL64
contains
pure subroutine f1(n, x)
integer, intent(in) :: n
real(r_typ), dimension(n), intent(in) :: x
real(r_typ) :: a
a = 0._r_typ
end subroutine f1
pure subroutine f2(x, y)
real(r_typ), intent(in) :: x, y
real(r_typ) :: p
p = merge(merge(2._r_typ, -2._r_typ, y.ge.0._r_typ), 0._r_typ, x.eq.0._r_typ)
end subroutine f2
end module
subroutine run
use iso_fortran_env
use stubs
implicit none
integer :: i, m, n
real(r_typ) :: a, b
real(r_typ), allocatable :: arr(:)
m = 4
n = 1
allocate(arr(m))
arr(1) = 1._r_typ
!$omp target teams distribute parallel do &
!$omp map(to: arr, m, n) &
!$omp private(i, a, b)
do i = 1, n
call f1(m, arr)
a = 1._r_typ
b = 1._r_typ
call f2(a, b)
enddo
deallocate(arr)
end subroutine run
program main
call run
end program main
Observations:
- In Reproducer 1, the error is triggered specifically by the combination of:
- omp target map(tofrom: out)
- do concurrent … reduce(+:out)
- calls to pure module procedures inside the loop.
- Removing the map(tofrom:) (and thus the reduction) makes the code compile.
- Adding an otherwise irrelevant extra reference to the mapped array inside the region (e.g., tmp = arr(m)) also makes it compile, even though it does not change semantics.
- In Reproducer 2, the failure occurs when a pure procedure with nested if statements is compiled for device execution inside target teams distribute parallel do.
- Rewriting the nested if into a branchless merge() expression makes the code compile without changing behavior.