Source code for psyclone.psyir.transformations.allarrayaccess2loop_trans
# -----------------------------------------------------------------------------
# SPDX-FileCopyrightText: Copyright (c) 2021-2026 Science and Technology
# Facilities Council
# SPDX-License-Identifier: BSD-3-Clause
# See the full LICENSE file in the project root for details.
# -----------------------------------------------------------------------------
'''Module providing a transformation that transforms all constant
index accesses to an array (i.e. ones that do not contain loop
iterators) to single-trip loops.
'''
from psyclone.psyir.transformations.arrayaccess2loop_trans import \
ArrayAccess2LoopTrans
from psyclone.psyGen import Transformation
from psyclone.psyir.nodes import Assignment
from psyclone.psyir.transformations.transformation_error \
import TransformationError
from psyclone.utils import transformation_documentation_wrapper
[docs]
@transformation_documentation_wrapper
class AllArrayAccess2LoopTrans(Transformation):
'''Provides a transformation from a PSyIR Assignment containing
constant index accesses to an array into single-trip loops. For
example:
>>> from psyclone.psyir.transformations import AllArrayAccess2LoopTrans
>>> from psyclone.psyir.backend.fortran import FortranWriter
>>> from psyclone.psyir.frontend.fortran import FortranReader
>>> from psyclone.psyir.nodes import Assignment
>>> code = ("program example\\n"
... " real a(10,10), b(10,10)\\n"
... " integer :: n\\n"
... " a(1,n-1) = b(1,n-1)\\n"
... "end program example\\n")
>>> psyir = FortranReader().psyir_from_source(code)
>>> assignment = psyir.walk(Assignment)[0]
>>> AllArrayAccess2LoopTrans().apply(assignment)
>>> print(FortranWriter()(psyir))
program example
real, dimension(10,10) :: a
real, dimension(10,10) :: b
integer :: n
integer :: idx
integer :: idx_1
<BLANKLINE>
do idx = 1, 1, 1
do idx_1 = n - 1, n - 1, 1
a(idx,idx_1) = b(idx,idx_1)
enddo
enddo
<BLANKLINE>
end program example
<BLANKLINE>
'''
[docs]
def apply(self, node: Assignment, options=None, **kwargs):
'''Apply the AllArrayAccess2Loop transformation if the supplied
node is an Assignment with an Array Reference on its
left-hand-side. Each constant array index access (i.e. one not
containing a loop iterator or a range) is then transformed into
an iterator and the assignment placed within a single-trip loop,
subject to any constraints in the ArrayAccess2Loop transformation.
If any of the AllArrayAccess2Loop constraints are not
satisfied for a loop index then this transformation does
nothing for that index and silently moves to the next.
:param node: an assignment.
:param options: a dictionary with options for transformations.
This is an optional argument that defaults to None.
:type options: Optional[Dict[str, Any]]
'''
self.validate(node, options, **kwargs)
trans = ArrayAccess2LoopTrans()
for index in node.lhs.children:
try:
trans.apply(index)
except TransformationError:
pass
[docs]
def validate(self, node: Assignment, options=None, **kwargs):
'''Perform any checks to ensure that it is valid to apply the
AllArrayAccess2LoopTrans transformation to the supplied
PSyIR Node.
:param node: the node that is being checked.
:param options: a dictionary with options for transformations.
This is an optional argument that defaults to None.
:type options: Optional[Dict[str, Any]]
'''
# TODO #2668: Deprecate options dict.
if not options:
self.validate_options(**kwargs)
# Not a PSyIR Assignment node
if not isinstance(node, Assignment):
raise TransformationError(
f"Error in AllArrayAccess2LoopTrans transformation. The "
f"supplied node argument should be a PSyIR Assignment, "
f"but found '{type(node).__name__}'.")
def __str__(self):
return (
"Convert the constant indices of a PSyIR array-element assignment "
"into single-trip Loops.")
@property
def name(self):
'''
:returns: the name of the transformation as a string.
:rtype: str
'''
return type(self).__name__
# For automatic document generation
__all__ = ['AllArrayAccess2LoopTrans']