-isl-0.15-61-gcea776f
+isl-0.15-86-g595055e
isl_pw_templ.c \
isl_union_macro.h \
isl_union_templ.c \
+ isl_union_single.c \
+ isl_union_multi.c \
isl_union_eval.c \
isl_union_neg.c \
isl.py \
isl_pw_templ.c \
isl_union_macro.h \
isl_union_templ.c \
+ isl_union_single.c \
+ isl_union_multi.c \
isl_union_eval.c \
isl_union_neg.c \
isl.py \
=over
-=item * Objects of type C<isl_union_pw_multi_aff> can no longer contain
-two or more C<isl_pw_multi_aff> objects with the same domain space.
-
=item * The function C<isl_union_pw_multi_aff_add> now consistently
computes the sum on the shared definition domain.
The function C<isl_union_pw_multi_aff_union_add> has been added
The union expression types defined by C<isl>
are C<isl_union_pw_aff>, C<isl_union_pw_multi_aff>,
C<isl_union_pw_qpolynomial> and C<isl_union_pw_qpolynomial_fold>.
+In case of
+C<isl_union_pw_aff>,
+C<isl_union_pw_qpolynomial> and C<isl_union_pw_qpolynomial_fold>,
+there can be at most one base expression for a given domain space.
+In case of
+C<isl_union_pw_multi_aff>,
+there can be multiple such expressions for a given domain space,
+but the domains of these expressions need to be disjoint.
An empty union expression can be created using the following functions.
#undef PARTS
#define PARTS pw_aff
-#include <isl_union_templ.c>
+#include <isl_union_single.c>
#include <isl_union_neg.c>
static __isl_give isl_set *align_params_pw_pw_set_and(
#undef PARTS
#define PARTS pw_multi_aff
-#include <isl_union_templ.c>
+#include <isl_union_multi.c>
#include <isl_union_neg.c>
/* Given a function "cmp" that returns the set of elements where
isl_union_pw_multi_aff *upma2;
isl_union_pw_multi_aff *res;
isl_pw_multi_aff *pma;
- isl_stat (*fn)(void **entry, void *user);
+ isl_stat (*fn)(__isl_take isl_pw_multi_aff *pma, void *user);
};
/* Given an isl_pw_multi_aff from upma1, store it in data->pma
* and call data->fn for each isl_pw_multi_aff in data->upma2.
*/
-static isl_stat bin_entry(void **entry, void *user)
+static isl_stat bin_entry(__isl_take isl_pw_multi_aff *pma, void *user)
{
struct isl_union_pw_multi_aff_bin_data *data = user;
- isl_pw_multi_aff *pma = *entry;
+ isl_stat r;
data->pma = pma;
- if (isl_hash_table_foreach(data->upma2->space->ctx, &data->upma2->table,
- data->fn, data) < 0)
- return isl_stat_error;
+ r = isl_union_pw_multi_aff_foreach_pw_multi_aff(data->upma2,
+ data->fn, data);
+ isl_pw_multi_aff_free(pma);
- return isl_stat_ok;
+ return r;
}
/* Call "fn" on each pair of isl_pw_multi_affs in "upma1" and "upma2".
static __isl_give isl_union_pw_multi_aff *bin_op(
__isl_take isl_union_pw_multi_aff *upma1,
__isl_take isl_union_pw_multi_aff *upma2,
- isl_stat (*fn)(void **entry, void *user))
+ isl_stat (*fn)(__isl_take isl_pw_multi_aff *pma, void *user))
{
isl_space *space;
struct isl_union_pw_multi_aff_bin_data data = { NULL, NULL, NULL, fn };
data.upma2 = upma2;
data.res = isl_union_pw_multi_aff_alloc_same_size(upma1);
- if (isl_hash_table_foreach(upma1->space->ctx, &upma1->table,
+ if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma1,
&bin_entry, &data) < 0)
goto error;
&pw_multi_aff_flat_range_product);
}
-/* If data->pma and *entry have the same domain space, then compute
+/* If data->pma and "pma2" have the same domain space, then compute
* their flat range product and the result to data->res.
*/
-static isl_stat flat_range_product_entry(void **entry, void *user)
+static isl_stat flat_range_product_entry(__isl_take isl_pw_multi_aff *pma2,
+ void *user)
{
struct isl_union_pw_multi_aff_bin_data *data = user;
- isl_pw_multi_aff *pma2 = *entry;
if (!isl_space_tuple_is_equal(data->pma->dim, isl_dim_in,
- pma2->dim, isl_dim_in))
+ pma2->dim, isl_dim_in)) {
+ isl_pw_multi_aff_free(pma2);
return isl_stat_ok;
+ }
pma2 = isl_pw_multi_aff_flat_range_product(
- isl_pw_multi_aff_copy(data->pma),
- isl_pw_multi_aff_copy(pma2));
+ isl_pw_multi_aff_copy(data->pma), pma2);
data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma2);
/* Compute the pullback of data->pma by the function represented by "pma2",
* provided the spaces match, and add the results to data->res.
*/
-static isl_stat pullback_entry(void **entry, void *user)
+static isl_stat pullback_entry(__isl_take isl_pw_multi_aff *pma2, void *user)
{
struct isl_union_pw_multi_aff_bin_data *data = user;
- isl_pw_multi_aff *pma2 = *entry;
if (!isl_space_tuple_is_equal(data->pma->dim, isl_dim_in,
- pma2->dim, isl_dim_out))
+ pma2->dim, isl_dim_out)) {
+ isl_pw_multi_aff_free(pma2);
return isl_stat_ok;
+ }
pma2 = isl_pw_multi_aff_pullback_pw_multi_aff(
- isl_pw_multi_aff_copy(data->pma),
- isl_pw_multi_aff_copy(pma2));
+ isl_pw_multi_aff_copy(data->pma), pma2);
data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma2);
if (!data->res)
return data.res;
}
-/* Replace the entry of isl_union_pw_aff to which "entry" points
- * by its floor.
+/* Return the floor of "pa".
*/
-static isl_stat floor_entry(void **entry, void *user)
+static __isl_give isl_pw_aff *floor_entry(__isl_take isl_pw_aff *pa, void *user)
{
- isl_pw_aff **pa = (isl_pw_aff **) entry;
-
- *pa = isl_pw_aff_floor(*pa);
- if (!*pa)
- return isl_stat_error;
-
- return isl_stat_ok;
+ return isl_pw_aff_floor(pa);
}
/* Given f, return floor(f).
__isl_give isl_union_pw_aff *isl_union_pw_aff_floor(
__isl_take isl_union_pw_aff *upa)
{
- isl_ctx *ctx;
-
- upa = isl_union_pw_aff_cow(upa);
- if (!upa)
- return NULL;
-
- ctx = isl_union_pw_aff_get_ctx(upa);
- if (isl_hash_table_foreach(ctx, &upa->table, &floor_entry, NULL) < 0)
- upa = isl_union_pw_aff_free(upa);
-
- return upa;
+ return isl_union_pw_aff_transform_inplace(upa, &floor_entry, NULL);
}
/* Compute
/* Check if "pma" can be plugged into data->pa.
* If so, perform the pullback and add the result to data->res.
*/
-static isl_stat pa_pb_pma(void **entry, void *user)
+static isl_stat pa_pb_pma(__isl_take isl_pw_multi_aff *pma, void *user)
{
struct isl_union_pw_aff_pullback_upma_data *data = user;
- isl_pw_multi_aff *pma = *entry;
isl_pw_aff *pa;
if (!isl_space_tuple_is_equal(data->pa->dim, isl_dim_in,
- pma->dim, isl_dim_out))
+ pma->dim, isl_dim_out)) {
+ isl_pw_multi_aff_free(pma);
return isl_stat_ok;
+ }
- pma = isl_pw_multi_aff_copy(pma);
pa = isl_pw_aff_copy(data->pa);
pa = isl_pw_aff_pullback_pw_multi_aff(pa, pma);
/* Check if any of the elements of data->upma can be plugged into pa,
* add if so add the result to data->res.
*/
-static isl_stat upa_pb_upma(void **entry, void *user)
+static isl_stat upa_pb_upma(__isl_take isl_pw_aff *pa, void *user)
{
struct isl_union_pw_aff_pullback_upma_data *data = user;
- isl_ctx *ctx;
- isl_pw_aff *pa = *entry;
+ isl_stat r;
data->pa = pa;
- ctx = isl_union_pw_multi_aff_get_ctx(data->upma);
- if (isl_hash_table_foreach(ctx, &data->upma->table,
- &pa_pb_pma, data) < 0)
- return isl_stat_error;
+ r = isl_union_pw_multi_aff_foreach_pw_multi_aff(data->upma,
+ &pa_pb_pma, data);
+ isl_pw_aff_free(pa);
- return isl_stat_ok;
+ return r;
}
/* Compute the pullback of "upa" by the function represented by "upma".
__isl_take isl_union_pw_multi_aff *upma)
{
struct isl_union_pw_aff_pullback_upma_data data = { NULL, NULL };
- isl_ctx *ctx;
isl_space *space;
space = isl_union_pw_multi_aff_get_space(upma);
if (!upa || !upma)
goto error;
- ctx = isl_union_pw_aff_get_ctx(upa);
data.upma = upma;
data.res = isl_union_pw_aff_alloc_same_size(upa);
- if (isl_hash_table_foreach(ctx, &upa->table, &upa_pb_upma, &data) < 0)
+ if (isl_union_pw_aff_foreach_pw_aff(upa, &upa_pb_upma, &data) < 0)
data.res = isl_union_pw_aff_free(data.res);
isl_union_pw_aff_free(upa);
* Otherwise, we would indirectly intersect the build domain with itself,
* which can lead to inefficiencies, in particular if the build domain
* contains any unknown divs.
+ *
+ * The pending and generated sets are not updated by this function to
+ * match the updated domain.
+ * The caller still needs to call isl_ast_build_set_pending_generated.
*/
__isl_give isl_ast_build *isl_ast_build_set_loop_bounds(
__isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds)
if (!build)
goto error;
- bounds = isl_basic_set_preimage_multi_aff(bounds,
- isl_multi_aff_copy(build->values));
build = update_values(build, isl_basic_set_copy(bounds));
if (!build)
goto error;
- set = isl_set_from_basic_set(isl_basic_set_copy(bounds));
+ set = isl_set_from_basic_set(bounds);
if (isl_ast_build_has_affine_value(build, build->depth)) {
set = isl_set_eliminate(set, isl_dim_set, build->depth, 1);
set = isl_set_compute_divs(set);
isl_set_copy(set));
build->domain = isl_set_intersect(build->domain, set);
} else {
- isl_basic_set *generated, *pending;
-
- pending = isl_basic_set_copy(bounds);
- pending = isl_basic_set_drop_constraints_involving_dims(pending,
- isl_dim_set, build->depth, 1);
- build->pending = isl_set_intersect(build->pending,
- isl_set_from_basic_set(pending));
- generated = isl_basic_set_copy(bounds);
- generated = isl_basic_set_drop_constraints_not_involving_dims(
- generated, isl_dim_set, build->depth, 1);
- build->generated = isl_set_intersect(build->generated,
- isl_set_from_basic_set(generated));
build->domain = isl_set_intersect(build->domain, set);
build = isl_ast_build_include_stride(build);
if (!build)
goto error;
}
- isl_basic_set_free(bounds);
if (!build->domain || !build->pending || !build->generated)
return isl_ast_build_free(build);
return NULL;
}
+/* Update the pending and generated sets of "build" according to "bounds".
+ * If the build has an affine value at the current depth,
+ * then isl_ast_build_set_loop_bounds has already set the pending set.
+ * Otherwise, do it here.
+ */
+__isl_give isl_ast_build *isl_ast_build_set_pending_generated(
+ __isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds)
+{
+ isl_basic_set *generated, *pending;
+
+ if (!build)
+ goto error;
+
+ if (isl_ast_build_has_affine_value(build, build->depth)) {
+ isl_basic_set_free(bounds);
+ return build;
+ }
+
+ build = isl_ast_build_cow(build);
+ if (!build)
+ goto error;
+
+ pending = isl_basic_set_copy(bounds);
+ pending = isl_basic_set_drop_constraints_involving_dims(pending,
+ isl_dim_set, build->depth, 1);
+ build->pending = isl_set_intersect(build->pending,
+ isl_set_from_basic_set(pending));
+ generated = bounds;
+ generated = isl_basic_set_drop_constraints_not_involving_dims(
+ generated, isl_dim_set, build->depth, 1);
+ build->generated = isl_set_intersect(build->generated,
+ isl_set_from_basic_set(generated));
+
+ if (!build->pending || !build->generated)
+ return isl_ast_build_free(build);
+
+ return build;
+error:
+ isl_ast_build_free(build);
+ isl_basic_set_free(bounds);
+ return NULL;
+}
+
/* Intersect build->domain with "set", where "set" is specified
* in terms of the internal schedule domain.
*/
isl_multi_aff_copy(build->values));
}
+/* Plug in the known affine values of outer loop iterators in "bset".
+ */
+__isl_give isl_basic_set *isl_ast_build_specialize_basic_set(
+ __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset)
+{
+ if (!build)
+ return isl_basic_set_free(bset);
+
+ return isl_basic_set_preimage_multi_aff(bset,
+ isl_multi_aff_copy(build->values));
+}
+
/* Simplify the map "map" based on what we know about
* the iterators of already generated loops.
*
return NULL;
n = isl_constraint_list_n_constraint(list);
if (n == 0) {
- isl_ctx *ctx = isl_basic_set_get_ctx(bset);
+ isl_ctx *ctx = isl_constraint_list_get_ctx(list);
isl_constraint_list_free(list);
return isl_ast_expr_alloc_int_si(ctx, 1);
}
__isl_take isl_ast_build *build, __isl_take isl_space *embedding);
__isl_give isl_ast_build *isl_ast_build_set_loop_bounds(
__isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds);
+__isl_give isl_ast_build *isl_ast_build_set_pending_generated(
+ __isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds);
__isl_give isl_ast_build *isl_ast_build_detect_strides(
__isl_take isl_ast_build *build, __isl_take isl_set *set);
__isl_give isl_ast_build *isl_ast_build_include_stride(
__isl_give isl_set *isl_ast_build_get_isolated(
__isl_keep isl_ast_build *build);
+__isl_give isl_basic_set *isl_ast_build_specialize_basic_set(
+ __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset);
__isl_give isl_basic_set *isl_ast_build_compute_gist_basic_set(
__isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset);
__isl_give isl_set *isl_ast_build_specialize(__isl_keep isl_ast_build *build,
depth = isl_ast_build_get_depth(build);
sub_build = isl_ast_build_copy(build);
bounds = isl_basic_set_remove_redundancies(bounds);
+ bounds = isl_ast_build_specialize_basic_set(sub_build, bounds);
sub_build = isl_ast_build_set_loop_bounds(sub_build,
isl_basic_set_copy(bounds));
degenerate = isl_ast_build_has_value(sub_build);
eliminated = isl_ast_build_has_affine_value(sub_build, depth);
if (degenerate < 0 || eliminated < 0)
executed = isl_union_map_free(executed);
+ if (!degenerate)
+ bounds = isl_ast_build_compute_gist_basic_set(build, bounds);
+ sub_build = isl_ast_build_set_pending_generated(sub_build,
+ isl_basic_set_copy(bounds));
if (eliminated)
executed = plug_in_values(executed, sub_build);
else
graft = isl_ast_graft_alloc_from_children(children,
isl_set_copy(guard), enforced, build, sub_build);
- if (!degenerate)
- bounds = isl_ast_build_compute_gist_basic_set(build, bounds);
if (!eliminated) {
isl_ast_build *for_build;
return NULL;
}
-/* Add variables to "tab" corresponding to the elements in "list"
- * that are not set to NaN.
+/* Add variables to info->bmap and info->tab corresponding to the elements
+ * in "list" that are not set to NaN.
+ * "extra_var" is the number of these elements.
* "dim" is the offset in the variables of "tab" where we should
* start considering the elements in "list".
* When this function returns, the total number of variables in "tab"
* is equal to "dim" plus the number of elements in "list".
*/
-static int add_sub_vars(struct isl_tab *tab, __isl_keep isl_aff_list *list,
- int dim)
+static int add_sub_vars(struct isl_coalesce_info *info,
+ __isl_keep isl_aff_list *list, int dim, int extra_var)
{
int i, n;
+ isl_space *space;
+ space = isl_basic_map_get_space(info->bmap);
+ info->bmap = isl_basic_map_cow(info->bmap);
+ info->bmap = isl_basic_map_extend_space(info->bmap, space,
+ extra_var, 0, 0);
+ if (!info->bmap)
+ return -1;
n = isl_aff_list_n_aff(list);
for (i = 0; i < n; ++i) {
int is_nan;
isl_aff_free(aff);
if (is_nan < 0)
return -1;
+ if (is_nan)
+ continue;
- if (!is_nan && isl_tab_insert_var(tab, dim + i) < 0)
+ if (isl_tab_insert_var(info->tab, dim + i) < 0)
return -1;
+ if (isl_basic_map_alloc_div(info->bmap) < 0)
+ return -1;
+ if (i != n - 1)
+ isl_basic_map_swap_div(info->bmap, i, n - 1);
}
return 0;
return -1;
}
-/* Add variables to info->tab corresponding to the elements in "list"
- * that are not set to NaN. The value of the added variable
- * is fixed to the purely affine expression defined by the element.
+/* Add variables to info->tab and info->bmap corresponding to the elements
+ * in "list" that are not set to NaN. The value of the added variable
+ * in info->tab is fixed to the purely affine expression defined by the element.
* "dim" is the offset in the variables of info->tab where we should
* start considering the elements in "list".
* When this function returns, the total number of variables in info->tab
* is equal to "dim" plus the number of elements in "list".
- * Additionally, add the div constraints that have been added info->bmap
- * after the tableau was constructed to info->tab. These constraints
- * start at position "n_ineq" in info->bmap.
- * The constraints need to be added to the tableau before
- * the equalities assigning the purely affine expression
- * because the position needs to match that in info->bmap.
- * They are frozen because the corresponding added equality is a consequence
- * of the two div constraints and the other equalities, meaning that
- * the div constraints would otherwise get marked as redundant,
- * while they are only redundant with respect to the extra equalities
- * added to the tableau, which do not appear explicitly in the basic map.
*/
static int add_subs(struct isl_coalesce_info *info,
- __isl_keep isl_aff_list *list, int dim, int n_ineq)
+ __isl_keep isl_aff_list *list, int dim)
{
- int i, extra_var, extra_con;
+ int extra_var;
int n;
- unsigned n_eq = info->bmap->n_eq;
if (!list)
return -1;
n = isl_aff_list_n_aff(list);
extra_var = n - (info->tab->n_var - dim);
- extra_con = info->bmap->n_ineq - n_ineq;
if (isl_tab_extend_vars(info->tab, extra_var) < 0)
return -1;
- if (isl_tab_extend_cons(info->tab, extra_con + 2 * extra_var) < 0)
+ if (isl_tab_extend_cons(info->tab, 2 * extra_var) < 0)
return -1;
- if (add_sub_vars(info->tab, list, dim) < 0)
+ if (add_sub_vars(info, list, dim, extra_var) < 0)
return -1;
- for (i = n_ineq; i < info->bmap->n_ineq; ++i) {
- if (isl_tab_add_ineq(info->tab, info->bmap->ineq[i]) < 0)
- return -1;
- if (isl_tab_freeze_constraint(info->tab, n_eq + i) < 0)
- return -1;
- }
-
return add_sub_equalities(info->tab, list, dim);
}
* is equal to the number of integer divisions in "i", while the number
* of NaN elements in the list is equal to the number of integer divisions
* in "j".
- * Adding extra integer divisions to "j" through isl_basic_map_align_divs
- * also adds the corresponding div constraints. These need to be added
- * to the corresponding tableau as well in add_subs to maintain consistency.
*
* If no coalescing can be performed, then we need to revert basic map "j"
* to its original state. We do the same if basic map "i" gets dropped
struct isl_tab_undo *snap;
unsigned dim;
enum isl_change change;
- int n_ineq;
bmap_j = isl_basic_map_copy(info[j].bmap);
- n_ineq = info[j].bmap->n_ineq;
- info[j].bmap = isl_basic_map_align_divs(info[j].bmap, info[i].bmap);
- if (!info[j].bmap)
- goto error;
-
snap = isl_tab_snap(info[j].tab);
dim = isl_basic_map_dim(bmap_j, isl_dim_all);
dim -= isl_basic_map_dim(bmap_j, isl_dim_div);
- if (add_subs(&info[j], list, dim, n_ineq) < 0)
+ if (add_subs(&info[j], list, dim) < 0)
goto error;
change = coalesce_local_pair(i, j, info);
/* Compute a superset of the convex hull of map that is described
* by only (translates of) the constraints in the constituents of map.
+ * Handle trivial cases where map is NULL or contains at most one disjunct.
+ */
+static __isl_give isl_basic_map *map_simple_hull_trivial(
+ __isl_take isl_map *map)
+{
+ isl_basic_map *hull;
+
+ if (!map)
+ return NULL;
+ if (map->n == 0)
+ return replace_map_by_empty_basic_map(map);
+
+ hull = isl_basic_map_copy(map->p[0]);
+ isl_map_free(map);
+ return hull;
+}
+
+/* Compute a superset of the convex hull of map that is described
+ * by only (translates of) the constraints in the constituents of map.
* Translation is only allowed if "shift" is set.
*/
static __isl_give isl_basic_map *map_simple_hull(__isl_take isl_map *map,
struct isl_basic_map *affine_hull;
struct isl_basic_set *bset = NULL;
- if (!map)
- return NULL;
- if (map->n == 0)
- return replace_map_by_empty_basic_map(map);
- if (map->n == 1) {
- hull = isl_basic_map_copy(map->p[0]);
- isl_map_free(map);
- return hull;
- }
+ if (!map || map->n <= 1)
+ return map_simple_hull_trivial(map);
map = isl_map_detect_equalities(map);
+ if (!map || map->n <= 1)
+ return map_simple_hull_trivial(map);
affine_hull = isl_map_affine_hull(isl_map_copy(map));
map = isl_map_align_divs(map);
model = map ? isl_basic_map_copy(map->p[0]) : NULL;
isl_mat_free(U);
if (T2) {
isl_mat_free(*T2);
- *T2 = NULL;
+ *T2 = isl_mat_alloc(ctx, 0, 1 + dim);
}
return isl_mat_alloc(ctx, 1 + dim, 0);
}
#define NO_SUB
-#include <isl_union_templ.c>
+#include <isl_union_single.c>
#include <isl_union_eval.c>
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_empty(enum isl_fold type,
#undef PARTS
#define PARTS pw_qpolynomial
-#include <isl_union_templ.c>
+#include <isl_union_single.c>
#include <isl_union_eval.c>
#include <isl_union_neg.c>
return NULL;
}
-static isl_stat poly_entry(void **entry, void *user)
+static __isl_give isl_pw_qpolynomial *poly_entry(
+ __isl_take isl_pw_qpolynomial *pwqp, void *user)
{
int *sign = user;
- isl_pw_qpolynomial **pwqp = (isl_pw_qpolynomial **)entry;
- *pwqp = isl_pw_qpolynomial_to_polynomial(*pwqp, *sign);
-
- return *pwqp ? isl_stat_ok : isl_stat_error;
+ return isl_pw_qpolynomial_to_polynomial(pwqp, *sign);
}
__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_to_polynomial(
__isl_take isl_union_pw_qpolynomial *upwqp, int sign)
{
- upwqp = isl_union_pw_qpolynomial_cow(upwqp);
- if (!upwqp)
- return NULL;
-
- if (isl_hash_table_foreach(upwqp->space->ctx, &upwqp->table,
- &poly_entry, &sign) < 0)
- goto error;
-
- return upwqp;
-error:
- isl_union_pw_qpolynomial_free(upwqp);
- return NULL;
+ return isl_union_pw_qpolynomial_transform_inplace(upwqp,
+ &poly_entry, &sign);
}
__isl_give isl_basic_map *isl_basic_map_from_qpolynomial(
return 0;
}
+static int test_simple_hull(struct isl_ctx *ctx)
+{
+ const char *str;
+ isl_set *set;
+ isl_basic_set *bset;
+ isl_bool is_empty;
+
+ str = "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x;"
+ "[y, x] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }";
+ set = isl_set_read_from_str(ctx, str);
+ bset = isl_set_simple_hull(set);
+ is_empty = isl_basic_set_is_empty(bset);
+ isl_basic_set_free(bset);
+
+ if (is_empty == isl_bool_error)
+ return -1;
+
+ if (is_empty == isl_bool_false)
+ isl_die(ctx, isl_error_unknown, "Empty set should be detected",
+ return -1);
+
+ return 0;
+}
+
void test_convex_hull_case(struct isl_ctx *ctx, const char *name)
{
char *filename;
"32e0 >= -31 + i2 and 32e0 <= 30 + i2 and 32e0 <= 31 + i1 and "
"32e0 <= 31 + i0)) or "
"i0 >= 0 }" },
+ { 1, "{ [a, b, c] : 2b = 1 + a and 2c = 2 + a; [0, 0, 0] }" },
};
/* A specialized coalescing test case that would result
{ &isl_union_pw_multi_aff_union_add, "{ A[] -> [0]; B[0] -> [1] }",
"{ B[x] -> [2] : x >= 0 }",
"{ A[] -> [0]; B[0] -> [3]; B[x] -> [2] : x >= 1 }" },
+ { &isl_union_pw_multi_aff_pullback_union_pw_multi_aff,
+ "{ A[] -> B[0]; C[x] -> B[1] : x < 10; C[y] -> B[2] : y >= 10 }",
+ "{ D[i] -> A[] : i < 0; D[i] -> C[i + 5] : i >= 0 }",
+ "{ D[i] -> B[0] : i < 0; D[i] -> B[1] : 0 <= i < 5; "
+ "D[i] -> B[2] : i >= 5 }" },
+ { &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
+ "{ B[x] -> C[2] : x > 0 }",
+ "{ B[x] -> A[1] : x <= 0; B[x] -> C[2] : x > 0 }" },
+ { &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
+ "{ B[x] -> A[2] : x >= 0 }",
+ "{ B[x] -> A[1] : x < 0; B[x] -> A[2] : x > 0; B[0] -> A[3] }" },
};
/* Perform some basic tests of binary operations on
return 0;
}
+struct {
+ __isl_give isl_union_pw_multi_aff *(*fn)(
+ __isl_take isl_union_pw_multi_aff *upma1,
+ __isl_take isl_union_pw_multi_aff *upma2);
+ const char *arg1;
+ const char *arg2;
+} upma_bin_fail_tests[] = {
+ { &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
+ "{ B[x] -> C[2] : x >= 0 }" },
+};
+
+/* Perform some basic tests of binary operations on
+ * isl_union_pw_multi_aff objects that are expected to fail.
+ */
+static int test_bin_upma_fail(isl_ctx *ctx)
+{
+ int i, n;
+ isl_union_pw_multi_aff *upma1, *upma2;
+ int on_error;
+
+ on_error = isl_options_get_on_error(ctx);
+ isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE);
+ n = ARRAY_SIZE(upma_bin_fail_tests);
+ for (i = 0; i < n; ++i) {
+ upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
+ upma_bin_fail_tests[i].arg1);
+ upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
+ upma_bin_fail_tests[i].arg2);
+ upma1 = upma_bin_fail_tests[i].fn(upma1, upma2);
+ isl_union_pw_multi_aff_free(upma1);
+ if (upma1)
+ break;
+ }
+ isl_options_set_on_error(ctx, on_error);
+ if (i < n)
+ isl_die(ctx, isl_error_unknown,
+ "operation not expected to succeed", return -1);
+
+ return 0;
+}
+
int test_aff(isl_ctx *ctx)
{
const char *str;
return -1;
if (test_bin_upma(ctx) < 0)
return -1;
+ if (test_bin_upma_fail(ctx) < 0)
+ return -1;
space = isl_space_set_alloc(ctx, 0, 1);
ls = isl_local_space_from_space(space);
{ "parse", &test_parse },
{ "single-valued", &test_sv },
{ "affine hull", &test_affine_hull },
+ { "simple_hull", &test_simple_hull },
{ "coalesce", &test_coalesce },
{ "factorize", &test_factorize },
{ "subset", &test_subset },
#include <isl_union_macro.h>
-/* Replace *entry by its opposite.
- *
- * Return isl_stat_ok on success and isl_stat_error on error.
+/* Return the opposite of "part".
*/
-static isl_stat FN(UNION,neg_entry)(void **entry, void *user)
+static __isl_give PART *FN(UNION,neg_entry)(__isl_take PART *part, void *user)
{
- PW **pw = (PW **) entry;
-
- *pw = FN(PW,neg)(*pw);
-
- return *pw ? isl_stat_ok : isl_stat_error;
+ return FN(PART,neg)(part);
}
/* Return the opposite of "u".
*/
__isl_give UNION *FN(UNION,neg)(__isl_take UNION *u)
{
- u = FN(UNION,cow)(u);
- if (!u)
- return NULL;
-
- if (isl_hash_table_foreach(u->space->ctx, &u->table,
- &FN(UNION,neg_entry), NULL) < 0)
- return FN(UNION,free)(u);
-
- return u;
+ return FN(UNION,transform_inplace)(u, &FN(UNION,neg_entry), NULL);
}
* and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
*/
-#include <isl_hash_private.h>
-#include <isl_union_macro.h>
-
-/* A union of expressions defined over different domain spaces.
- * "space" describes the parameters.
- * The entries of "table" are keyed on the domain space of the entry.
- */
-struct UNION {
- int ref;
-#ifdef HAS_TYPE
- enum isl_fold type;
-#endif
- isl_space *space;
-
- struct isl_hash_table table;
-};
-
__isl_give UNION *FN(UNION,cow)(__isl_take UNION *u);
isl_ctx *FN(UNION,get_ctx)(__isl_keep UNION *u)
return u;
}
-/* Return the number of base expressions in "u".
- */
-int FN(FN(UNION,n),PARTS)(__isl_keep UNION *u)
-{
- return u ? u->table.n : 0;
-}
-
-S(UNION,foreach_data)
-{
- isl_stat (*fn)(__isl_take PART *part, void *user);
- void *user;
-};
-
-static isl_stat FN(UNION,call_on_copy)(void **entry, void *user)
-{
- PART *part = *entry;
- S(UNION,foreach_data) *data = (S(UNION,foreach_data) *)user;
-
- return data->fn(FN(PART,copy)(part), data->user);
-}
-
-isl_stat FN(FN(UNION,foreach),PARTS)(__isl_keep UNION *u,
- isl_stat (*fn)(__isl_take PART *part, void *user), void *user)
-{
- S(UNION,foreach_data) data = { fn, user };
-
- if (!u)
- return isl_stat_error;
-
- return isl_hash_table_foreach(u->space->ctx, &u->table,
- &FN(UNION,call_on_copy), &data);
-}
-
-/* Is the domain space of "entry" equal to the domain of "space"?
- */
-static int FN(UNION,has_same_domain_space)(const void *entry, const void *val)
-{
- PART *part = (PART *)entry;
- isl_space *space = (isl_space *) val;
-
- if (isl_space_is_set(space))
- return isl_space_is_set(part->dim);
-
- return isl_space_tuple_is_equal(part->dim, isl_dim_in,
- space, isl_dim_in);
-}
-
-/* Return the entry, if any, in "u" that lives in "space".
- * If "reserve" is set, then an entry is created if it does not exist yet.
- * Return NULL on error and isl_hash_table_entry_none if no entry was found.
- * Note that when "reserve" is set, the function will never return
- * isl_hash_table_entry_none.
- *
- * First look for the entry (if any) with the same domain space.
- * If it exists, then check if the range space also matches.
- */
-static struct isl_hash_table_entry *FN(UNION,find_part_entry)(
- __isl_keep UNION *u, __isl_keep isl_space *space, int reserve)
-{
- isl_ctx *ctx;
- uint32_t hash;
- struct isl_hash_table_entry *entry;
- isl_bool equal;
- PART *part;
-
- if (!u || !space)
- return NULL;
-
- ctx = FN(UNION,get_ctx)(u);
- hash = isl_space_get_domain_hash(space);
- entry = isl_hash_table_find(ctx, &u->table, hash,
- &FN(UNION,has_same_domain_space), space, reserve);
- if (!entry)
- return reserve ? NULL : isl_hash_table_entry_none;
- if (reserve && !entry->data)
- return entry;
- part = entry->data;
- equal = isl_space_tuple_is_equal(part->dim, isl_dim_out,
- space, isl_dim_out);
- if (equal < 0)
- return NULL;
- if (equal)
- return entry;
- if (!reserve)
- return isl_hash_table_entry_none;
- isl_die(FN(UNION,get_ctx)(u), isl_error_invalid,
- "union expression can only contain a single "
- "expression over a given domain", return NULL);
-}
-
-/* Remove "part_entry" from the hash table of "u".
- */
-static __isl_give UNION *FN(UNION,remove_part_entry)(__isl_take UNION *u,
- struct isl_hash_table_entry *part_entry)
-{
- isl_ctx *ctx;
-
- if (!u || !part_entry)
- return FN(UNION,free)(u);
-
- ctx = FN(UNION,get_ctx)(u);
- isl_hash_table_remove(ctx, &u->table, part_entry);
- FN(PART,free)(part_entry->data);
-
- return u;
-}
-
/* Extract the element of "u" living in "space" (ignoring parameters).
*
* Return the ZERO element if "u" does not contain any element
/* Add "part" to "u".
* If "disjoint" is set, then "u" is not allowed to already have
- * a part that is defined on the same space as "part".
+ * a part that is defined over a domain that overlaps with the domain
+ * of "part".
* Otherwise, compute the union sum of "part" and the part in "u"
* defined on the same space.
*/
if (!u)
goto error;
+ if (FN(UNION,check_disjoint_domain_other)(u, part) < 0)
+ goto error;
entry = FN(UNION,find_part_entry)(u, part->dim, 1);
if (!entry)
goto error;
if (!entry->data)
entry->data = part;
else {
- if (disjoint)
- isl_die(FN(UNION,get_ctx)(u), isl_error_invalid,
- "additional part should live on separate "
- "space", goto error);
+ if (disjoint &&
+ FN(UNION,check_disjoint_domain)(entry->data, part) < 0)
+ goto error;
entry->data = FN(PART,union_add_)(entry->data,
FN(PART,copy)(part));
if (!entry->data)
return FN(UNION,alloc_same_size_on_space)(u, FN(UNION,get_space)(u));
}
-/* Call "fn" on each part entry of "u".
- */
-static isl_stat FN(UNION,foreach_inplace)(__isl_keep UNION *u,
- isl_stat (*fn)(void **part, void *user), void *user)
-{
- isl_ctx *ctx;
-
- if (!u)
- return isl_stat_error;
- ctx = FN(UNION,get_ctx)(u);
- return isl_hash_table_foreach(ctx, &u->table, fn, user);
-}
-
/* Internal data structure for isl_union_*_transform_space.
* "fn' is applied to each entry in the input.
* "res" collects the results.
return FN(UNION,transform_space)(u, FN(UNION,get_space)(u), fn, user);
}
+/* Apply data->fn to *part and store the result back into *part.
+ */
+static isl_stat FN(UNION,transform_inplace_entry)(void **part, void *user)
+{
+ S(UNION,transform_data) *data = (S(UNION,transform_data) *) user;
+
+ *part = data->fn(*part, data->user);
+ if (!*part)
+ return isl_stat_error;
+ return isl_stat_ok;
+}
+
+/* Update "u" by applying "fn" to each entry.
+ * This operation is assumed not to change the number of entries nor
+ * the spaces of the entries.
+ *
+ * If there is only one reference to "u", then change "u" inplace.
+ * Otherwise, create a new UNION from "u" and discard the original.
+ */
+static __isl_give UNION *FN(UNION,transform_inplace)(__isl_take UNION *u,
+ __isl_give PART *(*fn)(__isl_take PART *part, void *user), void *user)
+{
+ isl_bool single_ref;
+
+ single_ref = FN(UNION,has_single_reference)(u);
+ if (single_ref < 0)
+ return FN(UNION,free)(u);
+ if (single_ref) {
+ S(UNION,transform_data) data = { fn, user };
+ if (FN(UNION,foreach_inplace)(u,
+ &FN(UNION,transform_inplace_entry), &data) < 0)
+ return FN(UNION,free)(u);
+ return u;
+ }
+ return FN(UNION,transform)(u, fn, user);
+}
+
/* An isl_union_*_transform callback for use in isl_union_*_dup
* that simply returns "part".
*/
return FN(UNION,dup)(u);
}
-static isl_stat FN(UNION,free_u_entry)(void **entry, void *user)
-{
- PART *part = *entry;
- FN(PART,free)(part);
- return isl_stat_ok;
-}
-
__isl_null UNION *FN(UNION,free)(__isl_take UNION *u)
{
if (!u)
__isl_give PART *(*fn)(__isl_take PART *, __isl_take PART *);
};
-/* Check if data->u2 has an element living in the same space as *entry.
+/* Check if data->u2 has an element living in the same space as "part".
* If so, call data->fn on the two elements and add the result to
* data->res.
*/
-static isl_stat FN(UNION,match_bin_entry)(void **entry, void *user)
+static isl_stat FN(UNION,match_bin_entry)(__isl_take PART *part, void *user)
{
S(UNION,match_bin_data) *data = user;
struct isl_hash_table_entry *entry2;
isl_space *space;
- PART *part = *entry;
PART *part2;
space = FN(PART,get_space)(part);
entry2 = FN(UNION,find_part_entry)(data->u2, space, 0);
isl_space_free(space);
if (!entry2)
- return isl_stat_error;
- if (entry2 == isl_hash_table_entry_none)
+ goto error;
+ if (entry2 == isl_hash_table_entry_none) {
+ FN(PART,free)(part);
return isl_stat_ok;
+ }
part2 = entry2->data;
if (!isl_space_tuple_is_equal(part->dim, isl_dim_out,
part2->dim, isl_dim_out))
isl_die(FN(UNION,get_ctx)(data->u2), isl_error_invalid,
"entries should have the same range space",
- return isl_stat_error);
+ goto error);
- part = FN(PART, copy)(part);
part = data->fn(part, FN(PART, copy)(entry2->data));
data->res = FN(FN(UNION,add),PARTS)(data->res, part);
return isl_stat_error;
return isl_stat_ok;
+error:
+ FN(PART,free)(part);
+ return isl_stat_error;
}
/* This function is currently only used from isl_polynomial.c
data.u2 = u2;
data.res = FN(UNION,alloc_same_size)(u1);
- if (isl_hash_table_foreach(u1->space->ctx, &u1->table,
+ if (FN(FN(UNION,foreach),PARTS)(u1,
&FN(UNION,match_bin_entry), &data) < 0)
goto error;
}
/* Find the set in data->uset that lives in the same space as the domain
- * of *entry, apply data->fn to *entry and this set (if any), and add
+ * of "part", apply data->fn to *entry and this set (if any), and add
* the result to data->res.
*/
-static isl_stat FN(UNION,match_domain_entry)(void **entry, void *user)
+static isl_stat FN(UNION,match_domain_entry)(__isl_take PART *part, void *user)
{
S(UNION,match_domain_data) *data = user;
uint32_t hash;
struct isl_hash_table_entry *entry2;
- PW *pw = *entry;
isl_space *space;
- space = FN(PW,get_domain_space)(pw);
+ space = FN(PART,get_domain_space)(part);
hash = isl_space_get_hash(space);
entry2 = isl_hash_table_find(data->uset->dim->ctx, &data->uset->table,
hash, &FN(UNION,set_has_dim), space, 0);
isl_space_free(space);
- if (!entry2)
+ if (!entry2) {
+ FN(PART,free)(part);
return isl_stat_ok;
+ }
- pw = FN(PW,copy)(pw);
- pw = data->fn(pw, isl_set_copy(entry2->data));
+ part = data->fn(part, isl_set_copy(entry2->data));
- data->res = FN(FN(UNION,add),PARTS)(data->res, pw);
+ data->res = FN(FN(UNION,add),PARTS)(data->res, part);
if (!data->res)
return isl_stat_error;
data.uset = uset;
data.res = FN(UNION,alloc_same_size)(u);
- if (isl_hash_table_foreach(u->space->ctx, &u->table,
+ if (FN(FN(UNION,foreach),PARTS)(u,
&FN(UNION,match_domain_entry), &data) < 0)
goto error;
}
#endif
-static isl_stat FN(UNION,mul_isl_int_entry)(void **entry, void *user)
+static __isl_give PART *FN(UNION,mul_isl_int_entry)(__isl_take PART *part,
+ void *user)
{
- PW **pw = (PW **)entry;
isl_int *v = user;
- *pw = FN(PW,mul_isl_int)(*pw, *v);
- if (!*pw)
- return isl_stat_error;
-
- return isl_stat_ok;
+ return FN(PW,mul_isl_int)(part, *v);
}
__isl_give UNION *FN(UNION,mul_isl_int)(__isl_take UNION *u, isl_int v)
return zero;
}
- u = FN(UNION,cow)(u);
+ u = FN(UNION,transform_inplace)(u, &FN(UNION,mul_isl_int_entry), &v);
if (isl_int_is_neg(v))
u = FN(UNION,negate_type)(u);
- if (!u)
- return NULL;
-
- if (isl_hash_table_foreach(u->space->ctx, &u->table,
- &FN(UNION,mul_isl_int_entry), &v) < 0)
- goto error;
return u;
-error:
- FN(UNION,free)(u);
- return NULL;
}
-/* Multiply *entry by the isl_val "user".
- *
- * Return 0 on success and -1 on error.
+/* Multiply "part" by the isl_val "user" and return the result.
*/
-static isl_stat FN(UNION,scale_val_entry)(void **entry, void *user)
+static __isl_give PART *FN(UNION,scale_val_entry)(__isl_take PART *part,
+ void *user)
{
- PW **pw = (PW **)entry;
isl_val *v = user;
- *pw = FN(PW,scale_val)(*pw, isl_val_copy(v));
- if (!*pw)
- return isl_stat_error;
-
- return isl_stat_ok;
+ return FN(PART,scale_val)(part, isl_val_copy(v));
}
/* Multiply "u" by "v" and return the result.
isl_die(isl_val_get_ctx(v), isl_error_invalid,
"expecting rational factor", goto error);
- u = FN(UNION,cow)(u);
+ u = FN(UNION,transform_inplace)(u, &FN(UNION,scale_val_entry), v);
if (isl_val_is_neg(v))
u = FN(UNION,negate_type)(u);
- if (!u)
- return NULL;
-
- if (isl_hash_table_foreach(u->space->ctx, &u->table,
- &FN(UNION,scale_val_entry), v) < 0)
- goto error;
isl_val_free(v);
return u;
return NULL;
}
-/* Divide *entry by the isl_val "user".
- *
- * Return 0 on success and -1 on error.
+/* Divide "part" by the isl_val "user" and return the result.
*/
-static isl_stat FN(UNION,scale_down_val_entry)(void **entry, void *user)
+static __isl_give PART *FN(UNION,scale_down_val_entry)(__isl_take PART *part,
+ void *user)
{
- PW **pw = (PW **)entry;
isl_val *v = user;
- *pw = FN(PW,scale_down_val)(*pw, isl_val_copy(v));
- if (!*pw)
- return isl_stat_error;
-
- return isl_stat_ok;
+ return FN(PART,scale_down_val)(part, isl_val_copy(v));
}
/* Divide "u" by "v" and return the result.
isl_die(isl_val_get_ctx(v), isl_error_invalid,
"cannot scale down by zero", goto error);
- u = FN(UNION,cow)(u);
+ u = FN(UNION,transform_inplace)(u, &FN(UNION,scale_down_val_entry), v);
if (isl_val_is_neg(v))
u = FN(UNION,negate_type)(u);
- if (!u)
- return NULL;
-
- if (isl_hash_table_foreach(FN(UNION,get_ctx)(u), &u->table,
- &FN(UNION,scale_down_val_entry), v) < 0)
- goto error;
isl_val_free(v);
return u;
isl_bool FN(UNION,plain_is_equal)(__isl_keep UNION *u1, __isl_keep UNION *u2)
{
S(UNION,plain_is_equal_data) data = { NULL, isl_bool_true };
+ int n1, n2;
if (!u1 || !u2)
return isl_bool_error;
return isl_bool_true;
if (u1->table.n != u2->table.n)
return isl_bool_false;
+ n1 = FN(FN(UNION,n),PARTS)(u1);
+ n2 = FN(FN(UNION,n),PARTS)(u2);
+ if (n1 < 0 || n2 < 0)
+ return isl_bool_error;
+ if (n1 != n2)
+ return isl_bool_false;
u1 = FN(UNION,copy)(u1);
u2 = FN(UNION,copy)(u2);
# compiler: $LTCC
# compiler flags: $LTCFLAGS
# linker: $LD (gnu? $with_gnu_ld)
-# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.11
+# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.10ubuntu1
# automake: $automake_version
# autoconf: $autoconf_version
#
PROGRAM=libtool
PACKAGE=libtool
-VERSION="2.4.2 Debian-2.4.2-1.11"
+VERSION="2.4.2 Debian-2.4.2-1.10ubuntu1"
TIMESTAMP=""
package_revision=1.3337
for (int c2 = max(c1 + 24, -2 * c1 + 30); c2 <= c1 - (3 * c0 + 17) / 14 + 56; c2 += 1)
S1(c0, c1, c2);
}
- if (c0 >= 79 && c0 % 14 >= 9) {
+ if (c0 >= 70 && c0 % 14 >= 9) {
for (int c2 = max(c0 / 14 + 19, -((3 * c0 + 14) / 14) + c0 / 14 + 44); c2 <= -((3 * c0 + 17) / 14) + c0 / 14 + 51; c2 += 1)
S1(c0, c0 / 14 - 5, c2);
} else if (c0 <= 69 && c0 % 14 >= 9) {
for (int c0 = 0; c0 <= 1; c0 += 1)
for (int c5 = 0; c5 <= 31; c5 += 1)
for (int c6 = max(0, 2 * ((length - 1) % 16) + 2 * c5 - 60); c6 <= 30; c6 += 1) {
- if (length + c5 >= ((length - 1) % 32) + 2 && (length - 1) % 32 >= c5 && 2 * ((length - 1) % 32) + c6 >= 2 * c5 && 2 * c5 + 30 >= 2 * ((length - 1) % 32) + c6 && 2 * ((length - 1) % 32) + c6 == 2 * ((length - 1) % 16) + 2 * c5 && (2 * c5 - c6) % 32 == 0)
+ if (2 * length + c6 >= 2 * ((length - 1) % 16) + 4 && 2 * ((length - 1) % 16) >= c6 && 2 * ((length - 1) % 16) + 2 * c5 >= c6 && c6 + 62 >= 2 * ((length - 1) % 16) + 2 * c5 && 2 * ((length - 1) % 16) + 2 * c5 == 2 * ((length - 1) % 32) + c6 && (2 * c5 - c6) % 32 == 0)
S_3(c0, 0, (c6 / 2) - ((length - 1) % 16) + length - 1);
if (length <= 16 && length >= c5 + 1 && c6 >= 1 && length >= c6)
S_0(c0, c5, c6 - 1);