From 1a75912b452743c40943fc63ff6051f95119cbfe Mon Sep 17 00:00:00 2001 From: Michael Staneker Date: Tue, 24 Sep 2024 16:38:24 +0200 Subject: [PATCH 1/3] Fix edge case for vector section mapping conflicting with (rebuild of) Conditional --- .../single_column/tests/test_scc_vector.py | 47 +++++++++++++++++++ loki/transformations/single_column/vector.py | 4 +- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/loki/transformations/single_column/tests/test_scc_vector.py b/loki/transformations/single_column/tests/test_scc_vector.py index a496e03ce..287064603 100644 --- a/loki/transformations/single_column/tests/test_scc_vector.py +++ b/loki/transformations/single_column/tests/test_scc_vector.py @@ -562,3 +562,50 @@ def test_scc_vector_section_trim_complex( else: assert assign in loop.body assert(len(FindNodes(ir.Assignment).visit(loop.body)) == 4) + +@pytest.mark.parametrize('frontend', available_frontends()) +@pytest.mark.parametrize('trim_vector_sections', [False, True]) +def test_scc_devector_section_special_case(frontend, horizontal, vertical, blocking, trim_vector_sections): + """ + Test to highlight the limitations of vector-section trimming. + """ + + fcode_kernel = """ + subroutine some_kernel(start, end, nlon, flag0, flag1) + implicit none + + integer, intent(in) :: nlon, start, end + logical, intent(in) :: flag0, flag1 + real, dimension(nlon) :: work + + integer :: jl + + if(flag0)then + call some_other_kernel() + elseif(flag1)then + do jl=start,end + work(jl) = 1. + enddo + endif + + end subroutine some_kernel + """ + + routine = Subroutine.from_source(fcode_kernel, frontend=frontend) + + # check whether pipeline can be applied and works as expected + scc_pipeline = SCCVectorPipeline( + horizontal=horizontal, vertical=vertical, block_dim=blocking, + directive='openacc', trim_vector_sections=trim_vector_sections + ) + scc_pipeline.apply(routine, role='kernel', targets=['some_kernel',]) + + with pragmas_attached(routine, node_type=ir.Loop): + conditional = FindNodes(ir.Conditional).visit(routine.body)[0] + assert isinstance(conditional.body[0], ir.CallStatement) + assert len(conditional.body) == 1 + assert isinstance(conditional.else_body[0], ir.Conditional) + assert len(conditional.else_body) == 1 + assert isinstance(conditional.else_body[0].body[0], ir.Comment) + assert isinstance(conditional.else_body[0].body[1], ir.Loop) + assert conditional.else_body[0].body[1].pragma[0].content.lower() == 'loop vector' diff --git a/loki/transformations/single_column/vector.py b/loki/transformations/single_column/vector.py index 2cdc82dac..14f758789 100644 --- a/loki/transformations/single_column/vector.py +++ b/loki/transformations/single_column/vector.py @@ -137,7 +137,9 @@ def extract_vector_sections(cls, section, horizontal): subsec_body = cls.extract_vector_sections(separator.body, horizontal) if subsec_body: subsections += subsec_body - subsec_else = cls.extract_vector_sections(separator.else_body, horizontal) + subsec_else = cls.extract_vector_sections(separator.else_body[0].body, horizontal)\ + if separator.else_body and isinstance(separator.else_body[0], ir.Conditional)\ + else cls.extract_vector_sections(separator.else_body, horizontal) if subsec_else: subsections += subsec_else From 84c4f7fee1a89057aac7e307c8d9d58b9567f7cd Mon Sep 17 00:00:00 2001 From: Michael Staneker Date: Wed, 25 Sep 2024 08:45:36 +0200 Subject: [PATCH 2/3] edge case for vector section: add explanatory comment --- loki/transformations/single_column/vector.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/loki/transformations/single_column/vector.py b/loki/transformations/single_column/vector.py index 14f758789..8f59cca10 100644 --- a/loki/transformations/single_column/vector.py +++ b/loki/transformations/single_column/vector.py @@ -137,6 +137,9 @@ def extract_vector_sections(cls, section, horizontal): subsec_body = cls.extract_vector_sections(separator.body, horizontal) if subsec_body: subsections += subsec_body + # we need to prevent that the whole 'else_body' is wrapped in a section, + # as 'Conditional's rely on the fact that the first element of the 'else_body' + # (if 'has_elseif') is a Conditional itself subsec_else = cls.extract_vector_sections(separator.else_body[0].body, horizontal)\ if separator.else_body and isinstance(separator.else_body[0], ir.Conditional)\ else cls.extract_vector_sections(separator.else_body, horizontal) From e5d00c504b6eef5122a8b6472e76d24c4bddff59 Mon Sep 17 00:00:00 2001 From: Michael Staneker Date: Mon, 7 Oct 2024 07:31:50 +0200 Subject: [PATCH 3/3] edge case vector section mapping: actually test for 'has_elseif' and use proper if/else blocks --- .../transformations/single_column/tests/test_scc_vector.py | 6 ++++-- loki/transformations/single_column/vector.py | 7 ++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/loki/transformations/single_column/tests/test_scc_vector.py b/loki/transformations/single_column/tests/test_scc_vector.py index 287064603..66238d29b 100644 --- a/loki/transformations/single_column/tests/test_scc_vector.py +++ b/loki/transformations/single_column/tests/test_scc_vector.py @@ -8,7 +8,7 @@ import pytest from loki import Subroutine, Sourcefile, Dimension, fgen -from loki.frontend import available_frontends +from loki.frontend import available_frontends, OMNI from loki.ir import ( nodes as ir, FindNodes, pragmas_attached, is_loki_pragma ) @@ -563,7 +563,9 @@ def test_scc_vector_section_trim_complex( assert assign in loop.body assert(len(FindNodes(ir.Assignment).visit(loop.body)) == 4) -@pytest.mark.parametrize('frontend', available_frontends()) +@pytest.mark.parametrize('frontend', available_frontends( + skip={OMNI: 'OMNI automatically expands ELSEIF into a nested ELSE=>IF.'} +)) @pytest.mark.parametrize('trim_vector_sections', [False, True]) def test_scc_devector_section_special_case(frontend, horizontal, vertical, blocking, trim_vector_sections): """ diff --git a/loki/transformations/single_column/vector.py b/loki/transformations/single_column/vector.py index 8f59cca10..2764c019f 100644 --- a/loki/transformations/single_column/vector.py +++ b/loki/transformations/single_column/vector.py @@ -140,9 +140,10 @@ def extract_vector_sections(cls, section, horizontal): # we need to prevent that the whole 'else_body' is wrapped in a section, # as 'Conditional's rely on the fact that the first element of the 'else_body' # (if 'has_elseif') is a Conditional itself - subsec_else = cls.extract_vector_sections(separator.else_body[0].body, horizontal)\ - if separator.else_body and isinstance(separator.else_body[0], ir.Conditional)\ - else cls.extract_vector_sections(separator.else_body, horizontal) + if separator.has_elseif and separator.else_body: + subsec_else = cls.extract_vector_sections(separator.else_body[0].body, horizontal) + else: + subsec_else = cls.extract_vector_sections(separator.else_body, horizontal) if subsec_else: subsections += subsec_else