Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed logical evaluation of PRESENT intrinsics on Array variables #341

Merged
merged 9 commits into from
Aug 13, 2024
3 changes: 2 additions & 1 deletion loki/transformations/inline.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,8 @@ def _map_unbound_dims(var, val):
check for check in FindInlineCalls().visit(callee.body) if check.function == 'PRESENT'
)
present_map = {
check: sym.Literal('.true.') if check.arguments[0] in call.arg_map else sym.Literal('.false.')
check: sym.Literal('.true.') if check.arguments[0] in [arg.name for arg in call.arg_map]
else sym.Literal('.false.')
for check in present_checks
}
argmap.update(present_map)
Expand Down
58 changes: 58 additions & 0 deletions loki/transformations/tests/test_inline.py
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,63 @@ def test_inline_member_routines_with_associate(frontend):
assert len(assocs) == 2


@pytest.mark.parametrize('frontend', available_frontends(
xfail=[(OMNI, 'OMNI does not handle missing type definitions')]
))
def test_inline_member_routines_with_optionals(frontend):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OMNI currently fails this test, highlighting that the source is not valid fortran at the moment:

 INFO     Loki:logging.py:123 [Loki::OMNI] Parsing /tmp/loki/10428_os7au7hp/omni-a61442a405c4f93e25410eedc4838fd9.f90
ERROR    Loki:logging.py:123 Error: Execution of F_Front failed:
ERROR    Loki:logging.py:123   Full command: F_Front -fleave-comment /tmp/loki/10428_os7au7hp/omni-a61442a405c4f93e25410eedc4838fd9.f90
ERROR    Loki:logging.py:123   Output of the command:


"/tmp/loki/10428_os7au7hp/omni-a61442a405c4f93e25410eedc4838fd9.f90", line 5: "klev" is not a dummy argument.
"/tmp/loki/10428_os7au7hp/omni-a61442a405c4f93e25410eedc4838fd9.f90", line 5: "kidia" is not a dummy argument.
"/tmp/loki/10428_os7au7hp/omni-a61442a405c4f93e25410eedc4838fd9.f90", line 5: "kfdia" is not a dummy argument.
"/tmp/loki/10428_os7au7hp/omni-a61442a405c4f93e25410eedc4838fd9.f90", line 5: "ktdia" is not a dummy argument.
"/tmp/loki/10428_os7au7hp/omni-a61442a405c4f93e25410eedc4838fd9.f90", line 7: type txfu not found
"/tmp/loki/10428_os7au7hp/omni-a61442a405c4f93e25410eedc4838fd9.f90", line 7: Invalid type spec
"/tmp/loki/10428_os7au7hp/omni-a61442a405c4f93e25410eedc4838fd9.f90", line 8: type mf_phys_out_type not found
"/tmp/loki/10428_os7au7hp/omni-a61442a405c4f93e25410eedc4838fd9.f90", line 8: Invalid type spec
"/tmp/loki/10428_os7au7hp/omni-a61442a405c4f93e25410eedc4838fd9.f90", line 10: invalid left operand of '%'
"/tmp/loki/10428_os7au7hp/omni-a61442a405c4f93e25410eedc4838fd9.f90", line 10: invalid left operand of '%'
"/tmp/loki/10428_os7au7hp/omni-a61442a405c4f93e25410eedc4838fd9.f90", line 21: type toto not found
"/tmp/loki/10428_os7au7hp/omni-a61442a405c4f93e25410eedc4838fd9.f90", line 21: Invalid type spec

In particular, klev, kidia, kfdia, ktdia, and ydmf_phys_out are missing from the subroutine interface, and we should include dummy imports of txfu and mf_phys_out_type. That makes this at least fully correct Fortran code.
OMNI will then still fail the test because it is going to lack the relevant type definitions, so it is fine to exclude it from the frontend parameterisation as xfail.

"""
Ensure that internal routines with optional arguments get
inlined as expected (esp. present instrinsics are correctly
evaluated for all variables types)
"""
fcode = """
subroutine test_inline(klon, ydxfu, ydmf_phys_out)

use yomxfu , only : txfu
use mf_phys_type_mod , only : mf_phys_out_type

implicit none

integer(kind=4), intent(in) :: klon
type(txfu) ,intent(inout) :: ydxfu
type(mf_phys_out_type) ,intent(in) :: ydmf_phys_out

call member_rout (ydxfu%visicld, pvmin=ydmf_phys_out%visicld, psmax=1.0_8)

contains

subroutine member_rout (x, pvmin, pvmax, psmin, psmax)

real(kind=8) ,intent(inout) :: x(1:klon)
real(kind=8) ,intent(in) ,optional :: pvmin(1:klon)
real(kind=8) ,intent(in) ,optional :: pvmax(1:klon)
real(kind=8) ,intent(in) ,optional :: psmin
real(kind=8) ,intent(in) ,optional :: psmax

if (present (psmin)) x = psmin
if (present (psmax)) x = psmax
if (present (pvmin)) x = minval(pvmin(:))
if (present (pvmax)) x = maxval(pvmax(:))

end subroutine member_rout

end subroutine test_inline
"""

routine = Subroutine.from_source(fcode, frontend=frontend)

inline_member_procedures(routine=routine)

assert not routine.members

conds = FindNodes(ir.Conditional).visit(routine.body)
assert len(conds) == 4
assert conds[0].condition == 'False'
assert conds[1].condition == 'True'
assert conds[2].condition == 'True'
assert conds[3].condition == 'False'


@pytest.mark.parametrize('frontend', available_frontends(
skip={OFP: "OFP apparently has problems dealing with those Statement Functions",
OMNI: "OMNI automatically inlines Statement Functions"}
Expand Down Expand Up @@ -749,6 +806,7 @@ def test_inline_statement_functions(frontend, stmt_decls):
else:
assert FindInlineCalls().visit(routine.body)


@pytest.mark.parametrize('frontend', available_frontends())
@pytest.mark.parametrize('adjust_imports', [True, False])
def test_inline_marked_subroutines(frontend, adjust_imports, tmp_path):
Expand Down
Loading