Reference Guide  2.5.0
psyclone.psyir.transformations.region_trans.RegionTrans Class Reference
Inheritance diagram for psyclone.psyir.transformations.region_trans.RegionTrans:
Collaboration diagram for psyclone.psyir.transformations.region_trans.RegionTrans:

Public Member Functions

def get_node_list (self, nodes)
 
def validate (self, nodes, options=None)
 
- Public Member Functions inherited from psyclone.psyGen.Transformation
def name (self)
 
def apply (self, node, options=None)
 

Static Public Attributes

tuple excluded_node_types = ()
 

Detailed Description

This abstract class is a base class for all transformations that act
on a list of nodes. It gives access to a validate function that
makes sure that the nodes in the list are in the same order as in
the original AST, no node is duplicated, and that all nodes have
the same parent. We also check that all nodes to be enclosed are
valid for this transformation - this requires that the sub-class
populate the `excluded_node_types` tuple.

Definition at line 50 of file region_trans.py.

Member Function Documentation

◆ get_node_list()

def psyclone.psyir.transformations.region_trans.RegionTrans.get_node_list (   self,
  nodes 
)
This is a helper function for region based transformations.
The parameter for any of those transformations is either a single
node, a schedule, or a list of nodes. This function converts this
into a list of nodes according to the parameter type. This function
will always return a copy, to avoid issues e.g. if a child list
of a node should be provided, and a transformation changes the order
in this list (which would then also change the order of the
nodes in the tree).

:param nodes: can be a single node, a schedule or a list of nodes.
:type nodes: Union[:py:obj:`psyclone.psyir.nodes.Node`,
                   :py:obj:`psyclone.psyir.nodes.Schedule`,
                   List[:py:obj:`psyclone.psyir.nodes.Node`]
:param options: a dictionary with options for transformations.
:type options: Optional[Dict[str,Any]]

:returns: a list of nodes.
:rtype: List[:py:class:`psyclone.psyir.nodes.Node`]

:raises TransformationError: if the supplied parameter is neither a \
    single Node, nor a Schedule, nor a list of Nodes.

Definition at line 68 of file region_trans.py.

68  def get_node_list(self, nodes):
69  '''This is a helper function for region based transformations.
70  The parameter for any of those transformations is either a single
71  node, a schedule, or a list of nodes. This function converts this
72  into a list of nodes according to the parameter type. This function
73  will always return a copy, to avoid issues e.g. if a child list
74  of a node should be provided, and a transformation changes the order
75  in this list (which would then also change the order of the
76  nodes in the tree).
77 
78  :param nodes: can be a single node, a schedule or a list of nodes.
79  :type nodes: Union[:py:obj:`psyclone.psyir.nodes.Node`,
80  :py:obj:`psyclone.psyir.nodes.Schedule`,
81  List[:py:obj:`psyclone.psyir.nodes.Node`]
82  :param options: a dictionary with options for transformations.
83  :type options: Optional[Dict[str,Any]]
84 
85  :returns: a list of nodes.
86  :rtype: List[:py:class:`psyclone.psyir.nodes.Node`]
87 
88  :raises TransformationError: if the supplied parameter is neither a \
89  single Node, nor a Schedule, nor a list of Nodes.
90 
91  '''
92  if isinstance(nodes, list) and \
93  all(isinstance(node, Node) for node in nodes):
94  # We still need to return a copy, since the user might have
95  # provided Node.children as parameter.
96  return nodes[:]
97  if isinstance(nodes, Schedule):
98  # We've been passed a Schedule so default to enclosing its
99  # children.
100  return nodes.children[:]
101  if isinstance(nodes, Node):
102  # Single node that's not a Schedule
103  return [nodes]
104 
105  arg_type = str(type(nodes))
106  raise TransformationError(f"Error in {self.name}: "
107  f"Argument must be a single Node in a "
108  f"Schedule, a Schedule or a list of Nodes "
109  f"in a Schedule but have been passed an "
110  f"object of type: {arg_type}")
111 
Here is the caller graph for this function:

◆ validate()

def psyclone.psyir.transformations.region_trans.RegionTrans.validate (   self,
  nodes,
  options = None 
)
Checks that the nodes in node_list are valid for a region
transformation.

:param nodes: can be a single node, a schedule or a list of nodes.
:type nodes: Union[:py:obj:`psyclone.psyir.nodes.Node`,
                   :py:obj:`psyclone.psyir.nodes.Schedule`,
                   List[:py:obj:`psyclone.psyir.nodes.Node`]
:param options: a dictionary with options for transformations.
:type options: Optional[Dict[str,Any]]
:param bool options["node-type-check"]: this flag controls if the \
        type of the nodes enclosed in the region should be tested \
        to avoid using unsupported nodes inside a region.

:raises TransformationError: if the nodes in the list are not \
        in the original order in which they are in the AST, \
        a node is duplicated or the nodes have different parents.
:raises TransformationError: if any of the nodes to be enclosed in \
        the region are of an unsupported type.
:raises TransformationError: if the parent of the supplied Nodes is \
        not a Schedule or a Directive.
:raises TransformationError: if the nodes are in a NEMO \
        Schedule and the transformation acts on the child of a \
        single-line If or Where statment.
:raises TransformationError: if the supplied options are not a \
        dictionary.

Reimplemented from psyclone.psyGen.Transformation.

Reimplemented in psyclone.psyir.transformations.psy_data_trans.PSyDataTrans, psyclone.transformations.ACCDataTrans, psyclone.transformations.ACCKernelsTrans, psyclone.transformations.ACCParallelTrans, psyclone.transformations.OMPParallelTrans, psyclone.transformations.ParallelRegionTrans, psyclone.psyir.transformations.read_only_verify_trans.ReadOnlyVerifyTrans, and psyclone.psyir.transformations.extract_trans.ExtractTrans.

Definition at line 112 of file region_trans.py.

112  def validate(self, nodes, options=None):
113  '''Checks that the nodes in node_list are valid for a region
114  transformation.
115 
116  :param nodes: can be a single node, a schedule or a list of nodes.
117  :type nodes: Union[:py:obj:`psyclone.psyir.nodes.Node`,
118  :py:obj:`psyclone.psyir.nodes.Schedule`,
119  List[:py:obj:`psyclone.psyir.nodes.Node`]
120  :param options: a dictionary with options for transformations.
121  :type options: Optional[Dict[str,Any]]
122  :param bool options["node-type-check"]: this flag controls if the \
123  type of the nodes enclosed in the region should be tested \
124  to avoid using unsupported nodes inside a region.
125 
126  :raises TransformationError: if the nodes in the list are not \
127  in the original order in which they are in the AST, \
128  a node is duplicated or the nodes have different parents.
129  :raises TransformationError: if any of the nodes to be enclosed in \
130  the region are of an unsupported type.
131  :raises TransformationError: if the parent of the supplied Nodes is \
132  not a Schedule or a Directive.
133  :raises TransformationError: if the nodes are in a NEMO \
134  Schedule and the transformation acts on the child of a \
135  single-line If or Where statment.
136  :raises TransformationError: if the supplied options are not a \
137  dictionary.
138 
139  '''
140  # pylint: disable=too-many-branches
141 
142  # Ensure we are always validating a list of nodes, even if only
143  # one was supplied via the `node_list` argument.
144  node_list = self.get_node_list(nodes)
145 
146  if not options:
147  options = {}
148  if not isinstance(options, dict):
149  raise TransformationError(
150  f"Transformation apply method options argument must be a "
151  f"dictionary but found '{type(options).__name__}'.")
152  node_parent = node_list[0].parent
153  prev_position = -1
154  for child in node_list:
155  if child.parent is not node_parent:
156  raise TransformationError(
157  f"Error in {self.name} transformation: supplied nodes "
158  f"are not children of the same parent.")
159  if prev_position >= 0 and prev_position+1 != child.position:
160  raise TransformationError(
161  f"Children are not consecutive children of one parent: "
162  f"child '{child}' has position {child.position}, but "
163  f"previous child had position {prev_position}.")
164  prev_position = child.position
165 
166  # Check that the proposed region contains only supported node types
167  if options.get("node-type-check", True):
168  for child in node_list:
169  # Stop at any instance of Kern to avoid going into the
170  # actual kernels, e.g. in Nemo inlined kernels
171  flat_list = [item for item in child.walk(object, Kern)
172  if not isinstance(item, Schedule)]
173  for item in flat_list:
174  if isinstance(item, self.excluded_node_types):
175  raise TransformationError(
176  f"Nodes of type '{type(item).__name__}' cannot be "
177  f"enclosed by a {self.name} transformation")
178 
179  # If we've been passed a list that contains one or more Schedules
180  # then something is wrong. e.g. two Schedules that are both children
181  # of an IfBlock would imply that the transformation is being applied
182  # around both the if-body and the else-body and that doesn't make
183  # sense.
184  if (len(node_list) > 1 and
185  any([isinstance(node, Schedule) for node in node_list])):
186  raise TransformationError(
187  "Cannot apply a transformation to multiple nodes when one "
188  "or more is a Schedule. Either target a single Schedule "
189  "or the children of a Schedule.")
190 
191  # Sanity check that we've not been passed the condition part of
192  # an If statement or the bounds of a Loop. If the parent node is
193  # a Loop or IfBlock then we can only accept a single Schedule.
194  if not isinstance(node_parent, Schedule) and \
195  not isinstance(node_list[0], Schedule):
196  # We've already checked for lists with len > 1 that contain a
197  # Schedule above so if the first item is a Schedule then that's
198  # all the list contains.
199  raise TransformationError(
200  "Cannot apply transformation to the immediate children of a "
201  "Loop/IfBlock unless it is to a single Schedule representing"
202  " the Loop/If/Else body.")

References psyclone.psyir.transformations.extract_trans.ExtractTrans.excluded_node_types, psyclone.psyir.transformations.loop_swap_trans.LoopSwapTrans.excluded_node_types, psyclone.psyir.transformations.loop_trans.LoopTrans.excluded_node_types, psyclone.psyir.transformations.omp_target_trans.OMPTargetTrans.excluded_node_types, psyclone.psyir.transformations.parallel_loop_trans.ParallelLoopTrans.excluded_node_types, psyclone.psyir.transformations.profile_trans.ProfileTrans.excluded_node_types, psyclone.psyir.transformations.psy_data_trans.PSyDataTrans.excluded_node_types, psyclone.psyir.transformations.region_trans.RegionTrans.excluded_node_types, psyclone.transformations.ACCLoopTrans.excluded_node_types, psyclone.transformations.ParallelRegionTrans.excluded_node_types, psyclone.transformations.OMPSingleTrans.excluded_node_types, psyclone.transformations.OMPMasterTrans.excluded_node_types, psyclone.transformations.OMPParallelTrans.excluded_node_types, psyclone.transformations.ACCParallelTrans.excluded_node_types, psyclone.transformations.ACCKernelsTrans.excluded_node_types, psyclone.transformations.ACCDataTrans.excluded_node_types, and psyclone.psyir.transformations.region_trans.RegionTrans.get_node_list().

Here is the call graph for this function:
Here is the caller graph for this function:

The documentation for this class was generated from the following file: