From 8e4da8cbbdad93338123322b13ad83bfa016f2d0 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner <inform@tiker.net> Date: Wed, 12 Aug 2015 23:41:23 -0500 Subject: [PATCH] Add 'existing_ok' mode to rename_iname --- loopy/__init__.py | 76 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 3 deletions(-) diff --git a/loopy/__init__.py b/loopy/__init__.py index 3a4674749..7850d67e9 100644 --- a/loopy/__init__.py +++ b/loopy/__init__.py @@ -660,23 +660,93 @@ def duplicate_inames(knl, inames, within, new_inames=None, suffix=None, # }}} -def rename_iname(knl, old_iname, new_iname, within): +# {{{ rename_inames + +def rename_iname(knl, old_iname, new_iname, existing_ok=False, within=None): """ :arg within: a stack match as understood by :func:`loopy.context_matching.parse_stack_match`. + :arg existing_ok: execute even if *new_iname* already exists """ var_name_gen = knl.get_var_name_generator() - if var_name_gen.is_name_conflicting(new_iname): + does_exist = var_name_gen.is_name_conflicting(new_iname) + + if does_exist and not existing_ok: raise ValueError("iname '%s' conflicts with an existing identifier" "--cannot rename" % new_iname) - knl = duplicate_inames(knl, [old_iname], within=within, new_inames=[new_iname]) + if does_exist: + # {{{ check that the domains match up + + dom = knl.get_inames_domain(frozenset((old_iname, new_iname))) + + var_dict = dom.get_var_dict() + _, old_idx = var_dict[old_iname] + _, new_idx = var_dict[new_iname] + + par_idx = dom.dim(dim_type.param) + dom_old = dom.move_dims( + dim_type.param, par_idx, dim_type.set, old_idx, 1) + dom_old = dom_old.move_dims( + dim_type.set, dom_old.dim(dim_type.set), dim_type.param, par_idx, 1) + dom_old = dom_old.project_out( + dim_type.set, new_idx if new_idx < old_idx else new_idx - 1, 1) + + par_idx = dom.dim(dim_type.param) + dom_new = dom.move_dims( + dim_type.param, par_idx, dim_type.set, new_idx, 1) + dom_new = dom_new.move_dims( + dim_type.set, dom_new.dim(dim_type.set), dim_type.param, par_idx, 1) + dom_new = dom_new.project_out( + dim_type.set, old_idx if old_idx < new_idx else old_idx - 1, 1) + + if not (dom_old <= dom_new and dom_new <= dom_old): + raise LoopyError( + "inames {old} and {new} do not iterate over the same domain" + .format(old=old_iname, new=new_iname)) + + # }}} + + from pymbolic import var + subst_dict = {old_iname: var(new_iname)} + + from loopy.context_matching import parse_stack_match + within = parse_stack_match(within) + + from pymbolic.mapper.substitutor import make_subst_func + rule_mapping_context = SubstitutionRuleMappingContext( + knl.substitutions, var_name_gen) + ijoin = RuleAwareSubstitutionMapper(rule_mapping_context, + make_subst_func(subst_dict), within) + + knl = rule_mapping_context.finish_kernel( + ijoin.map_kernel(knl)) + + new_instructions = [] + for insn in knl.instructions: + if (old_iname in insn.forced_iname_deps + and within(knl, insn, ())): + insn = insn.copy( + forced_iname_deps=( + (insn.forced_iname_deps - frozenset([old_iname])) + | frozenset([new_iname]))) + + new_instructions.append(insn) + + knl = knl.copy(instructions=new_instructions) + + else: + knl = duplicate_inames( + knl, [old_iname], within=within, new_inames=[new_iname]) + knl = remove_unused_inames(knl, [old_iname]) return knl +# }}} + # {{{ link inames -- GitLab