Skip to content

Commit

Permalink
Merge pull request #322 from ecmwf-ifs/naan-create-edges
Browse files Browse the repository at this point in the history
InlineTransformation: Update Scheduler SGraph if marked_inline is activated
  • Loading branch information
reuterbal authored Jun 12, 2024
2 parents af121bc + f23fd4a commit eb793e2
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 7 deletions.
1 change: 0 additions & 1 deletion loki/batch/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,6 @@ def _get_definition_items(_item, sgraph_items):

if transformation.creates_items:
self._discover()

self._parse_items()

def callgraph(self, path, with_file_graph=False, with_legend=False):
Expand Down
15 changes: 10 additions & 5 deletions loki/transformations/inline.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ class InlineTransformation(Transformation):
# Ensure correct recursive inlining by traversing from the leaves
reverse_traversal = True

# This transformation will potentially change the edges in the callgraph
creates_items = False

def __init__(
self, inline_constants=False, inline_elementals=True,
inline_internals=False, inline_marked=True,
Expand All @@ -95,6 +98,8 @@ def __init__(
self.adjust_imports = adjust_imports
self.external_only = external_only
self.resolve_sequence_association = resolve_sequence_association
if self.inline_marked:
self.creates_items = True

def transform_subroutine(self, routine, **kwargs):

Expand Down Expand Up @@ -194,8 +199,8 @@ def map_inline_call(self, expr, *args, **kwargs):

def resolve_sequence_association_for_inlined_calls(routine, inline_internals, inline_marked):
"""
Resolve sequence association in calls to all member procedures (if `inline_internals = True`)
or in calls to procedures that have been marked with an inline pragma (if `inline_marked = True`).
Resolve sequence association in calls to all member procedures (if `inline_internals = True`)
or in calls to procedures that have been marked with an inline pragma (if `inline_marked = True`).
If both `inline_internals` and `inline_marked` are `False`, no processing is done.
"""
call_map = {}
Expand All @@ -211,9 +216,9 @@ def resolve_sequence_association_for_inlined_calls(routine, inline_internals, in
# asked sequence assoc to happen with inlining, so source for routine should be
# found in calls to be inlined.
raise ValueError(
f"Cannot resolve sequence association for call to `{call.name}` " +
f"to be inlined in routine `{routine.name}`, because " +
f"the `CallStatement` referring to `{call.name}` does not contain " +
f"Cannot resolve sequence association for call to ``{call.name}`` " +
f"to be inlined in routine ``{routine.name}``, because " +
f"the ``CallStatement`` referring to ``{call.name}`` does not contain " +
"the source code of the procedure. " +
"If running in batch processing mode, please recheck Scheduler configuration."
)
Expand Down
77 changes: 76 additions & 1 deletion loki/transformations/tests/test_inline.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from loki.expression import symbols as sym
from loki.frontend import available_frontends, OMNI, OFP
from loki.ir import nodes as ir, FindNodes
from loki.batch import Scheduler, SchedulerConfig

from loki.transformations.inline import (
inline_elemental_functions, inline_constant_parameters,
Expand Down Expand Up @@ -963,7 +964,6 @@ def test_inline_marked_subroutines_declarations(frontend):
"""
module = Module.from_source(fcode, frontend=frontend)
outer = module['outer']
inner = module['inner']

inline_marked_subroutines(routine=outer, adjust_imports=True)

Expand Down Expand Up @@ -1328,3 +1328,78 @@ def test_inline_transformation_adjust_imports(frontend):
assert imports[0].symbols == ('x',)
assert imports[1].module == 'bnds_module'
assert 'm' in imports[1].symbols and 'n' in imports[1].symbols


@pytest.mark.parametrize('frontend', available_frontends())
def test_inline_transformation_intermediate(tmp_path, frontend):
fcode_outermost = """
module outermost_mod
implicit none
contains
subroutine outermost()
use intermediate_mod, only: intermediate
!$loki inline
call intermediate()
end subroutine outermost
end module outermost_mod
"""

fcode_intermediate = """
module intermediate_mod
implicit none
contains
subroutine intermediate()
use innermost_mod, only: innermost
call innermost()
end subroutine intermediate
end module intermediate_mod
"""

fcode_innermost = """
module innermost_mod
implicit none
contains
subroutine innermost()
end subroutine innermost
end module innermost_mod
"""

(tmp_path/'outermost_mod.F90').write_text(fcode_outermost)
(tmp_path/'intermediate_mod.F90').write_text(fcode_intermediate)
(tmp_path/'innermost_mod.F90').write_text(fcode_innermost)

config = {
'default': {
'mode': 'idem',
'role': 'kernel',
'expand': True,
'strict': True
},
'routines': {
'outermost': {'role': 'kernel'}
}
}

scheduler = Scheduler(paths=[tmp_path], config=SchedulerConfig.from_dict(config), frontend=frontend)

def _get_successors(item):
return scheduler.sgraph.successors(scheduler[item])

# check graph edges before transformation
assert len(scheduler.items) == 3
assert len(_get_successors('outermost_mod#outermost')) == 1
assert scheduler['intermediate_mod#intermediate'] in _get_successors('outermost_mod#outermost')
assert len(_get_successors('intermediate_mod#intermediate')) == 1
assert scheduler['innermost_mod#innermost'] in _get_successors('intermediate_mod#intermediate')

scheduler.process( transformation=InlineTransformation() )

# check graph edges were updated correctly
assert len(scheduler.items) == 2
assert len(_get_successors('outermost_mod#outermost')) == 1
assert scheduler['innermost_mod#innermost'] in _get_successors('outermost_mod#outermost')

0 comments on commit eb793e2

Please sign in to comment.