Merge branch 'maint'
authorSven Verdoolaege <skimo@kotnet.org>
Mon, 15 Apr 2013 20:36:51 +0000 (22:36 +0200)
committerSven Verdoolaege <skimo@kotnet.org>
Mon, 15 Apr 2013 20:36:51 +0000 (22:36 +0200)
ChangeLog
Makefile.am
configure.ac
isl_ast_codegen.c
isl_map.c
isl_schedule.c
isl_test.c
test_inputs/codegen/atomic2.c [new file with mode: 0644]
test_inputs/codegen/atomic2.in [new file with mode: 0644]
test_inputs/codegen/unroll6.c [new file with mode: 0644]
test_inputs/codegen/unroll6.in [new file with mode: 0644]

index 2f7588c..afe4b05 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+version: 0.11.2
+date: Tue Apr  9 18:45:10 CEST 2013
+changes:
+       - make code generation output the same on Solaris
+       - fix some hard to trigger bugs
+---
 version: 0.11.1
 date: Mon Dec 10 11:55:30 CET 2012
 changes:
@@ -91,8 +97,4 @@ changes:
        - fix several hard to trigger bugs
        - improved argument parsing
        - support parametric vertex enumeration for barvinok
----
-version: 0.08
-date: Fri Oct 21 12:36:20 CEST 2011
-changes:
        - optionally use Bernstein expansion to compute bounds
index a55b967..7218498 100644 (file)
@@ -276,6 +276,8 @@ EXTRA_DIST = \
        doc/mypod2latex \
        doc/manual.tex \
        doc/user.pod \
+       interface/all.h \
+       interface/isl.py.top \
        test_inputs
 
 dist-hook:
index 7baa1f9..3213de0 100644 (file)
@@ -1,10 +1,10 @@
-AC_INIT([isl], [0.11.1], [isl-development@googlegroups.com])
+AC_INIT([isl], [0.11.2], [isl-development@googlegroups.com])
 AC_CONFIG_AUX_DIR([.])
 AC_CONFIG_MACRO_DIR([m4])
 AM_INIT_AUTOMAKE([foreign])
 m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
 AC_SUBST(versioninfo)
-versioninfo=11:1:1
+versioninfo=11:2:1
 
 if test "x$prefix" != "xNONE"; then
        prefix_wd=`cd $prefix && pwd`
index 368d25f..d124027 100644 (file)
@@ -7,6 +7,7 @@
  * Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
  */
 
+#include <limits.h>
 #include <isl/aff.h>
 #include <isl/set.h>
 #include <isl/ilp.h>
@@ -2090,7 +2091,8 @@ static int update_unrolling_lower_bound(struct isl_find_unroll_data *data,
                return 0;
        }
 
-       if (!data->lower || isl_int_cmp_si(data->tmp, *data->n) < 0) {
+       if (isl_int_cmp_si(data->tmp, INT_MAX) <= 0 &&
+           (!data->lower || isl_int_cmp_si(data->tmp, *data->n) < 0)) {
                isl_aff_free(data->lower);
                data->lower = lower;
                *data->n = isl_int_get_si(data->tmp);
@@ -2286,6 +2288,9 @@ static __isl_give isl_basic_set_list *do_unroll(__isl_take isl_set *domain,
  * specialized to the current depth.
  * "done" contains the union of the separation domains that have already
  * been handled.
+ * "atomic" contains the domain that has effectively been made atomic.
+ * This domain may be larger than the intersection of option[atomic]
+ * and the schedule domain.
  */
 struct isl_codegen_domains {
        isl_basic_set_list *list;
@@ -2298,6 +2303,7 @@ struct isl_codegen_domains {
 
        isl_map *sep_class;
        isl_set *done;
+       isl_set *atomic;
 };
 
 /* Add domains to domains->list for each individual value of the current
@@ -2362,7 +2368,8 @@ static int compute_unroll_domains(struct isl_codegen_domains *domains,
 
 /* Construct a single basic set that includes the intersection of
  * the schedule domain, the atomic option domain and the class domain.
- * Add the resulting basic set to domains->list.
+ * Add the resulting basic set to domains->list and save a copy
+ * in domains->atomic for use in compute_partial_domains.
  *
  * We construct a single domain rather than trying to combine
  * the schedule domains of individual domains because we are working
@@ -2388,12 +2395,13 @@ static int compute_atomic_domain(struct isl_codegen_domains *domains,
        atomic_domain = isl_set_intersect(atomic_domain, isl_set_copy(domain));
        empty = isl_set_is_empty(atomic_domain);
        if (empty < 0 || empty) {
-               isl_set_free(atomic_domain);
+               domains->atomic = atomic_domain;
                return empty < 0 ? -1 : 0;
        }
 
        atomic_domain = isl_set_coalesce(atomic_domain);
        bset = isl_set_unshifted_simple_hull(atomic_domain);
+       domains->atomic = isl_set_from_basic_set(isl_basic_set_copy(bset));
        domains->list = isl_basic_set_list_add(domains->list, bset);
 
        return 0;
@@ -2466,6 +2474,11 @@ static int compute_separate_domain(struct isl_codegen_domains *domains,
  * the result with the current "class_domain" to ensure that the domains
  * are disjoint from those generated from other class domains.
  *
+ * The domain that has been made atomic may be larger than specified
+ * by the user since it needs to be representable as a single basic set.
+ * This possibly larger domain is stored in domains->atomic by
+ * compute_atomic_domain.
+ *
  * If anything is left after handling separate, unroll and atomic,
  * we split it up into basic sets and append the basic sets to domains->list.
  */
@@ -2499,9 +2512,8 @@ static int compute_partial_domains(struct isl_codegen_domains *domains,
        domain = isl_set_intersect(domain, isl_set_copy(class_domain));
 
        if (compute_atomic_domain(domains, domain) < 0)
-               goto error;
-       domain = isl_set_subtract(domain,
-                                   isl_set_copy(domains->option[atomic]));
+               domain = isl_set_free(domain);
+       domain = isl_set_subtract(domain, domains->atomic);
 
        domain = isl_set_coalesce(domain);
        domain = isl_set_make_disjoint(domain);
index c011a94..e095c18 100644 (file)
--- a/isl_map.c
+++ b/isl_map.c
@@ -3065,6 +3065,7 @@ __isl_give isl_basic_map *isl_basic_map_insert_dims(
                res = isl_basic_map_set_rational(res);
        if (isl_basic_map_plain_is_empty(bmap)) {
                isl_basic_map_free(bmap);
+               free(dim_map);
                return isl_basic_map_set_to_empty(res);
        }
        res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
index d1f8e66..032b637 100644 (file)
@@ -2971,10 +2971,83 @@ isl_ctx *isl_schedule_get_ctx(__isl_keep isl_schedule *schedule)
        return schedule ? isl_space_get_ctx(schedule->dim) : NULL;
 }
 
+/* Set max_out to the maximal number of output dimensions over
+ * all maps.
+ */
+static int update_max_out(__isl_take isl_map *map, void *user)
+{
+       int *max_out = user;
+       int n_out = isl_map_dim(map, isl_dim_out);
+
+       if (n_out > *max_out)
+               *max_out = n_out;
+
+       isl_map_free(map);
+       return 0;
+}
+
+/* Internal data structure for map_pad_range.
+ *
+ * "max_out" is the maximal schedule dimension.
+ * "res" collects the results.
+ */
+struct isl_pad_schedule_map_data {
+       int max_out;
+       isl_union_map *res;
+};
+
+/* Pad the range of the given map with zeros to data->max_out and
+ * then add the result to data->res.
+ */
+static int map_pad_range(__isl_take isl_map *map, void *user)
+{
+       struct isl_pad_schedule_map_data *data = user;
+       int i;
+       int n_out = isl_map_dim(map, isl_dim_out);
+
+       map = isl_map_add_dims(map, isl_dim_out, data->max_out - n_out);
+       for (i = n_out; i < data->max_out; ++i)
+               map = isl_map_fix_si(map, isl_dim_out, i, 0);
+
+       data->res = isl_union_map_add_map(data->res, map);
+       if (!data->res)
+               return -1;
+
+       return 0;
+}
+
+/* Pad the ranges of the maps in the union map with zeros such they all have
+ * the same dimension.
+ */
+static __isl_give isl_union_map *pad_schedule_map(
+       __isl_take isl_union_map *umap)
+{
+       struct isl_pad_schedule_map_data data;
+
+       if (!umap)
+               return NULL;
+       if (isl_union_map_n_map(umap) <= 1)
+               return umap;
+
+       data.max_out = 0;
+       if (isl_union_map_foreach_map(umap, &update_max_out, &data.max_out) < 0)
+               return isl_union_map_free(umap);
+
+       data.res = isl_union_map_empty(isl_union_map_get_space(umap));
+       if (isl_union_map_foreach_map(umap, &map_pad_range, &data) < 0)
+               data.res = isl_union_map_free(data.res);
+
+       isl_union_map_free(umap);
+       return data.res;
+}
+
 /* Return an isl_union_map of the schedule.  If we have already constructed
  * a band forest, then this band forest may have been modified so we need
  * to extract the isl_union_map from the forest rather than from
- * the originally computed schedule.
+ * the originally computed schedule.  This reconstructed schedule map
+ * then needs to be padded with zeros to unify the schedule space
+ * since the result of isl_band_list_get_suffix_schedule may not have
+ * a unified schedule space.
  */
 __isl_give isl_union_map *isl_schedule_get_map(__isl_keep isl_schedule *sched)
 {
@@ -2984,8 +3057,10 @@ __isl_give isl_union_map *isl_schedule_get_map(__isl_keep isl_schedule *sched)
        if (!sched)
                return NULL;
 
-       if (sched->band_forest)
-               return isl_band_list_get_suffix_schedule(sched->band_forest);
+       if (sched->band_forest) {
+               umap = isl_band_list_get_suffix_schedule(sched->band_forest);
+               return pad_schedule_map(umap);
+       }
 
        umap = isl_union_map_empty(isl_space_copy(sched->dim));
        for (i = 0; i < sched->n; ++i) {
index 1f03972..bc8b748 100644 (file)
@@ -2251,6 +2251,43 @@ int test_special_schedule(isl_ctx *ctx, const char *domain,
        return 0;
 }
 
+/* Check that the schedule map is properly padded, even after being
+ * reconstructed from the band forest.
+ */
+static int test_padded_schedule(isl_ctx *ctx)
+{
+       const char *str;
+       isl_union_set *D;
+       isl_union_map *validity, *proximity;
+       isl_schedule *sched;
+       isl_union_map *map1, *map2;
+       isl_band_list *list;
+       int equal;
+
+       str = "[N] -> { S0[i] : 0 <= i <= N; S1[i, j] : 0 <= i, j <= N }";
+       D = isl_union_set_read_from_str(ctx, str);
+       validity = isl_union_map_empty(isl_union_set_get_space(D));
+       proximity = isl_union_map_copy(validity);
+       sched = isl_union_set_compute_schedule(D, validity, proximity);
+       map1 = isl_schedule_get_map(sched);
+       list = isl_schedule_get_band_forest(sched);
+       isl_band_list_free(list);
+       map2 = isl_schedule_get_map(sched);
+       isl_schedule_free(sched);
+       equal = isl_union_map_is_equal(map1, map2);
+       isl_union_map_free(map1);
+       isl_union_map_free(map2);
+
+       if (equal < 0)
+               return -1;
+       if (!equal)
+               isl_die(ctx, isl_error_unknown,
+                       "reconstructed schedule map not the same as original",
+                       return -1);
+
+       return 0;
+}
+
 int test_schedule(isl_ctx *ctx)
 {
        const char *D, *W, *R, *V, *P, *S;
@@ -2511,6 +2548,9 @@ int test_schedule(isl_ctx *ctx)
        if (test_has_schedule(ctx, D, V, P) < 0)
                return -1;
 
+       if (test_padded_schedule(ctx) < 0)
+               return -1;
+
        return 0;
 }
 
diff --git a/test_inputs/codegen/atomic2.c b/test_inputs/codegen/atomic2.c
new file mode 100644 (file)
index 0000000..9c4a57e
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = ((b0 + 32767) % 32768) + 1; c0 <= 65534; c0 += 32768)
+  A(c0);
diff --git a/test_inputs/codegen/atomic2.in b/test_inputs/codegen/atomic2.in
new file mode 100644 (file)
index 0000000..99901d0
--- /dev/null
@@ -0,0 +1,4 @@
+# Check that isl properly handles atomic domains that are unions.
+[nn, b0] -> { A[a] -> [a, 0, b0] : exists (e0 = [(b0 - a)/32768]: 32768e0 = b0 - a and a >= 1 and b0 >= 0 and b0 <= 32767 and a <= 65534) }
+[nn, b0] -> { : b0 >= 0 and b0 <= 32767 }
+[nn, b0] -> { [a, b, c] -> atomic[2] : c >= 1; [a, 0, c] -> atomic[2] }
diff --git a/test_inputs/codegen/unroll6.c b/test_inputs/codegen/unroll6.c
new file mode 100644 (file)
index 0000000..f5e6982
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  if (((-t1 + 128) % 128) + nn >= 128 * g + 130 && 128 * g + 127 >= (-t1 + 128) % 128 && nn >= 128 * g + 6)
+    for (int c1 = 393214; c1 < nn - 1; c1 += 393216)
+      A(c1, ((t1 + 127) % 128) + 128 * g + 1, ((t1 + 127) % 128) + 1);
+  if (nn >= t1 + 128 * g + 130 && t1 + 128 * g + 127 >= 0 && t1 <= 2 && t1 >= 1)
+    for (int c1 = 393214; c1 < nn - 1; c1 += 393216)
+      A(c1, t1 + 128 * g + 128, t1 + 128);
+}
diff --git a/test_inputs/codegen/unroll6.in b/test_inputs/codegen/unroll6.in
new file mode 100644 (file)
index 0000000..b4338e3
--- /dev/null
@@ -0,0 +1,7 @@
+# Check that the right lower bound is chosen for unrolling.
+# Older versions of isl would pick a lower bound that resulted
+# in a number of slices that exceeds the maximal value of an integer
+# and then only generated code for a truncated number (zero) of slices.
+[nn, t1, g] -> { A[a, b, c] -> [c] : exists (e0 = [(2 + a)/393216], e1 = [(t1 - c)/128]: 128g = b - c and 393216e0 = 2 + a and 128e1 = t1 - c and c <= 130 and c >= 6 - nn + b and c <= 128 + b and nn >= 137 and t1 >= 0 and c >= 1 and a <= -2 + nn and a >= 1 and nn <= 9223372036854775807 and b >= 1 and b <= -2 + nn and t1 <= 127) }
+[nn, t1, g] -> { : nn <= 9223372036854775807 and nn >= 137 and t1 >= 0 and t1 <= 127 }
+{ [c] -> unroll[x] }