diff --git a/loopy/__init__.py b/loopy/__init__.py index 58029467c7bb263203bf33430eb306fe6f16bf14..ecadbf4e95b4f7e12d5093c6a21929599fcdcc62 100644 --- a/loopy/__init__.py +++ b/loopy/__init__.py @@ -669,7 +669,7 @@ def rename_iname(knl, old_iname, new_iname, within): raise ValueError("iname '%s' conflicts with an existing identifier" "--cannot rename" % new_iname) - knl = duplicate_inames([old_iname], within, [new_iname]) + knl = duplicate_inames(knl, [old_iname], within=within, new_inames=[new_iname]) knl = remove_unused_inames(knl, [old_iname]) return knl @@ -1116,8 +1116,19 @@ def add_dependency(kernel, insn_match, dependency): :func:`loopy.context_matching.parse_match`. """ + if dependency not in kernel.id_to_insn: + raise LoopyError("cannot add dependency on non-existent instruction ID '%s'" + % dependency) + def add_dep(insn): - return insn.copy(insn_deps=insn.insn_deps + [dependency]) + new_deps = insn.insn_deps + added_deps = frozenset([dependency]) + if new_deps is None: + new_deps = added_deps + else: + new_deps = new_deps | added_deps + + return insn.copy(insn_deps=new_deps) return map_instructions(kernel, insn_match, add_dep) diff --git a/loopy/context_matching.py b/loopy/context_matching.py index cc375c43897c0ad5e138d4f020f4e48f9a463451..61203ece2c38ae7beb385bd8b4758c3ce5eeeea8 100644 --- a/loopy/context_matching.py +++ b/loopy/context_matching.py @@ -251,11 +251,21 @@ def parse_match(expr_str): return left_query - from pytools.lex import LexIterator, lex - pstate = LexIterator( - [(tag, s, idx, matchobj) - for (tag, s, idx, matchobj) in lex(_LEX_TABLE, expr_str, match_objects=True) - if tag is not _whitespace], expr_str) + from pytools.lex import LexIterator, lex, InvalidTokenError + try: + pstate = LexIterator( + [(tag, s, idx, matchobj) + for (tag, s, idx, matchobj) in lex(_LEX_TABLE, expr_str, + match_objects=True) + if tag is not _whitespace], expr_str) + except InvalidTokenError as e: + from loopy.diagnostic import LoopyError + raise LoopyError( + "invalid match expression: '{match_expr}' ({err_type}: {err_str})" + .format( + match_expr=expr_str, + err_type=type(e).__name__, + err_str=str(e))) if pstate.is_at_end(): pstate.raise_parse_error("unexpected end of input") diff --git a/loopy/frontend/fortran/__init__.py b/loopy/frontend/fortran/__init__.py index aad2328b0bfbf4b37c6c6453358668d14fd39388..2626069a0551a7e11c7b8703965423be8011860c 100644 --- a/loopy/frontend/fortran/__init__.py +++ b/loopy/frontend/fortran/__init__.py @@ -211,7 +211,8 @@ def parse_transformed_fortran(source, free_form=True, strict=True, return proc_dict["RESULT"] -def parse_fortran(source, filename="", free_form=True, strict=True): +def parse_fortran(source, filename="", free_form=True, strict=True, + auto_dependencies=True): """ :returns: a list of :class:`loopy.LoopKernel` objects """ @@ -231,7 +232,7 @@ def parse_fortran(source, filename="", free_form=True, strict=True) "and returned invalid data (Sorry!)") from loopy.frontend.fortran.translator import F2LoopyTranslator - f2loopy = F2LoopyTranslator(filename) + f2loopy = F2LoopyTranslator(filename, auto_dependencies=auto_dependencies) f2loopy(tree) return f2loopy.make_kernels() diff --git a/loopy/frontend/fortran/translator.py b/loopy/frontend/fortran/translator.py index 895606aa38df3bac78e05d18822a5dbf494d0948..f34c69978c0b9390d7bf216f70043b472a51cc67 100644 --- a/loopy/frontend/fortran/translator.py +++ b/loopy/frontend/fortran/translator.py @@ -197,9 +197,11 @@ class Scope(object): # {{{ translator class F2LoopyTranslator(FTreeWalkerBase): - def __init__(self, filename): + def __init__(self, filename, auto_dependencies): FTreeWalkerBase.__init__(self) + self.auto_dependencies = auto_dependencies + self.scope_stack = [] self.isl_context = isl.Context() @@ -223,7 +225,7 @@ class F2LoopyTranslator(FTreeWalkerBase): new_id = "insn%d" % self.insn_id_counter self.insn_id_counter += 1 - if scope.previous_instruction_id: + if self.auto_dependencies and scope.previous_instruction_id: insn_deps = frozenset([scope.previous_instruction_id]) else: insn_deps = frozenset() diff --git a/loopy/precompute.py b/loopy/precompute.py index 1227082a9b304ad920940e2339e643ad2da65daa..11b1396f15b4f9dc440ee75480a1d25fbc1e091a 100644 --- a/loopy/precompute.py +++ b/loopy/precompute.py @@ -218,7 +218,8 @@ class RuleInvocationReplacer(RuleAwareIdentityMapper): def precompute(kernel, subst_use, sweep_inames=[], within=None, storage_axes=None, temporary_name=None, precompute_inames=None, storage_axis_to_tag={}, default_tag="l.auto", dtype=None, - fetch_bounding_box=False, temporary_is_local=None): + fetch_bounding_box=False, temporary_is_local=None, + insn_id=None): """Precompute the expression described in the substitution rule determined by *subst_use* and store it in a temporary array. A precomputation needs two things to operate, a list of *sweep_inames* (order irrelevant) and an @@ -278,6 +279,7 @@ def precompute(kernel, subst_use, sweep_inames=[], within=None, If the specified inames do not already exist, they will be created. If they do already exist, their loop domain is verified against the one required for this precomputation. + :arg insn_id: The ID of the instruction performing the precomputation. If `storage_axes` is not specified, it defaults to the arrangement `` with the direct sweep axes being the @@ -631,9 +633,11 @@ def precompute(kernel, subst_use, sweep_inames=[], within=None, # }}} from loopy.kernel.data import ExpressionInstruction - compute_insn_id = kernel.make_unique_instruction_id(based_on=c_subst_name) + if insn_id is None: + insn_id = kernel.make_unique_instruction_id(based_on=c_subst_name) + compute_insn = ExpressionInstruction( - id=compute_insn_id, + id=insn_id, assignee=assignee, expression=compute_expression)