Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@
22) PR #3439 for #3415. Fix datatype method for StructureReference nodes
that return arrays.

21) PR #3434 for #2813. Migrates the setup files to use a
pyproject.toml rather than setup.py.

Expand Down
73 changes: 12 additions & 61 deletions src/psyclone/psyir/nodes/intrinsic_call.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,36 +427,6 @@ def _int_return_type(node: IntrinsicCall) -> DataType:
)


def _iparity_return_type(node: IntrinsicCall) -> DataType:
"""Helper function for the IPARITY case.

The result is the same type as the "array" argument. If the
"dim" argument is not present, a scalar of that type is returned.
Otherwise an ArrayType of rank n-1 (where n is the rank of "array") of
that type is returned instead.

:param node: The IntrinsicCall whose return type to compute.

:returns: the computed datatype for the IntrinsicCall.
"""
# TODO #3415: Replace with _type_of_named_arg_accounting_for_dim_arg(
# node, "array").
dtype = ScalarType(
node.argument_by_name("array").datatype.intrinsic,
node.argument_by_name("array").datatype.precision,
)
# If dim is not present then we return a scalar.
if "dim" not in node.argument_names:
return dtype
# We have a dimension specified. We don't know the resultant shape
# in any detail as its dependent on the value of dim
return ArrayType(
dtype,
[ArrayType.Extent.DEFERRED]
* (len(node.argument_by_name("array").datatype.shape) - 1),
)


def _get_bound_function_return_type(node: IntrinsicCall) -> DataType:
"""Helper function for the return types of functions like LBOUND and
LCOBOUND etc.
Expand Down Expand Up @@ -554,33 +524,6 @@ def _matmul_return_type(node: IntrinsicCall) -> DataType:
return ArrayType(stype, shape)


def _maxval_return_type(node: IntrinsicCall) -> DataType:
""" Helper function for the MAXVAL (and similar) intrinsic return
types.

If the "dim" argument is absent, or the "array" argument has rank one
then the result is a ScalarType of the type of the "array" argument.
Otherwise the result is an ArrayType of rank n-1 (where n is the rank of
the "array" argument) with the same datatype of the "array" argument.

:param node: The IntrinsicCall whose return type to compute.

:returns: the computed datatype for the IntrinsicCall.
"""
# TODO #3415: Replace with _type_of_named_arg_accounting_for_dim_arg(
# node, "array").
dtype = ScalarType(
node.argument_by_name("array").datatype.intrinsic,
node.argument_by_name("array").datatype.precision
)
arg = node.argument_by_name("array")
if "dim" not in node.argument_names:
return dtype
# We have a dimension specified. We don't know the resultant shape
# in any detail as its dependent on the value of dim
return _type_of_arg_with_rank_minus_one(arg, dtype)


def _dot_product_return_type(node: IntrinsicCall) -> DataType:
"""Helper value for DOT_PRODUCT intrinsic return type.

Expand Down Expand Up @@ -2858,7 +2801,9 @@ class Intrinsic(IAttr, Enum):
)
),
optional_args={"mask": DataNode},
return_type=_iparity_return_type,
return_type=lambda node: (
_type_of_named_arg_accounting_for_dim_arg(node, "array")
),
reference_accesses=lambda node: (
_compute_reference_accesses(
node
Expand Down Expand Up @@ -3381,7 +3326,9 @@ class Intrinsic(IAttr, Enum):
)
),
optional_args={"mask": DataNode},
return_type=_maxval_return_type,
return_type=lambda node: (
_type_of_named_arg_accounting_for_dim_arg(node, "array")
),
reference_accesses=lambda node: (
_compute_reference_accesses(
node
Expand Down Expand Up @@ -3510,7 +3457,9 @@ class Intrinsic(IAttr, Enum):
)
),
optional_args={"mask": DataNode},
return_type=_maxval_return_type,
return_type=lambda node: (
_type_of_named_arg_accounting_for_dim_arg(node, "array")
),
reference_accesses=lambda node: (
_compute_reference_accesses(
node,
Expand Down Expand Up @@ -4063,7 +4012,9 @@ class Intrinsic(IAttr, Enum):
optional_args={"mask": DataNode,
"identity": DataNode,
"ordered": DataNode},
return_type=_maxval_return_type,
return_type=lambda node: (
_type_of_named_arg_accounting_for_dim_arg(node, "array")
),
reference_accesses=lambda node: (
_compute_reference_accesses(
node
Expand Down
2 changes: 2 additions & 0 deletions src/psyclone/psyir/nodes/structure_reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,8 @@ def _get_cursor_shape(cursor, cursor_type):
shape = cursor_shape

if shape:
if isinstance(cursor_type, ArrayType):
return ArrayType(cursor_type.elemental_type, shape)
return ArrayType(cursor_type, shape)

# We must have a scalar.
Expand Down
75 changes: 0 additions & 75 deletions src/psyclone/tests/psyir/nodes/intrinsic_call_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,8 @@
_type_of_intrinsic_with_precision_of_named_arg,
_findloc_return_type,
_int_return_type,
_iparity_return_type,
_get_bound_function_return_type,
_matmul_return_type,
_maxval_return_type,
)
from psyclone.psyir.symbols import (
ArrayType,
Expand Down Expand Up @@ -1390,39 +1388,6 @@ def test_int_return_type(fortran_reader):
assert rtype.precision.symbol.name == "wp"


def test_iparity_return_type(fortran_reader):
"""Test the _iparity_return_type helper function."""
code = """
subroutine x
integer, dimension(100, 100) :: array
integer :: k
k = IPARITY(array)
end subroutine x
"""
# TODO #3415: Test is superfluous with this issue fixed.
psyir = fortran_reader.psyir_from_source(code)
# TODO #3268 Can't iparity directily with fortran reader, so need to
# create the Intrinsics manually using the psyir from the generated code.
intrinsic = psyir.walk(Call)[0]
intrinsic = IntrinsicCall.create(
IntrinsicCall.Intrinsic.IPARITY,
[x.copy() for x in intrinsic.arguments]
)

assert _iparity_return_type(intrinsic) == INTEGER_TYPE

k_sym = psyir.children[0].symbol_table.lookup("k")
intrinsic = psyir.walk(Call)[0]
intrinsic = IntrinsicCall.create(
IntrinsicCall.Intrinsic.IPARITY,
[("array", intrinsic.arguments[0].copy()), ("dim", Reference(k_sym))],
)
res = _iparity_return_type(intrinsic)
assert isinstance(res, ArrayType)
assert len(res.shape) == 1
assert res.shape[0] == ArrayType.Extent.DEFERRED


def test_get_bound_function_return_type(fortran_reader):
"""Test the _get_bound_function_return_type helper function."""
code = """subroutine x
Expand Down Expand Up @@ -1557,46 +1522,6 @@ def test_matmul_return_type(fortran_reader):
assert res.shape[1].upper.arguments[1].value == "2"


def test_maxval_return_type(fortran_reader):
'''Test for the _maxval_return_type function.'''
# TODO #3415: Test is superfluous with this issue fixed.
code = """subroutine test
integer, parameter :: wp = 8
integer*8, dimension(100,100) :: x
integer, dimension(100) :: z
integer(kind=wp), dimension(100) :: m
integer :: y
y = MAXVAL(x)
z = MAXVAL(x, dim=2)
y = MAXVAL(m)
end subroutine test
"""
psyir = fortran_reader.psyir_from_source(code)
intrs = psyir.walk(IntrinsicCall)

# Input is a int*8 so the return type should be an int*8
res = _maxval_return_type(intrs[0])
assert res.intrinsic == ScalarType.Intrinsic.INTEGER
assert res.precision == 8

# Input is a 2D array of int*8 with dim specified so the result
# is a 1D int*8 array.
res = _maxval_return_type(intrs[1])
assert isinstance(res, ArrayType)
assert res.intrinsic == ScalarType.Intrinsic.INTEGER
assert res.precision == 8
assert len(res.shape) == 1
assert res.shape[0] == ArrayType.Extent.DEFERRED

# Input is a 1D array of int(kind=wp) so the result is an
# int(kind=wp)
res = _maxval_return_type(intrs[2])
assert isinstance(res, ScalarType)
assert res.intrinsic == ScalarType.Intrinsic.INTEGER
assert isinstance(res.precision, Reference)
assert res.precision.symbol.name == "wp"


@pytest.mark.parametrize(
"code, expected",
[
Expand Down
22 changes: 21 additions & 1 deletion src/psyclone/tests/psyir/nodes/structure_reference_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
from psyclone.core import Signature
from psyclone.errors import GenerationError, InternalError
from psyclone.psyir import symbols, nodes
from psyclone.psyir.symbols.datatypes import ArrayType, ScalarType
from psyclone.tests.utilities import check_links


Expand Down Expand Up @@ -240,7 +241,7 @@ def test_struct_ref_semantic_nav():
"found: ['broken']" in str(err.value))


def test_struct_ref_datatype():
def test_struct_ref_datatype(fortran_reader):
'''Test the datatype() method of StructureReference.'''
atype = symbols.ArrayType(symbols.REAL_TYPE, [10, 8])
rtype = symbols.StructureType.create([
Expand Down Expand Up @@ -327,6 +328,25 @@ def test_struct_ref_datatype():
create(ssym, ["nx"], overwrite_datatype=symbols.REAL_TYPE)
assert sref.datatype == symbols.REAL_TYPE

# Test that the structuretype datatype for this case does not contain
# multiply nested array types.
code = (
"subroutine test(n,m)\n"
" integer :: n, m\n"
" type :: array_type\n"
" real :: array(10,10)\n"
" end type\n"
" type(array_type) :: ref\n"
" real :: result\n"
" integer :: dimension\n"
" result = maxval(ref%array)\n"
"end subroutine\n")
psyir = fortran_reader.psyir_from_source(code)
node = psyir.walk(nodes.StructureReference)[0]
assert isinstance(node.datatype, ArrayType)
assert isinstance(node.datatype.elemental_type, ScalarType)
assert node.datatype.elemental_type.intrinsic == ScalarType.Intrinsic.REAL


def test_structure_reference_unresolved_type():
'''
Expand Down
Loading