Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b8b5be2
#2884 Improve ref2arrayrange handling of structures (still incomplete)
sergisiso Dec 19, 2025
630d037
#1858 Add ref2arrayrange validation for structures
sergisiso Dec 19, 2025
9fe01c1
#1858 Improve reference2arrayrange validation
sergisiso Dec 23, 2025
2ac0192
#1858 Use get_full_range to populate ref2arrayrange, which now suppor…
sergisiso Dec 24, 2025
4dc1977
#1858 Add ref2arrayrange apply implementation for Structure and Membe…
sergisiso Dec 24, 2025
f80b9d0
#1858 Test ref2arrayrange for structures and fix issues
sergisiso Dec 24, 2025
8bd7d07
#1858 Test ref2arrayrange with structures support in InlineTrans
sergisiso Dec 27, 2025
f068912
#1858 Clean up PR
sergisiso Dec 27, 2025
d564191
#1858 Test unsupported derived type accessors in ref2arrayrange
sergisiso Dec 27, 2025
8e0cd52
#1858 Attempt removing fldread.f90 nemo exclusion
sergisiso Dec 27, 2025
ec54f74
#1858 Add missing ref2arrayrange test
sergisiso Dec 28, 2025
2a5d61f
#1858 Merge ref2arrayrange pointer assignment improvements
sergisiso Dec 28, 2025
f030f27
#1858 Allow ref2arrayrange to validate direct children of Range
sergisiso Dec 31, 2025
d9cfd3b
#1858 Add lbcnfd to the NEMO files to import
sergisiso Dec 31, 2025
ddb7b7b
#1858 Bring branch up to date
sergisiso Jan 6, 2026
a693caa
Merge branch 'master' into 1858_ref2arrayrange_structures
sergisiso Jan 7, 2026
a02d5a5
Merge branch 'master' into 1858_ref2arrayrange_structures
arporter Jan 12, 2026
b09a553
#1858 Add xfail for 2951.
sergisiso Jan 12, 2026
36dea00
#1858 Clean up PR
sergisiso Jan 12, 2026
054a2fd
Merge branch 'master' into 1858_ref2arrayrange_structures
arporter Jan 14, 2026
991dc35
#1858 Update xfail test
sergisiso Jan 14, 2026
acf7061
#3266 update changelog
arporter Jan 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
18) PR #3266 for #1858. Adds support for derived-type accessors in
the Reference2ArrayRangeTrans transformation.

17) PR #3277 for #3276. Update copyright statements for 2026.

16) PR #3258 for #279. Removes Arguments.dofs and generally improves
Expand Down
6 changes: 1 addition & 5 deletions examples/nemo/scripts/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
"ldfdyn", "sbcapr", "sbctide", "zdfgls", "sbcrnf", "sbcisf", "dynldf_iso",
"stopts", "icb_oce", "domvvl", "sms_pisces", "zdfmfc", "abl", "ice1d",
"sed", "p2zlim", "oce_trc", "p4zpoc", "tide_mod", "sbcwave", "isf_oce",
"step_oce", "bdyice",
"step_oce", "bdyice", "lbcnfd"
]

# Files that PSyclone could process but would reduce the performance.
Expand Down Expand Up @@ -201,7 +201,6 @@ def normalise_loops(
:param hoist_expressions: whether to hoist bounds and loop invariant
statements out of the loop nest.
'''
filename = schedule.root.name
if hoist_local_arrays and schedule.name not in CONTAINS_STMT_FUNCTIONS:
# Apply the HoistLocalArraysTrans when possible, it cannot be applied
# to files with statement functions because it will attempt to put the
Expand Down Expand Up @@ -230,9 +229,6 @@ def normalise_loops(
# Convert all array implicit loops to explicit loops
explicit_loops = ArrayAssignment2LoopsTrans()
for assignment in schedule.walk(Assignment):
if filename == "fldread.f90":
# TODO #2951: This file has issues converting SturctureRefs
Comment thread
arporter marked this conversation as resolved.
continue
try:
explicit_loops.apply(
assignment, options={'verbose': True})
Expand Down
57 changes: 34 additions & 23 deletions src/psyclone/psyir/nodes/array_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,18 +193,22 @@ def is_lower_bound(self, index):
'''
return self._is_bound(index, "lower")

def _get_bound_expression(self, pos: int, bound: str):
def _get_bound_expression(self, position: int, bound: str):
'''
Lookup the upper or lower bound of this ArrayMixin.

:param pos: the dimension of the array for which to lookup the bound.
:param position: the dimension of the array for which to lookup the
bound.
:param bound: "upper" or "lower" - the bound which to lookup.

:returns: the declared bound for the specified dimension of this array
or a call to the {U/L}BOUND intrinsic if it is unknown.
:rtype: :py:class:`psyclone.psyir.nodes.Node`

:raises InternalError: if bound is neither "upper" or "lower".
:raises ValueError: if the shape of the given 'position' is needed to
generate the bound expression, but we don't have that type
information.

'''
if bound not in ("upper", "lower"):
Expand All @@ -229,8 +233,13 @@ def _get_bound_expression(self, pos: int, bound: str):
cursor = cursor.member
# Collect member information.
if isinstance(cursor, ArrayMixin):
new_indices = [idx.copy() for idx in cursor.indices]
cnames.append((cursor.name.lower(), new_indices))
try:
new_indices = [idx.copy() for idx in cursor.indices]
cnames.append((cursor.name.lower(), new_indices))
except InternalError:
# The node is incomplete, but we can still use the type
# information to populate the bounds
cnames.append(cursor.name.lower())
else:
cnames.append(cursor.name.lower())
# Continue to resolve datatype unless we hit an
Expand All @@ -243,17 +252,23 @@ def _get_bound_expression(self, pos: int, bound: str):
continue
cursor_type = cursor_type.components[cursor.name.lower()].datatype

if (isinstance(cursor_type, ArrayType) and
cursor_type.shape[pos] not in [ArrayType.Extent.DEFERRED,
ArrayType.Extent.ATTRIBUTE]):
# We have the full type information and the bound is known.
if bound == "lower":
return cursor_type.shape[pos].lower.copy()
# If the upper bound is required and is of ArrayType.Extent type
# then we'll have to proceed to construct a call to the UBOUND
# intrinsic.
if not isinstance(cursor_type.shape[pos].upper, ArrayType.Extent):
return cursor_type.shape[pos].upper.copy()
if isinstance(cursor_type, ArrayType):
if position > len(cursor_type.shape):
raise ValueError(
Comment thread
arporter marked this conversation as resolved.
f"In '{type(self).__name__}' '{self.name}' the specified "
f"index '{position}' must be less than the number of "
f"dimensions '{len(cursor_type.shape)}'.")
if cursor_type.shape[position] not in [ArrayType.Extent.DEFERRED,
ArrayType.Extent.ATTRIBUTE]:
# We have the full type information and the bound is known.
if bound == "lower":
return cursor_type.shape[position].lower.copy()
# If the upper bound is required and is of ArrayType.Extent
# type then we'll have to proceed to construct a call to the
# UBOUND intrinsic.
if not isinstance(cursor_type.shape[position].upper,
ArrayType.Extent):
return cursor_type.shape[position].upper.copy()

# We've either failed to resolve the type or we don't know the extent
# of the array dimension so construct a call to the BOUND intrinsic.
Expand All @@ -279,10 +294,10 @@ def _get_bound_expression(self, pos: int, bound: str):
if bound == "lower":
return IntrinsicCall.create(
IntrinsicCall.Intrinsic.LBOUND,
[ref, ("dim", Literal(str(pos+1), INTEGER_TYPE))])
[ref, ("dim", Literal(str(position+1), INTEGER_TYPE))])
return IntrinsicCall.create(
IntrinsicCall.Intrinsic.UBOUND,
[ref, ("dim", Literal(str(pos+1), INTEGER_TYPE))])
[ref, ("dim", Literal(str(position+1), INTEGER_TYPE))])

def get_lbound_expression(self, pos):
'''
Expand All @@ -294,12 +309,11 @@ def get_lbound_expression(self, pos):
lower bound.

:returns: the declared lower bound for the specified dimension of
the array accesed or a call to the LBOUND intrinsic if it is
the array accessed or a call to the LBOUND intrinsic if it is
unknown.
:rtype: :py:class:`psyclone.psyir.nodes.Node`

'''
self._validate_index(pos)
# Call the helper function
return self._get_bound_expression(pos, "lower")

Expand All @@ -313,12 +327,11 @@ def get_ubound_expression(self, pos):
upper bound.

:returns: the declared upper bound for the specified dimension of
the array accesed or a call to the UBOUND intrinsic if it is
the array accessed or a call to the UBOUND intrinsic if it is
unknown.
:rtype: :py:class:`psyclone.psyir.nodes.Node`

'''
self._validate_index(pos)
# Call the helper function
return self._get_bound_expression(pos, "upper")

Expand All @@ -334,8 +347,6 @@ def get_full_range(self, pos):
pos for this ArrayMixin.
:rtype: :py:class:`psyclone.psyir.nodes.Range`
'''
self._validate_index(pos)

lbound = self.get_lbound_expression(pos)
ubound = self.get_ubound_expression(pos)

Expand Down
5 changes: 1 addition & 4 deletions src/psyclone/psyir/transformations/inline_trans.py
Original file line number Diff line number Diff line change
Expand Up @@ -860,10 +860,7 @@ def _generate_formal_arg_replacement(
break
cursor = cursor.member

# TODO #1858 - once we support converting structure accesses into
# explicit array accesses, we can put back the testing in
# inline_trans_test.py that covers this code and remove the pragma:
if not actual_arg.walk(Range) and local_indices: # pragma: no cover
if not actual_arg.walk(Range) and local_indices:
# There are no Ranges in the actual argument but the local
# reference is an array access.
# Create updated index expressions for that access.
Expand Down
Loading
Loading