Cutout Improvements and Transformation Affected Nodes API
Multistate Cutouts
Allow cutouts from SDFG where the cutout consists of one or more entire states that form a coherent, self-contained SDFG. In practice, that means that there is a single distinct entry state to the cutout's state machine. This mode of constructing cutouts will always create a copy of states and does not contain a reference-cutout mode like in-state cutouts, since states hold a back reference to the SDFG they're contained in and that reference must point to the new cutout SDFG for the cutout to validate.
Transformation Affected Nodes API
This gives transformations a get_affected_nodes API method where the set of nodes touched by the transformation is returned. For most pattern transformations, this set of nodes is equivalent to the matched pattern nodes. However, some transformations (like MapToLoop) may modify additional nodes (or states) that are NOT matched by the pattern nodes, like loop bodies. This makes it impossible for anything other than the transformation itself to report what nodes are affected. With this API call, a transformation author can (and must) provide this information transparently iff the set of affected nodes diverges from the patched pattern nodes. If not overridden, the standard pattern node matches are used.
"Alibi Nodes" in Cutouts
If a cutout inside of a scope region borders one of the scope nodes (exit or entry), the cutout attempts to cross the scope via each memlet path to connect the corresponding data containers. In the example image below, a cutout of the tasklet prog_39 would result in the cutout procedure attempting to add the map exit and the access node to C to the cutout. Having only the map exit in the cutout, but not the entry trivially leads to a fault. Including the entry node would require including the entire content of the scope. Both these solutions are not what the cutout should intuitively contain.

To address this, this PR adds "Alibi Nodes" to cutouts that cross scope borders. What this means, is that in the example above, the access across the map exit border is detected and instead of inserting both the exit node and the outside access node to the cutout, the outgoing memlet from prog_39 is analyzed, and a new data container with a shape corresponding to the accessed subset is inserted into the cutout SDFG. The memlet is then attached to that new alibi data container instead. This further solves the problem that the memlet crossing the scope border may have symbols in the index term, which can only be defined by the map itself.
Miscellaneous Other Points
- Changes the
assignmentsproperty onInterstateEdges to aDictProperty(from a regular property withdtype=dict). This is necessary to get proper metadata which can be used to infer what type of information this property contains.
Haven‘t looked into it yet, but we should add at least simple two positive tests for cutout. But no over-engineering, can do this after deadlines thoroughly.
Agreed. Particularly multistate cutouts and alibi nodes themselves currently have no coverage. This has to be added, I'll take thosw two specific ones up asap after deadlines.
Some points from earlier discussions:
- Alibi cutouts: I think it makes total sense to stay within the scope defined by the given nodes. Including temporary data containers makes total sense.
- Affected nodes: I don't have a very strong opinion on it, but I think we should not introduce this concept in the same PR. Maybe we can separate this into a draft PR? Even if it is not harmful right now because it is not used within dace and defaults to something reasonable, we should have a broad agreement on it with more developers. It changes how we write transformations. Also how does this compare to "annotate_memlets"? Is the enclosing scope affected? Maybe the state/nested SDFG? I am thinking about a more general API. I see more applications for this: When I fuse two nodes, I don't know what happened to the nodes. Is it gone? Are both nodes gone? Did we create a new one that replaces another? This is quite crucial to know when you want to pin a sequence of transformations to a subgraph, you want to know how it is transformed like a trace
Some points from earlier discussions:
- Alibi cutouts: I think it makes total sense to include to stay within the scope defined by the given nodes. Including temporary data containers makes total sense.
- Affected nodes: I don't have a very strong opinion on it, but I think we should not introduce this concept in the same PR. Maybe we can separate this into a draft PR? Even if it is not harmful right now because it is not used within dace and defaults to something reasonable, we should have a broad agreement on it with more developers. It changes how we write transformations. Also how does this compare to "annotate_memlets"? Is the enclosing scope affected? Maybe the state/nested SDFG? I am thinking about a more general API. I see more applications for this: When I fuse two nodes, I don't know what happened to the nodes. Is it gone? Are both nodes gone? Did we create a new one that replaces another? This is quite crucial to know when you want to pin a sequence of transformations to a subgraph, you want to know how it is transformed like a trace
So maybe separate the PRs?
Some points from earlier discussions:
- Alibi cutouts: I think it makes total sense to include to stay within the scope defined by the given nodes. Including temporary data containers makes total sense.
- Affected nodes: I don't have a very strong opinion on it, but I think we should not introduce this concept in the same PR. Maybe we can separate this into a draft PR? Even if it is not harmful right now because it is not used within dace and defaults to something reasonable, we should have a broad agreement on it with more developers. It changes how we write transformations. Also how does this compare to "annotate_memlets"? Is the enclosing scope affected? Maybe the state/nested SDFG? I am thinking about a more general API. I see more applications for this: When I fuse two nodes, I don't know what happened to the nodes. Is it gone? Are both nodes gone? Did we create a new one that replaces another? This is quite crucial to know when you want to pin a sequence of transformations to a subgraph, you want to know how it is transformed like a trace
Sorry, but it would be nice to know what the graph translation of a transformation was in general, maybe we can actually solve this by some form of "graph changes instrumentation" instead of manual specification.
This has now been handled by #1201 and #1208. No longer relevant.