From 0b1f80ec7351754a0bb06b4f6b086974f469b987 Mon Sep 17 00:00:00 2001
From: Andreas Kloeckner <inform@tiker.net>
Date: Tue, 6 Nov 2012 11:34:50 -0500
Subject: [PATCH] Implement delete_unused_inames.

---
 MEMO              |  8 +++++---
 loopy/__init__.py | 52 ++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 50 insertions(+), 10 deletions(-)

diff --git a/MEMO b/MEMO
index 9c603fd58..9227c654b 100644
--- a/MEMO
+++ b/MEMO
@@ -50,9 +50,7 @@ To-do
 
 - rename iname
 
-- delete unused inames
-
-- link_inames
+- when are link_inames, duplicate_inames safe?
 
 - ExpandingIdentityMapper
   extract_subst -> needs WalkMapper
@@ -96,6 +94,8 @@ Fixes:
 Future ideas
 ^^^^^^^^^^^^
 
+- Storage sharing for temporaries?
+
 - Kernel splitting (via what variables get computed in a kernel)
 
 - Put all OpenCL functions into mangler
@@ -145,6 +145,8 @@ Future ideas
 Dealt with
 ^^^^^^^^^^
 
+- delete unused inames
+
 - Expose iname-duplicate-and-rename as a primitive.
 
 - make sure simple side effects work
diff --git a/loopy/__init__.py b/loopy/__init__.py
index 83cdd7a50..6257e36b0 100644
--- a/loopy/__init__.py
+++ b/loopy/__init__.py
@@ -183,9 +183,7 @@ def split_iname(kernel, split_iname, inner_length,
         s = s.intersect(inner_constraint_set)
 
         if within is None:
-            s = (s
-                .eliminate(name_dim_type, name_idx, 1)
-                .remove_dims(name_dim_type, name_idx, 1))
+            s = s.project_out(name_dim_type, name_idx, 1)
 
         return s
 
@@ -345,8 +343,7 @@ def join_inames(kernel, inames, new_iname=None, tag=None, within=None):
         iname_dt, iname_idx = iname_to_dim[iname]
 
         if within is None:
-            new_domain = new_domain.eliminate(iname_dt, iname_idx, 1)
-            new_domain = new_domain.remove_dims(iname_dt, iname_idx, 1)
+            new_domain = new_domain.project_out(iname_dt, iname_idx, 1)
 
     def subst_forced_iname_deps(fid):
         result = set()
@@ -661,8 +658,49 @@ def link_inames(knl, inames, new_iname, within=None, tag=None):
 # {{{ delete unused inames
 
 def delete_unused_inames(knl, inames=None):
-    from warnings import warn
-    warn("delete_unused_inames is unimplemented")
+    """Delete those among *inames* that are unused, i.e. project them
+    out of the domain. If these inames pose implicit restrictions on
+    other inames, these restrictions will persist as existentially
+    quantified variables.
+
+    :arg inames: may be an iterable of inames or a string of comma-separated inames.
+    """
+
+    # {{{ normalize arguments
+
+    if inames is None:
+        inames = knl.all_inames()
+    elif isinstance(inames, str):
+        inames = inames.split(",")
+
+    # }}}
+
+    # {{{ check which inames are unused
+
+    inames = set(inames)
+    used_inames = set()
+    for insn in knl.instructions:
+        used_inames.update(knl.insn_inames(insn.id))
+
+    unused_inames = inames - used_inames
+
+    # }}}
+
+    # {{{ remove them
+
+    from loopy.kernel import DomainChanger
+
+    for iname in unused_inames:
+        domch = DomainChanger(knl, (iname,))
+
+        dom = domch.domain
+        dt, idx = dom.get_var_dict()[iname]
+        dom = dom.project_out(dt, idx, 1)
+
+        knl = knl.copy(domains=domch.get_domains_with(dom))
+
+    # }}}
+
     return knl
 
 # }}}
-- 
GitLab