Loop-Carried Lexical Forward Dependence
7.3. Loop-Carried Lexical Forward Dependence#
The following example tests the restriction on an SIMD loop with the loop-carried lexical forward-dependence. This dependence must be preserved for the correct execution of SIMD loops.
A loop can be vectorized even though the iterations are not completely independent when it has loop-carried dependences that are forward lexical dependences, indicated in the code below by the read of A[j+1] and the write to A[j] in C/C++ code (or A(j+1) and A(j) in Fortran). That is, the read of A[j+1] (or A(j+1) in Fortran) before the write to A[j] (or A(j) in Fortran) ordering must be preserved for each iteration in j for valid SIMD code generation.
This test assures that the compiler preserves the loop carried lexical forward-dependence for generating a correct SIMD code.
//%compiler: clang
//%cflags: -fopenmp
/*
* name: SIMD.8
* type: C
* version: omp_4.0
*/
#include <stdio.h>
#include <math.h>
int P[1000];
float A[1000];
float do_work(float *arr)
{
float pri;
int i;
#pragma omp simd lastprivate(pri)
for (i = 0; i < 999; ++i) {
int j = P[i];
pri = 0.5f;
if (j % 2 == 0) {
pri = A[j+1] + arr[i];
}
A[j] = pri * 1.5f;
pri = pri + A[j];
}
return pri;
}
int main(void)
{
float pri, arr[1000];
int i;
for (i = 0; i < 1000; ++i) {
P[i] = i;
A[i] = i * 1.5f;
arr[i] = i * 1.8f;
}
pri = do_work(&arr[0]);
if (pri == 8237.25) {
printf("passed: result pri = %7.2f (8237.25) \n", pri);
}
else {
printf("failed: result pri = %7.2f (8237.25) \n", pri);
}
return 0;
}
!!%compiler: gfortran
!!%cflags: -fopenmp
! name: SIMD.8
! type: F-free
! version: omp_4.0
module work
integer :: P(1000)
real :: A(1000)
contains
function do_work(arr) result(pri)
implicit none
real, dimension(*) :: arr
real :: pri
integer :: i, j
!$omp simd private(j) lastprivate(pri)
do i = 1, 999
j = P(i)
pri = 0.5
if (mod(j-1, 2) == 0) then
pri = A(j+1) + arr(i)
endif
A(j) = pri * 1.5
pri = pri + A(j)
end do
end function do_work
end module work
program simd_8f
use work
implicit none
real :: pri, arr(1000)
integer :: i
do i = 1, 1000
P(i) = i
A(i) = (i-1) * 1.5
arr(i) = (i-1) * 1.8
end do
pri = do_work(arr)
if (pri == 8237.25) then
print 2, "passed", pri
else
print 2, "failed", pri
endif
2 format(a, ": result pri = ", f7.2, " (8237.25)")
end program