Esempio n. 1
0
    def can_be_applied(self, graph, expr_index, sdfg, permissive=False):
        state = self.start_state

        # The transformation applies only to nested SDFGs
        if not graph.parent:
            return False

        # Only empty states can be eliminated
        if state.number_of_nodes() > 0:
            return False

        out_edges = graph.out_edges(state)
        in_edges = graph.in_edges(state)

        # If this is a start state, there are no incoming edges
        if len(in_edges) != 0:
            return False

        # We only match start states with one sink and no conditions
        if len(out_edges) != 1:
            return False
        edge = out_edges[0]
        if not edge.data.is_unconditional():
            return False
        # Assignments that make descriptors into symbols cannot be eliminated
        for assign in edge.data.assignments.values():
            if graph.arrays.keys() & symbolic.free_symbols_and_functions(
                    assign):
                return False

        return True
Esempio n. 2
0
 def _data_independent_assignments(self, edge: InterstateEdge,
                                   arrays: Set[str]) -> Dict[str, Any]:
     """
     Return symbol assignments that only depend on other symbols and constants, rather than data descriptors.
     """
     return {
         k: v if (not (symbolic.free_symbols_and_functions(v) & arrays))
         else _UnknownValue
         for k, v in edge.assignments.items()
     }
Esempio n. 3
0
    def _candidates(nsdfg: nodes.NestedSDFG) -> Set[str]:
        candidates = set(nsdfg.symbol_mapping.keys())
        if len(candidates) == 0:
            return set()

        for desc in nsdfg.sdfg.arrays.values():
            candidates -= set(map(str, desc.free_symbols))

        ignore = set()
        for nstate in cfg.stateorder_topological_sort(nsdfg.sdfg):
            state_syms = nstate.free_symbols

            # Try to be conservative with C++ tasklets
            for node in nstate.nodes():
                if (isinstance(node, nodes.Tasklet)
                        and node.language is dtypes.Language.CPP):
                    for candidate in candidates:
                        if re.findall(r'\b%s\b' % re.escape(candidate),
                                      node.code.as_string):
                            state_syms.add(candidate)

            # Any symbol used in this state is considered used
            candidates -= (state_syms - ignore)
            if len(candidates) == 0:
                return set()

            # Any symbol that is set in all outgoing edges is ignored from
            # this point
            local_ignore = None
            for e in nsdfg.sdfg.out_edges(nstate):
                # Look for symbols in condition
                candidates -= (set(
                    map(str, symbolic.symbols_in_ast(
                        e.data.condition.code[0]))) - ignore)

                for assign in e.data.assignments.values():
                    candidates -= (
                        symbolic.free_symbols_and_functions(assign) - ignore)

                if local_ignore is None:
                    local_ignore = set(e.data.assignments.keys())
                else:
                    local_ignore &= e.data.assignments.keys()
            if local_ignore is not None:
                ignore |= local_ignore

        return candidates
Esempio n. 4
0
    def _candidates(
        cls, nsdfg: nodes.NestedSDFG
    ) -> Tuple[Set[str], Set[Tuple[SDFGState, nodes.AccessNode]]]:
        # Start with all non-transient arrays
        candidates = set(conn for conn in nsdfg.out_connectors.keys())
        candidate_nodes: Set[Tuple[SDFGState, nodes.AccessNode]] = set()

        # Remove candidates that are used more than once in the outer SDFG
        state = nsdfg.sdfg.parent
        sdfg = nsdfg.sdfg.parent_sdfg
        for e in state.out_edges(nsdfg):
            if e.data.is_empty():
                continue
            outer_desc = sdfg.arrays[e.data.data]
            if isinstance(outer_desc, dt.View):
                candidates.remove(e.src_conn)
                continue
            if not outer_desc.transient:
                candidates.remove(e.src_conn)
                continue
            if not isinstance(state.memlet_path(e)[-1].dst, nodes.AccessNode):
                candidates.remove(e.src_conn)
                continue

            all_access_nodes = [(s, n) for s in sdfg.nodes()
                                for n in s.data_nodes()
                                if n.data == e.data.data]
            if len(all_access_nodes) > 1:
                candidates.remove(e.src_conn)
                continue
            if all_access_nodes[0][0].out_degree(all_access_nodes[0][1]) > 0:
                candidates.remove(e.src_conn)
                continue

        if not candidates:
            return set(), set()

        # Remove candidates that are used in the nested SDFG
        for nstate in nsdfg.sdfg.nodes():
            for node in nstate.data_nodes():
                if node.data in candidates:
                    # If used in nested SDFG
                    if nstate.out_degree(node) > 0:
                        candidates.remove(node.data)
                        continue
                    # If a result of a code node
                    if any(not isinstance(
                            nstate.memlet_path(e)[0].src, nodes.AccessNode)
                           for e in nstate.in_edges(node)):
                        candidates.remove(node.data)
                        continue

                    # Add node for later use
                    candidate_nodes.add((nstate, node))

        # Any array that is used in interstate edges is removed
        for e in nsdfg.sdfg.edges():
            candidates -= (set(
                map(str, symbolic.symbols_in_ast(e.data.condition.code[0]))))
            for assign in e.data.assignments.values():
                candidates -= (symbolic.free_symbols_and_functions(assign))

        candidate_nodes = {
            n
            for n in candidate_nodes if n[1].data in candidates
        }

        return candidates, candidate_nodes