psyclone.psyir.transformations.inline_trans#

This module contains the InlineTrans transformation.

Classes#

  • InlineTrans: This transformation takes a Call (which may have a return value)

class psyclone.psyir.transformations.inline_trans.InlineTrans[source]#

This transformation takes a Call (which may have a return value) and replaces it with the body of the target routine. It is used as follows:

>>> from psyclone.psyir.backend.fortran import FortranWriter
>>> from psyclone.psyir.frontend.fortran import FortranReader
>>> from psyclone.psyir.nodes import Call, Routine
>>> from psyclone.psyir.transformations import InlineTrans
>>> code = """
... module test_mod
... contains
...   subroutine run_it()
...     integer :: i
...     real :: a(10)
...     do i=1,10
...       a(i) = 1.0
...       call sub(a(i))
...     end do
...   end subroutine run_it
...   subroutine sub(x)
...     real, intent(inout) :: x
...     x = 2.0*x
...   end subroutine sub
... end module test_mod"""
>>> psyir = FortranReader().psyir_from_source(code)
>>> call = psyir.walk(Call)[0]
>>> inline_trans = InlineTrans()
>>> inline_trans.apply(call)
>>> # Uncomment the following line to see a text view of the schedule
>>> # print(psyir.walk(Routine)[0].view())
>>> print(FortranWriter()(psyir.walk(Routine)[0]))
subroutine run_it()
  integer :: i
  real, dimension(10) :: a

  do i = 1, 10, 1
    a(i) = 1.0
    a(i) = 2.0 * a(i)
  enddo

end subroutine run_it

The target of the call must already be present in the same Container (module) as the call site. This may be achieved using KernelModuleInlineTrans.

Warning

Routines/calls with any of the following characteristics are not supported and will result in a TransformationError:

  • the routine contains an early Return statement;

  • the routine contains a variable with UnknownInterface;

  • the routine contains a variable with StaticInterface;

  • the routine contains an UnsupportedType variable with ArgumentInterface;

  • the shape of any array arguments as declared inside the routine does not match the shape of the arrays being passed as arguments;

  • the routine accesses an un-resolved symbol;

  • the routine accesses a symbol declared in the Container to which it belongs.

Some of these restrictions will be lifted by #924.

Inheritance

Inheritance diagram of InlineTrans
apply(node, routine=None, use_first_callee_and_no_arg_check=False, permit_codeblocks=False, permit_unsupported_type_args=False, **kwargs)[source]#

Takes the body of the routine that is the target of the supplied call and replaces the call with it.

Parameters:
  • node (Call) – the Call node to inline.

  • routine (Optional[Routine]) – Optional Routine to be inlined. (By default, PSyclone will search for a target routine with a matching signature).

  • use_first_callee_and_no_arg_check (bool) – if True, simply use the first potential callee routine. No argument type-checking is performed.

  • permit_codeblocks (bool) – If False (the default), raise an Exception if the target routine contains a CodeBlock.

  • permit_unsupported_type_args (bool) – If True then the target routine is permitted to have arguments of UnsupportedType.

Raises:

InternalError – if the merge of the symbol tables fails. In theory this should never happen because validate() should catch such a situation.

validate(node, **kwargs)[source]#

Checks that the supplied node is a valid target for inlining.

Parameters:
  • node (Call) – the target PSyIR Call to inline.

  • routine (psyclone.psyir.nodes.routine.Routine | None) – Optional Routine to be inlined. (By default, PSyclone will search for a target routine with a matching signature).

  • use_first_callee_and_no_arg_check (bool) – if True, simply use the first potential callee routine. No argument type-checking is performed.

  • permit_codeblocks (bool) – If False (the default), raise an Exception if the target routine contains a CodeBlock.

  • permit_unsupported_type_args (bool) – If True then the target routine is permitted to have arguments of UnsupportedType.

Raises:
  • TransformationError – if the supplied node is not a Call, is an IntrinsicCall or a call to a PSyclone-generated or ELEMENTAL routine.

  • TransformationError – if the routine body contains a Return that is not the first or last statement.

  • TransformationError – if the routine body contains a CodeBlock and permit_codeblocks is not True.

  • TransformationError – if the routine contains an ALLOCATE (as we don’t support adding the required DEALLOCATE).

  • TransformationError – if the called routine has a named argument.

  • TransformationError – if the call-site is not within a Routine.

  • TransformationError – if any of the variables declared within the called routine are of UnknownInterface.

  • TransformationError – if any of the variables declared within the called routine have a StaticInterface.

  • TransformationError – if any of the subroutine arguments is of UnsupportedType.

  • TransformationError – if a symbol of a given name is imported from different containers at the call site and within the routine.

  • TransformationError – if the routine accesses an un-resolved symbol.

  • TransformationError – if the number of arguments in the call does not match the number of formal arguments of the routine.

  • TransformationError – if a symbol declared in the parent container is accessed in the target routine.

  • TransformationError – if the shape of an array formal argument does not match that of the corresponding actual argument.

  • TransformationError – if one of the declaratoins in the routine depends on an argument that is written to prior to the call.

  • InternalError – if an unhandled Node type is returned by Reference.previous_accesses().

Return type:

None