add isl_schedule_foreach_band
[platform/upstream/isl.git] / isl_union_map.c
index 70f0159..b1d0096 100644 (file)
@@ -639,6 +639,19 @@ __isl_give isl_union_set *isl_union_set_intersect_params(
        return isl_union_map_intersect_params(uset, set);
 }
 
+static __isl_give isl_union_map *union_map_intersect_params(
+       __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+       return isl_union_map_intersect_params(umap,
+                                               isl_set_from_union_set(uset));
+}
+
+static __isl_give isl_union_map *union_map_gist_params(
+       __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+       return isl_union_map_gist_params(umap, isl_set_from_union_set(uset));
+}
+
 struct isl_union_map_match_bin_data {
        isl_union_map *umap2;
        isl_union_map *res;
@@ -712,10 +725,61 @@ __isl_give isl_union_map *isl_union_map_intersect(
        return match_bin_op(umap1, umap2, &isl_map_intersect);
 }
 
+/* Compute the intersection of the two union_sets.
+ * As a special case, if exactly one of the two union_sets
+ * is a parameter domain, then intersect the parameter domain
+ * of the other one with this set.
+ */
 __isl_give isl_union_set *isl_union_set_intersect(
        __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
 {
+       int p1, p2;
+
+       p1 = isl_union_set_is_params(uset1);
+       p2 = isl_union_set_is_params(uset2);
+       if (p1 < 0 || p2 < 0)
+               goto error;
+       if (!p1 && p2)
+               return union_map_intersect_params(uset1, uset2);
+       if (p1 && !p2)
+               return union_map_intersect_params(uset2, uset1);
        return isl_union_map_intersect(uset1, uset2);
+error:
+       isl_union_set_free(uset1);
+       isl_union_set_free(uset2);
+       return NULL;
+}
+
+static int gist_params_entry(void **entry, void *user)
+{
+       struct isl_union_map_gen_bin_set_data *data = user;
+       isl_map *map = *entry;
+       int empty;
+
+       map = isl_map_copy(map);
+       map = isl_map_gist_params(map, isl_set_copy(data->set));
+
+       empty = isl_map_is_empty(map);
+       if (empty < 0) {
+               isl_map_free(map);
+               return -1;
+       }
+
+       data->res = isl_union_map_add_map(data->res, map);
+
+       return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_gist_params(
+       __isl_take isl_union_map *umap, __isl_take isl_set *set)
+{
+       return gen_bin_set_op(umap, set, &gist_params_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_gist_params(
+       __isl_take isl_union_set *uset, __isl_take isl_set *set)
+{
+       return isl_union_map_gist_params(uset, set);
 }
 
 __isl_give isl_union_map *isl_union_map_gist(__isl_take isl_union_map *umap,
@@ -727,6 +791,8 @@ __isl_give isl_union_map *isl_union_map_gist(__isl_take isl_union_map *umap,
 __isl_give isl_union_set *isl_union_set_gist(__isl_take isl_union_set *uset,
        __isl_take isl_union_set *context)
 {
+       if (isl_union_set_is_params(context))
+               return union_map_gist_params(uset, context);
        return isl_union_map_gist(uset, context);
 }
 
@@ -814,12 +880,102 @@ static int intersect_domain_entry(void **entry, void *user)
        return 0;
 }
 
+/* Intersect the domain of "umap" with "uset".
+ * If "uset" is a parameters domain, then intersect the parameter
+ * domain of "umap" with this set.
+ */
 __isl_give isl_union_map *isl_union_map_intersect_domain(
        __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
 {
+       if (isl_union_set_is_params(uset))
+               return union_map_intersect_params(umap, uset);
        return gen_bin_op(umap, uset, &intersect_domain_entry);
 }
 
+static int gist_domain_entry(void **entry, void *user)
+{
+       struct isl_union_map_gen_bin_data *data = user;
+       uint32_t hash;
+       struct isl_hash_table_entry *entry2;
+       isl_space *dim;
+       isl_map *map = *entry;
+       int empty;
+
+       dim = isl_map_get_space(map);
+       dim = isl_space_domain(dim);
+       hash = isl_space_get_hash(dim);
+       entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+                                    hash, &has_dim, dim, 0);
+       isl_space_free(dim);
+       if (!entry2)
+               return 0;
+
+       map = isl_map_copy(map);
+       map = isl_map_gist_domain(map, isl_set_copy(entry2->data));
+
+       empty = isl_map_is_empty(map);
+       if (empty < 0) {
+               isl_map_free(map);
+               return -1;
+       }
+
+       data->res = isl_union_map_add_map(data->res, map);
+
+       return 0;
+}
+
+/* Compute the gist of "umap" with respect to the domain "uset".
+ * If "uset" is a parameters domain, then compute the gist
+ * with respect to this parameter domain.
+ */
+__isl_give isl_union_map *isl_union_map_gist_domain(
+       __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+       if (isl_union_set_is_params(uset))
+               return union_map_gist_params(umap, uset);
+       return gen_bin_op(umap, uset, &gist_domain_entry);
+}
+
+static int gist_range_entry(void **entry, void *user)
+{
+       struct isl_union_map_gen_bin_data *data = user;
+       uint32_t hash;
+       struct isl_hash_table_entry *entry2;
+       isl_space *space;
+       isl_map *map = *entry;
+       int empty;
+
+       space = isl_map_get_space(map);
+       space = isl_space_range(space);
+       hash = isl_space_get_hash(space);
+       entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+                                    hash, &has_dim, space, 0);
+       isl_space_free(space);
+       if (!entry2)
+               return 0;
+
+       map = isl_map_copy(map);
+       map = isl_map_gist_range(map, isl_set_copy(entry2->data));
+
+       empty = isl_map_is_empty(map);
+       if (empty < 0) {
+               isl_map_free(map);
+               return -1;
+       }
+
+       data->res = isl_union_map_add_map(data->res, map);
+
+       return 0;
+}
+
+/* Compute the gist of "umap" with respect to the range "uset".
+ */
+__isl_give isl_union_map *isl_union_map_gist_range(
+       __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+       return gen_bin_op(umap, uset, &gist_range_entry);
+}
+
 static int intersect_range_entry(void **entry, void *user)
 {
        struct isl_union_map_gen_bin_data *data = user;
@@ -1019,10 +1175,22 @@ __isl_give isl_union_map *isl_union_map_product(__isl_take isl_union_map *umap1,
        return bin_op(umap1, umap2, &product_entry);
 }
 
+static int set_product_entry(void **entry, void *user)
+{
+       struct isl_union_map_bin_data *data = user;
+       isl_set *set2 = *entry;
+
+       set2 = isl_set_product(isl_set_copy(data->map), isl_set_copy(set2));
+
+       data->res = isl_union_set_add_set(data->res, set2);
+
+       return 0;
+}
+
 __isl_give isl_union_set *isl_union_set_product(__isl_take isl_union_set *uset1,
        __isl_take isl_union_set *uset2)
 {
-       return isl_union_map_product(uset1, uset2);
+       return bin_op(uset1, uset2, &set_product_entry);
 }
 
 static int range_product_entry(void **entry, void *user)
@@ -1347,6 +1515,37 @@ __isl_give isl_union_map *isl_union_map_reverse(__isl_take isl_union_map *umap)
        return cond_un_op(umap, &reverse_entry);
 }
 
+static int params_entry(void **entry, void *user)
+{
+       isl_map *map = *entry;
+       isl_union_set **res = user;
+
+       *res = isl_union_set_add_set(*res, isl_map_params(isl_map_copy(map)));
+
+       return 0;
+}
+
+/* Compute the parameter domain of the given union map.
+ */
+__isl_give isl_set *isl_union_map_params(__isl_take isl_union_map *umap)
+{
+       int empty;
+
+       empty = isl_union_map_is_empty(umap);
+       if (empty < 0)
+               return isl_union_map_free(umap);
+       if (empty)
+               return isl_set_empty(isl_union_map_get_space(umap));
+       return isl_set_from_union_set(cond_un_op(umap, &params_entry));
+}
+
+/* Compute the parameter domain of the given union set.
+ */
+__isl_give isl_set *isl_union_set_params(__isl_take isl_union_set *uset)
+{
+       return isl_union_map_params(uset);
+}
+
 static int domain_entry(void **entry, void *user)
 {
        isl_map *map = *entry;
@@ -1513,6 +1712,11 @@ static int is_subset_entry(void **entry, void *user)
        entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
                                     hash, &has_dim, map->dim, 0);
        if (!entry2) {
+               int empty = isl_map_is_empty(map);
+               if (empty < 0)
+                       return -1;
+               if (empty)
+                       return 0;
                data->is_subset = 0;
                return -1;
        }
@@ -2045,6 +2249,27 @@ __isl_give isl_union_map *isl_union_map_zip(__isl_take isl_union_map *umap)
        return cond_un_op(umap, &zip_entry);
 }
 
+static int curry_entry(void **entry, void *user)
+{
+       isl_map *map = *entry;
+       isl_union_map **res = user;
+
+       if (!isl_map_can_curry(map))
+               return 0;
+
+       *res = isl_union_map_add_map(*res, isl_map_curry(isl_map_copy(map)));
+
+       return 0;
+}
+
+/* Given a union map, take the maps of the form (A -> B) -> C and
+ * return the union of the corresponding maps A -> (B -> C).
+ */
+__isl_give isl_union_map *isl_union_map_curry(__isl_take isl_union_map *umap)
+{
+       return cond_un_op(umap, &curry_entry);
+}
+
 static int lift_entry(void **entry, void *user)
 {
        isl_set *set = *entry;