(root)/
gcc-13.2.0/
libgomp/
testsuite/
libgomp.fortran/
non-rectangular-loop-1.f90
! { dg-do run }
! { dg-additional-options "-msse2" { target sse2_runtime } }
! { dg-additional-options "-mavx" { target avx_runtime } }

! PR fortran/107424

! Nonrectangular loop nests checks

! See PR or non-rectangular-loop-1a.f90 for the commented tests
! Hint: Those use step for loop vars part of nonrectangular loop nests

module m
  implicit none (type, external)
contains

! The 'k' loop uses i or j as start value
! but a constant end value such that 'lastprivate'
! should be well-defined
subroutine lastprivate_check_simd_1
  integer :: n,m,p, i,j,k

  n = 11
  m = 23
  p = 27

  ! Use 'i' or 'j', unit step on 'i' or on 'j' -> 4 loops
  ! Then same, except use non-unit step for 'k'

!  !$omp simd collapse(3) lastprivate(k)
!  do i = 1, n
!    do j = 1, m, 2
!      do k = j - 41, p
!        if (k < 1 - 41 .or. k > p) error stop
!      end do
!    end do
!  end do
!  if (k /= p + 1) error stop

!  !$omp simd collapse(3) lastprivate(k)
!  do i = 1, n, 2
!    do j = 1, m
!      do k = i - 41, p
!        if (k < 1 - 41 .or. k > p) error stop
!      end do
!    end do
!  end do
!  if (k /= p + 1) error stop

  !$omp simd collapse(3) lastprivate(k)
  do i = 1, n, 2
    do j = 1, m
      do k = j - 41, p
        if (k < 1 - 41 .or. k > p) then
          print *, i, j, k,p, " -> i, j, k, p   (k < 1 - 41 .or. k > p)"
          error stop
        end if
      end do
    end do
  end do
  if (k /= p + 1) error stop

  k = -43
  m = 0
  !$omp simd collapse(3) lastprivate(k)
  do i = 1, n, 2
    do j = 1, m
      do k = j - 41, p
        if (k < 1 - 41 .or. k > p) then
          print *, i, j, k,p, " -> i, j, k, p   (k < 1 - 41 .or. k > p)"
          error stop
        end if
      end do
    end do
  end do
  if (k /= -43) error stop

  m = 23

  !$omp simd collapse(3) lastprivate(k)
  do i = 1, n
    do j = 1, m, 2
      do k = i - 41, p
        if (k < 1 - 41 .or. k > p) error stop
      end do
    end do
  end do
  if (k /= p + 1) error stop

  n = -5
  k = - 70
  !$omp simd collapse(3) lastprivate(k)
  do i = 1, n
    do j = 1, m, 2
      do k = i - 41, p
        if (k < 1 - 41 .or. k > p) error stop
      end do
    end do
  end do
  if (k /= -70) error stop

  n = 11

  ! Same but 'private' for all (i,j) vars

!  !$omp simd collapse(3) lastprivate(k) private(i,j)
!  do i = 1, n
!    do j = 1, m, 2
!      do k = j - 41, p
!        if (k < 1 - 41 .or. k > p) error stop
!      end do
!    end do
!  end do
!  if (k /= p + 1) error stop
!
!  !$omp simd collapse(3) lastprivate(k) private(i,j)
!  do i = 1, n, 2
!    do j = 1, m
!      do k = i - 41, p
!        if (k < 1 - 41 .or. k > p) error stop
!      end do
!    end do
!  end do
!  if (k /= p + 1) error stop

  !$omp simd collapse(3) lastprivate(k) private(i,j)
  do i = 1, n, 2
    do j = 1, m
      do k = j - 41, p
        if (k < 1 - 41 .or. k > p) error stop
      end do
    end do
  end do
  if (k /= p + 1) error stop

  !$omp simd collapse(3) lastprivate(k) private(i,j)
  do i = 1, n
    do j = 1, m, 2
      do k = i - 41, p
        if (k < 1 - 41 .or. k > p) error stop
      end do
    end do
  end do
  if (k /= p + 1) error stop

  ! Same - but with lastprivate(i,j)

!  !$omp simd collapse(3) lastprivate(k) lastprivate(i,j)
!  do i = 1, n
!    do j = 1, m, 2
!      do k = j - 41, p
!        if (k < 1 - 41 .or. k > p) error stop
!      end do
!    end do
!  end do
!  if (k /= p + 1) error stop
!  if (i /= n + 1 .or. j /= m + 2) error stop

!  !$omp simd collapse(3) lastprivate(k) lastprivate(i,j)
!  do i = 1, n, 2
!    do j = 1, m
!      do k = i - 41, p
!        if (k < 1 - 41 .or. k > p) error stop
!      end do
!    end do
!  end do
!  if (k /= p + 1) error stop
!  if (i /= n + 2 .or. j /= m + 1) error stop

  !$omp simd collapse(3) lastprivate(k) lastprivate(i,j)
  do i = 1, n, 2
    do j = 1, m
      do k = j - 41, p
        if (k < 1 - 41 .or. k > p) error stop
      end do
    end do
  end do
  if (k /= p + 1) error stop
  if (i /= n + 2 .or. j /= m + 1) error stop

  !$omp simd collapse(3) lastprivate(k) lastprivate(i,j)
  do i = 1, n
    do j = 1, m, 2
      do k = i - 41, p
        if (k < 1 - 41 .or. k > p) error stop
      end do
    end do
  end do
  if (k /= p + 1) error stop
  if (i /= n + 1 .or. j /= m + 2) error stop
end subroutine lastprivate_check_simd_1


! Same but with do simd
subroutine lastprivate_check_do_simd_1
  integer :: n,m,p, i,j,k

  n = 11
  m = 23
  p = 27

  ! Use 'i' or 'j', unit step on 'i' or on 'j' -> 4 loops
  ! Then same, except use non-unit step for 'k'

!  !$omp parallel do simd collapse(3) lastprivate(k)
!  do i = 1, n
!    do j = 1, m, 2
!      do k = j - 41, p
!        if (k < 1 - 41 .or. k > p) error stop
!      end do
!    end do
!  end do
!  if (k /= p + 1) error stop

!  !$omp parallel do simd collapse(3) lastprivate(k)
!  do i = 1, n, 2
!    do j = 1, m
!      do k = i - 41, p
!        if (k < 1 - 41 .or. k > p) error stop
!      end do
!    end do
!  end do
!  if (k /= p + 1) error stop

  !$omp parallel do simd collapse(3) lastprivate(k)
  do i = 1, n, 2
    do j = 1, m
      do k = j - 41, p
        if (k < 1 - 41 .or. k > p) error stop
      end do
    end do
  end do
  if (k /= p + 1) error stop

  !$omp parallel do simd collapse(3) lastprivate(k)
  do i = 1, n
    do j = 1, m, 2
      do k = i - 41, p
        if (k < 1 - 41 .or. k > p) error stop
      end do
    end do
  end do
  if (k /= p + 1) error stop

  ! Same but 'private' for all (i,j) vars

!  !$omp parallel do simd collapse(3) lastprivate(k) private(i,j)
!  do i = 1, n
!    do j = 1, m, 2
!      do k = j - 41, p
!        if (k < 1 - 41 .or. k > p) error stop
!      end do
!    end do
!  end do
!  if (k /= p + 1) error stop

!  !$omp parallel do simd collapse(3) lastprivate(k) private(i,j)
!  do i = 1, n, 2
!    do j = 1, m
!      do k = i - 41, p
!        if (k < 1 - 41 .or. k > p) error stop
!      end do
!    end do
!  end do
!  if (k /= p + 1) error stop

  !$omp parallel do simd collapse(3) lastprivate(k) private(i,j)
  do i = 1, n, 2
    do j = 1, m
      do k = j - 41, p
        if (k < 1 - 41 .or. k > p) error stop
      end do
    end do
  end do
  if (k /= p + 1) error stop

  !$omp parallel do simd collapse(3) lastprivate(k) private(i,j)
  do i = 1, n
    do j = 1, m, 2
      do k = i - 41, p
        if (k < 1 - 41 .or. k > p) error stop
      end do
    end do
  end do
  if (k /= p + 1) error stop

  ! Same - but with lastprivate(i,j)

!  !$omp parallel do simd collapse(3) lastprivate(k) lastprivate(i,j)
!  do i = 1, n
!    do j = 1, m, 2
!      do k = j - 41, p
!        if (k < 1 - 41 .or. k > p) error stop
!      end do
!    end do
!  end do
!  if (k /= p + 1) error stop
!  if (i /= n + 1 .or. j /= m + 2) error stop

!  !$omp parallel do simd collapse(3) lastprivate(k) lastprivate(i,j)
!  do i = 1, n, 2
!    do j = 1, m
!      do k = i - 41, p
!        if (k < 1 - 41 .or. k > p) error stop
!      end do
!    end do
!  end do
!  if (k /= p + 1) error stop
!  if (i /= n + 2 .or. j /= m + 1) error stop

  !$omp parallel do simd collapse(3) lastprivate(k) lastprivate(i,j)
  do i = 1, n, 2
    do j = 1, m
      do k = j - 41, p
        if (k < 1 - 41 .or. k > p) error stop
      end do
    end do
  end do
  if (k /= p + 1) error stop
  if (i /= n + 2 .or. j /= m + 1) error stop

  !$omp parallel do simd collapse(3) lastprivate(k) lastprivate(i,j)
  do i = 1, n
    do j = 1, m, 2
      do k = i - 41, p
        if (k < 1 - 41 .or. k > p) error stop
      end do
    end do
  end do
  if (k /= p + 1) error stop
  if (i /= n + 1 .or. j /= m + 2) error stop
end subroutine lastprivate_check_do_simd_1



! Same but with do
subroutine lastprivate_check_do_1
  integer :: n,m,p, i,j,k

  n = 11
  m = 23
  p = 27

  ! Use 'i' or 'j', unit step on 'i' or on 'j' -> 4 loops
  ! Then same, except use non-unit step for 'k'

!  !$omp parallel do collapse(3) lastprivate(k)
!  do i = 1, n
!    do j = 1, m, 2
!      do k = j - 41, p
!        if (k < 1 - 41 .or. k > p) error stop
!      end do
!    end do
!  end do
!  if (k /= p + 1) error stop

!  !$omp parallel do collapse(3) lastprivate(k)
!  do i = 1, n, 2
!    do j = 1, m
!      do k = i - 41, p
!        if (k < 1 - 41 .or. k > p) error stop
!      end do
!    end do
!  end do
!  if (k /= p + 1) error stop

  !$omp parallel do collapse(3) lastprivate(k)
  do i = 1, n, 2
    do j = 1, m
      do k = j - 41, p
        if (k < 1 - 41 .or. k > p) error stop
      end do
    end do
  end do
  if (k /= p + 1) error stop

  !$omp parallel do collapse(3) lastprivate(k)
  do i = 1, n
    do j = 1, m, 2
      do k = i - 41, p
        if (k < 1 - 41 .or. k > p) error stop
      end do
    end do
  end do
  if (k /= p + 1) error stop

  ! Same but 'private' for all (i,j) vars

!  !$omp parallel do collapse(3) lastprivate(k) private(i,j)
!  do i = 1, n
!    do j = 1, m, 2
!      do k = j - 41, p
!        if (k < 1 - 41 .or. k > p) error stop
!      end do
!    end do
!  end do
!  if (k /= p + 1) error stop

!  !$omp parallel do collapse(3) lastprivate(k) private(i,j)
!  do i = 1, n, 2
!    do j = 1, m
!      do k = i - 41, p
!        if (k < 1 - 41 .or. k > p) error stop
!      end do
!    end do
!  end do
!  if (k /= p + 1) error stop

  !$omp parallel do collapse(3) lastprivate(k) private(i,j)
  do i = 1, n, 2
    do j = 1, m
      do k = j - 41, p
        if (k < 1 - 41 .or. k > p) error stop
      end do
    end do
  end do
  if (k /= p + 1) error stop

  !$omp parallel do collapse(3) lastprivate(k) private(i,j)
  do i = 1, n
    do j = 1, m, 2
      do k = i - 41, p
        if (k < 1 - 41 .or. k > p) error stop
      end do
    end do
  end do
  if (k /= p + 1) error stop

  ! Same - but with lastprivate(i,j)

!  !$omp parallel do collapse(3) lastprivate(k) lastprivate(i,j)
!  do i = 1, n
!    do j = 1, m, 2
!      do k = j - 41, p
!        if (k < 1 - 41 .or. k > p) error stop
!      end do
!    end do
!  end do
!  if (k /= p + 1) error stop
!  if (i /= n + 1 .or. j /= m + 2) error stop

!  !$omp parallel do collapse(3) lastprivate(k) lastprivate(i,j)
!  do i = 1, n, 2
!    do j = 1, m
!      do k = i - 41, p
!        if (k < 1 - 41 .or. k > p) error stop
!      end do
!    end do
!  end do
!  if (k /= p + 1) error stop
!  if (i /= n + 2 .or. j /= m + 1) error stop

  !$omp parallel do collapse(3) lastprivate(k) lastprivate(i,j)
  do i = 1, n, 2
    do j = 1, m
      do k = j - 41, p
        if (k < 1 - 41 .or. k > p) error stop
      end do
    end do
  end do
  if (k /= p + 1) error stop
  if (i /= n + 2 .or. j /= m + 1) error stop

  !$omp parallel do collapse(3) lastprivate(k) lastprivate(i,j)
  do i = 1, n
    do j = 1, m, 2
      do k = i - 41, p
        if (k < 1 - 41 .or. k > p) error stop
      end do
    end do
  end do
  if (k /= p + 1) error stop
  if (i /= n + 1 .or. j /= m + 2) error stop
end subroutine lastprivate_check_do_1



subroutine lastprivate_check_2
  integer :: n,m,p, i,j,k,ll

  n = 11
  m = 23
  p = 27

!  !$omp parallel do simd collapse(3) lastprivate(p)
!  do i = 1, n
!    do j = 1, m,2
!      do k = 1, j + 41
!        do ll = 1, p, 2
!          if (k > 23 + 41 .or. k < 1) error stop
!        end do
!      end do
!    end do
!  end do
!  if (ll /= 29) error stop

!  !$omp simd collapse(3) lastprivate(p)
!  do i = 1, n
!    do j = 1, m,2
!      do k = 1, j + 41
!        do ll = 1, p, 2
!          if (k > 23 + 41 .or. k < 1) error stop
!        end do
!      end do
!    end do
!  end do
!  if (ll /= 29) error stop

!  !$omp simd collapse(3) lastprivate(k)
!  do i = 1, n,2
!    do j = 1, m
!      do k = 1, i + 41
!        if (k > 11 + 41 .or. k < 1) error stop
!      end do
!    end do
!  end do
!if (k /= 53) then
!  print *, k, 53
!  error stop
!endif

!$omp simd collapse(3) lastprivate(k)
do i = 1, n,2
  do j = 1, m
    do k = 1, j + 41
      if (k > 23 + 41 .or. k < 1) error stop
    end do
  end do
end do
if (k /= 65) then
  print *, k, 65
  error stop
endif


!$omp simd collapse(3) lastprivate(k)
do i = 1, n
  do j = 1, m,2
    do k = 1, i + 41
      if (k > 11 + 41 .or. k < 1) error stop
    end do
  end do
end do
if (k /= 53) then
  print *, k, 53
  error stop
endif

! - Same but without 'private':
!!$omp simd collapse(3) lastprivate(k)
!do i = 1, n
!  do j = 1, m,2
!    do k = 1, j + 41
!      if (k > 23 + 41 .or. k < 1) error stop
!    end do
!  end do
!end do
!if (k /= 65) then
!  print *, k, 65
!  error stop
!endif


!!$omp simd collapse(3) lastprivate(k)
!do i = 1, n,2
!  do j = 1, m
!    do k = 1, i + 41
!      if (k > 11 + 41 .or. k < 1) error stop
!    end do
!  end do
!end do
!if (k /= 53) then
!  print *, k, 53
!  error stop
!endif

!$omp simd collapse(3) lastprivate(k)
do i = 1, n,2
  do j = 1, m
    do k = 1, j + 41
      if (k > 23 + 41 .or. k < 1) error stop
    end do
  end do
end do
if (k /= 65) then
  print *, k, 65
  error stop
endif


!$omp simd collapse(3) lastprivate(k)
do i = 1, n
  do j = 1, m,2
    do k = 1, i + 41
      if (k > 11 + 41 .or. k < 1) error stop
    end do
  end do
end do
if (k /= 53) then
  print *, k, 53
  error stop
endif

! - all with lastprivate
!!$omp simd collapse(3) lastprivate(k) lastprivate(i, j)
!do i = 1, n
!  do j = 1, m,2
!    do k = 1, j + 41
!      if (k > 23 + 41 .or. k < 1) error stop
!    end do
!  end do
!end do
!if (k /= 65) then
!  print *, k, 65
!  error stop
!endif


!!$omp simd collapse(3) lastprivate(k) lastprivate(i, j)
!do i = 1, n,2
!  do j = 1, m
!    do k = 1, i + 41
!      if (k > 11 + 41 .or. k < 1) error stop
!    end do
!  end do
!end do
!if (k /= 53) then
!  print *, k, 53
!  error stop
!endif

!$omp simd collapse(3) lastprivate(k) lastprivate(i, j)
do i = 1, n,2
  do j = 1, m
    do k = 1, j + 41
      if (k > 23 + 41 .or. k < 1) error stop
    end do
  end do
end do
if (k /= 65) then
  print *, k, 65
  error stop
endif


!$omp simd collapse(3) lastprivate(k) lastprivate(i, j)
do i = 1, n
  do j = 1, m,2
    do k = 1, i + 41
      if (k > 11 + 41 .or. k < 1) error stop
    end do
  end do
end do
if (k /= 53) then
  print *, k, 53
  error stop
endif

end
end module m

program main
  use m
  implicit none (type, external)
  call lastprivate_check_simd_1
  call lastprivate_check_do_simd_1
  call lastprivate_check_do_1
  call lastprivate_check_2
end