isl_ast_build_ast_from_schedule: properly handle union atomic options
authorSven Verdoolaege <skimo@kotnet.org>
Mon, 15 Apr 2013 12:02:05 +0000 (14:02 +0200)
committerSven Verdoolaege <skimo@kotnet.org>
Mon, 15 Apr 2013 20:24:05 +0000 (22:24 +0200)
In particular, if the domain for which a given dimension should
be atomic is a union of basic sets, then the actual atomic domain
may be larger than this union and we need to make sure that this
larger set is removed from the remainder domain to preserve
the invariant that the elements of the list computed by compute_domains
are disjoint.

Reported-by: Tobias Grosser <tobias@grosser.es>
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
isl_ast_codegen.c
test_inputs/codegen/atomic2.c [new file with mode: 0644]
test_inputs/codegen/atomic2.in [new file with mode: 0644]

index aae71b4..3eb964b 100644 (file)
@@ -2288,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 th 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;
@@ -2300,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
@@ -2364,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
@@ -2390,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;
@@ -2468,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.
  */
@@ -2501,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);
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] }