From d6f47ffe47d7b70e62e8494583a37c9e617a62a4 Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Wed, 13 May 2026 11:15:56 +0100 Subject: [PATCH 01/24] Add basic means to force promote variables to parallel regions --- .../maximal_omp_parallel_region_trans.py | 5 +-- .../transformations/maximal_region_trans.py | 14 ++++---- .../transformations/omp_parallel_trans.py | 6 ++-- .../transformations/parallel_region_trans.py | 34 +++++++++++++++++-- 4 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/psyclone/psyir/transformations/maximal_omp_parallel_region_trans.py b/src/psyclone/psyir/transformations/maximal_omp_parallel_region_trans.py index a4d51a995d..01990b0203 100644 --- a/src/psyclone/psyir/transformations/maximal_omp_parallel_region_trans.py +++ b/src/psyclone/psyir/transformations/maximal_omp_parallel_region_trans.py @@ -36,6 +36,7 @@ '''This module contains the MaximalOMPParallelRegionTrans.''' from typing import Union +from collections.abc import Iterable from psyclone.psyir.nodes import ( OMPTaskwaitDirective, @@ -85,9 +86,9 @@ class MaximalOMPParallelRegionTrans(MaximalRegionTrans): DynamicOMPTaskDirective, ) - def apply(self, nodes: Union[Node, Schedule, list[Node]], **kwargs): + def apply(self, nodes: Union[Node, Schedule, list[Node]], force_private: Iterable[str] = (), **kwargs): '''Applies the transformation to the nodes provided. :param nodes: can be a single node, a schedule or a list of nodes. ''' - super().apply(nodes, **kwargs) + super().apply(nodes, force_private=force_private, **kwargs) diff --git a/src/psyclone/psyir/transformations/maximal_region_trans.py b/src/psyclone/psyir/transformations/maximal_region_trans.py index 2642df88a3..1ad91397b1 100644 --- a/src/psyclone/psyir/transformations/maximal_region_trans.py +++ b/src/psyclone/psyir/transformations/maximal_region_trans.py @@ -36,6 +36,7 @@ '''This module contains the MaximalRegionTrans.''' import abc +from collections.abc import Iterable from typing import Union from psyclone.psyir.nodes import ( @@ -148,6 +149,7 @@ def _can_be_in_region(self, node: Node) -> bool: def _compute_transformable_sections( self, node_list: list[Node], trans: Transformation, + force_private: Iterable[str] = (), ) -> list[list[Node]]: ''' Computes the sections of the input node_list to apply the @@ -168,7 +170,7 @@ def _compute_transformable_sections( # Check that validation still succeeds if we add this child # to the current block. try: - trans.validate(current_block + [child]) + trans.validate(current_block + [child], force_private=force_private) current_block.append(child) except TransformationError: # If validation now fails, then don't add this to the @@ -210,7 +212,7 @@ def _compute_transformable_sections( return all_blocks - def validate(self, nodes: Union[Node, Schedule, list[Node]], **kwargs): + def validate(self, nodes: Union[Node, Schedule, list[Node]], force_private: Iterable[str] = (), **kwargs): '''Validates whether this transformation can be applied to the nodes provided. @@ -238,7 +240,7 @@ def validate(self, nodes: Union[Node, Schedule, list[Node]], **kwargs): f"{prev_position}.") prev_position = child.position - def apply(self, nodes: Union[Node, Schedule, list[Node]], **kwargs): + def apply(self, nodes: Union[Node, Schedule, list[Node]], force_private: Iterable[str] = (), **kwargs): '''Applies the transformation to the nodes provided. :param nodes: can be a single node, a schedule or a list of nodes. @@ -246,12 +248,12 @@ def apply(self, nodes: Union[Node, Schedule, list[Node]], **kwargs): node_list = self.get_node_list(nodes) # Call validate. - self.validate(nodes, **kwargs) + self.validate(nodes, force_private=force_private, **kwargs) par_trans = self._transformation() - all_blocks = self._compute_transformable_sections(node_list, par_trans) + all_blocks = self._compute_transformable_sections(node_list, par_trans, force_private=force_private) # Apply the transformation to all of the blocks found. for block in all_blocks: - par_trans.apply(block) + par_trans.apply(block, force_private=force_private, **kwargs) diff --git a/src/psyclone/psyir/transformations/omp_parallel_trans.py b/src/psyclone/psyir/transformations/omp_parallel_trans.py index c6fe3843d7..483e74cf48 100644 --- a/src/psyclone/psyir/transformations/omp_parallel_trans.py +++ b/src/psyclone/psyir/transformations/omp_parallel_trans.py @@ -40,6 +40,8 @@ # J. Dendy, Met Office '''This module provides the OMPParallelTrans transformation.''' +from collections.abc import Iterable + from psyclone import psyGen from psyclone.psyir.nodes import ( ACCDirective, @@ -130,14 +132,14 @@ def validate(self, nodes: list[Node], options=None, **kwargs): # TODO #2668: Remove options. super().validate(nodes, options, **kwargs) - def apply(self, nodes: list[Node], options=None, **kwargs): + def apply(self, nodes: list[Node], options=None, force_private: Iterable[str] = (), **kwargs): ''' Surrounds the provided node list with an OpenMP Parallel region. :param nodes: list of Nodes to put within parallel region. ''' # TODO #2668: Remove options. - super().apply(nodes, options, **kwargs) + super().apply(nodes, options, force_private=force_private, **kwargs) __all__ = ["OMPParallelTrans"] diff --git a/src/psyclone/psyir/transformations/parallel_region_trans.py b/src/psyclone/psyir/transformations/parallel_region_trans.py index 48b78482e5..f487d44f4e 100644 --- a/src/psyclone/psyir/transformations/parallel_region_trans.py +++ b/src/psyclone/psyir/transformations/parallel_region_trans.py @@ -43,13 +43,13 @@ This module provides the implementation of ParallelRegionTrans ''' - +from collections.abc import Iterable from abc import ABC, abstractmethod from psyclone.psyir.transformations.transformation_error import ( TransformationError) from psyclone import psyGen from psyclone.psyir.transformations.region_trans import RegionTrans -from psyclone.psyir.nodes import CodeBlock, Node, Return +from psyclone.psyir.nodes import CodeBlock, Node, Return, RegionDirective from psyclone.utils import transformation_documentation_wrapper @@ -76,6 +76,29 @@ def __str__(self) -> str: ''' + def _check_symbol_table_vars(self, region_node, force_private: Iterable[str] = ()): + ''' + Check the symbol table of the provided region node contains the variable + to be forcibly promoted. Return a set of explicitly_private_symbols. + ''' + explicitly_private_symbols = set() + + for symbol_name in force_private: + sym = None + try: + sym = region_node.scope.symbol_table.lookup(symbol_name) + except KeyError as err: + # This is not an error, but we will log the missed string + print( + "%s has been provided with the '%s' symbol name in " + "the 'force_private' option, but there is no such " + "symbol in this scope.", err, symbol_name) + if sym: + explicitly_private_symbols.add(sym) + + return explicitly_private_symbols + + def validate(self, nodes: list[Node], options=None, **kwargs): # pylint: disable=arguments-renamed ''' @@ -101,7 +124,7 @@ def validate(self, nodes: list[Node], options=None, **kwargs): # TODO #2668: Remove options. super().validate(node_list, options, **kwargs) - def apply(self, nodes: list[Node], options=None, **kwargs): + def apply(self, nodes: list[Node], options=None, force_private: Iterable[str] = (), **kwargs): # pylint: disable=arguments-renamed ''' Apply this transformation to a subset of the nodes within a @@ -139,3 +162,8 @@ def apply(self, nodes: list[Node], options=None, **kwargs): # of the nodes being enclosed and at the original location # of the first of these nodes node_parent.addchild(directive, index=node_position) + + new_region_directive = nodes[0].ancestor(RegionDirective) + if force_private: + new_region_directive.explicitly_private_symbols.update( + self._check_symbol_table_vars(new_region_directive, force_private)) From 7a6af649bce1b48b0d4a5e6acb2c592347678b08 Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Wed, 13 May 2026 16:02:04 +0100 Subject: [PATCH 02/24] Removal of some manual piping to rely on kwags --- .../maximal_omp_parallel_region_trans.py | 4 ++-- .../psyir/transformations/maximal_region_trans.py | 10 ++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/psyclone/psyir/transformations/maximal_omp_parallel_region_trans.py b/src/psyclone/psyir/transformations/maximal_omp_parallel_region_trans.py index 01990b0203..bfc4e9008a 100644 --- a/src/psyclone/psyir/transformations/maximal_omp_parallel_region_trans.py +++ b/src/psyclone/psyir/transformations/maximal_omp_parallel_region_trans.py @@ -86,9 +86,9 @@ class MaximalOMPParallelRegionTrans(MaximalRegionTrans): DynamicOMPTaskDirective, ) - def apply(self, nodes: Union[Node, Schedule, list[Node]], force_private: Iterable[str] = (), **kwargs): + def apply(self, nodes: Union[Node, Schedule, list[Node]], **kwargs): '''Applies the transformation to the nodes provided. :param nodes: can be a single node, a schedule or a list of nodes. ''' - super().apply(nodes, force_private=force_private, **kwargs) + super().apply(nodes, **kwargs) diff --git a/src/psyclone/psyir/transformations/maximal_region_trans.py b/src/psyclone/psyir/transformations/maximal_region_trans.py index 1ad91397b1..60a0feeccc 100644 --- a/src/psyclone/psyir/transformations/maximal_region_trans.py +++ b/src/psyclone/psyir/transformations/maximal_region_trans.py @@ -149,7 +149,6 @@ def _can_be_in_region(self, node: Node) -> bool: def _compute_transformable_sections( self, node_list: list[Node], trans: Transformation, - force_private: Iterable[str] = (), ) -> list[list[Node]]: ''' Computes the sections of the input node_list to apply the @@ -170,7 +169,7 @@ def _compute_transformable_sections( # Check that validation still succeeds if we add this child # to the current block. try: - trans.validate(current_block + [child], force_private=force_private) + trans.validate(current_block + [child]) current_block.append(child) except TransformationError: # If validation now fails, then don't add this to the @@ -212,7 +211,7 @@ def _compute_transformable_sections( return all_blocks - def validate(self, nodes: Union[Node, Schedule, list[Node]], force_private: Iterable[str] = (), **kwargs): + def validate(self, nodes: Union[Node, Schedule, list[Node]], **kwargs): '''Validates whether this transformation can be applied to the nodes provided. @@ -248,11 +247,10 @@ def apply(self, nodes: Union[Node, Schedule, list[Node]], force_private: Iterabl node_list = self.get_node_list(nodes) # Call validate. - self.validate(nodes, force_private=force_private, **kwargs) + self.validate(nodes, **kwargs) par_trans = self._transformation() - - all_blocks = self._compute_transformable_sections(node_list, par_trans, force_private=force_private) + all_blocks = self._compute_transformable_sections(node_list, par_trans) # Apply the transformation to all of the blocks found. for block in all_blocks: From f8d72735f38add402d94170e3e79df8864fe1f3d Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Wed, 13 May 2026 16:06:05 +0100 Subject: [PATCH 03/24] Further piping change --- src/psyclone/psyir/transformations/maximal_region_trans.py | 4 ++-- src/psyclone/psyir/transformations/omp_parallel_trans.py | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/psyclone/psyir/transformations/maximal_region_trans.py b/src/psyclone/psyir/transformations/maximal_region_trans.py index 60a0feeccc..83d4af5860 100644 --- a/src/psyclone/psyir/transformations/maximal_region_trans.py +++ b/src/psyclone/psyir/transformations/maximal_region_trans.py @@ -239,7 +239,7 @@ def validate(self, nodes: Union[Node, Schedule, list[Node]], **kwargs): f"{prev_position}.") prev_position = child.position - def apply(self, nodes: Union[Node, Schedule, list[Node]], force_private: Iterable[str] = (), **kwargs): + def apply(self, nodes: Union[Node, Schedule, list[Node]], **kwargs): '''Applies the transformation to the nodes provided. :param nodes: can be a single node, a schedule or a list of nodes. @@ -254,4 +254,4 @@ def apply(self, nodes: Union[Node, Schedule, list[Node]], force_private: Iterabl # Apply the transformation to all of the blocks found. for block in all_blocks: - par_trans.apply(block, force_private=force_private, **kwargs) + par_trans.apply(block, **kwargs) diff --git a/src/psyclone/psyir/transformations/omp_parallel_trans.py b/src/psyclone/psyir/transformations/omp_parallel_trans.py index 483e74cf48..c6fe3843d7 100644 --- a/src/psyclone/psyir/transformations/omp_parallel_trans.py +++ b/src/psyclone/psyir/transformations/omp_parallel_trans.py @@ -40,8 +40,6 @@ # J. Dendy, Met Office '''This module provides the OMPParallelTrans transformation.''' -from collections.abc import Iterable - from psyclone import psyGen from psyclone.psyir.nodes import ( ACCDirective, @@ -132,14 +130,14 @@ def validate(self, nodes: list[Node], options=None, **kwargs): # TODO #2668: Remove options. super().validate(nodes, options, **kwargs) - def apply(self, nodes: list[Node], options=None, force_private: Iterable[str] = (), **kwargs): + def apply(self, nodes: list[Node], options=None, **kwargs): ''' Surrounds the provided node list with an OpenMP Parallel region. :param nodes: list of Nodes to put within parallel region. ''' # TODO #2668: Remove options. - super().apply(nodes, options, force_private=force_private, **kwargs) + super().apply(nodes, options, **kwargs) __all__ = ["OMPParallelTrans"] From e7ee06ca0dd1a575a1736d3a4904ab727bec8117 Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Wed, 13 May 2026 16:08:25 +0100 Subject: [PATCH 04/24] housekeeping --- .../psyir/transformations/maximal_omp_parallel_region_trans.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/psyclone/psyir/transformations/maximal_omp_parallel_region_trans.py b/src/psyclone/psyir/transformations/maximal_omp_parallel_region_trans.py index bfc4e9008a..a4d51a995d 100644 --- a/src/psyclone/psyir/transformations/maximal_omp_parallel_region_trans.py +++ b/src/psyclone/psyir/transformations/maximal_omp_parallel_region_trans.py @@ -36,7 +36,6 @@ '''This module contains the MaximalOMPParallelRegionTrans.''' from typing import Union -from collections.abc import Iterable from psyclone.psyir.nodes import ( OMPTaskwaitDirective, From e19e40eea569c414d5d2ef5a9f3c1a78c15dc958 Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Thu, 14 May 2026 09:44:44 +0100 Subject: [PATCH 05/24] Pipe in some variables to enable correct passing validation --- .../psyir/transformations/maximal_region_trans.py | 4 ++-- src/psyclone/psyir/transformations/omp_parallel_trans.py | 8 +++++++- .../psyir/transformations/parallel_region_trans.py | 9 ++++----- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/psyclone/psyir/transformations/maximal_region_trans.py b/src/psyclone/psyir/transformations/maximal_region_trans.py index 83d4af5860..4cae40eda2 100644 --- a/src/psyclone/psyir/transformations/maximal_region_trans.py +++ b/src/psyclone/psyir/transformations/maximal_region_trans.py @@ -239,7 +239,7 @@ def validate(self, nodes: Union[Node, Schedule, list[Node]], **kwargs): f"{prev_position}.") prev_position = child.position - def apply(self, nodes: Union[Node, Schedule, list[Node]], **kwargs): + def apply(self, nodes: Union[Node, Schedule, list[Node]], force_private: Iterable[str] = (), **kwargs): '''Applies the transformation to the nodes provided. :param nodes: can be a single node, a schedule or a list of nodes. @@ -254,4 +254,4 @@ def apply(self, nodes: Union[Node, Schedule, list[Node]], **kwargs): # Apply the transformation to all of the blocks found. for block in all_blocks: - par_trans.apply(block, **kwargs) + par_trans.apply(block, force_private=force_private) diff --git a/src/psyclone/psyir/transformations/omp_parallel_trans.py b/src/psyclone/psyir/transformations/omp_parallel_trans.py index c6fe3843d7..591f4b613f 100644 --- a/src/psyclone/psyir/transformations/omp_parallel_trans.py +++ b/src/psyclone/psyir/transformations/omp_parallel_trans.py @@ -40,6 +40,7 @@ # J. Dendy, Met Office '''This module provides the OMPParallelTrans transformation.''' +from collections.abc import Iterable from psyclone import psyGen from psyclone.psyir.nodes import ( ACCDirective, @@ -48,6 +49,7 @@ OMPParallelDirective, OMPDirective, Return, + RegionDirective ) from psyclone.psyir.transformations.parallel_region_trans import ( ParallelRegionTrans) @@ -130,7 +132,7 @@ def validate(self, nodes: list[Node], options=None, **kwargs): # TODO #2668: Remove options. super().validate(nodes, options, **kwargs) - def apply(self, nodes: list[Node], options=None, **kwargs): + def apply(self, nodes: list[Node], options=None, force_private: Iterable[str] = (), **kwargs): ''' Surrounds the provided node list with an OpenMP Parallel region. @@ -139,5 +141,9 @@ def apply(self, nodes: list[Node], options=None, **kwargs): # TODO #2668: Remove options. super().apply(nodes, options, **kwargs) + if force_private: + new_region_directive = nodes[0].ancestor(RegionDirective) + new_region_directive.explicitly_private_symbols.update( + super()._check_symbol_table_vars(new_region_directive, force_private)) __all__ = ["OMPParallelTrans"] diff --git a/src/psyclone/psyir/transformations/parallel_region_trans.py b/src/psyclone/psyir/transformations/parallel_region_trans.py index f487d44f4e..a192e7c736 100644 --- a/src/psyclone/psyir/transformations/parallel_region_trans.py +++ b/src/psyclone/psyir/transformations/parallel_region_trans.py @@ -76,7 +76,10 @@ def __str__(self) -> str: ''' - def _check_symbol_table_vars(self, region_node, force_private: Iterable[str] = ()): + def _check_symbol_table_vars( + self, region_node: RegionDirective, + force_private: Iterable[str] = () + ) -> set[] : ''' Check the symbol table of the provided region node contains the variable to be forcibly promoted. Return a set of explicitly_private_symbols. @@ -163,7 +166,3 @@ def apply(self, nodes: list[Node], options=None, force_private: Iterable[str] = # of the first of these nodes node_parent.addchild(directive, index=node_position) - new_region_directive = nodes[0].ancestor(RegionDirective) - if force_private: - new_region_directive.explicitly_private_symbols.update( - self._check_symbol_table_vars(new_region_directive, force_private)) From 900a81f357a2bd82848f4cd4515d37ecab7aa3bf Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Thu, 14 May 2026 10:11:41 +0100 Subject: [PATCH 06/24] formatting fixes, flake8, function data types, logging --- .../transformations/omp_parallel_trans.py | 25 +++++++++++++++---- .../transformations/parallel_region_trans.py | 24 +++++++++++------- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/psyclone/psyir/transformations/omp_parallel_trans.py b/src/psyclone/psyir/transformations/omp_parallel_trans.py index 591f4b613f..11d101c88e 100644 --- a/src/psyclone/psyir/transformations/omp_parallel_trans.py +++ b/src/psyclone/psyir/transformations/omp_parallel_trans.py @@ -39,7 +39,7 @@ # M. Schreiber, Univ. Grenoble Alpes / Inria / Lab. Jean Kuntzmann # J. Dendy, Met Office '''This module provides the OMPParallelTrans transformation.''' - +import logging from collections.abc import Iterable from psyclone import psyGen from psyclone.psyir.nodes import ( @@ -132,7 +132,10 @@ def validate(self, nodes: list[Node], options=None, **kwargs): # TODO #2668: Remove options. super().validate(nodes, options, **kwargs) - def apply(self, nodes: list[Node], options=None, force_private: Iterable[str] = (), **kwargs): + def apply( + self, nodes: list[Node], + options=None, force_private: Iterable[str] = (), + **kwargs): ''' Surrounds the provided node list with an OpenMP Parallel region. @@ -141,9 +144,21 @@ def apply(self, nodes: list[Node], options=None, force_private: Iterable[str] = # TODO #2668: Remove options. super().apply(nodes, options, **kwargs) + # Privatise the provided variables if they are found within the symbol + # table of the ancestor RegionDirective to the nodes which have just + # had a region spanned over. if force_private: - new_region_directive = nodes[0].ancestor(RegionDirective) - new_region_directive.explicitly_private_symbols.update( - super()._check_symbol_table_vars(new_region_directive, force_private)) + new_region_directive = None + try: + new_region_directive = nodes[0].ancestor(RegionDirective) + except TypeError as err: + logging.warning( + "Could not find an OMPParallelTrans ancestor as %", err) + if new_region_directive: + new_region_directive.explicitly_private_symbols.update( + super()._check_symbol_table_vars( + new_region_directive, + force_private)) + __all__ = ["OMPParallelTrans"] diff --git a/src/psyclone/psyir/transformations/parallel_region_trans.py b/src/psyclone/psyir/transformations/parallel_region_trans.py index a192e7c736..370d987559 100644 --- a/src/psyclone/psyir/transformations/parallel_region_trans.py +++ b/src/psyclone/psyir/transformations/parallel_region_trans.py @@ -43,6 +43,7 @@ This module provides the implementation of ParallelRegionTrans ''' +import logging from collections.abc import Iterable from abc import ABC, abstractmethod from psyclone.psyir.transformations.transformation_error import ( @@ -50,6 +51,7 @@ from psyclone import psyGen from psyclone.psyir.transformations.region_trans import RegionTrans from psyclone.psyir.nodes import CodeBlock, Node, Return, RegionDirective +from psyclone.psyir.symbols import DataSymbol from psyclone.utils import transformation_documentation_wrapper @@ -77,12 +79,15 @@ def __str__(self) -> str: ''' def _check_symbol_table_vars( - self, region_node: RegionDirective, - force_private: Iterable[str] = () - ) -> set[] : + self, + region_node: RegionDirective, + force_private: Iterable[str] = ()) -> set[DataSymbol]: ''' - Check the symbol table of the provided region node contains the variable - to be forcibly promoted. Return a set of explicitly_private_symbols. + Check that the symbol table of the provided region node contains the + variable variables in the provided list. Return a set of DataSymbols. + + This is intended to be used as part of privatising the variables + contained in the list for the provided region in the child classes. ''' explicitly_private_symbols = set() @@ -92,7 +97,7 @@ def _check_symbol_table_vars( sym = region_node.scope.symbol_table.lookup(symbol_name) except KeyError as err: # This is not an error, but we will log the missed string - print( + logging.warning( "%s has been provided with the '%s' symbol name in " "the 'force_private' option, but there is no such " "symbol in this scope.", err, symbol_name) @@ -101,7 +106,6 @@ def _check_symbol_table_vars( return explicitly_private_symbols - def validate(self, nodes: list[Node], options=None, **kwargs): # pylint: disable=arguments-renamed ''' @@ -127,7 +131,10 @@ def validate(self, nodes: list[Node], options=None, **kwargs): # TODO #2668: Remove options. super().validate(node_list, options, **kwargs) - def apply(self, nodes: list[Node], options=None, force_private: Iterable[str] = (), **kwargs): + def apply( + self, nodes: list[Node], + options=None, force_private: Iterable[str] = (), + **kwargs): # pylint: disable=arguments-renamed ''' Apply this transformation to a subset of the nodes within a @@ -165,4 +172,3 @@ def apply(self, nodes: list[Node], options=None, force_private: Iterable[str] = # of the nodes being enclosed and at the original location # of the first of these nodes node_parent.addchild(directive, index=node_position) - From 0e6b1851a6f44549c10323d0736a71b6bd48c248 Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Thu, 14 May 2026 10:13:03 +0100 Subject: [PATCH 07/24] flake8 format --- src/psyclone/psyir/transformations/maximal_region_trans.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/psyclone/psyir/transformations/maximal_region_trans.py b/src/psyclone/psyir/transformations/maximal_region_trans.py index 4cae40eda2..b8fbb2c8cf 100644 --- a/src/psyclone/psyir/transformations/maximal_region_trans.py +++ b/src/psyclone/psyir/transformations/maximal_region_trans.py @@ -239,7 +239,10 @@ def validate(self, nodes: Union[Node, Schedule, list[Node]], **kwargs): f"{prev_position}.") prev_position = child.position - def apply(self, nodes: Union[Node, Schedule, list[Node]], force_private: Iterable[str] = (), **kwargs): + def apply( + self, nodes: Union[Node, Schedule, list[Node]], + force_private: Iterable[str] = (), + **kwargs): '''Applies the transformation to the nodes provided. :param nodes: can be a single node, a schedule or a list of nodes. From 67b8682f64634915a0355c469cf59c9ddb0f7ca2 Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Thu, 14 May 2026 14:10:01 +0100 Subject: [PATCH 08/24] Remove snuck through argument which is no longer needed here --- src/psyclone/psyir/transformations/parallel_region_trans.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/psyclone/psyir/transformations/parallel_region_trans.py b/src/psyclone/psyir/transformations/parallel_region_trans.py index 370d987559..3d28d92bf1 100644 --- a/src/psyclone/psyir/transformations/parallel_region_trans.py +++ b/src/psyclone/psyir/transformations/parallel_region_trans.py @@ -131,10 +131,7 @@ def validate(self, nodes: list[Node], options=None, **kwargs): # TODO #2668: Remove options. super().validate(node_list, options, **kwargs) - def apply( - self, nodes: list[Node], - options=None, force_private: Iterable[str] = (), - **kwargs): + def apply(self, nodes: list[Node], **kwargs): # pylint: disable=arguments-renamed ''' Apply this transformation to a subset of the nodes within a From b0f9d356faac9938be3574e38c396f2a22947edd Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Thu, 14 May 2026 14:11:08 +0100 Subject: [PATCH 09/24] fix --- src/psyclone/psyir/transformations/parallel_region_trans.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/psyclone/psyir/transformations/parallel_region_trans.py b/src/psyclone/psyir/transformations/parallel_region_trans.py index 3d28d92bf1..eafab5880e 100644 --- a/src/psyclone/psyir/transformations/parallel_region_trans.py +++ b/src/psyclone/psyir/transformations/parallel_region_trans.py @@ -131,7 +131,7 @@ def validate(self, nodes: list[Node], options=None, **kwargs): # TODO #2668: Remove options. super().validate(node_list, options, **kwargs) - def apply(self, nodes: list[Node], **kwargs): + def apply(self, nodes: list[Node], options=None, **kwargs): # pylint: disable=arguments-renamed ''' Apply this transformation to a subset of the nodes within a From f58867f065a1197f8e71378967eb3545af7a82d2 Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Fri, 15 May 2026 13:44:20 +0100 Subject: [PATCH 10/24] push up WIP test --- .../maximal_region_trans_test.py | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/psyclone/tests/psyir/transformations/maximal_region_trans_test.py b/src/psyclone/tests/psyir/transformations/maximal_region_trans_test.py index ad62f9c510..81872c12e9 100644 --- a/src/psyclone/tests/psyir/transformations/maximal_region_trans_test.py +++ b/src/psyclone/tests/psyir/transformations/maximal_region_trans_test.py @@ -47,7 +47,8 @@ from psyclone.psyir.transformations import ( MaximalRegionTrans, TransformationError, - OMPParallelTrans + OMPParallelTrans, + OMPLoopTrans, ) @@ -342,3 +343,36 @@ class OneParTrans(MaximalRegionTrans): assert isinstance(routine.children[0], OMPParallelDirective) assert isinstance(routine.children[1], Assignment) assert isinstance(routine.children[2], OMPParallelDirective) + + +def test_apply_force_private(fortran_reader): + '''Test the apply function of MaxParallelRegionTrans with force privates.''' + code = """subroutine x + integer :: i, ii, k, l, block + integer :: array_l(8) + block = 2 + do ii = 1, 4 + do k = 4, 1, -1 + l = 0 + do i = ii, min(ii+block -1, 4) + l = l + 1 + array_l(l) = 1 + 2 + end do + end do + end do + end subroutine x + """ + psyir = fortran_reader.psyir_from_source(code) + loop_trans = OMPLoopTrans() + # Apply loop_trans to all the loops possible. + for loop in psyir.walk(Loop): + if loop.variable.name == "ii": + loop_trans.apply(loop, ignore_dependencies_for=["array_l"], nowait=True) + trans = MaxParTrans() + nodes = psyir.walk(Routine)[0].children[:] + mtrans.apply(nodes, force_private = ["array_l"]) + assert len(psyir.walk(OMPParallelDirective)) == 1 + pdir = psyir.walk(OMPParallelDirective)[0] + # All of the blocks here should be in the same ParallelDirective + for node in nodes: + assert node.parent.parent is pdir From 5fe3c287ba4ef2cfb595e249335f07dcdd06d343 Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Fri, 15 May 2026 14:18:50 +0100 Subject: [PATCH 11/24] Un pipe force_private --- .../psyir/transformations/maximal_region_trans.py | 2 +- src/psyclone/psyir/transformations/omp_parallel_trans.py | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/psyclone/psyir/transformations/maximal_region_trans.py b/src/psyclone/psyir/transformations/maximal_region_trans.py index f4b350e0aa..9c7354fefb 100644 --- a/src/psyclone/psyir/transformations/maximal_region_trans.py +++ b/src/psyclone/psyir/transformations/maximal_region_trans.py @@ -249,7 +249,7 @@ def validate(self, nodes: Union[Node, Schedule, list[Node]], **kwargs): def apply( self, nodes: Union[Node, Schedule, list[Node]], - force_private: Iterable[str] = (), + #force_private: Iterable[str] = (), **kwargs): '''Applies the transformation to the nodes provided. diff --git a/src/psyclone/psyir/transformations/omp_parallel_trans.py b/src/psyclone/psyir/transformations/omp_parallel_trans.py index 11d101c88e..d883b57f4a 100644 --- a/src/psyclone/psyir/transformations/omp_parallel_trans.py +++ b/src/psyclone/psyir/transformations/omp_parallel_trans.py @@ -134,7 +134,7 @@ def validate(self, nodes: list[Node], options=None, **kwargs): def apply( self, nodes: list[Node], - options=None, force_private: Iterable[str] = (), + options=None,# force_private: Iterable[str] = (), **kwargs): ''' Surrounds the provided node list with an OpenMP Parallel region. @@ -144,6 +144,12 @@ def apply( # TODO #2668: Remove options. super().apply(nodes, options, **kwargs) + if 'force_private' in kwargs.items(): + force_private = kwargs.get("force_private") + else: + force_private = None + print(f"OMP Par kwargs: {kwargs}") + # Privatise the provided variables if they are found within the symbol # table of the ancestor RegionDirective to the nodes which have just # had a region spanned over. From 14c53ca5a0d6b6d16b98cc2e6adb4bc4d91e2a07 Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Fri, 15 May 2026 14:26:35 +0100 Subject: [PATCH 12/24] Push pipe adjust recomended --- src/psyclone/psyir/transformations/omp_parallel_trans.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/psyclone/psyir/transformations/omp_parallel_trans.py b/src/psyclone/psyir/transformations/omp_parallel_trans.py index d883b57f4a..91c987657e 100644 --- a/src/psyclone/psyir/transformations/omp_parallel_trans.py +++ b/src/psyclone/psyir/transformations/omp_parallel_trans.py @@ -134,7 +134,7 @@ def validate(self, nodes: list[Node], options=None, **kwargs): def apply( self, nodes: list[Node], - options=None,# force_private: Iterable[str] = (), + options=None, force_private: Iterable[str] = (), **kwargs): ''' Surrounds the provided node list with an OpenMP Parallel region. From 967b3570969fb5d87a5d25362d3ba3097a4393f0 Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Fri, 15 May 2026 14:56:02 +0100 Subject: [PATCH 13/24] debugging updates --- .../psyir/transformations/maximal_region_trans.py | 1 - .../psyir/transformations/omp_parallel_trans.py | 12 ++++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/psyclone/psyir/transformations/maximal_region_trans.py b/src/psyclone/psyir/transformations/maximal_region_trans.py index 9c7354fefb..36a7c7d544 100644 --- a/src/psyclone/psyir/transformations/maximal_region_trans.py +++ b/src/psyclone/psyir/transformations/maximal_region_trans.py @@ -249,7 +249,6 @@ def validate(self, nodes: Union[Node, Schedule, list[Node]], **kwargs): def apply( self, nodes: Union[Node, Schedule, list[Node]], - #force_private: Iterable[str] = (), **kwargs): '''Applies the transformation to the nodes provided. diff --git a/src/psyclone/psyir/transformations/omp_parallel_trans.py b/src/psyclone/psyir/transformations/omp_parallel_trans.py index 91c987657e..585b30ea5d 100644 --- a/src/psyclone/psyir/transformations/omp_parallel_trans.py +++ b/src/psyclone/psyir/transformations/omp_parallel_trans.py @@ -144,12 +144,12 @@ def apply( # TODO #2668: Remove options. super().apply(nodes, options, **kwargs) - if 'force_private' in kwargs.items(): - force_private = kwargs.get("force_private") - else: - force_private = None - print(f"OMP Par kwargs: {kwargs}") - + # if 'force_private' in kwargs.items(): + # force_private = kwargs.get("force_private") + # else: + # force_private = None + # + print(f"OMP Par kwargs: {kwargs}") # Privatise the provided variables if they are found within the symbol # table of the ancestor RegionDirective to the nodes which have just # had a region spanned over. From fc94fff6d7a3f873eb61233c336626e4fb1b45fe Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Fri, 15 May 2026 15:21:45 +0100 Subject: [PATCH 14/24] Fix conflict and remove debugging stuff --- src/psyclone/psyir/transformations/maximal_region_trans.py | 5 ----- src/psyclone/psyir/transformations/omp_parallel_trans.py | 6 ------ 2 files changed, 11 deletions(-) diff --git a/src/psyclone/psyir/transformations/maximal_region_trans.py b/src/psyclone/psyir/transformations/maximal_region_trans.py index 36a7c7d544..e66abf79c1 100644 --- a/src/psyclone/psyir/transformations/maximal_region_trans.py +++ b/src/psyclone/psyir/transformations/maximal_region_trans.py @@ -37,12 +37,7 @@ '''This module contains the MaximalRegionTrans.''' import abc -<<<<<<< HEAD -from collections.abc import Iterable -from typing import Union -======= from typing import Union, Any ->>>>>>> 3432_split_and_propagate_kwargs from psyclone.psyir.nodes import ( Node, diff --git a/src/psyclone/psyir/transformations/omp_parallel_trans.py b/src/psyclone/psyir/transformations/omp_parallel_trans.py index 585b30ea5d..11d101c88e 100644 --- a/src/psyclone/psyir/transformations/omp_parallel_trans.py +++ b/src/psyclone/psyir/transformations/omp_parallel_trans.py @@ -144,12 +144,6 @@ def apply( # TODO #2668: Remove options. super().apply(nodes, options, **kwargs) - # if 'force_private' in kwargs.items(): - # force_private = kwargs.get("force_private") - # else: - # force_private = None - # - print(f"OMP Par kwargs: {kwargs}") # Privatise the provided variables if they are found within the symbol # table of the ancestor RegionDirective to the nodes which have just # had a region spanned over. From 1b635a24b40a76f20bd2a1f942d13f8bff9e69d9 Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Mon, 18 May 2026 11:05:38 +0100 Subject: [PATCH 15/24] Add test for adding first privates to spanned region over difficult source --- .../maximal_region_trans_test.py | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/psyclone/tests/psyir/transformations/maximal_region_trans_test.py b/src/psyclone/tests/psyir/transformations/maximal_region_trans_test.py index 88dc601d1a..8b0b5c84d3 100644 --- a/src/psyclone/tests/psyir/transformations/maximal_region_trans_test.py +++ b/src/psyclone/tests/psyir/transformations/maximal_region_trans_test.py @@ -42,6 +42,7 @@ Assignment, IfBlock, Routine, + Loop, OMPParallelDirective, ) from psyclone.psyir.transformations import ( @@ -349,7 +350,8 @@ class OneParTrans(MaximalRegionTrans): def test_apply_force_private(fortran_reader): - '''Test the apply function of MaxParallelRegionTrans with force privates.''' + '''Test the apply function of MaxParallelRegionTrans + with force privates.''' code = """subroutine x integer :: i, ii, k, l, block integer :: array_l(8) @@ -366,16 +368,23 @@ def test_apply_force_private(fortran_reader): end subroutine x """ psyir = fortran_reader.psyir_from_source(code) - loop_trans = OMPLoopTrans() # Apply loop_trans to all the loops possible. + ltrans = OMPLoopTrans(omp_schedule="static") for loop in psyir.walk(Loop): if loop.variable.name == "ii": - loop_trans.apply(loop, ignore_dependencies_for=["array_l"], nowait=True) - trans = MaxParTrans() - nodes = psyir.walk(Routine)[0].children[:] - mtrans.apply(nodes, force_private = ["array_l"]) + ltrans.apply( + loop, + ignore_dependencies_for=["array_l"], + nowait=True) + + # Apply maximum transformation to code + mtrans = MaxParTrans() + routine = psyir.walk(Routine) + # Note, i, ii, k, l seem to be set as first private + mtrans.apply(routine, force_private=["i", "ii", "k", "l", "array_l"]) + # assertions assert len(psyir.walk(OMPParallelDirective)) == 1 - pdir = psyir.walk(OMPParallelDirective)[0] - # All of the blocks here should be in the same ParallelDirective - for node in nodes: - assert node.parent.parent is pdir + nodes = psyir.walk(Routine)[0].children[:] + assert isinstance(nodes[0], OMPParallelDirective) is True + pdir = psyir.walk(OMPParallelDirective) + assert len(pdir[0].explicitly_private_symbols) == 5 From a0006612852ac4834d30211920d5cf783fffc182 Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Mon, 18 May 2026 11:09:07 +0100 Subject: [PATCH 16/24] formatting --- .../tests/psyir/transformations/maximal_region_trans_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/psyclone/tests/psyir/transformations/maximal_region_trans_test.py b/src/psyclone/tests/psyir/transformations/maximal_region_trans_test.py index 8b0b5c84d3..af3271434f 100644 --- a/src/psyclone/tests/psyir/transformations/maximal_region_trans_test.py +++ b/src/psyclone/tests/psyir/transformations/maximal_region_trans_test.py @@ -376,7 +376,6 @@ def test_apply_force_private(fortran_reader): loop, ignore_dependencies_for=["array_l"], nowait=True) - # Apply maximum transformation to code mtrans = MaxParTrans() routine = psyir.walk(Routine) From a559f9aecc9cf62da32634be83bf603407bea9c6 Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Tue, 19 May 2026 11:25:37 +0100 Subject: [PATCH 17/24] Add changes and debugging findings --- .../transformations/omp_parallel_trans.py | 8 ++--- .../transformations/parallel_region_trans.py | 2 ++ .../parallel_region_trans_test.py | 32 +++++++++++++++++-- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/psyclone/psyir/transformations/omp_parallel_trans.py b/src/psyclone/psyir/transformations/omp_parallel_trans.py index 11d101c88e..247727889b 100644 --- a/src/psyclone/psyir/transformations/omp_parallel_trans.py +++ b/src/psyclone/psyir/transformations/omp_parallel_trans.py @@ -148,12 +148,8 @@ def apply( # table of the ancestor RegionDirective to the nodes which have just # had a region spanned over. if force_private: - new_region_directive = None - try: - new_region_directive = nodes[0].ancestor(RegionDirective) - except TypeError as err: - logging.warning( - "Could not find an OMPParallelTrans ancestor as %", err) + new_region_directive = nodes[0].ancestor(RegionDirective) + print(f"new_region_directive: {new_region_directive}") if new_region_directive: new_region_directive.explicitly_private_symbols.update( super()._check_symbol_table_vars( diff --git a/src/psyclone/psyir/transformations/parallel_region_trans.py b/src/psyclone/psyir/transformations/parallel_region_trans.py index eafab5880e..e225504f43 100644 --- a/src/psyclone/psyir/transformations/parallel_region_trans.py +++ b/src/psyclone/psyir/transformations/parallel_region_trans.py @@ -94,7 +94,9 @@ def _check_symbol_table_vars( for symbol_name in force_private: sym = None try: + print(region_node.scope.symbol_table) sym = region_node.scope.symbol_table.lookup(symbol_name) + print(sym) except KeyError as err: # This is not an error, but we will log the missed string logging.warning( diff --git a/src/psyclone/tests/psyir/transformations/parallel_region_trans_test.py b/src/psyclone/tests/psyir/transformations/parallel_region_trans_test.py index 6195bdce63..59ffb22d76 100644 --- a/src/psyclone/tests/psyir/transformations/parallel_region_trans_test.py +++ b/src/psyclone/tests/psyir/transformations/parallel_region_trans_test.py @@ -47,8 +47,8 @@ import pytest from psyclone.psyir.transformations.transformation_error import ( TransformationError) -from psyclone.psyir.nodes import CodeBlock -from psyclone.psyir.nodes import (Literal, Loop) +from psyclone.psyir.nodes import (OMPParallelDirective, Routine) +from psyclone.psyir.nodes import (CodeBlock, Literal, Loop) from psyclone.psyir.transformations import OMPParallelTrans from psyclone.psyir.symbols import (DataSymbol, INTEGER_TYPE) @@ -69,3 +69,31 @@ def test_parallelregion_refuse_codeblock(): otrans.validate([parent]) assert ("Nodes of type 'CodeBlock' cannot be enclosed by a " "OMPParallelTrans transformation" in str(err.value)) + + +def test_sym_tab_exception(fortran_reader): + '''Check exception handling of _check_symbol_table_vars. We use + OMPParallelTrans as ParallelRegionTrans is abstract. ''' + code = """subroutine x + integer :: i, outside_var + integer :: array_i(4) + outside_var = 2 + do i = 1, 4 + array_i(i) = 1 + 2 + end do + end subroutine x + """ + psyir = fortran_reader.psyir_from_source(code) + otrans = OMPParallelTrans() + nodes = [] + ### debug ### + nodes = psyir.walk(Routine)[0].children[:] + + ### debug ### + # for loop in psyir.walk(Loop): + # nodes.append(loop) + otrans.apply(nodes, force_private=["outside_var"]) + + print(psyir.view()) + assert len(psyir.walk(OMPParallelDirective)) == 2 + From c467b47a58f0178c358a58e4c37a8bc646d1fa40 Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Tue, 19 May 2026 14:30:01 +0100 Subject: [PATCH 18/24] Update and accept coverage loss --- .../transformations/omp_parallel_trans.py | 9 ++++--- .../transformations/parallel_region_trans.py | 4 +-- .../parallel_region_trans_test.py | 27 ------------------- 3 files changed, 6 insertions(+), 34 deletions(-) diff --git a/src/psyclone/psyir/transformations/omp_parallel_trans.py b/src/psyclone/psyir/transformations/omp_parallel_trans.py index 247727889b..2e103fa63b 100644 --- a/src/psyclone/psyir/transformations/omp_parallel_trans.py +++ b/src/psyclone/psyir/transformations/omp_parallel_trans.py @@ -49,7 +49,7 @@ OMPParallelDirective, OMPDirective, Return, - RegionDirective + RegionDirective, ) from psyclone.psyir.transformations.parallel_region_trans import ( ParallelRegionTrans) @@ -149,12 +149,13 @@ def apply( # had a region spanned over. if force_private: new_region_directive = nodes[0].ancestor(RegionDirective) - print(f"new_region_directive: {new_region_directive}") if new_region_directive: - new_region_directive.explicitly_private_symbols.update( - super()._check_symbol_table_vars( + region_set = set(super()._check_symbol_table_vars( new_region_directive, force_private)) + if region_set: + new_region_directive.explicitly_private_symbols.update( + region_set) __all__ = ["OMPParallelTrans"] diff --git a/src/psyclone/psyir/transformations/parallel_region_trans.py b/src/psyclone/psyir/transformations/parallel_region_trans.py index e225504f43..e53e425c5d 100644 --- a/src/psyclone/psyir/transformations/parallel_region_trans.py +++ b/src/psyclone/psyir/transformations/parallel_region_trans.py @@ -94,9 +94,7 @@ def _check_symbol_table_vars( for symbol_name in force_private: sym = None try: - print(region_node.scope.symbol_table) - sym = region_node.scope.symbol_table.lookup(symbol_name) - print(sym) + sym = region_node.scope.symbol_table.lookup(symbol_name.lower()) except KeyError as err: # This is not an error, but we will log the missed string logging.warning( diff --git a/src/psyclone/tests/psyir/transformations/parallel_region_trans_test.py b/src/psyclone/tests/psyir/transformations/parallel_region_trans_test.py index 59ffb22d76..e6c8ae6de1 100644 --- a/src/psyclone/tests/psyir/transformations/parallel_region_trans_test.py +++ b/src/psyclone/tests/psyir/transformations/parallel_region_trans_test.py @@ -47,7 +47,6 @@ import pytest from psyclone.psyir.transformations.transformation_error import ( TransformationError) -from psyclone.psyir.nodes import (OMPParallelDirective, Routine) from psyclone.psyir.nodes import (CodeBlock, Literal, Loop) from psyclone.psyir.transformations import OMPParallelTrans from psyclone.psyir.symbols import (DataSymbol, INTEGER_TYPE) @@ -71,29 +70,3 @@ def test_parallelregion_refuse_codeblock(): "OMPParallelTrans transformation" in str(err.value)) -def test_sym_tab_exception(fortran_reader): - '''Check exception handling of _check_symbol_table_vars. We use - OMPParallelTrans as ParallelRegionTrans is abstract. ''' - code = """subroutine x - integer :: i, outside_var - integer :: array_i(4) - outside_var = 2 - do i = 1, 4 - array_i(i) = 1 + 2 - end do - end subroutine x - """ - psyir = fortran_reader.psyir_from_source(code) - otrans = OMPParallelTrans() - nodes = [] - ### debug ### - nodes = psyir.walk(Routine)[0].children[:] - - ### debug ### - # for loop in psyir.walk(Loop): - # nodes.append(loop) - otrans.apply(nodes, force_private=["outside_var"]) - - print(psyir.view()) - assert len(psyir.walk(OMPParallelDirective)) == 2 - From c44ef4a226237149c510c697e3a3109eeb8d4ed3 Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Tue, 19 May 2026 14:51:37 +0100 Subject: [PATCH 19/24] small adjustments --- src/psyclone/psyir/transformations/omp_parallel_trans.py | 4 ++-- .../tests/psyir/transformations/parallel_region_trans_test.py | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/psyclone/psyir/transformations/omp_parallel_trans.py b/src/psyclone/psyir/transformations/omp_parallel_trans.py index 2e103fa63b..46702ac036 100644 --- a/src/psyclone/psyir/transformations/omp_parallel_trans.py +++ b/src/psyclone/psyir/transformations/omp_parallel_trans.py @@ -150,9 +150,9 @@ def apply( if force_private: new_region_directive = nodes[0].ancestor(RegionDirective) if new_region_directive: - region_set = set(super()._check_symbol_table_vars( + region_set = super()._check_symbol_table_vars( new_region_directive, - force_private)) + force_private) if region_set: new_region_directive.explicitly_private_symbols.update( region_set) diff --git a/src/psyclone/tests/psyir/transformations/parallel_region_trans_test.py b/src/psyclone/tests/psyir/transformations/parallel_region_trans_test.py index e6c8ae6de1..8a315f0082 100644 --- a/src/psyclone/tests/psyir/transformations/parallel_region_trans_test.py +++ b/src/psyclone/tests/psyir/transformations/parallel_region_trans_test.py @@ -68,5 +68,3 @@ def test_parallelregion_refuse_codeblock(): otrans.validate([parent]) assert ("Nodes of type 'CodeBlock' cannot be enclosed by a " "OMPParallelTrans transformation" in str(err.value)) - - From 4fbdada9994fa5c493b57717b7a62f6611e364fc Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Tue, 19 May 2026 15:01:03 +0100 Subject: [PATCH 20/24] fix flake8 stuff --- src/psyclone/psyir/transformations/parallel_region_trans.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/psyclone/psyir/transformations/parallel_region_trans.py b/src/psyclone/psyir/transformations/parallel_region_trans.py index e53e425c5d..5e37380e50 100644 --- a/src/psyclone/psyir/transformations/parallel_region_trans.py +++ b/src/psyclone/psyir/transformations/parallel_region_trans.py @@ -94,7 +94,8 @@ def _check_symbol_table_vars( for symbol_name in force_private: sym = None try: - sym = region_node.scope.symbol_table.lookup(symbol_name.lower()) + sym = region_node.scope.symbol_table.lookup( + symbol_name.lower()) except KeyError as err: # This is not an error, but we will log the missed string logging.warning( From ca0530df87d9a782e73de80dc5b4f2d18c1593cc Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Tue, 19 May 2026 15:26:49 +0100 Subject: [PATCH 21/24] update logger --- src/psyclone/psyir/transformations/parallel_region_trans.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/psyclone/psyir/transformations/parallel_region_trans.py b/src/psyclone/psyir/transformations/parallel_region_trans.py index 5e37380e50..f688880d7c 100644 --- a/src/psyclone/psyir/transformations/parallel_region_trans.py +++ b/src/psyclone/psyir/transformations/parallel_region_trans.py @@ -98,7 +98,8 @@ def _check_symbol_table_vars( symbol_name.lower()) except KeyError as err: # This is not an error, but we will log the missed string - logging.warning( + logger = logging.getLogger(__name__) + logger.warning( "%s has been provided with the '%s' symbol name in " "the 'force_private' option, but there is no such " "symbol in this scope.", err, symbol_name) From 70045419e8b8762bb3c37f297bb213087ec3e41e Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Tue, 19 May 2026 15:30:57 +0100 Subject: [PATCH 22/24] remove old import --- src/psyclone/psyir/transformations/omp_parallel_trans.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/psyclone/psyir/transformations/omp_parallel_trans.py b/src/psyclone/psyir/transformations/omp_parallel_trans.py index 46702ac036..15769e9825 100644 --- a/src/psyclone/psyir/transformations/omp_parallel_trans.py +++ b/src/psyclone/psyir/transformations/omp_parallel_trans.py @@ -39,7 +39,7 @@ # M. Schreiber, Univ. Grenoble Alpes / Inria / Lab. Jean Kuntzmann # J. Dendy, Met Office '''This module provides the OMPParallelTrans transformation.''' -import logging + from collections.abc import Iterable from psyclone import psyGen from psyclone.psyir.nodes import ( From a2dfb777eb86af179c708408e318e161c4058038 Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Wed, 20 May 2026 09:21:55 +0100 Subject: [PATCH 23/24] Some housekeeping of comment and unneeded change --- src/psyclone/psyir/transformations/maximal_region_trans.py | 4 +--- src/psyclone/psyir/transformations/omp_parallel_trans.py | 5 ++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/psyclone/psyir/transformations/maximal_region_trans.py b/src/psyclone/psyir/transformations/maximal_region_trans.py index e66abf79c1..813820dc2a 100644 --- a/src/psyclone/psyir/transformations/maximal_region_trans.py +++ b/src/psyclone/psyir/transformations/maximal_region_trans.py @@ -242,9 +242,7 @@ def validate(self, nodes: Union[Node, Schedule, list[Node]], **kwargs): f"{prev_position}.") prev_position = child.position - def apply( - self, nodes: Union[Node, Schedule, list[Node]], - **kwargs): + def apply(self, nodes: Union[Node, Schedule, list[Node]], **kwargs): '''Applies the transformation to the nodes provided. :param nodes: can be a single node, a schedule or a list of nodes. diff --git a/src/psyclone/psyir/transformations/omp_parallel_trans.py b/src/psyclone/psyir/transformations/omp_parallel_trans.py index 15769e9825..6f8550aeb8 100644 --- a/src/psyclone/psyir/transformations/omp_parallel_trans.py +++ b/src/psyclone/psyir/transformations/omp_parallel_trans.py @@ -144,9 +144,8 @@ def apply( # TODO #2668: Remove options. super().apply(nodes, options, **kwargs) - # Privatise the provided variables if they are found within the symbol - # table of the ancestor RegionDirective to the nodes which have just - # had a region spanned over. + # Privatise the provided variables for the new RegionDirective, if they + # are found within the symbol table of the ancestor Routine. if force_private: new_region_directive = nodes[0].ancestor(RegionDirective) if new_region_directive: From f8f81d9b22df7faf5443c63e5813ec605141f503 Mon Sep 17 00:00:00 2001 From: MetBenjaminWent Date: Thu, 21 May 2026 09:26:09 +0100 Subject: [PATCH 24/24] Add test recommended by Aidan --- .../parallel_region_trans_test.py | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/psyclone/tests/psyir/transformations/parallel_region_trans_test.py b/src/psyclone/tests/psyir/transformations/parallel_region_trans_test.py index 8a315f0082..17a0cb6515 100644 --- a/src/psyclone/tests/psyir/transformations/parallel_region_trans_test.py +++ b/src/psyclone/tests/psyir/transformations/parallel_region_trans_test.py @@ -44,6 +44,7 @@ ''' +import logging import pytest from psyclone.psyir.transformations.transformation_error import ( TransformationError) @@ -68,3 +69,32 @@ def test_parallelregion_refuse_codeblock(): otrans.validate([parent]) assert ("Nodes of type 'CodeBlock' cannot be enclosed by a " "OMPParallelTrans transformation" in str(err.value)) + + +def test_parallelregion_check_symtab_var(fortran_reader, caplog): + ''' + Check ParallelRegionTrans._check_symbol_table_vars try and except, + if the logging message produces a warning when a variable is not + in the routine scope.We use OMPParallelTrans as ParallelRegionTrans + is abstract. + ''' + otrans = OMPParallelTrans() + code = """subroutine test + integer :: i + do i = 1, 100 + + end do + end subroutine""" + psyir = fortran_reader.psyir_from_source(code) + otrans.apply(psyir.children[0].children[0]) + parallel = psyir.children[0].children[0] + caplog.clear() + with caplog.at_level(logging.WARNING, + logger="psyclone.psyir.transformations"): + otrans._check_symbol_table_vars(parallel, ("j")) + + long_string = \ + "\"Could not find 'j' in the Symbol Table.\" has been "\ + "provided with the 'j' symbol name in the 'force_private' option, "\ + "but there is no such symbol in this scope." + assert (long_string in caplog.text)