Skip to content

Commit

Permalink
Merge branch 'master' into 2779_split_element_order
Browse files Browse the repository at this point in the history
  • Loading branch information
mo-jdendy authored Nov 27, 2024
2 parents ee39963 + f85e5f7 commit fdb54f2
Show file tree
Hide file tree
Showing 12 changed files with 181 additions and 43 deletions.
3 changes: 3 additions & 0 deletions changelog
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,9 @@
112) PR #2795 for #2774. Generalises MatMul2CodeTrans to cope with
non-contiguous array slices.

113) PR #2769 for #2768. Generalises Sign2CodeTrans and Abs2CodeTrans
to allow non-floating point scalar literals.

release 2.5.0 14th of February 2024

1) PR #2199 for #2189. Fix bugs with missing maps in enter data
Expand Down
Binary file modified psyclone.pdf
Binary file not shown.
5 changes: 3 additions & 2 deletions src/psyclone/parse/algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -687,8 +687,9 @@ def get_kernel(parse_tree, alg_filename, arg_type_defns):
datatype = arg_type_defns.get(var_name)
arguments.append(Arg('variable', full_text, varname=var_name,
datatype=datatype))
elif isinstance(argument, Part_Ref):
# An indexed variable e.g. arg(n)
elif isinstance(argument, (Part_Ref, Structure_Constructor)):
# An indexed variable e.g. arg(n). (Sometimes fparser matches
# these as structure constructors - fparser/#384.)
full_text = argument.tostr().lower()
var_name = str(argument.items[0]).lower()
datatype = arg_type_defns.get(var_name)
Expand Down
4 changes: 2 additions & 2 deletions src/psyclone/psyad/domain/lfric/lfric_adjoint_harness.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def _compute_lfric_inner_products(prog, scalars, field_sums, sum_sym):
'''
table = prog.symbol_table
idef_sym = table.add_lfric_precision_symbol("i_def")
idef_type = ScalarType(ScalarType.Intrinsic.REAL, idef_sym)
idef_type = ScalarType(ScalarType.Intrinsic.INTEGER, idef_sym)

# Initialise the sum to zero: sum = 0.0
prog.addchild(Assignment.create(Reference(sum_sym),
Expand Down Expand Up @@ -157,7 +157,7 @@ def _compute_field_inner_products(routine, field_pairs):
rdef_sym = table.add_lfric_precision_symbol("r_def")
rdef_type = ScalarType(ScalarType.Intrinsic.REAL, rdef_sym)
idef_sym = table.add_lfric_precision_symbol("i_def")
idef_type = ScalarType(ScalarType.Intrinsic.REAL, idef_sym)
idef_type = ScalarType(ScalarType.Intrinsic.INTEGER, idef_sym)

builtin_factory = LFRicBuiltinFunctorFactory.get()

Expand Down
13 changes: 9 additions & 4 deletions src/psyclone/psyir/backend/c.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,15 @@ def literal_node(self, node):
:rtype: str
'''
result = node.value
# C Scientific notation is always an 'e' letter
result = result.replace('d', 'e')
result = result.replace('D', 'e')
if node.datatype.intrinsic == ScalarType.Intrinsic.REAL:
try:
_ = int(node.value)
result = node.value + ".0"
except ValueError:
# It is already formatted as a real.
result = node.value
else:
result = node.value
return result

def ifblock_node(self, node):
Expand Down
23 changes: 17 additions & 6 deletions src/psyclone/psyir/backend/fortran.py
Original file line number Diff line number Diff line change
Expand Up @@ -1350,12 +1350,23 @@ def literal_node(self, node):
)
quote_symbol = '"'
result = f"{quote_symbol}{node.value}{quote_symbol}"
elif (node.datatype.intrinsic == ScalarType.Intrinsic.REAL and
precision == ScalarType.Precision.DOUBLE):
# The PSyIR stores real scalar values using the standard 'e'
# notation. If the scalar is in fact double precision then this
# 'e' must be replaced by 'd' for Fortran.
result = node.value.replace("e", "d", 1)
elif node.datatype.intrinsic == ScalarType.Intrinsic.REAL:
# Ensure it ends with ".0" if it isn't already explicitly
# formatted as a real.
result = node.value
try:
_ = int(result)
if precision == ScalarType.Precision.DOUBLE:
result = result + ".0d0"
else:
result = result + ".0"
except ValueError:
# It is already formatted as a real.
if precision == ScalarType.Precision.DOUBLE:
# The PSyIR stores real, scalar values using the standard
# 'e' notation. If the scalar is in fact double precision
# then this 'e' must be replaced by 'd' for Fortran.
result = result.replace("e", "d", 1)
else:
result = node.value

Expand Down
31 changes: 20 additions & 11 deletions src/psyclone/psyir/transformations/intrinsics/abs2code_trans.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
Intrinsic2CodeTrans)
from psyclone.psyir.nodes import (
BinaryOperation, Assignment, Reference, Literal, IfBlock, IntrinsicCall)
from psyclone.psyir.symbols import DataSymbol, REAL_TYPE
from psyclone.psyir.symbols import DataSymbol


class Abs2CodeTrans(Intrinsic2CodeTrans):
Expand Down Expand Up @@ -72,6 +72,19 @@ def __init__(self):
super().__init__()
self._intrinsic = IntrinsicCall.Intrinsic.ABS

def validate(self, node, options=None):
'''
Check that it is safe to apply the transformation to the supplied node.
:param node: the SIGN call to transform.
:type node: :py:class:`psyclone.psyir.nodes.IntrinsicCall`
:param options: any of options for the transformation.
:type options: dict[str, Any]
'''
super().validate(node, options=options)
super()._validate_scalar_arg(node)

def apply(self, node, options=None):
'''Apply the ABS intrinsic conversion transformation to the specified
node. This node must be an ABS UnaryOperation. The ABS
Expand Down Expand Up @@ -112,16 +125,12 @@ def apply(self, node, options=None):
symbol_table = node.scope.symbol_table
assignment = node.ancestor(Assignment)

# Create two temporary variables. There is an assumption here
# that the ABS Operator returns a PSyIR real type. This might
# not be what is wanted (e.g. the args might PSyIR integers),
# or there may be errors (arguments are of different types)
# but this can't be checked as we don't have the appropriate
# methods to query nodes (see #658).
# Create two temporary variables.
result_type = node.arguments[0].datatype
symbol_res_var = symbol_table.new_symbol(
"res_abs", symbol_type=DataSymbol, datatype=REAL_TYPE)
"res_abs", symbol_type=DataSymbol, datatype=result_type)
symbol_tmp_var = symbol_table.new_symbol(
"tmp_abs", symbol_type=DataSymbol, datatype=REAL_TYPE)
"tmp_abs", symbol_type=DataSymbol, datatype=result_type)

# Replace operation with a temporary (res_X).
node.replace_with(Reference(symbol_res_var))
Expand All @@ -134,7 +143,7 @@ def apply(self, node, options=None):

# if condition: tmp_var>0.0
lhs = Reference(symbol_tmp_var)
rhs = Literal("0.0", REAL_TYPE)
rhs = Literal("0", result_type)
if_condition = BinaryOperation.create(BinaryOperation.Operator.GT,
lhs, rhs)

Expand All @@ -146,7 +155,7 @@ def apply(self, node, options=None):
# else_body: res_var=-1.0*tmp_var
lhs = Reference(symbol_res_var)
lhs_child = Reference(symbol_tmp_var)
rhs_child = Literal("-1.0", REAL_TYPE)
rhs_child = Literal("-1", result_type)
rhs = BinaryOperation.create(BinaryOperation.Operator.MUL, lhs_child,
rhs_child)
else_body = [Assignment.create(lhs, rhs)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@
import abc
from psyclone.psyGen import Transformation
from psyclone.psyir.nodes import Assignment, IntrinsicCall
from psyclone.psyir.transformations.transformation_error import \
TransformationError
from psyclone.psyir.symbols import ArrayType, ScalarType
from psyclone.psyir.transformations.transformation_error import (
TransformationError)


class Intrinsic2CodeTrans(Transformation, metaclass=abc.ABCMeta):
Expand Down Expand Up @@ -95,3 +96,31 @@ def validate(self, node, options=None):
f"Error in {self.name} transformation. This transformation "
f"requires the operator to be part of an assignment "
f"statement, but no such assignment was found.")

def _validate_scalar_arg(self, node, options=None):
'''
Check that the argument to the intrinsic is a scalar of known type.
:param node: the target intrinsic call.
:type node: :py:class:`psyclone.psyir.nodes.IntrinsicCall`
:param options: any options for the transformation.
:type options: dict[str, Any]
:raises TransformationError: if the supplied SIGN call operates on
an argument of array type or unsupported/unresolved type.
'''
result_type = node.arguments[0].datatype
if isinstance(result_type, ArrayType):
raise TransformationError(
f"Transformation {self.name} cannot be applied to SIGN calls "
f"which have an array as argument but "
f"'{node.arguments[0].debug_string()}' is of array type. It "
f"may be possible to use the ArrayAssignment2LoopsTrans "
f"to convert this to a scalar argument.")
if not isinstance(result_type, ScalarType):
raise TransformationError(
f"Transformation {self.name} cannot be applied to "
f"'{node.debug_string()} because the type of the "
f"argument '{node.arguments[0].debug_string()}' is "
f"{result_type}")
33 changes: 22 additions & 11 deletions src/psyclone/psyir/transformations/intrinsics/sign2code_trans.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
from psyclone.psyir.transformations import Abs2CodeTrans
from psyclone.psyir.nodes import (
BinaryOperation, Assignment, Reference, Literal, IfBlock, IntrinsicCall)
from psyclone.psyir.symbols import DataSymbol, REAL_TYPE
from psyclone.psyir.symbols import DataSymbol


class Sign2CodeTrans(Intrinsic2CodeTrans):
Expand Down Expand Up @@ -74,6 +74,19 @@ def __init__(self):
super().__init__()
self._intrinsic = IntrinsicCall.Intrinsic.SIGN

def validate(self, node, options=None):
'''
Check that it is safe to apply the transformation to the supplied node.
:param node: the SIGN call to transform.
:type node: :py:class:`psyclone.psyir.nodes.IntrinsicCall`
:param options: any options for the transformation.
:type options: dict[str, Any]
'''
super().validate(node, options=options)
super()._validate_scalar_arg(node)

def apply(self, node, options=None):
'''Apply the SIGN intrinsic conversion transformation to the specified
node. This node must be a SIGN IntrinsicCall. The SIGN
Expand Down Expand Up @@ -121,16 +134,14 @@ def apply(self, node, options=None):
symbol_table = node.scope.symbol_table
assignment = node.ancestor(Assignment)

# Create two temporary variables. There is an assumption here
# that the SIGN IntrinsicCall returns a PSyIR real type. This might
# not be what is wanted (e.g. the args might PSyIR integers),
# or there may be errors (arguments are of different types)
# but this can't be checked as we don't have the appropriate
# methods to query nodes (see #658).
# Create two temporary variables. We need to get the type of the
# first argument to SIGN. validate() has checked that this is a
# known, scalar type.
result_type = node.arguments[0].datatype
res_var_symbol = symbol_table.new_symbol(
"res_sign", symbol_type=DataSymbol, datatype=REAL_TYPE)
"res_sign", symbol_type=DataSymbol, datatype=result_type)
tmp_var_symbol = symbol_table.new_symbol(
"tmp_sign", symbol_type=DataSymbol, datatype=REAL_TYPE)
"tmp_sign", symbol_type=DataSymbol, datatype=result_type)

# Replace operator with a temporary (res_var).
node.replace_with(Reference(res_var_symbol))
Expand All @@ -155,14 +166,14 @@ def apply(self, node, options=None):

# if_condition: tmp_var<0.0
lhs = Reference(tmp_var_symbol)
rhs = Literal("0.0", REAL_TYPE)
rhs = Literal("0", result_type)
if_condition = BinaryOperation.create(BinaryOperation.Operator.LT,
lhs, rhs)

# then_body: res_var=res_var*-1.0
lhs = Reference(res_var_symbol)
lhs_child = Reference(res_var_symbol)
rhs_child = Literal("-1.0", REAL_TYPE)
rhs_child = Literal("-1", result_type)
rhs = BinaryOperation.create(BinaryOperation.Operator.MUL,
lhs_child, rhs_child)
then_body = [Assignment.create(lhs, rhs)]
Expand Down
3 changes: 3 additions & 0 deletions src/psyclone/tests/psyir/backend/c_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ def test_cw_literal():
lit = Literal('1', INTEGER_TYPE)
assert cwriter(lit) == '1'

lit = Literal('1', REAL_TYPE)
assert cwriter(lit) == '1.0'

# Test that scientific notation is output correctly
lit = Literal("3e5", REAL_TYPE, None)
assert cwriter(lit) == '3e5'
Expand Down
9 changes: 9 additions & 0 deletions src/psyclone/tests/psyir/backend/fortran_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1393,6 +1393,7 @@ def test_fw_char_literal(fortran_writer):
result = fortran_writer(lit)
assert result == "'hello'"


# literal is already checked within previous tests


Expand Down Expand Up @@ -1687,6 +1688,10 @@ def test_fw_literal_node(fortran_writer):
result = fortran_writer(lit1)
assert result == '3.14'

lit1 = Literal('3', REAL_TYPE)
result = fortran_writer(lit1)
assert result == '3.0'

lit1 = Literal('3.14E0', REAL_TYPE)
result = fortran_writer(lit1)
assert result == '3.14e0'
Expand All @@ -1695,6 +1700,10 @@ def test_fw_literal_node(fortran_writer):
result = fortran_writer(lit1)
assert result == '3.14d0'

lit1 = Literal('3', REAL_DOUBLE_TYPE)
result = fortran_writer(lit1)
assert result == '3.0d0'

# Check that BOOLEANS use the FORTRAN formatting
lit1 = Literal('true', BOOLEAN_TYPE)
result = fortran_writer(lit1)
Expand Down
Loading

0 comments on commit fdb54f2

Please sign in to comment.