Skip to content

[Flang][OpenMP][Regression] OMP SIMD regression with compiler directives. #169532

@scamp-nvidia

Description

@scamp-nvidia

@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.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions