Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
b5df016
Initial test
ThrudPrimrose Sep 22, 2025
eb2b0ae
improvements.py
ThrudPrimrose Sep 22, 2025
075b0e2
More passes
ThrudPrimrose Sep 22, 2025
530b01b
Some test
ThrudPrimrose Sep 22, 2025
5b61cc0
Fix test case
ThrudPrimrose Sep 22, 2025
d871904
Fix test
ThrudPrimrose Sep 22, 2025
da176db
Append global code
ThrudPrimrose Sep 22, 2025
0881a9d
Generate unique names, fix gpu preset
ThrudPrimrose Sep 22, 2025
3daee89
Improve information
ThrudPrimrose Sep 22, 2025
a857ff6
refactor
ThrudPrimrose Sep 22, 2025
3044e0f
Add new test case
ThrudPrimrose Sep 24, 2025
f6e5640
Fix typecast and nested SDFG issues
ThrudPrimrose Sep 24, 2025
bb0eff8
Fix bugs add tests
ThrudPrimrose Sep 24, 2025
2351c9d
Add test for the pass version.
ThrudPrimrose Sep 24, 2025
73e26ea
Bugfix
ThrudPrimrose Sep 24, 2025
6781033
Fix
ThrudPrimrose Sep 24, 2025
b83dda8
Fixes
ThrudPrimrose Sep 24, 2025
ebd6a98
Stuff
ThrudPrimrose Sep 24, 2025
0356117
Merge branch 'split-tasklet-pass-fix' into explicit-vectorization
ThrudPrimrose Sep 24, 2025
6126056
Fix pipelines
ThrudPrimrose Sep 24, 2025
6af5244
refactor
ThrudPrimrose Sep 24, 2025
0b46bc6
Extend
ThrudPrimrose Sep 24, 2025
2fcbfd3
Stuff
ThrudPrimrose Sep 25, 2025
d9efd84
Dealias
ThrudPrimrose Sep 25, 2025
975e2ae
Add connector dealiasing
ThrudPrimrose Sep 25, 2025
efecc9c
Fix for duplicate names
ThrudPrimrose Sep 25, 2025
81e3f53
Force connectors
ThrudPrimrose Sep 25, 2025
67b3fed
Some fixes for duplicate full range views
ThrudPrimrose Sep 25, 2025
8058078
Even more fixes
ThrudPrimrose Sep 25, 2025
105ca91
Wcr + propagation changes behaviour with the new naems
ThrudPrimrose Sep 25, 2025
fb19803
fix test - dealias changes memlet order
ThrudPrimrose Sep 25, 2025
6935fe6
run code cleaner
ThrudPrimrose Sep 25, 2025
3053126
Do not reinsert edges just change connectors
ThrudPrimrose Sep 25, 2025
3ca9759
Do not change test
ThrudPrimrose Sep 25, 2025
628e2a7
Fixes
ThrudPrimrose Sep 25, 2025
91a5907
Minor fixes
ThrudPrimrose Sep 25, 2025
c11aee4
Utils and fixes
ThrudPrimrose Sep 29, 2025
a8862e4
Some refactor
ThrudPrimrose Sep 29, 2025
9dff346
Fixes and stuff
ThrudPrimrose Oct 1, 2025
c16ec90
Updatess
ThrudPrimrose Oct 2, 2025
d79519f
Fix bugs save the princess
ThrudPrimrose Oct 4, 2025
82721b0
Something
ThrudPrimrose Oct 5, 2025
0f2d086
Add SDFG construction utilities
ThrudPrimrose Oct 7, 2025
fccc4f2
Add test case
ThrudPrimrose Oct 7, 2025
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
2 changes: 1 addition & 1 deletion dace/config_schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ required:
type: str
title: Arguments
description: Compiler argument flags
default: '-std=c++14 -fPIC -Wall -Wextra -O3 -march=native -ffast-math -Wno-unused-parameter -Wno-unused-label'
default: '-fopenmp -std=c++14 -fPIC -Wall -Wextra -O0 -g -march=native -ffast-math -Wno-unused-parameter -Wno-unused-label'
default_Windows: '/O2 /fp:fast /arch:AVX2 /D_USRDLL /D_WINDLL /D__restrict__=__restrict'

libs:
Expand Down
3 changes: 3 additions & 0 deletions dace/frontend/python/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from dace.frontend.python import (newast, common as pycommon, cached_program, preprocessing)
from dace.sdfg import SDFG, utils as sdutils
from dace.data import create_datadescriptor, Data
from dace.sdfg.dealias import dealias

try:
from typing import get_origin, get_args
Expand Down Expand Up @@ -286,6 +287,8 @@ def to_sdfg(self, *args, simplify=None, save=False, validate=False, use_cache=Fa
# Add to cache
self._cache.add(cachekey, sdfg, None)

dealias(sdfg)

return sdfg

def __sdfg__(self, *args, **kwargs) -> SDFG:
Expand Down
149 changes: 149 additions & 0 deletions dace/sdfg/dealias.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# Copyright 2019-2025 ETH Zurich and the DaCe authors. All rights reserved.
import dace
import copy
from typing import Set, Dict

from dace.sdfg.graph import MultiConnectorEdge
from dace import SDFGState

FULL_VIEW_SUFFIX = "fullview"
SLICE_SUFFIX = "slice"


def _get_new_connector_name(edge: MultiConnectorEdge, repldict: Dict[str, str], other_repldict: Dict[str, str],
state: SDFGState, sdfg: dace.SDFG) -> str:
"""
Determine new connector name for an edge based on data access patterns.
Following the description in the dealias routine

Args:
edge: The edge containing data access information
repldict: Dictionary of existing replacements to avoid name conflicts
state: The SDFG state containing the edge

Returns:
str: New connector name - either the original array name (for full access)
or a unique slice name (for partial access)
"""
arr = state.sdfg.arrays[edge.data.data]
data_shape = arr.shape

# Full subset?
full_range = dace.subsets.Range([(0, dim - 1, 1) for dim in data_shape])
is_complete_subset = edge.data.subset == full_range

combined_repldict = repldict | other_repldict

if is_complete_subset:
candidate_name = edge.data.data
i = 1
while candidate_name in sdfg.arrays or candidate_name in repldict.values():
candidate_name = f"{edge.data.data}_{FULL_VIEW_SUFFIX}_{i}"
i += 1
return candidate_name
else:
i = 1
candidate_name = f"{edge.data.data}_{SLICE_SUFFIX}_{i}"
while candidate_name in combined_repldict.values() or candidate_name in sdfg.arrays:
i += 1
candidate_name = f"{edge.data.data}_{SLICE_SUFFIX}_{i}"
return candidate_name


def dealias(sdfg: dace.SDFG):
"""
Remove aliasing in nested SDFG connectors by replacing temporary names with meaningful ones.

Temporary connector names (e.g., tmpxceX) are replaced with names that reflect the actual data
being accessed (e.g. <data_name>_slice_<id> or <data_name>). Depending on applicability

The function handles two main cases:
1. Full array access: A[::] -> connector gets named 'A'
2. Partial array access: A[i:j] -> connector gets named 'A_slice_<id>' <id> is needed in
case multiple slices of the same array are used.


Args:
sdfg (dace.SDFG): Modified in-place.
"""
recurse_in: Set[dace.nodes.NestedSDFG] = set()

for state in sdfg.all_states():
for node in state.nodes():
if isinstance(node, dace.nodes.NestedSDFG):
recurse_in.add(node)

in_edges = state.in_edges(node)
out_edges = state.out_edges(node)

# Gather all replacements we need
# E.g. A[::] -> tmpxceX (NestedSDFG)
# Needs to be replaced with A[::] -> A_slice (NestedSDFG)
# A_slice is chosen if the subset is different than the complete shape A
# Otherwise A is chosen
# Also consider the case where A[i] -> tmp1 (NestedSDFG)
# A[j] -> tmp2
# In this case we need not map them to A twice but to A_slice1, A_slice2
input_repldict = dict()
output_repldict = dict()
for in_edge in in_edges:
# Skip "__return"
if in_edge.data is not None and in_edge.data.data == "__return":
continue
if in_edge.data is not None and in_edge.data.data != in_edge.dst_conn:
new_connector = _get_new_connector_name(in_edge, input_repldict, output_repldict, state,
node.sdfg)
input_repldict[in_edge.dst_conn] = new_connector

for out_edge in out_edges:
if out_edge.data is not None and out_edge.data.data == "__return":
continue
if out_edge.data is not None and out_edge.data.data != out_edge.src_conn:
new_connector = _get_new_connector_name(out_edge, output_repldict, input_repldict, state,
node.sdfg)
output_repldict[out_edge.src_conn] = new_connector

# Replace connectors rm tmpxceX connector with A
for dst_name in set(input_repldict.keys()):
rmed = node.remove_in_connector(dst_name)
assert rmed, f"Could not removed in connector that is not used anymore: {dst_name}"
for dst_name in set(output_repldict.keys()):
rmed = node.remove_out_connector(dst_name)
assert rmed, f"Could not removed out connector that is not used anymore: {dst_name}"
for src_name in set(input_repldict.values()):
added = node.add_in_connector(src_name, force=True)
assert added, f"Could add the new in connector to the nested sdfg: {src_name}"
for src_name in set(output_repldict.values()):
added = node.add_out_connector(src_name, force=True)
assert added, f"Could add the new out connector to the nested sdfg: {src_name}"

# Update edges
for in_edge in state.in_edges(node):
if in_edge.dst_conn in input_repldict:
in_edge.dst_conn = input_repldict[in_edge.dst_conn]
for out_edge in state.out_edges(node):
if out_edge.src_conn in output_repldict:
out_edge.src_conn = output_repldict[out_edge.src_conn]

# Replace the data containers
# If data / access nodes are not manually changed before hand
# Dace will try to assign to scalars from a symbolic value and crash the thing
replace_dict = (input_repldict | output_repldict)
print(replace_dict)
added_arrays: Set[str] = set()
for dst_name, src_name in replace_dict.items():
desc: dace.data.Data = node.sdfg.arrays[dst_name]
added_arrays.add(src_name)
if src_name in node.sdfg.arrays:
assert src_name in added_arrays, f"{src_name} is in sdfg.arrays but has not been added by dealias for replacements: {replace_dict}."
else:
node.sdfg.remove_data(dst_name, validate=False)
node.sdfg.add_datadesc(name=src_name, datadesc=desc, find_new_name=False)

# Necessary for DaCe to try assign the value to the missing access node from a tasklet
for inner_state in node.sdfg.all_states():
for inner_node in inner_state.nodes():
if isinstance(inner_node, dace.nodes.AccessNode) and inner_node.data in replace_dict:
inner_node.data = replace_dict[inner_node.data]

node.sdfg.replace_dict(repldict=replace_dict)
Loading