Skip to content

Commit

Permalink
Merge pull request #2298 from stfc/1987_operators_to_intrinsic_calls
Browse files Browse the repository at this point in the history
(close #1987) Replace Intrinsic Operators with IntrinsicCalls
  • Loading branch information
arporter authored Sep 19, 2023
2 parents b4ceb72 + 3a8afd3 commit eba697a
Show file tree
Hide file tree
Showing 112 changed files with 2,857 additions and 3,694 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/compilation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ jobs:
module load python/${PYTHON_VERSION}
. .runner_venv/bin/activate
module load gcc/${GFORTRAN_VERSION} openmpi netcdf_fortran
pytest -n 2 --f90=gfortran --compile --compileopencl src/psyclone/tests
pytest -n 2 --f90=gfortran --f90flags="-ffree-line-length-none" --compile --compileopencl src/psyclone/tests
module rm netcdf_fortran gcc
- name: Unit tests with compilation - nvfortran
run: |
Expand All @@ -108,7 +108,7 @@ jobs:
# Although we're using gfortran, we link with the OpenCL lib that comes
# with CUDA.
make -C examples allclean
F90=gfortran F90FLAGS="-L/apps/packages/compilers/nvidia-hpcsdk/Linux_x86_64/${NVFORTRAN_VERSION}/cuda/${CUDA_VERSION}/targets/x86_64-linux/lib" make -C examples compile
F90=gfortran F90FLAGS="-ffree-line-length-none -L/apps/packages/compilers/nvidia-hpcsdk/Linux_x86_64/${NVFORTRAN_VERSION}/cuda/${CUDA_VERSION}/targets/x86_64-linux/lib" make -C examples compile
- name: Tutorials with compilation - gfortran
run: |
module load python/${PYTHON_VERSION}
Expand Down
2 changes: 2 additions & 0 deletions changelog
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,8 @@

201) PR #2148 towards #2105. Adds {Min,Max}Val2Code transformations.

202) PR 2298 for #1987. Change all intrinsic Operations to IntrinsicCalls.

release 2.3.1 17th of June 2022

1) PR #1747 for #1720. Adds support for If blocks to PSyAD.
Expand Down
95 changes: 18 additions & 77 deletions doc/developer_guide/psyir.rst
Original file line number Diff line number Diff line change
Expand Up @@ -497,37 +497,22 @@ See the full Range API in the
Operation Nodes
---------------

Arithmetic operations and various intrinsic/query functions are represented
in the PSyIR by sub-classes of the `Operation` node. The operations are
classified according to the number of operands:
Arithmetic and logic operations are represented in the PSyIR by sub-classes
of the `Operation` node. The operations are classified according to the number
of operands:

- Those having one operand are represented by
`psyclone.psyir.nodes.UnaryOperation` nodes,

- those having two operands are represented by
`psyclone.psyir.nodes.BinaryOperation` nodes.

- and those having more than two or a variable number of operands are
represented by `psyclone.psyir.nodes.NaryOperation` nodes.

See the documentation for each Operation class in the
:ref_guide:`Operation psyclone.psyir.nodes.html#psyclone.psyir.nodes.Operation`,
:ref_guide:`UnaryOperation psyclone.psyir.nodes.html#psyclone.psyir.nodes.UnaryOperation`,
:ref_guide:`BinaryOperation psyclone.psyir.nodes.html#psyclone.psyir.nodes.BinaryOperation` and
:ref_guide:`NaryOperation psyclone.psyir.nodes.html#psyclone.psyir.nodes.NaryOperation`
:ref_guide:`UnaryOperation psyclone.psyir.nodes.html#psyclone.psyir.nodes.UnaryOperation` and
:ref_guide:`BinaryOperation psyclone.psyir.nodes.html#psyclone.psyir.nodes.BinaryOperation`
sections of the reference guide.

Note that where an intrinsic (such as
Fortran's `MAX`) can have a variable number of arguments, the class
used to represent it in the PSyIR is determined by the actual number
of arguments in a particular instance. e.g. `MAX(var1, var2)` would be
represented by a `psyclone.psyir.nodes.BinaryOperation` but `MAX(var1,
var2, var3)` would be represented by a
`psyclone.psyir.nodes.NaryOperation`.

The PSyIR supports the concept of named arguments for operation
nodes, see the :ref:`named_arguments-label` section for more details.

.. note:: Similar to Fortran, the PSyIR has two comparison operators, one for
booleans (EQV) and one for non-booleans (EQ). These are not
interchangeable because they have different precedence priorities and
Expand All @@ -544,57 +529,16 @@ IntrinsicCall Nodes
PSyIR `IntrinsicCall` nodes (see :ref_guide:`IntrinsicCall
psyclone.psyir.nodes.html#psyclone.psyir.nodes.IntrinsicCall`) capture
all PSyIR intrinsics that are not expressed as language symbols (`+`,`-`,`*`
etc). The latter are captured as `Operation` nodes. At the moment some
intrinsics that should be captured as `IntrinsicCall` nodes are
captured as `Operation` nodes (for example `sin` and `cos`). These
will be migrated to being captured as `IntrinsicCall` nodes in the
near future. Supported `IntrinsicCall` intrinsics are listed in the
`IntrinsicCall.Intrinsic` enumeration within the class:

+--------------+------------------------------+--------------------------------+
| Name | Positional arguments | Optional arguments |
+--------------+------------------------------+------+-------------------------+
| ALLOCATE | One or more Reference or | stat | Reference to an integer |
| | ArrayReferences to which | | variable which will hold|
| | memory will be allocated. | | return status. |
| | +------+-------------------------+
| | | mold | Reference to an array |
| | | | which is used to specify|
| | | | the dimensions of the |
| | | | allocated object. |
| | +------+-------------------------+
| | |source| Reference to an array |
| | | | which is used to specify|
| | | | both the dimensions & |
| | | | initial value(s) of the |
| | | | allocated object. |
| | +------+-------------------------+
| | |errmsg| Reference to a character|
| | | | variable which will |
| | | | contain an error message|
| | | | should the operation |
| | | | fail. |
+--------------+------------------------------+------+-------------------------+
| DEALLOCATE | One or more References. | stat | Reference which will |
| | | | hold return status. |
+--------------+------------------------------+------+-------------------------+
| RANDOM_NUMBER| A single Reference which will| |
| | be filled with pseudo-random | |
| | numbers in the range | |
| | [0.0, 1.0]. | |
+--------------+------------------------------+------+-------------------------+
| SUM, MAXVAL, | A single DataNode. | dim | A DataNode specifying |
| MINVAL | | | one of the supplied |
| | | | array's dimensions. |
| | +------+-------------------------+
| | | mask | A DataNode indicating |
| | | | on which elements to |
| | | | apply the function. |
+--------------+------------------------------+------+-------------------------+
| HUGE, TINY | A single Reference or | |
| | Literal. | |
+--------------+------------------------------+--------------------------------+
etc). The latter are captured as `Operation` nodes. At the moment the
available PSyIR `IntrinsicCall` match those of the `Fortran 2018 standard
<https://fortranwiki.org/fortran/show/Intrinsic+procedures>`_
In addition to Fortran Intrinsics, special Fortran statements such as:
`ALLOCATE`, `DEALLOCATE` and `NULLIFY` are also PSyIR IntrinsicCalls.


IntrinsicCalls, like Calls, have properties to inform if the call is to a
pure, elemental, inquiry (does not touch the first argument data) function
or is available on a GPU device.

CodeBlock Node
--------------
Expand Down Expand Up @@ -702,9 +646,7 @@ psyclone.psyir.nodes.html#psyclone.psyir.nodes.Directive`.
Named arguments
---------------

The `Call` node and the three subclasses of the `Operation` node
(`UnaryOperation`, `BinaryOperation` and `NaryOperation`) all support
named arguments.
The `Call` node (and its sub-classes) support named arguments.

The argument names are provided by the `argument_names` property. This
property returns a list of names. The first entry in the list refers
Expand Down Expand Up @@ -752,10 +694,9 @@ re-ordered; an argument that has replaced a named argument will not be
a named argument; an inserted argument will not be a named argument,
and the name of a deleted named argument will be removed.

Making a copy of the `Call` node or one of the three subclasses of
Operation nodes (`UnaryOperation`, `BinaryOperation` or
`NaryOperation`) also causes problems with consistency between the
internal `_argument_names` list and the arguments. The reason for this
Making a copy of the `Call` node also causes problems with consistency
between the internal `_argument_names` list and the arguments.
The reason for this
is that the arguments get copied and therefore have a different `id`,
whereas the `id`s in the internal `_argument_names` list are simply
copied. To solve this problem, the `copy()` method is specialised to
Expand Down
6 changes: 2 additions & 4 deletions doc/user_guide/psyir.rst
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ PSyIR nodes are: ``Loop``, ``WhileLoop``, ``IfBlock``, ``CodeBlock``,
subclassed into ``ArrayReference``, ``StructureReference`` and
``ArrayOfStructuresReference``, the ``Operation`` class is further
subclassed into ``UnaryOperation``, ``BinaryOperation`` and
``NaryOperation`` and the ``Container`` class is further subclassed
the ``Container`` class is further subclassed
into ``FileContainer`` (representing a file that may contain more than
one ``Container`` and/or ``Routine``. Those nodes representing
references to structures (derived types in Fortran) have a ``Member``
Expand Down Expand Up @@ -780,9 +780,7 @@ parent reference are not.
Named arguments
---------------

The `Call` and three sub-classes of `Operation` node
(`UnaryOperation`, `BinaryOperation` and `NaryOperation`) all support
named arguments.
The `Call` node (and its sub-classes) support named arguments.

Named arguments can be set or modified via the `create()`,
`append_named_arg()`, `insert_named_arg()` or `replace_named_arg()`
Expand Down
8 changes: 4 additions & 4 deletions doc/user_guide/transformations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ can be found in the API-specific sections).
:members: apply
:noindex:

.. warning:: This transformation assumes that the ABS Operator acts on
.. warning:: This transformation assumes that the ABS Intrinsic acts on
PSyIR Real scalar data and does not check that this is
not the case. Once issue #658 is on master then this
limitation can be fixed.
Expand Down Expand Up @@ -275,7 +275,7 @@ can be found in the API-specific sections).
:members: apply
:noindex:

.. warning:: This transformation assumes that the MAX Operator acts on
.. warning:: This transformation assumes that the MAX Intrinsic acts on
PSyIR Real scalar data and does not check that this is
not the case. Once issue #658 is on master then this
limitation can be fixed.
Expand All @@ -292,7 +292,7 @@ can be found in the API-specific sections).
:members: apply
:noindex:

.. warning:: This transformation assumes that the MIN Operator acts on
.. warning:: This transformation assumes that the MIN Intrinsic acts on
PSyIR Real scalar data and does not check that this is
not the case. Once issue #658 is on master then this
limitation can be fixed.
Expand Down Expand Up @@ -436,7 +436,7 @@ can be found in the API-specific sections).
:members: apply
:noindex:

.. warning:: This transformation assumes that the SIGN Operator acts
.. warning:: This transformation assumes that the SIGN Intrinsic acts
on PSyIR Real scalar data and does not check whether or not
this is the case. Once issue #658 is on master then this
limitation can be fixed.
Expand Down
15 changes: 7 additions & 8 deletions examples/lfric/eg15/matvec_opt.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -----------------------------------------------------------------------------
# BSD 3-Clause License
#
# Copyright (c) 2020-2022, Science and Technology Facilities Council
# Copyright (c) 2020-2023, Science and Technology Facilities Council
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -31,8 +31,8 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# -----------------------------------------------------------------------------
# Author R. W. Ford STFC Daresbury Lab.

# Author: R. W. Ford, STFC Daresbury Lab.
# Modified: S. Siso, STFC Daresbury Lab.

'''An example PSyclone transformation script to demonstrate
optimisations to the matrix vector kernel to improve its performance
Expand Down Expand Up @@ -68,9 +68,8 @@
-oalg /dev/null -opsy /dev/null
'''
from __future__ import print_function
import sys
from psyclone.psyir.nodes import BinaryOperation
from psyclone.psyir.nodes import IntrinsicCall
from psyclone.psyir.transformations import Matmul2CodeTrans
from psyclone.psyir.backend.fortran import FortranWriter

Expand All @@ -93,9 +92,9 @@ def trans(psy):
if kernel.name.lower() == "matrix_vector_kernel_code":
kernel_schedule = kernel.get_kernel_schedule()
# Replace matmul with inline code
for bin_op in kernel_schedule.walk(BinaryOperation):
if bin_op.operator is BinaryOperation.Operator.MATMUL:
matmul2code_trans.apply(bin_op)
for icall in kernel_schedule.walk(IntrinsicCall):
if icall.intrinsic is IntrinsicCall.Intrinsic.MATMUL:
matmul2code_trans.apply(icall)
# Future optimisations will go here.
print(kernel_schedule.view())
result = fortran_writer(kernel_schedule)
Expand Down
8 changes: 4 additions & 4 deletions examples/lfric/scripts/everything_everywhere_all_at_once.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
from psyclone.domain.lfric import LFRicConstants
from psyclone.dynamo0p3 import DynHaloExchange, DynHaloExchangeStart
from psyclone.psyir.transformations import Matmul2CodeTrans
from psyclone.psyir.nodes import BinaryOperation, Container, KernelSchedule
from psyclone.psyir.nodes import IntrinsicCall, Container, KernelSchedule
from psyclone.transformations import Dynamo0p3ColourTrans, \
Dynamo0p3OMPLoopTrans, \
OMPParallelTrans, \
Expand Down Expand Up @@ -133,10 +133,10 @@ def trans(psy):
for kschedule in root.walk(KernelSchedule):
if ENABLE_INTRINSIC_INLINING:
# Expand MATMUL intrinsic
for bop in kschedule.walk(BinaryOperation):
if bop.operator == BinaryOperation.Operator.MATMUL:
for icall in kschedule.walk(IntrinsicCall):
if icall.intrinsic == IntrinsicCall.Intrinsic.MATMUL:
try:
matmul_trans.apply(bop)
matmul_trans.apply(icall)
except TransformationError:
pass

Expand Down
8 changes: 4 additions & 4 deletions examples/lfric/scripts/inline_kernels_and_intrinsics.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
'''

from psyclone.domain.common.transformations import KernelModuleInlineTrans
from psyclone.psyir.nodes import BinaryOperation, Container, KernelSchedule
from psyclone.psyir.nodes import IntrinsicCall, Container, KernelSchedule
from psyclone.psyir.transformations import Matmul2CodeTrans
from psyclone.transformations import TransformationError

Expand Down Expand Up @@ -70,10 +70,10 @@ def trans(psy):
root = psy.invokes.invoke_list[0].schedule.ancestor(Container)
for kschedule in root.walk(KernelSchedule):
# Expand MATMUL intrinsic
for bop in kschedule.walk(BinaryOperation):
if bop.operator == BinaryOperation.Operator.MATMUL:
for icall in kschedule.walk(IntrinsicCall):
if icall.intrinsic == IntrinsicCall.Intrinsic.MATMUL:
try:
matmul_trans.apply(bop)
matmul_trans.apply(icall)
except TransformationError as err:
print(f"Inline MATMUL failed for '{kschedule.name}' "
"because:")
Expand Down
27 changes: 12 additions & 15 deletions examples/nemo/eg4/sir_trans_all.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -----------------------------------------------------------------------------
# BSD 3-Clause License
#
# Copyright (c) 2020-2021, Science and Technology Facilities Council
# Copyright (c) 2020-2023, Science and Technology Facilities Council
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -32,6 +32,7 @@
# POSSIBILITY OF SUCH DAMAGE.
# -----------------------------------------------------------------------------
# Author: R. W. Ford, STFC Daresbury Lab
# Modified: S. Siso, STFC Daresbury Lab

'''Module providing a transformation script that converts the supplied
PSyIR to the Stencil intermediate representation (SIR) and
Expand All @@ -48,12 +49,10 @@
the original code is translated.
'''
from __future__ import print_function
from psyclone.psyir.backend.sir import SIRWriter
from psyclone.psyir.backend.fortran import FortranWriter
from psyclone.nemo import NemoKern
from psyclone.psyir.nodes import (UnaryOperation, BinaryOperation,
NaryOperation, Operation, Assignment)
from psyclone.psyir.nodes import IntrinsicCall, Assignment
from psyclone.psyir.transformations import Abs2CodeTrans, Sign2CodeTrans, \
Min2CodeTrans, Max2CodeTrans, HoistTrans
from psyclone.domain.nemo.transformations import NemoAllArrayRange2LoopTrans, \
Expand Down Expand Up @@ -101,21 +100,19 @@ def trans(psy):
for kernel in schedule.walk(NemoKern):

kernel_schedule = kernel.get_kernel_schedule()
for oper in kernel_schedule.walk(Operation):
if oper.operator == UnaryOperation.Operator.ABS:
for icall in kernel_schedule.walk(IntrinsicCall):
if icall.intrinsic == IntrinsicCall.Intrinsic.ABS:
# Apply ABS transformation
abs_trans.apply(oper)
elif oper.operator == BinaryOperation.Operator.SIGN:
abs_trans.apply(icall)
elif icall.intrinsic == IntrinsicCall.Intrinsic.SIGN:
# Apply SIGN transformation
sign_trans.apply(oper)
elif oper.operator in [BinaryOperation.Operator.MIN,
NaryOperation.Operator.MIN]:
sign_trans.apply(icall)
elif icall.intrinsic == IntrinsicCall.Intrinsic.MIN:
# Apply (2-n arg) MIN transformation
min_trans.apply(oper)
elif oper.operator in [BinaryOperation.Operator.MAX,
NaryOperation.Operator.MAX]:
min_trans.apply(icall)
elif icall.intrinsic in IntrinsicCall.Intrinsic.MAX:
# Apply (2-n arg) MAX transformation
max_trans.apply(oper)
max_trans.apply(icall)

# Remove any loop invariant assignments inside k-loops to make
# them perfectly nested. At the moment this transformation
Expand Down
Loading

0 comments on commit eba697a

Please sign in to comment.