Consider this example of an interesting interaction of OMP SIMD and zero iteration DO loop:
program foo
implicit none
integer(kind=4) :: i, j, me1, me2
me1 = 1
me2 = 1
i = me1
j = 42 !...dummy flag to test IV after loop exit
!$omp simd
do j=i+1, me2
me1 = me1+1
enddo
print *, 'me1 ', me1
print *, 'IV j should be 2, is: ', j
end program foo
WIthout OMP SIMD the behavior is predictable. Given the values before the DO of i=me1=1 and me2=1, the loop is
do j=2,1
so expected behavior is that the loop has no iterations, but the interation variable (IV) value after the loop is expected to be 2. Which it is for gfortran, ifort, ifx, and NAG. IFX has an oddity in that OMP SIMD is interpreted by default even without any OPENMP options (this was a behavior change that I strongly opposed but I lost the argument). SO for ifx you have to compile with an option to explicitly turn off SIMD. Here is that example
ifx -qno-openmp-simd ifx_simd_deadcode.f90 ; ./a.out
me1 1
IV j should be 2, is: 2
So far so good, all 4 compilers give the same result.
Now if we enable SIMD (Ifx default)
NAG doesn’t like the OMP SIMD syntax and won’t compile this example.
Gfortran 13 compiles but the value of the IV value after the loop is undefined
rm a.out ; gfortran -fopenmp -O0 ifx_simd_deadcode.f90 ; ./a.out
me1 1
IV j should be 2, is: 1867453140
similarly, ifx with SIMD enabled does not show J = 2. Rather, it keeps the value of 42 assigned prior to the loop
rm a.out ; ifx -qopenmp -O0 ifx_simd_deadcode.f90 ; ./a.out
me1 1
IV j should be 2, is: 42
I even tried adding J to a LASTPRIVATE clause
program foo
implicit none
integer(kind=4) :: i, j, me1, me2
me1 = 1
me2 = 1
i = me1
j = 42 !...dummy flag to test IV after loop exit
!$omp simd lastprivate(j)
do j=i+1, me2
me1 = me1+1
enddo
print *, 'me1 ', me1
print *, 'IV j should be 2, is: ', j
end program foo
but still both gfortran and ifx give odd results
rm a.out ; ifx -qopenmp -O0 ifx_simd_deadcode_lastprivate.f90 ; ./a.out
me1 1
IV j should be 2, is: 42
rm a.out ; gfortran -fopenmp -O0 ifx_simd_deadcode_lastprivate.f90 ; ./a.out
me1 1
IV j should be 2, is: 1815540460
and I hate to say it, but ifort seems to give the result I expected
rm a.out ; ifort -qopenmp -O0 ifx_simd_deadcode.f90 -diag-disable=10448 ; ./a.out
me1 1
IV j should be 2, is: 2
I have read through SIMD in the OMP specs for 5.0 and 5.2 but am unable to find any reference to what the expected behavior is for this example.
I did note that the -qopt-report 3 for ifx showed that in the SIMD enabled case that the optimizer removed the “dead code” for the loop, hence I know why J is 42 instead of 2. It decided that my loop didn’t have any interations, hence off with it’s head. Not very Fortran-like behavior, IMHO.
The questions then are:
What is the expected value of J after the SIMD loop, with or without LASTPRIVATE
Where is this documented in the OMP Spec?
