isl_access_info_compute_flow: handle multi-valued sink access relations
authorSven Verdoolaege <skimo@kotnet.org>
Wed, 26 May 2010 20:30:49 +0000 (22:30 +0200)
committerSven Verdoolaege <skimo@kotnet.org>
Mon, 31 May 2010 17:53:58 +0000 (19:53 +0200)
In particular, if any given sink iteration accesses more than one
data element, then we compute dependences for each of these data elements.
Before, we would only compute a dependence for the data elements
that was accessed last before the sink.

isl_flow.c
isl_test.c

index 2e51b92..40b2e57 100644 (file)
@@ -447,9 +447,10 @@ static int intermediate_sources(__isl_keep isl_access_info *acc,
 }
 
 /* Given a "sink" access, a list of n "source" accesses,
- * compute for each iteration of the sink access,
+ * compute for each iteration of the sink access
+ * and for each element accessed by that iteration,
  * the source access in the list that last accessed the
- * same element accessed by the sink access before this sink access.
+ * element accessed by the sink access before this sink access.
  * Each access is given as a map from the loop iterators
  * to the array indices.
  * The result is a list of n relations between source and sink
@@ -474,6 +475,12 @@ static int intermediate_sources(__isl_keep isl_access_info *acc,
  *                                                             of dep
  *                     add result to possible last accesses at level l of write w2
  *                     and replace possible last accesses dep by the remainder
+ *
+ *
+ * To deal with multi-valued sink access relations, the sink iteration
+ * domain is first extended with dimensions that correspond to the data
+ * space.  After the computation is finished, these extra dimensions are
+ * projected out again.
  */
 __isl_give isl_flow *isl_access_info_compute_flow(__isl_take isl_access_info *acc)
 {
@@ -483,15 +490,28 @@ __isl_give isl_flow *isl_access_info_compute_flow(__isl_take isl_access_info *ac
        int depth;
        struct isl_map **temp_rel;
        struct isl_flow *res;
+       isl_dim *dim;
+       isl_map *id;
+       unsigned n_sink;
+       unsigned n_data;
 
        acc = isl_access_info_sort_sources(acc);
 
+       n_sink = isl_map_dim(acc->sink.map, isl_dim_in);
+       n_data = isl_map_dim(acc->sink.map, isl_dim_out);
+       dim = isl_dim_range(isl_map_get_dim(acc->sink.map));
+       id = isl_map_identity(dim);
+       id = isl_map_insert(id, isl_dim_in, 0, n_sink);
+       acc->sink.map = isl_map_insert(acc->sink.map, isl_dim_in,
+                                       n_sink, n_data);
+       acc->sink.map = isl_map_intersect(acc->sink.map, id);
+
        res = isl_flow_alloc(acc);
        if (!res)
                goto error;
        ctx = acc->sink.map->ctx;
 
-       depth = 2 * isl_map_dim(acc->sink.map, isl_dim_in) + 1;
+       depth = 2 * n_sink + 1;
        todo = isl_map_domain(isl_map_copy(acc->sink.map));
        if (isl_set_fast_is_empty(todo))
                goto done;
@@ -541,6 +561,9 @@ __isl_give isl_flow *isl_access_info_compute_flow(__isl_take isl_access_info *ac
 
        free(temp_rel);
 done:
+       for (j = 0; j < res->n_source; ++j)
+               res->dep[j].map = isl_map_project_out(res->dep[j].map,
+                                       isl_dim_out, n_sink, n_data);
        res->no_source = todo;
        isl_access_info_free(acc);
        return res;
index 5e622ba..9eb4cc1 100644 (file)
@@ -12,6 +12,7 @@
 #include <limits.h>
 #include <isl_ctx.h>
 #include <isl_set.h>
+#include <isl_flow.h>
 #include <isl_constraint.h>
 
 static char *srcdir;
@@ -1034,6 +1035,70 @@ void test_lexmin(struct isl_ctx *ctx)
        isl_map_free(map);
 }
 
+struct dep {
+       isl_map *dep;
+};
+
+static int collect_dep(__isl_take isl_map *dep, void *dep_user, void *user)
+{
+       struct dep *d = (struct dep *)user;
+
+       d->dep = isl_map_union(d->dep, dep);
+
+       return 0;
+}
+
+static int common_space(void *first, void *second)
+{
+       int depth = *(int *)first;
+       return 2 * depth;
+}
+
+int map_is_equal(__isl_keep isl_map *map, const char *str)
+{
+       isl_map *map2;
+       int equal;
+
+       map2 = isl_map_read_from_str(map->ctx, str, -1);
+       equal = isl_map_is_equal(map, map2);
+       isl_map_free(map2);
+
+       return equal;
+}
+
+void test_dep(struct isl_ctx *ctx)
+{
+       const char *str;
+       isl_dim *dim;
+       isl_map *map;
+       isl_access_info *ai;
+       isl_flow *flow;
+       int depth;
+       struct dep dep;
+
+       depth = 5;
+
+       str = "{ [1,i,0,0,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";
+       map = isl_map_read_from_str(ctx, str, -1);
+       ai = isl_access_info_alloc(map, &depth, &common_space, 1);
+
+       str = "{ [0,i,0,j,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";
+       map = isl_map_read_from_str(ctx, str, -1);
+       ai = isl_access_info_add_source(ai, map, &depth);
+
+       flow = isl_access_info_compute_flow(ai);
+       dim = isl_dim_alloc(ctx, 0, 5, 5);
+       dep.dep = isl_map_empty(dim);
+
+       isl_flow_foreach(flow, collect_dep, &dep);
+
+       str = "{ [0,i,0,j,0] -> [1,i,0,0,0] : 0 <= i,j <= 10 }";
+       assert(map_is_equal(dep.dep, str));
+
+       isl_map_free(dep.dep);
+       isl_flow_free(flow);
+}
+
 int main()
 {
        struct isl_ctx *ctx;
@@ -1042,6 +1107,7 @@ int main()
        assert(srcdir);
 
        ctx = isl_ctx_alloc();
+       test_dep(ctx);
        test_read(ctx);
        test_construction(ctx);
        test_dim(ctx);