Reference Guide  2.5.0
psyclone.core.variables_access_info.VariablesAccessInfo Class Reference
Inheritance diagram for psyclone.core.variables_access_info.VariablesAccessInfo:
Collaboration diagram for psyclone.core.variables_access_info.VariablesAccessInfo:

Public Member Functions

def __init__ (self, nodes=None, options=None)
 
def __str__ (self)
 
def options (self, key=None)
 
def location (self)
 
def next_location (self)
 
def add_access (self, signature, access_type, node, component_indices=None)
 
def all_signatures (self)
 
def merge (self, other_access_info)
 
def is_written (self, signature)
 
def is_read (self, signature)
 
def has_read_write (self, signature)
 

Detailed Description

This class stores all `SingleVariableAccessInfo` instances for all
variables in the corresponding code section. It maintains 'location'
information, which is an integer number that is increased for each new
statement. It can be used to easily determine if one access is before
another.

:param nodes: optional, a single PSyIR node or list of nodes from
    which to initialise this object.
:type nodes: Optional[:py:class:`psyclone.psyir.nodes.Node` |
    List[:py:class:`psyclone.psyir.nodes.Node`]]
:param options: a dictionary with options to influence which variable
    accesses are to be collected.
:type options: Dict[str, Any]
:param Any options["COLLECT-ARRAY-SHAPE-READS"]: if this option is set
    to a True value, arrays used as first parameter to the PSyIR query
    operators lbound, ubound, or size will be reported as 'read'.
    Otherwise, these accesses will be ignored.
:param Any options["USE-ORIGINAL-NAMES"]: if this option is set to a
    True value, an imported symbol that is renamed (``use mod, a=>b``)
    will be reported using the original name (``b`` in the example).
    Otherwise these symbols will be reported using the renamed name
    (``a``).

:raises InternalError: if the optional options parameter is not a
    dictionary.
:raises InternalError: if the nodes parameter either is a list and
    contains an element that is not a
    :py:class:`psyclone.psyir.nodes.Node`, of if nodes is not a list and
    is not of type :py:class:`psyclone.psyir.nodes.Node`

Definition at line 49 of file variables_access_info.py.

Member Function Documentation

◆ __str__()

def psyclone.core.variables_access_info.VariablesAccessInfo.__str__ (   self)
Gives a shortened visual representation of all variables
and their access mode. The output is one of: READ, WRITE, READ+WRITE,
or READWRITE for each variable accessed.
READ+WRITE is used if the statement (or set of statements)
contain individual read and write accesses, e.g. 'a=a+1'. In this
case two accesses to `a` will be recorded, but the summary displayed
using this function will be 'READ+WRITE'. Same applies if this object
stores variable access information about more than one statement, e.g.
'a=b; b=1'. There would be two different accesses to 'b' with two
different locations, but the string representation would show this as
READ+WRITE. If a variable is is passed to a kernel for which no
individual variable information is available, and the metadata for
this kernel indicates a READWRITE access, this is marked as READWRITE
in the string output.

Definition at line 132 of file variables_access_info.py.

132  def __str__(self):
133  '''Gives a shortened visual representation of all variables
134  and their access mode. The output is one of: READ, WRITE, READ+WRITE,
135  or READWRITE for each variable accessed.
136  READ+WRITE is used if the statement (or set of statements)
137  contain individual read and write accesses, e.g. 'a=a+1'. In this
138  case two accesses to `a` will be recorded, but the summary displayed
139  using this function will be 'READ+WRITE'. Same applies if this object
140  stores variable access information about more than one statement, e.g.
141  'a=b; b=1'. There would be two different accesses to 'b' with two
142  different locations, but the string representation would show this as
143  READ+WRITE. If a variable is is passed to a kernel for which no
144  individual variable information is available, and the metadata for
145  this kernel indicates a READWRITE access, this is marked as READWRITE
146  in the string output.'''
147 
148  all_signatures = self.all_signatures
149  output_list = []
150  for signature in all_signatures:
151  mode = ""
152  if self.has_read_write(signature):
153  mode = "READWRITE"
154  else:
155  if self.is_read(signature):
156  if self.is_written(signature):
157  mode = "READ+WRITE"
158  else:
159  mode = "READ"
160  elif self.is_written(signature):
161  mode = "WRITE"
162  output_list.append(f"{signature}: {mode}")
163  return ", ".join(output_list)
164 

References psyclone.core.variables_access_info.VariablesAccessInfo.all_signatures(), psyclone.core.single_variable_access_info.SingleVariableAccessInfo.has_read_write(), psyclone.core.variables_access_info.VariablesAccessInfo.has_read_write(), psyclone.core.single_variable_access_info.SingleVariableAccessInfo.is_read(), psyclone.core.variables_access_info.VariablesAccessInfo.is_read(), psyclone.psyir.tools.read_write_info.ReadWriteInfo.is_read(), psyclone.core.single_variable_access_info.SingleVariableAccessInfo.is_written(), and psyclone.core.variables_access_info.VariablesAccessInfo.is_written().

Here is the call graph for this function:

◆ add_access()

def psyclone.core.variables_access_info.VariablesAccessInfo.add_access (   self,
  signature,
  access_type,
  node,
  component_indices = None 
)
Adds access information for the variable with the given signature.
If the `component_indices` parameter is not an instance of
`ComponentIndices`, it is used to construct an instance. Therefore it
can be None, a list or a list of lists of PSyIR nodes. In the case of
a list of lists, this will be used unmodified to construct the
ComponentIndices structures. If it is a simple list, it is assumed
that it contains the indices used in accessing the last component
of the signature. For example, for `a%b` with
`component_indices=[i,j]`, it will create `[[], [i,j]` as component
indices, indicating that no index is used in the first component `a`.
If the access is supposed to be for `a(i)%b(j)`, then the
`component_indices` argument must be specified as a list of lists,
i.e. `[[i], [j]]`.

:param signature: the signature of the variable.
:type signature: :py:class:`psyclone.core.Signature`
:param access_type: the type of access (READ, WRITE, ...)
:type access_type: :py:class:`psyclone.core.access_type.AccessType`
:param node: Node in PSyIR in which the access happens.
:type node: :py:class:`psyclone.psyir.nodes.Node` instance
:param component_indices: index information for the access.
:type component_indices: \
    :py:class:`psyclone.core.component_indices.ComponentIndices`, or \
    any other type that can be used to construct a ComponentIndices \
    instance (None, List[:py:class:`psyclone.psyir.nodes.Node`] \
     or List[List[:py:class:`psyclone.psyir.nodes.Node`]])

Definition at line 206 of file variables_access_info.py.

206  def add_access(self, signature, access_type, node, component_indices=None):
207  '''Adds access information for the variable with the given signature.
208  If the `component_indices` parameter is not an instance of
209  `ComponentIndices`, it is used to construct an instance. Therefore it
210  can be None, a list or a list of lists of PSyIR nodes. In the case of
211  a list of lists, this will be used unmodified to construct the
212  ComponentIndices structures. If it is a simple list, it is assumed
213  that it contains the indices used in accessing the last component
214  of the signature. For example, for `a%b` with
215  `component_indices=[i,j]`, it will create `[[], [i,j]` as component
216  indices, indicating that no index is used in the first component `a`.
217  If the access is supposed to be for `a(i)%b(j)`, then the
218  `component_indices` argument must be specified as a list of lists,
219  i.e. `[[i], [j]]`.
220 
221  :param signature: the signature of the variable.
222  :type signature: :py:class:`psyclone.core.Signature`
223  :param access_type: the type of access (READ, WRITE, ...)
224  :type access_type: :py:class:`psyclone.core.access_type.AccessType`
225  :param node: Node in PSyIR in which the access happens.
226  :type node: :py:class:`psyclone.psyir.nodes.Node` instance
227  :param component_indices: index information for the access.
228  :type component_indices: \
229  :py:class:`psyclone.core.component_indices.ComponentIndices`, or \
230  any other type that can be used to construct a ComponentIndices \
231  instance (None, List[:py:class:`psyclone.psyir.nodes.Node`] \
232  or List[List[:py:class:`psyclone.psyir.nodes.Node`]])
233 
234  '''
235  if not isinstance(signature, Signature):
236  raise InternalError(f"Got '{signature}' of type "
237  f"'{type(signature).__name__}' but expected "
238  f"it to be of type psyclone.core.Signature.")
239 
240  # To make it easier for the user, we allow to implicitly create the
241  # component indices instance here:
242  if not isinstance(component_indices, ComponentIndices):
243  # Handle some convenient cases:
244  # 1. Add the right number of [] if component_indices is None:
245  if component_indices is None:
246  component_indices = [[]] * len(signature)
247  elif isinstance(component_indices, list):
248  # 2. If the argument is a simple list (not a list of lists),
249  # assume that the indices are for the last component, and
250  # add enough [] to give the right number of entries in the
251  # list that is used to create the ComponentIndices instance:
252  is_list_of_lists = all(isinstance(indx, list)
253  for indx in component_indices)
254  if not is_list_of_lists:
255  component_indices = [[]] * (len(signature)-1) \
256  + [component_indices]
257 
258  component_indices = ComponentIndices(component_indices)
259 
260  if len(signature) != len(component_indices):
261  raise InternalError(f"Cannot add '{component_indices}' with "
262  f"length {len(component_indices)} as "
263  f"indices for '{signature}' which "
264  f"requires {len(signature)} elements.")
265 
266  if signature in self:
267  self[signature].add_access_with_location(access_type,
268  self._location, node,
269  component_indices)
270  else:
271  var_info = SingleVariableAccessInfo(signature)
272  var_info.add_access_with_location(access_type, self._location,
273  node, component_indices)
274  self[signature] = var_info
275 

References psyclone.core.single_variable_access_info.AccessInfo._location, and psyclone.core.variables_access_info.VariablesAccessInfo._location.

◆ all_signatures()

def psyclone.core.variables_access_info.VariablesAccessInfo.all_signatures (   self)
:returns: all signatures contained in this instance, sorted (in \
             order to make test results reproducible).
:rtype: List[:py:class:`psyclone.core.signature`]

Definition at line 277 of file variables_access_info.py.

277  def all_signatures(self):
278  ''':returns: all signatures contained in this instance, sorted (in \
279  order to make test results reproducible).
280  :rtype: List[:py:class:`psyclone.core.signature`]
281  '''
282  list_of_vars = list(self.keys())
283  list_of_vars.sort()
284  return list_of_vars
285 
Here is the caller graph for this function:

◆ has_read_write()

def psyclone.core.variables_access_info.VariablesAccessInfo.has_read_write (   self,
  signature 
)
Checks if the specified variable signature has at least one
READWRITE access (which is typically only used in a function call).

:param signature: signature of the variable
:type signature: :py:class:`psyclone.core.Signature`

:returns: True if the specified variable name has (at least one) \
    READWRITE access.
:rtype: bool

:raises: KeyError if the signature cannot be found.

Definition at line 354 of file variables_access_info.py.

354  def has_read_write(self, signature):
355  '''Checks if the specified variable signature has at least one
356  READWRITE access (which is typically only used in a function call).
357 
358  :param signature: signature of the variable
359  :type signature: :py:class:`psyclone.core.Signature`
360 
361  :returns: True if the specified variable name has (at least one) \
362  READWRITE access.
363  :rtype: bool
364 
365  :raises: KeyError if the signature cannot be found.'''
366 
367  var_access_info = self[signature]
368  return var_access_info.has_read_write()
369 
370 
371 # ---------- Documentation utils -------------------------------------------- #
372 # The list of module members that we wish AutoAPI to generate
373 # documentation for. (See https://psyclone-ref.readthedocs.io)
Here is the caller graph for this function:

◆ is_read()

def psyclone.core.variables_access_info.VariablesAccessInfo.is_read (   self,
  signature 
)
Checks if the specified variable signature is at least read once.

:param signature: signature of the variable
:type signature: :py:class:`psyclone.core.Signature`

:returns: True if the specified variable name is read (at least \
    once).
:rtype: bool

:raises: KeyError if the signature cannot be found.

Definition at line 339 of file variables_access_info.py.

339  def is_read(self, signature):
340  '''Checks if the specified variable signature is at least read once.
341 
342  :param signature: signature of the variable
343  :type signature: :py:class:`psyclone.core.Signature`
344 
345  :returns: True if the specified variable name is read (at least \
346  once).
347  :rtype: bool
348 
349  :raises: KeyError if the signature cannot be found.'''
350 
351  var_access_info = self[signature]
352  return var_access_info.is_read()
353 
Here is the caller graph for this function:

◆ is_written()

def psyclone.core.variables_access_info.VariablesAccessInfo.is_written (   self,
  signature 
)
Checks if the specified variable signature is at least
written once.

:param signature: signature of the variable.
:type signature: :py:class:`psyclone.core.Signature`

:returns: True if the specified variable is written (at least \
    once).
:rtype: bool

:raises: KeyError if the signature name cannot be found.

Definition at line 322 of file variables_access_info.py.

322  def is_written(self, signature):
323  '''Checks if the specified variable signature is at least
324  written once.
325 
326  :param signature: signature of the variable.
327  :type signature: :py:class:`psyclone.core.Signature`
328 
329  :returns: True if the specified variable is written (at least \
330  once).
331  :rtype: bool
332 
333  :raises: KeyError if the signature name cannot be found.
334 
335  '''
336  var_access_info = self[signature]
337  return var_access_info.is_written()
338 
Here is the caller graph for this function:

◆ location()

def psyclone.core.variables_access_info.VariablesAccessInfo.location (   self)
Returns the current location of this instance, which is
the location at which the next accesses will be stored.
See the Developers' Guide for more information.

:returns: the current location of this object.
:rtype: int

Definition at line 193 of file variables_access_info.py.

193  def location(self):
194  '''Returns the current location of this instance, which is
195  the location at which the next accesses will be stored.
196  See the Developers' Guide for more information.
197 
198  :returns: the current location of this object.
199  :rtype: int'''
200  return self._location
201 

References psyclone.core.single_variable_access_info.AccessInfo._location, and psyclone.core.variables_access_info.VariablesAccessInfo._location.

◆ merge()

def psyclone.core.variables_access_info.VariablesAccessInfo.merge (   self,
  other_access_info 
)
Merges data from a VariablesAccessInfo instance to the
information in this instance.

:param other_access_info: the other VariablesAccessInfo instance.
:type other_access_info: \
    :py:class:`psyclone.core.VariablesAccessInfo`

Definition at line 286 of file variables_access_info.py.

286  def merge(self, other_access_info):
287  '''Merges data from a VariablesAccessInfo instance to the
288  information in this instance.
289 
290  :param other_access_info: the other VariablesAccessInfo instance.
291  :type other_access_info: \
292  :py:class:`psyclone.core.VariablesAccessInfo`
293  '''
294 
295  # For each variable add all accesses. After merging the new data,
296  # we need to increase the location so that all further added data
297  # will have a location number that is larger.
298  max_new_location = 0
299  for signature in other_access_info.all_signatures:
300  var_info = other_access_info[signature]
301  for access_info in var_info.all_accesses:
302  # Keep track of how much we need to update the next location
303  # in this object:
304  if access_info.location > max_new_location:
305  max_new_location = access_info.location
306  new_location = access_info.location + self._location
307  if signature in self:
308  var_info = self[signature]
309  else:
310  var_info = SingleVariableAccessInfo(signature)
311  self[signature] = var_info
312 
313  var_info.add_access_with_location(access_info.access_type,
314  new_location,
315  access_info.node,
316  access_info.
317  component_indices)
318  # Increase the current location of this instance by the amount of
319  # locations just merged in
320  self._location = self._location + max_new_location
321 

References psyclone.core.single_variable_access_info.AccessInfo._location, and psyclone.core.variables_access_info.VariablesAccessInfo._location.

◆ next_location()

def psyclone.core.variables_access_info.VariablesAccessInfo.next_location (   self)
Increases the location number.

Definition at line 202 of file variables_access_info.py.

202  def next_location(self):
203  '''Increases the location number.'''
204  self._location = self._location + 1
205 

References psyclone.core.single_variable_access_info.AccessInfo._location, and psyclone.core.variables_access_info.VariablesAccessInfo._location.

◆ options()

def psyclone.core.variables_access_info.VariablesAccessInfo.options (   self,
  key = None 
)
Returns the value of the options for a specified key,
or None if the key is not specified in the options. If no
key is specified, the whole option dictionary is returned.

:param key: the option to query, or None if all options should
            be returned.
:type key: Optional[str]

:returns: the value of the option associated with the provided key
          or the whole option dictionary if it is not supplied.
:rtype: Union[None, Any, dict]

:raises InternalError: if an invalid key is specified.

Definition at line 165 of file variables_access_info.py.

165  def options(self, key=None):
166  '''Returns the value of the options for a specified key,
167  or None if the key is not specified in the options. If no
168  key is specified, the whole option dictionary is returned.
169 
170  :param key: the option to query, or None if all options should
171  be returned.
172  :type key: Optional[str]
173 
174  :returns: the value of the option associated with the provided key
175  or the whole option dictionary if it is not supplied.
176  :rtype: Union[None, Any, dict]
177 
178  :raises InternalError: if an invalid key is specified.
179 
180  '''
181  if key:
182  if key not in VariablesAccessInfo._DEFAULT_OPTIONS:
183  valids = list(VariablesAccessInfo._DEFAULT_OPTIONS.keys())
184  # This makes sure the message always contains the valid
185  # keys in the same order, important for testing.
186  valids.sort()
187  raise InternalError(f"Option key '{key}' is invalid, it "
188  f"must be one of {valids}.")
189  return self._options.get(key, None)
190  return self._options
191 

References psyclone.core.variables_access_info.VariablesAccessInfo._options, psyclone.profiler.Profiler._options, and psyclone.psyir.nodes.psy_data_node.PSyDataNode._options.

Here is the caller graph for this function:

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