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

Added FindSingleUseData Pass #1906

Merged
merged 6 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
73 changes: 73 additions & 0 deletions dace/transformation/passes/analysis/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,79 @@ def apply_pass(self, top_sdfg: SDFG, _) -> Dict[int, Dict[str, Set[SDFGState]]]:
return top_result


@properties.make_properties
@transformation.explicit_cf_compatible
class FindSingleUseData(ppl.Pass):
"""
For each SDFG find all data descriptors that are referenced in exactly one location.

In addition to the requirement that there exists exactly one AccessNode that
refers to a data descriptor the following conditions have to be meet as well:
- The data is not read on an interstate edge.
- The data is not accessed in the branch condition, loop condition, etc. of
control flow regions.
- There must be at least one AccessNode that refers to the data. I.e. if it exists
inside `SDFG.arrays` but there is no AccessNode, then it is _not_ included.

It is also important to note that the degree of the AccessNodes are ignored.
"""

CATEGORY: str = 'Analysis'

def modifies(self) -> ppl.Modifies:
return ppl.Modifies.Nothing

def should_reapply(self, modified: ppl.Modifies) -> bool:
# If anything was modified, reapply
return modified & ppl.Modifies.AccessNodes & ppl.Modifies.CFG

def apply_pass(self, sdfg: SDFG, _) -> Dict[SDFG, Set[str]]:
"""
:return: A dictionary mapping SDFGs to a `set` of strings containing the name
of the data descriptors that are only used once.
"""
# TODO(pschaad): Should we index on cfg or the SDFG itself.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For something related to data containers and the question of 'can I remove this' I think it makes sense to index on the SDFG level

exclusive_data: Dict[SDFG, Set[str]] = {}
for nsdfg in sdfg.all_sdfgs_recursive():
exclusive_data[nsdfg] = self._find_single_use_data_in_sdfg(nsdfg)
return exclusive_data

def _find_single_use_data_in_sdfg(self, sdfg: SDFG) -> Set[str]:
"""Scans an SDFG and computes the data that is only used once in the SDFG.

The rules used to classify data descriptors are outlined above. The function
will not scan nested SDFGs.

:return: The set of data descriptors that are used once in the SDFG.
"""
# If we encounter a data descriptor for the first time we immediately
# classify it as single use. We will undo this decision as soon as
# learn that it is used somewhere else.
single_use_data: Set[str] = set()
previously_seen: Set[str] = set()

for state in sdfg.states():
for dnode in state.data_nodes():
data_name: str = dnode.data
if data_name in single_use_data:
single_use_data.discard(data_name) # Classified too early -> Undo
elif data_name not in previously_seen:
single_use_data.add(data_name) # Never seen -> Assume single use
previously_seen.add(data_name)

# By definition, data that is referenced by interstate edges is not single
# use data, also remove it.
for edge in sdfg.all_interstate_edges():
single_use_data.difference_update(edge.data.free_symbols)

# By definition, data that is referenced by the conditions (branching condition,
# loop condition, ...) is not single use data, also remove that.
for cfr in sdfg.all_control_flow_regions():
single_use_data.difference_update(cfr.used_symbols(all_symbols=True, with_contents=False))

return single_use_data


@properties.make_properties
@transformation.explicit_cf_compatible
class FindAccessNodes(ppl.Pass):
Expand Down
Loading
Loading