-
Notifications
You must be signed in to change notification settings - Fork 15.3k
Description
@kparzysz landed #169346 yesterday, fixing compatibility with compiler directives and OpenMP regions from their recent change #168884 . However, I suspect there's still something subtle that needs to be fixed. Our testing suite has highlighted a newly emerged issue after this change with the combination of a directive and an OpenMP SIMD clause. Consider the following code:
! simd_dir_repro.F90
program simd_dir_repro
implicit none
integer, parameter :: dp = kind(1.0d0)
integer, parameter :: veclen = 128
integer, parameter :: grid_ntri = 4
real(dp) :: y(veclen,3)
real(dp) :: grid_mapping(2,3,grid_ntri)
real(dp), parameter :: eps = 1.0d-12
integer :: id_simd(veclen)
integer :: sum_simd, i, iv
!-----------------------------
! Simple, deterministic setup
!-----------------------------
y(:,:) = 0.0_dp
grid_mapping(:,:,:) = 0.0_dp
! Just to make it not *too* trivial, add some variation in mapping:
grid_mapping(1,1,1) = 0.1_dp
grid_mapping(2,2,1) = 0.2_dp
! Still, with y=0 and grid_mapping( :,3,: ) = 0, we get dx = 0,
! so bc_coords = [0, 0, 1] and the condition is always satisfied
! on the first triangle.
do iv = 1, veclen
id_simd(iv) = -1
end do
call compute_id_simd (veclen, grid_ntri, y, grid_mapping, eps, id_simd)
sum_simd = sum(id_simd)
write(*,*) "sum_simd:", sum_simd
if (sum_simd /= 128) then
write(*,*) "MISMATCH!"
else
write(*,*) "OK!"
end if
end program simd_dir_repro
subroutine compute_id_simd(veclen, grid_ntri, y, grid_mapping, eps, id)
implicit none
integer, intent(in) :: veclen, grid_ntri
integer, intent(out) :: id(veclen)
real(kind(1.0d0)), intent(in) :: y(veclen,3)
real(kind(1.0d0)), intent(in) :: grid_mapping(2,3,grid_ntri)
real(kind(1.0d0)), intent(in) :: eps
real(kind(1.0d0)) :: dx(2), bc_coords(3)
integer :: iv, itri
#ifndef DISABLE_SIMD
!$omp simd
#endif
#ifndef DISABLE_VECT
!dir$ anything_here
#endif
vecloop: do iv = 1, veclen
triangleloop: do itri = 1, grid_ntri
dx(1) = y(iv,1) - grid_mapping(1,3,itri)
dx(2) = y(iv,3) - grid_mapping(2,3,itri)
bc_coords(1:2) = grid_mapping(1:2,1,itri) * dx(1) + &
grid_mapping(1:2,2,itri) * dx(2)
bc_coords(3) = 1.0d0 - bc_coords(1) - bc_coords(2)
if (minval(bc_coords) .ge. -eps) then
id(iv) = itri
cycle vecloop
end if
end do triangleloop
end do vecloop
end subroutine compute_id_simd
If I compile the code as it stands with gfortran or nvfortran, then I get the right answer. However, with Flang, I only get the right answer if I either disable the "!$omp simd" clause or the "!dir$ anything_here" clause. The two together cause something to go off the rail and end up with the wrong answer.
[scamp]$ gfortran test.F90 -o test -fopenmp
[scamp]$ ./test
sum_simd: 128
OK!
[scamp]$ nvfortran test.F90 -o test -mp
[scamp]$ ./test
sum_simd: 128
OK!
[scamp]$ flang test.F90 -o test -fopenmp
./test.F90:57:9: warning: Unrecognized compiler directive was ignored [-Wignored-directive]
!dir$ anything_here
^
./test.F90:57:9: warning: Compiler directives are not allowed inside OpenMP loop constructs
!dir$ anything_here
^
[scamp]$ ./test
sum_simd: -128
MISMATCH!
[scamp]$ flang test.F90 -o test -fopenmp -DDISABLE_SIMD
./test.F90:57:9: warning: Unrecognized compiler directive was ignored [-Wignored-directive]
!dir$ anything_here
^
[scamp]$ ./test
sum_simd: 128
OK!
[scamp]$ flang test.F90 -o test -fopenmp -DDISABLE_VECT
[scamp]$ ./test
sum_simd: 128
OK!
[scamp]$
This worked prior to the recent changes and clearly appears to be a correctness issue in comparison to GCC and NVHPC. Note that I put an entirely dummy directive in to highlight that it's a wiring issue when directives are present.
Tagging @kiranchandramohan for OpenMP correctness regression too.