ecmwf-ifs / loki

Freely programmable source-to-source translation for Fortran

Home Page:https://sites.ecmwf.int/docs/loki/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

SCC-stack: UnboundLocalError when a field of a derived type is used to declare a temporary array

skarppinen opened this issue · comments

This is bug occurs when running "loki-transform.py" with mode = scc-stack.
The error message is "UnboundLocalError: local variable 'new_type' referenced before assignment", coming from expression/mappers.py:600

Here is a reproducer of the issue, note the comments in the Fortran code:

module mod3
    implicit none 
    type :: mytype
            integer :: i
    end type mytype
contains
    subroutine wrapper
        integer :: h_start = 1
        integer, parameter :: h_dim = 10
        integer :: h_end 
        integer :: v_start = 1
        integer, parameter :: v_dim = 20
        integer, parameter :: block_size = 30
        integer :: block_index
        
        type(mytype) :: m 
        m%i = 2

        real :: arr(h_dim, v_dim, block_size)

        h_end = h_dim
        do block_index = 1, block_size 
        call depth1(h_start, h_end, h_dim, v_start, v_dim, &
            m, arr(:, :, block_index))
        end do
        print *, "Sum of array is ", sum(arr)
    end subroutine wrapper

    subroutine depth1(h_start, h_end, h_dim, v_start, v_dim, m, array)
        ! Arguments.
        integer, intent(in) :: h_start
        integer, intent(in) :: h_end
        integer, intent(in) :: h_dim
        integer, intent(in) :: v_start
        integer, intent(in) :: v_dim
        real, intent(inout) :: array(h_dim, v_dim)
        type(mytype), intent(in) :: m

        ! Non-array local variables.
        integer :: v_index
        integer :: h_index

        ! Temporary arrays.
        real :: tmp1(h_dim, v_dim), tmpx(h_dim, v_dim)
        real :: tmpy(h_dim, v_dim, m%i) ! NOTE: This temporary is declared using m%i, which is the root of the issue.

        do v_index = v_start, v_dim
            do h_index = h_start, h_end
                tmpx(h_index, v_index) = 4.0 
                ! NOTE: Here we write to the offending array. If this is omitted, the crash doesn't occur.
                tmpy(h_index, v_index, 1) = 13.0
                tmp1(h_index, v_index) = exp(log(real(h_index)) + log(real(v_index)) - 1.0)
            end do
        end do

        do v_index = v_start, v_dim
            do h_index = h_start, h_end
                array(h_index, v_index) = exp(tmp1(h_index, v_index) + 0.25)
            end do
        end do


        do v_index = v_start, v_dim
            do h_index = h_start, h_end
                array(h_index, v_index) = log(tmp1(h_index, v_index)) + array(h_index, v_index) * 2.0
            end do
        end do

    end subroutine depth1
end module mod3

To call "loki-transform.py" I use:
loki-transform.py convert --out-path scc-stack --path src --global-var-offload --data-offload --remove-openmp --directive openacc --mode scc-stack --config loki-config --inline-members

although most of the options do nothing here.
The contents of "loki-config" are:

[default]
# Specifies the behaviour of auto-expanded routines
role = 'kernel'
expand = true  # Automatically expand subroutine calls
strict = true # Throw exceptions during discovery

# Define entry point for call-tree transformation
[[routine]]
name = 'wrapper'
role = 'driver'
expand = true

[[dimension]]
name = 'horizontal'
size = 'h_dim'
index = 'h_index'
bounds = ['h_start', 'h_end']

[[dimension]]
name = 'vertical'
size = 'v_dim'
index = 'v_index'

[[dimension]]
name = 'block_dim'
size = 'block_size'
index = 'block_index'

Possibly related to nested derived types. In Acraneb2, it crashes for YDML_PHY_MF%YRPHY3%N_SPBAND, where YRPHY3 is passed on to a nested kernel (AC_CLOUD_MODEL2) as YDPHY3 and YDPHY3%N_SPBAND.

new_type depend on is_type_changed which is set on line 586 in mappers.py

is_type_changed = (
kind is not old_type.kind or initial is not old_type.initial or
any(new is not old for new, old in zip_longest(as_tuple(bind_names), as_tuple(old_type.bind_names)))
)

but all the variables that show up in the logical test are None, both new and old. expr.type is correctly integer, but its expr.type.kind and expr.type.initial are attributes are both None

I made a minimal test branch here: https://github.com/rolfhm/minimal_test/tree/pool_crash

I can confirm that this issue is indeed fixed by #192