Skip to content

Commit

Permalink
Loop Region Code Generation (#1597)
Browse files Browse the repository at this point in the history
This PR adapts code generation to make use of hierarchical control flow
regions, and by extension `LoopRegion`s. This forms the fourth core
element of the [plan to make loops first class citizens of
SDFGs](https://github.com/orgs/spcl/projects/10) and marks the last
element in the architecture.

By extending codegen with the capability of handling hierarchical
control flow graphs and SDFGs, a myriad of complexities that come with
control flow detection are circumvented, which currently lead to
significant issues for certain SDFGs (e.g., #635 and #1586). Making use
of control flow regions such as `LoopRegion`s instead allows codegen to
be much less 'smart' and behave more akin to a lookup table that decides
what code to generate for what SDFG element, making it significantly
less error prone.
  • Loading branch information
phschaad authored Jul 5, 2024
1 parent b5f5624 commit adc1f41
Show file tree
Hide file tree
Showing 47 changed files with 2,284 additions and 1,545 deletions.
14 changes: 4 additions & 10 deletions dace/codegen/codegen.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
# Copyright 2019-2021 ETH Zurich and the DaCe authors. All rights reserved.
import functools
import os
from typing import List, Set
from typing import List

import dace
from dace import dtypes
from dace import data
from dace.sdfg import SDFG, utils as sdutils
from dace.sdfg import SDFG
from dace.codegen.targets import framecode
from dace.codegen.codeobject import CodeObject
from dace.config import Config
Expand Down Expand Up @@ -95,7 +94,7 @@ def _get_codegen_targets(sdfg: SDFG, frame: framecode.DaCeCodeGenerator):
for node, parent in sdfg.all_nodes_recursive():
# Query nodes and scopes
if isinstance(node, SDFGState):
frame.targets.add(disp.get_state_dispatcher(parent, node))
frame.targets.add(disp.get_state_dispatcher(node.sdfg, node))
elif isinstance(node, dace.nodes.EntryNode):
frame.targets.add(disp.get_scope_dispatcher(node.schedule))
elif isinstance(node, dace.nodes.Node):
Expand Down Expand Up @@ -149,7 +148,7 @@ def _get_codegen_targets(sdfg: SDFG, frame: framecode.DaCeCodeGenerator):
disp.instrumentation[sdfg.instrument] = provider_mapping[sdfg.instrument]


def generate_code(sdfg, validate=True) -> List[CodeObject]:
def generate_code(sdfg: SDFG, validate=True) -> List[CodeObject]:
"""
Generates code as a list of code objects for a given SDFG.
Expand Down Expand Up @@ -186,11 +185,6 @@ def generate_code(sdfg, validate=True) -> List[CodeObject]:
shutil.move(f'{tmp_dir}/test2.sdfg', 'test2.sdfg')
raise RuntimeError(f'SDFG serialization failed - files do not match:\n{diff}')

# Convert any loop constructs with hierarchical loop regions into simple 1-level state machine loops.
# TODO (later): Adapt codegen to deal with hierarchical CFGs instead.
sdutils.inline_loop_blocks(sdfg)
sdutils.inline_control_flow_regions(sdfg)

# Before generating the code, run type inference on the SDFG connectors
infer_types.infer_connector_types(sdfg)

Expand Down
Loading

0 comments on commit adc1f41

Please sign in to comment.