Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(close #1987) Replace Intrinsic Operators with IntrinsicCalls #2298

Merged
merged 35 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
e49c710
#1987 The intrinsic Enum is now a namedtuple that contains attributes…
sergisiso Aug 8, 2023
41b4405
#1987 Clean up IntrinsicCall class
sergisiso Aug 8, 2023
6fe613b
#1987 Move existing Operator intrinsics to Intriniscs call and introd…
sergisiso Aug 9, 2023
e47ac26
#1987 Introduce all remaining intrinsics
sergisiso Aug 15, 2023
c179dc0
#1987 Update usage of intrinsic from Operation to IntrinsicCall
sergisiso Aug 17, 2023
af97f94
#1987 Continue updating IntrinsicCall uses
sergisiso Aug 22, 2023
1b57d37
#1987 Fix IntrinsicCall uses in OpenCL and C
sergisiso Aug 22, 2023
4a49def
#1987 Fix remaining IntrinsicCall uses
sergisiso Aug 22, 2023
a093e36
1987 Bring to master
sergisiso Aug 23, 2023
be3cdaa
#1987 Fix most IntrinsicCall use in examples and some more tests
sergisiso Aug 23, 2023
236bd37
#1987 Fix reamining IntrinsicCall uses
sergisiso Aug 30, 2023
03f4d8b
Merge remote-tracking branch 'origin/master' into 1987_operators_to_i…
sergisiso Aug 30, 2023
62f11a5
#1987 Select case produce module prodecure for generic interfaces
sergisiso Aug 30, 2023
d5cfdf9
#2298 Update Intrinsics documentation
sergisiso Aug 31, 2023
bf177f7
#2298 Fix test with module procedure keyword
sergisiso Aug 31, 2023
f754f8c
#2298 Re-introduce support in the C backend support for some of the P…
sergisiso Aug 31, 2023
c6da21a
#2298 Clean up IntrinsicCall PR code
sergisiso Aug 31, 2023
a9929e5
#2298 Clean up remaining IntrinsicCall PR code
sergisiso Sep 1, 2023
25a295d
Merge remote-tracking branch 'origin/master' into 1987_operators_to_i…
sergisiso Sep 1, 2023
f4b4c27
#2298 Fix IntrinsicCall issue with named positional arguments
sergisiso Sep 1, 2023
3c68c6d
#2298 DataSymbols initial_value now has a parent Assignment, and fix …
sergisiso Sep 1, 2023
95a2c08
Merge remote-tracking branch 'origin/master' into 1987_operators_to_i…
sergisiso Sep 1, 2023
b416472
#2298 Update NEMO scripts with new IntrinsicCall features
sergisiso Sep 1, 2023
7e86da3
#2298 Allow more intrinsics on GPUs
sergisiso Sep 1, 2023
d4b374a
#2298 Fix for LFRic Random_Number and missing coverage
sergisiso Sep 1, 2023
d3bac71
#2298 Fix Integration Test issues
sergisiso Sep 2, 2023
9506f46
#2298 Remove remaining 1987 TODOs
sergisiso Sep 2, 2023
a0f2904
#2298 Fix pylint issues, comments and tests
sergisiso Sep 13, 2023
c7c4326
#2298 Bring to master
sergisiso Sep 14, 2023
ea4b370
#2298 Bring to master
sergisiso Sep 14, 2023
3285a81
#2298 Add dangling parent to shape nodes and clean up PR
sergisiso Sep 15, 2023
6720800
#2298 Fix with processing NEMO obs_fbm
sergisiso Sep 18, 2023
3fabad8
#2298 Add test for missing code coverage
sergisiso Sep 18, 2023
a923ad2
#2298 Remove unneeded copy operation
sergisiso Sep 18, 2023
3a8afd3
#2298 update changelog and UG
arporter Sep 19, 2023
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
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
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
Loading