HoistTemporaryArraysTransformationAllocatable: multi-variable declarations are not separated if not all variables become dummy args
reuterbal opened this issue · comments
Balthasar Reuter commented
Thanks to @skarppinen for bringing this to my attention.
The hoisted variables receive an intent
attribute but other non-hoisted variables do not. This requires separating the declarations.
The following reproduces the issue:
@pytest.mark.parametrize('frontend', available_frontends())
def test_hoist_mixed_variable_declarations(frontend, config):
fcode_driver = """
subroutine driver(NLON, NZ, NB, FIELD1, FIELD2)
use kernel_mod, only: kernel
implicit none
INTEGER, PARAMETER :: JPRB = SELECTED_REAL_KIND(13,300)
INTEGER, INTENT(IN) :: NLON, NZ, NB
real(kind=jprb), intent(inout) :: field1(nlon, nb)
real(kind=jprb), intent(inout) :: field2(nlon, nz, nb)
integer :: b
do b=1,nb
call KERNEL(1, nlon, nlon, nz, 2, field1(:,b), field2(:,:,b))
end do
end subroutine driver
""".strip()
fcode_kernel = """
module kernel_mod
implicit none
contains
subroutine kernel(start, end, klon, klev, nclv, field1, field2)
use iso_c_binding, only : c_size_t
implicit none
integer, parameter :: jprb = selected_real_kind(13,300)
integer, intent(in) :: nclv
integer, intent(in) :: start, end, klon, klev
real(kind=jprb), intent(inout) :: field1(klon)
real(kind=jprb), intent(inout) :: field2(klon,klev)
real(kind=jprb) :: tmp1(klon)
real(kind=jprb) :: tmp2(klon, klev), tmp3(nclv)
real(kind=jprb) :: tmp4(2), tmp5(klon, nclv)
integer :: jk, jl, jm
do jk=1,klev
tmp1(jl) = 0.0_jprb
do jl=start,end
tmp2(jl, jk) = field2(jl, jk)
tmp1(jl) = field2(jl, jk)
end do
field1(jl) = tmp1(jl)
end do
do jm=1,nclv
tmp3(jm) = 0._jprb
do jl=start,end
tmp5(jl, jm) = field1(jl)
enddo
enddo
end subroutine kernel
end module kernel_mod
""".strip()
basedir = gettempdir()/'test_hoist_mixed_variable_declarations'
basedir.mkdir(exist_ok=True)
(basedir/'driver.F90').write_text(fcode_driver)
(basedir/'kernel_mod.F90').write_text(fcode_kernel)
config = {
'default': {
'mode': 'idem',
'role': 'kernel',
'expand': True,
'strict': True
},
'routine': [{
'name': 'driver',
'role': 'driver',
}]
}
scheduler = Scheduler(paths=[basedir], config=SchedulerConfig.from_dict(config), frontend=frontend)
if frontend == OMNI:
for item in scheduler.items:
normalize_range_indexing(item.routine)
scheduler.process(transformation=HoistTemporaryArraysAnalysis(dim_vars=('klev',)), reverse=True)
scheduler.process(transformation=HoistTemporaryArraysTransformationAllocatable())
scheduler['kernel_mod#kernel'].source.to_fortran() # Fails with AssertionError