stfc / PSyclone

Domain-specific compiler and code transformation system for Finite Difference/Volume/Element Earth-system models in Fortran
BSD 3-Clause "New" or "Revised" License
104 stars 27 forks source link

[InlineTrans] branch main, error inlining subroutine using complex array bounds #2703

Open hbrunie opened 1 month ago

hbrunie commented 1 month ago

Commit used:

commit ddd2e56bc67e4d3342230083acfa0b7a99c12d25 (HEAD -> master, origin/master)
Merge: 9f219c98c 94c56772e
Author: Andy Porter <arporter@users.noreply.github.com>
Date:   Wed Aug 28 09:53:26 2024 +0100

    Merge pull request #2675 from stfc/1351-dof-kernels-code

    #1351 DoF Kernel Metadata Checks

Here is the test (pytest) I made that crashes. It looks like the transformation assumes that the iteration step inside the loop should shift with regards to the bounds of the arrays declaration. Nevertheless this gives an incorrect inline transformation.

from psyclone.psyir.frontend.fortran import FortranReader
from psyclone.psyir.nodes import Node, Routine, Call
from psyclone.psyir.transformations import InlineTrans
from psyclone.psyir.symbols import DataSymbol, UnresolvedType

def test_psyir_inline_cplx_arrays():
    def inline_uvtra_step_into_step(psyir_code: Node) -> Routine:
        for node_routine in psyir_code.walk(Routine):
            if node_routine.name != "step":
                continue
            trans = InlineTrans()
            for call in node_routine.walk(Call):
                assert call.children[0].name == "step_uvtra"
                trans.validate(call)
                trans.apply(call)
            return node_routine
        assert False

    input_code = """subroutine step(lhs_u, rhs_u, nx, ny)
  integer, intent(in) :: ny,nx
  real*8,dimension(0:nx+1,0:ny+1), intent(inout) :: lhs_u
  real*8,dimension(0:nx+1,0:ny+1), intent(in) :: rhs_u

  call step_uvtra(lhs_u, rhs_u, nx,ny)
  end subroutine

  subroutine step_uvtra(lu, ru, nx, ny)
  real*8, dimension(0:nx + 1,ny + 1), intent(inout) :: lu
  real*8, dimension(0:nx + 1,ny + 1), intent(in) :: ru 
  integer, intent(in) :: ny,nx
  integer :: j,i
  do j = 1, ny, 1
    do i = 0, nx, 1
      lu(i,j) = ru(i,j)
    enddo
  enddo
  end subroutine"""

    reader = FortranReader()
    psyir_tree: Node = reader.psyir_from_source(input_code)
    routine: Routine = inline_uvtra_step_into_step(psyir_tree)

    wrong_inlined_code = """subroutine step(lhs_u, rhs_u, nx, ny)
  integer, intent(in) :: ny
  integer, intent(in) :: nx
  real*8, dimension(0:nx + 1,0:ny + 1), intent(inout) :: lhs_u
  real*8, dimension(0:nx + 1,0:ny + 1), intent(in) :: rhs_u
  integer :: j
  integer :: i

  do j = 1, ny, 1
    do i = 0, nx, 1
      lhs_u(i,j - 1 + 0) = rhs_u(i,j - 1 + 0)
    enddo
  enddo

end subroutine step
"""
    assert routine.debug_string() == wrong_inlined_code

    correct_inlined_code = """subroutine step(lhs_u, rhs_u, nx, ny)
  integer, intent(in) :: ny
  integer, intent(in) :: nx
  real*8, dimension(0:nx + 1,0:ny + 1), intent(inout) :: lhs_u
  real*8, dimension(0:nx + 1,0:ny + 1), intent(in) :: rhs_u
  integer :: j
  integer :: i

  do j = 1, ny, 1
    do i = 0, nx, 1
      lhs_u(i,j) = rhs_u(i,j)
    enddo
  enddo

end subroutine step
"""
    assert routine.debug_string() == correct_inlined_code