isl_ast_codegen.c: create_node_scaled: reflect current domain slice in schedule
[platform/upstream/isl.git] / isl_ast_codegen.c
index 368d25f..8398adb 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>
@@ -314,24 +315,17 @@ static __isl_give isl_ast_graft *after_each_for(__isl_keep isl_ast_graft *graft,
        return graft;
 }
 
-/* Eliminate the schedule dimension "pos" from "executed" and return
- * the result.
+/* Plug in all the know values of the current and outer dimensions
+ * in the domain of "executed".  In principle, we only need to plug
+ * in the known value of the current dimension since the values of
+ * outer dimensions have been plugged in already.
+ * However, it turns out to be easier to just plug in all known values.
  */
-static __isl_give isl_union_map *eliminate(__isl_take isl_union_map *executed,
-       int pos, __isl_keep isl_ast_build *build)
+static __isl_give isl_union_map *plug_in_values(
+       __isl_take isl_union_map *executed, __isl_keep isl_ast_build *build)
 {
-       isl_space *space;
-       isl_map *elim;
-
-       space = isl_ast_build_get_space(build, 1);
-       space = isl_space_map_from_set(space);
-       elim = isl_map_identity(space);
-       elim = isl_map_eliminate(elim, isl_dim_in, pos, 1);
-
-       executed = isl_union_map_apply_domain(executed,
-                                               isl_union_map_from_map(elim));
-
-       return executed;
+       return isl_ast_build_substitute_values_union_map_domain(build,
+                                                                   executed);
 }
 
 /* Check if the constraint "c" is a lower bound on dimension "pos",
@@ -1248,8 +1242,13 @@ static __isl_give isl_ast_node *create_for(__isl_keep isl_ast_build *build,
  * it can be printed as an assignment of the single value to the loop
  * "iterator".
  *
- * If the current level is eliminated, we eliminate the current dimension
- * from the inverse schedule to make sure no inner dimensions depend
+ * If the current level is eliminated, we explicitly plug in the value
+ * for the current level found by isl_ast_build_set_loop_bounds in the
+ * inverse schedule.  This ensures that if we are working on a slice
+ * of the domain based on information available in the inverse schedule
+ * and the build domain, that then this information is also reflected
+ * in the inverse schedule.  This operation also eliminates the current
+ * dimension from the inverse schedule making sure no inner dimensions depend
  * on the current dimension.  Otherwise, we create a for node, marking
  * it degenerate if appropriate.  The initial for node is still incomplete
  * and will be completed in either refine_degenerate or refine_generic.
@@ -1292,7 +1291,7 @@ static __isl_give isl_ast_graft *create_node_scaled(
        if (degenerate < 0 || eliminated < 0)
                executed = isl_union_map_free(executed);
        if (eliminated)
-               executed = eliminate(executed, depth, build);
+               executed = plug_in_values(executed, sub_build);
        else
                node = create_for(build, degenerate);
 
@@ -2090,7 +2089,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 +2286,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 +2301,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 +2366,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 +2393,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 +2472,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 +2510,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);