isl backend: remove dependence on internal represenation of isl_constraint
[cloog.git] / source / isl / constraints.c
blob0dc3ca68cb54faf0adeb1934f3870fe23777415e
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <ctype.h>
4 #include <cloog/isl/cloog.h>
5 #include <cloog/isl/backend.h>
6 #include <isl/aff.h>
7 #include <isl/set.h>
10 #define ALLOC(type) (type*)malloc(sizeof(type))
11 #define ALLOCN(type,n) (type*)malloc((n)*sizeof(type))
13 CloogConstraintSet *cloog_constraint_set_from_isl_basic_set(struct isl_basic_set *bset)
15 return (CloogConstraintSet *)bset;
18 CloogConstraint *cloog_constraint_from_isl_constraint(struct isl_constraint *constraint)
20 return (CloogConstraint *)constraint;
23 isl_constraint *cloog_constraint_to_isl(CloogConstraint *constraint)
25 return (isl_constraint *)constraint;
28 isl_basic_set *cloog_constraints_set_to_isl(CloogConstraintSet *constraints)
30 return (isl_basic_set *)constraints;
34 /******************************************************************************
35 * Memory leaks hunting *
36 ******************************************************************************/
40 void cloog_constraint_set_free(CloogConstraintSet *constraints)
42 isl_basic_set_free(cloog_constraints_set_to_isl(constraints));
46 int cloog_constraint_set_contains_level(CloogConstraintSet *constraints,
47 int level, int nb_parameters)
49 isl_basic_set *bset;
50 bset = cloog_constraints_set_to_isl(constraints);
51 return isl_basic_set_dim(bset, isl_dim_set) >= level;
54 struct cloog_isl_dim {
55 enum isl_dim_type type;
56 int pos;
59 static struct cloog_isl_dim basic_set_cloog_dim_to_isl_dim(
60 __isl_keep isl_basic_set *bset, int pos)
62 enum isl_dim_type types[] = { isl_dim_set, isl_dim_div, isl_dim_param };
63 int i;
64 struct cloog_isl_dim ci_dim;
66 for (i = 0; i < 3; ++i) {
67 unsigned dim = isl_basic_set_dim(bset, types[i]);
68 if (pos < dim) {
69 ci_dim.type = types[i];
70 ci_dim.pos = pos;
71 return ci_dim;
73 pos -= dim;
75 assert(0);
78 static struct cloog_isl_dim set_cloog_dim_to_isl_dim(
79 CloogConstraintSet *constraints, int pos)
81 isl_basic_set *bset;
83 bset = cloog_constraints_set_to_isl(constraints);
84 return basic_set_cloog_dim_to_isl_dim(bset, pos);
87 /* Check if the variable at position level is defined by an
88 * equality. If so, return the row number. Otherwise, return -1.
90 CloogConstraint *cloog_constraint_set_defining_equality(
91 CloogConstraintSet *constraints, int level)
93 struct isl_constraint *c;
94 struct cloog_isl_dim dim;
95 isl_basic_set *bset;
97 bset = cloog_constraints_set_to_isl(constraints);
98 dim = set_cloog_dim_to_isl_dim(constraints, level - 1);
99 if (isl_basic_set_has_defining_equality(bset, dim.type, dim.pos, &c))
100 return cloog_constraint_from_isl_constraint(c);
101 else
102 return NULL;
106 /* Check if the variable (e) at position level is defined by a
107 * pair of inequalities
108 * <a, i> + -m e + <b, p> + k1 >= 0
109 * <-a, i> + m e + <-b, p> + k2 >= 0
110 * with 0 <= k1 + k2 < m
111 * If so return the row number of the upper bound and set *lower
112 * to the row number of the lower bound. If not, return -1.
114 * If the variable at position level occurs in any other constraint,
115 * then we currently return -1. The modulo guard that we would generate
116 * would still be correct, but we would also need to generate
117 * guards corresponding to the other constraints, and this has not
118 * been implemented yet.
120 CloogConstraint *cloog_constraint_set_defining_inequalities(
121 CloogConstraintSet *constraints,
122 int level, CloogConstraint **lower, int nb_par)
124 struct isl_constraint *u;
125 struct isl_constraint *l;
126 struct isl_constraint *c;
127 struct cloog_isl_dim dim;
128 struct isl_basic_set *bset;
130 bset = cloog_constraints_set_to_isl(constraints);
131 dim = set_cloog_dim_to_isl_dim(constraints, level - 1);
132 if (!isl_basic_set_has_defining_inequalities(bset, dim.type, dim.pos,
133 &l, &u))
134 return cloog_constraint_invalid();
135 for (c = isl_basic_set_first_constraint(isl_basic_set_copy(bset)); c;
136 c = isl_constraint_next(c)) {
137 if (isl_constraint_is_equal(c, l))
138 continue;
139 if (isl_constraint_is_equal(c, u))
140 continue;
141 *lower = cloog_constraint_from_isl_constraint(c);
142 if (cloog_constraint_involves(*lower, level-1)) {
143 isl_constraint_free(l);
144 isl_constraint_free(u);
145 *lower = NULL;
146 isl_constraint_free(c);
147 return NULL;
150 *lower = cloog_constraint_from_isl_constraint(l);
151 return cloog_constraint_from_isl_constraint(u);
154 int cloog_constraint_set_total_dimension(CloogConstraintSet *constraints)
156 isl_basic_set *bset;
157 bset = cloog_constraints_set_to_isl(constraints);
158 return isl_basic_set_total_dim(bset);
161 int cloog_constraint_set_n_iterators(CloogConstraintSet *constraints, int n_par)
163 isl_basic_set *bset;
164 bset = cloog_constraints_set_to_isl(constraints);
165 return isl_basic_set_dim(bset, isl_dim_set);
169 /******************************************************************************
170 * Equalities spreading functions *
171 ******************************************************************************/
174 /* Equalities are stored inside a Matrix data structure called "equal".
175 * This matrix has (nb_scattering + nb_iterators + 1) rows (i.e. total
176 * dimensions + 1, the "+ 1" is because a statement can be included inside an
177 * external loop without iteration domain), and (nb_scattering + nb_iterators +
178 * nb_parameters + 2) columns (all unknowns plus the scalar plus the equality
179 * type). The ith row corresponds to the equality "= 0" for the ith dimension
180 * iterator. The first column gives the equality type (0: no equality, then
181 * EQTYPE_* -see pprint.h-). At each recursion of pprint, if an equality for
182 * the current level is found, the corresponding row is updated. Then the
183 * equality if it exists is used to simplify expressions (e.g. if we have
184 * "i+1" while we know that "i=2", we simplify it in "3"). At the end of
185 * the pprint call, the corresponding row is reset to zero.
188 CloogEqualities *cloog_equal_alloc(int n, int nb_levels, int nb_parameters)
190 int i;
191 CloogEqualities *equal = ALLOC(CloogEqualities);
193 equal->total_dim = nb_levels - 1 + nb_parameters;
194 equal->n = n;
195 equal->constraints = ALLOCN(isl_constraint *, n);
196 equal->types = ALLOCN(int, n);
197 for (i = 0; i < n; ++i) {
198 equal->constraints[i] = NULL;
199 equal->types[i] = EQTYPE_NONE;
201 return equal;
204 int cloog_equal_total_dimension(CloogEqualities *equal)
206 return equal->total_dim;
209 void cloog_equal_free(CloogEqualities *equal)
211 int i;
213 for (i = 0; i < equal->n; ++i)
214 isl_constraint_free(equal->constraints[i]);
215 free(equal->constraints);
216 free(equal->types);
217 free(equal);
220 int cloog_equal_count(CloogEqualities *equal)
222 return equal->n;
227 * cloog_constraint_equal_type function :
228 * This function returns the type of the equality in the constraint (line) of
229 * (constraints) for the element (level). An equality is 'constant' iff all
230 * other factors are null except the constant one. It is a 'pure item' iff
231 * it is equal or opposite to a single variable or parameter.
232 * Otherwise it is an 'affine expression'.
233 * For instance:
234 * i = -13 is constant, i = j, j = -M are pure items,
235 * j = 2*M, i = j+1, 2*j = M are affine expressions.
237 * - constraints is the matrix of constraints,
238 * - level is the column number in equal of the element which is 'equal to',
240 static int cloog_constraint_equal_type(CloogConstraint *cc, int level)
242 int i;
243 isl_int c;
244 int type = EQTYPE_NONE;
245 struct isl_constraint *constraint = cloog_constraint_to_isl(cc);
247 isl_int_init(c);
248 isl_constraint_get_constant(constraint, &c);
249 if (!isl_int_is_zero(c))
250 type = EQTYPE_CONSTANT;
251 isl_constraint_get_coefficient(constraint, isl_dim_set, level - 1, &c);
252 if (!isl_int_is_one(c) && !isl_int_is_negone(c))
253 type = EQTYPE_EXAFFINE;
254 for (i = 0; i < isl_constraint_dim(constraint, isl_dim_param); ++i) {
255 isl_constraint_get_coefficient(constraint, isl_dim_param, i, &c);
256 if (isl_int_is_zero(c))
257 continue;
258 if ((!isl_int_is_one(c) && !isl_int_is_negone(c)) ||
259 type != EQTYPE_NONE) {
260 type = EQTYPE_EXAFFINE;
261 break;
263 type = EQTYPE_PUREITEM;
265 for (i = 0; i < isl_constraint_dim(constraint, isl_dim_set); ++i) {
266 if (i == level - 1)
267 continue;
268 isl_constraint_get_coefficient(constraint, isl_dim_set, i, &c);
269 if (isl_int_is_zero(c))
270 continue;
271 if ((!isl_int_is_one(c) && !isl_int_is_negone(c)) ||
272 type != EQTYPE_NONE) {
273 type = EQTYPE_EXAFFINE;
274 break;
276 type = EQTYPE_PUREITEM;
278 for (i = 0; i < isl_constraint_dim(constraint, isl_dim_div); ++i) {
279 isl_constraint_get_coefficient(constraint, isl_dim_div, i, &c);
280 if (isl_int_is_zero(c))
281 continue;
282 if ((!isl_int_is_one(c) && !isl_int_is_negone(c)) ||
283 type != EQTYPE_NONE) {
284 type = EQTYPE_EXAFFINE;
285 break;
287 type = EQTYPE_PUREITEM;
289 isl_int_clear(c);
291 if (type == EQTYPE_NONE)
292 type = EQTYPE_CONSTANT;
294 return type;
298 int cloog_equal_type(CloogEqualities *equal, int level)
300 return equal->types[level-1];
305 * cloog_equal_add function:
306 * This function updates the row (level-1) of the equality matrix (equal) with
307 * the row that corresponds to the row (line) of the matrix (matrix).
308 * - equal is the matrix of equalities,
309 * - matrix is the matrix of constraints,
310 * - level is the column number in matrix of the element which is 'equal to',
311 * - line is the line number in matrix of the constraint we want to study,
312 * - the infos structure gives the user all options on code printing and more.
314 * line is set to an invalid constraint for equalities that CLooG itself has
315 * discovered because the lower and upper bound of a loop happened to be equal.
316 * This situation shouldn't happen in the isl port since isl should
317 * have found the equality itself.
319 void cloog_equal_add(CloogEqualities *equal, CloogConstraintSet *matrix,
320 int level, CloogConstraint *line, int nb_par)
322 isl_constraint *c;
323 assert(cloog_constraint_is_valid(line));
325 equal->types[level-1] = cloog_constraint_equal_type(line, level);
326 c = cloog_constraint_to_isl(line);
327 equal->constraints[level - 1] = isl_constraint_copy(c);
332 * cloog_equal_del function :
333 * This function reset the equality corresponding to the iterator (level)
334 * in the equality matrix (equal).
335 * - July 2nd 2002: first version.
337 void cloog_equal_del(CloogEqualities *equal, int level)
339 equal->types[level-1] = EQTYPE_NONE;
340 isl_constraint_free(equal->constraints[level - 1]);
341 equal->constraints[level-1] = NULL;
346 /******************************************************************************
347 * Processing functions *
348 ******************************************************************************/
351 * Function cloog_constraint_set_normalize:
352 * This function will modify the constraint system in such a way that when
353 * there is an equality depending on the element at level 'level', there are
354 * no more (in)equalities depending on this element.
356 * The simplified form of isl automatically satisfies this condition.
358 void cloog_constraint_set_normalize(CloogConstraintSet *matrix, int level)
365 * cloog_constraint_set_copy function:
366 * this functions builds and returns a "hard copy" (not a pointer copy) of a
367 * CloogConstraintSet data structure.
369 CloogConstraintSet *cloog_constraint_set_copy(CloogConstraintSet *constraints)
371 isl_basic_set *bset;
372 bset = cloog_constraints_set_to_isl(constraints);
373 return cloog_constraint_set_from_isl_basic_set(isl_basic_set_dup(bset));
378 * cloog_constraint_set_simplify function:
379 * this function simplify all constraints inside the matrix "matrix" thanks to
380 * an equality matrix "equal" that gives for some elements of the affine
381 * constraint an equality with other elements, preferably constants.
382 * For instance, if a row of the matrix contains i+j+3>=0 and the equality
383 * matrix gives i=n and j=2, the constraint is simplified to n+3>=0. The
384 * simplified constraints are returned back inside a new simplified matrix.
385 * - matrix is the set of constraints to simplify,
386 * - equal is the matrix of equalities,
387 * - level is a level we don't want to simplify (-1 if none),
388 * - nb_par is the number of parameters of the program.
390 * isl should have performed these simplifications already in isl_set_gist.
392 CloogConstraintSet *cloog_constraint_set_simplify(CloogConstraintSet *matrix,
393 CloogEqualities *equal, int level, int nb_par)
395 return cloog_constraint_set_copy(matrix);
399 static struct cloog_isl_dim constraint_cloog_dim_to_isl_dim(
400 CloogConstraint *constraint, int pos)
402 enum isl_dim_type types[] = { isl_dim_set, isl_dim_div, isl_dim_param };
403 int i;
404 struct cloog_isl_dim ci_dim;
406 for (i = 0; i < 3; ++i) {
407 isl_constraint *c = cloog_constraint_to_isl(constraint);
408 unsigned dim = isl_constraint_dim(c, types[i]);
409 if (pos < dim) {
410 ci_dim.type = types[i];
411 ci_dim.pos = pos;
412 return ci_dim;
414 pos -= dim;
416 assert(0);
419 static struct clast_expr *div_expr(CloogConstraint *constraint, int pos,
420 CloogNames *names)
422 int i, nb_elts;
423 unsigned dim = cloog_constraint_total_dimension(constraint);
424 cloog_int_t c;
425 struct clast_reduction *r;
426 struct clast_expr *e = NULL;
427 struct isl_div *div;
429 div = isl_constraint_div(cloog_constraint_to_isl(constraint), pos);
431 cloog_int_init(c);
432 for (i = 0, nb_elts = 0; i < dim; ++i) {
433 struct cloog_isl_dim dim;
435 dim = constraint_cloog_dim_to_isl_dim(constraint, i);
436 isl_div_get_coefficient(div, dim.type, dim.pos, &c);
437 if (!cloog_int_is_zero(c))
438 ++nb_elts;
440 isl_div_get_constant(div, &c);
441 if (!cloog_int_is_zero(c))
442 ++nb_elts;
444 r = new_clast_reduction(clast_red_sum, nb_elts);
445 for (i = 0, nb_elts = 0; i < dim; ++i) {
446 struct clast_expr *v;
447 struct cloog_isl_dim dim;
449 dim = constraint_cloog_dim_to_isl_dim(constraint, i);
450 isl_div_get_coefficient(div, dim.type, dim.pos, &c);
451 if (cloog_int_is_zero(c))
452 continue;
454 v = cloog_constraint_variable_expr(constraint, 1 + i, names);
456 r->elts[nb_elts++] = &new_clast_term(c, v)->expr;
458 isl_div_get_constant(div, &c);
459 if (!cloog_int_is_zero(c))
460 r->elts[nb_elts++] = &new_clast_term(c, NULL)->expr;
462 isl_div_get_denominator(div, &c);
463 e = &new_clast_binary(clast_bin_fdiv, &r->expr, c)->expr;
465 cloog_int_clear(c);
467 isl_div_free(div);
469 return e;
473 * Return clast_expr corresponding to the variable "level" (1 based) in
474 * the given constraint.
476 struct clast_expr *cloog_constraint_variable_expr(CloogConstraint *constraint,
477 int level, CloogNames *names)
479 struct cloog_isl_dim dim;
480 const char *name;
482 assert(constraint);
484 dim = constraint_cloog_dim_to_isl_dim(constraint, level - 1);
485 if (dim.type == isl_dim_div)
486 return div_expr(constraint, dim.pos, names);
488 if (dim.type == isl_dim_set)
489 name = cloog_names_name_at_level(names, level);
490 else
491 name = names->parameters[dim.pos];
493 return &new_clast_name(name)->expr;
498 * Return true if constraint c involves variable v (zero-based).
500 int cloog_constraint_involves(CloogConstraint *constraint, int v)
502 isl_int c;
503 int res;
505 isl_int_init(c);
506 cloog_constraint_coefficient_get(constraint, v, &c);
507 res = !isl_int_is_zero(c);
508 isl_int_clear(c);
509 return res;
512 int cloog_constraint_is_lower_bound(CloogConstraint *constraint, int v)
514 isl_int c;
515 int res;
517 isl_int_init(c);
518 cloog_constraint_coefficient_get(constraint, v, &c);
519 res = isl_int_is_pos(c);
520 isl_int_clear(c);
521 return res;
524 int cloog_constraint_is_upper_bound(CloogConstraint *constraint, int v)
526 isl_int c;
527 int res;
529 isl_int_init(c);
530 cloog_constraint_coefficient_get(constraint, v, &c);
531 res = isl_int_is_neg(c);
532 isl_int_clear(c);
533 return res;
536 int cloog_constraint_is_equality(CloogConstraint *constraint)
538 return isl_constraint_is_equality(cloog_constraint_to_isl(constraint));
541 void cloog_constraint_clear(CloogConstraint *constraint)
543 isl_constraint_clear(cloog_constraint_to_isl(constraint));
546 void cloog_constraint_coefficient_get(CloogConstraint *constraint,
547 int var, cloog_int_t *val)
549 struct cloog_isl_dim dim;
550 isl_constraint *c;
552 if (!constraint)
553 return;
555 dim = constraint_cloog_dim_to_isl_dim(constraint, var);
556 c = cloog_constraint_to_isl(constraint);
557 isl_constraint_get_coefficient(c, dim.type, dim.pos, val);
560 void cloog_constraint_coefficient_set(CloogConstraint *constraint,
561 int var, cloog_int_t val)
563 struct cloog_isl_dim dim;
564 isl_constraint *c;
566 assert(constraint);
568 dim = constraint_cloog_dim_to_isl_dim(constraint, var);
569 c = cloog_constraint_to_isl(constraint);
570 isl_constraint_set_coefficient(c, dim.type, dim.pos, val);
573 void cloog_constraint_constant_get(CloogConstraint *constraint, cloog_int_t *val)
575 isl_constraint_get_constant(cloog_constraint_to_isl(constraint), val);
579 * Copy the coefficient of constraint c into dst in PolyLib order,
580 * i.e., first the coefficients of the variables, then the coefficients
581 * of the parameters and finally the constant.
583 void cloog_constraint_copy_coefficients(CloogConstraint *constraint,
584 cloog_int_t *dst)
586 int i;
587 unsigned dim;
589 dim = cloog_constraint_total_dimension(constraint);
591 for (i = 0; i < dim; ++i)
592 cloog_constraint_coefficient_get(constraint, i, dst+i);
593 cloog_constraint_constant_get(constraint, dst+dim);
596 CloogConstraint *cloog_constraint_invalid(void)
598 return NULL;
601 int cloog_constraint_is_valid(CloogConstraint *constraint)
603 return constraint != NULL;
606 int cloog_constraint_total_dimension(CloogConstraint *constraint)
608 isl_constraint *c;
609 c = cloog_constraint_to_isl(constraint);
610 return isl_constraint_dim(c, isl_dim_all);
615 * Check whether there is any need for the constraint "upper" on
616 * "level" to get reduced.
617 * In case of the isl backend, there should be no need to do so
618 * if the level corresponds to an existentially quantified variable.
619 * Moreover, the way reduction is performed does not work for such
620 * variables since its position might chance during the construction
621 * of a set for reduction.
623 int cloog_constraint_needs_reduction(CloogConstraint *upper, int level)
625 isl_basic_set *bset;
626 isl_constraint *c;
627 struct cloog_isl_dim dim;
629 c = cloog_constraint_to_isl(upper);
630 bset = isl_basic_set_from_constraint(isl_constraint_copy(c));
631 dim = basic_set_cloog_dim_to_isl_dim(bset, level - 1);
632 isl_basic_set_free(bset);
634 return dim.type == isl_dim_set;
639 * Create a CloogConstraintSet containing enough information to perform
640 * a reduction on the upper equality (in this case lower is an invalid
641 * CloogConstraint) or the pair of inequalities upper and lower
642 * from within insert_modulo_guard.
643 * In the isl backend, we return a CloogConstraintSet containing both
644 * bounds, as the stride may change during the reduction and we may
645 * need to recompute the bound on the modulo expression.
647 CloogConstraintSet *cloog_constraint_set_for_reduction(CloogConstraint *upper,
648 CloogConstraint *lower)
650 struct isl_basic_set *bset;
651 isl_constraint *c;
653 c = cloog_constraint_to_isl(upper);
654 bset = isl_basic_set_from_constraint(isl_constraint_copy(c));
655 if (cloog_constraint_is_valid(lower)) {
656 c = cloog_constraint_to_isl(lower);
657 bset = isl_basic_set_add_constraint(bset,
658 isl_constraint_copy(c));
660 return cloog_constraint_set_from_isl_basic_set(bset);
664 static int add_constant_term(CloogConstraint *c, void *user)
666 isl_int *bound = (isl_int *)user;
667 isl_int v;
669 isl_int_init(v);
671 cloog_constraint_constant_get(c, &v);
672 isl_int_add(*bound, *bound, v);
674 isl_int_clear(v);
676 return 0;
680 /* Return an isl_basic_set representation of the equality stored
681 * at position i in the given CloogEqualities.
683 static __isl_give isl_basic_set *equality_to_basic_set(CloogEqualities *equal,
684 int i)
686 isl_constraint *c;
687 isl_basic_set *bset;
688 unsigned nparam;
689 unsigned nvar;
691 c = isl_constraint_copy(equal->constraints[i]);
692 bset = isl_basic_set_from_constraint(c);
693 nparam = isl_basic_set_dim(bset, isl_dim_param);
694 nvar = isl_basic_set_dim(bset, isl_dim_set);
695 bset = isl_basic_set_add(bset, isl_dim_set,
696 equal->total_dim - (nparam + nvar));
697 return bset;
701 * Reduce the modulo guard expressed by "constraints" using equalities
702 * found in outer nesting levels (stored in "equal").
703 * The modulo guard may be an equality or a pair of inequalities.
704 * In case of a pair of inequalities, *bound contains the bound on the
705 * corresponding modulo expression. If any reduction is performed
706 * then this bound is recomputed.
708 * "level" may not correspond to an existentially quantified variable.
710 * We first check if there are any equalities we can use. If not,
711 * there is again nothing to reduce.
712 * For the actual reduction, we use isl_basic_set_gist, but this
713 * function will only perform the reduction we want here if the
714 * the variable that imposes the modulo constraint has been projected
715 * out (i.e., turned into an existentially quantified variable).
716 * After the call to isl_basic_set_gist, we need to move the
717 * existential variable back into the position where the calling
718 * function expects it (assuming there are any constraints left).
719 * We do this by adding an equality between the given dimension and
720 * the existentially quantified variable.
722 * If there are no existentially quantified variables left, then
723 * we don't need to add this equality.
724 * If, on the other hand, the resulting basic set involves more
725 * than one existentially quantified variable, then the caller
726 * will not be able to handle the result, so we just return the
727 * original input instead.
729 CloogConstraintSet *cloog_constraint_set_reduce(CloogConstraintSet *constraints,
730 int level, CloogEqualities *equal, int nb_par, cloog_int_t *bound)
732 int j;
733 isl_ctx *ctx;
734 isl_dim *idim;
735 struct isl_basic_set *eq;
736 struct isl_basic_map *id;
737 struct cloog_isl_dim dim;
738 struct isl_constraint *c;
739 struct isl_div *div;
740 unsigned constraints_dim;
741 unsigned n_div;
742 int pos;
743 isl_basic_set *bset, *orig;
745 bset = cloog_constraints_set_to_isl(constraints);
746 orig = isl_basic_set_copy(bset);
747 ctx = isl_basic_set_get_ctx(bset);
748 dim = set_cloog_dim_to_isl_dim(constraints, level - 1);
749 assert(dim.type == isl_dim_set);
751 eq = NULL;
752 for (j = 0; j < level - 1; ++j) {
753 isl_basic_set *bset_j;
754 if (equal->types[j] != EQTYPE_EXAFFINE)
755 continue;
756 bset_j = equality_to_basic_set(equal, j);
757 if (!eq)
758 eq = bset_j;
759 else
760 eq = isl_basic_set_intersect(eq, bset_j);
762 if (!eq) {
763 isl_basic_set_free(orig);
764 return cloog_constraint_set_from_isl_basic_set(bset);
767 idim = isl_dim_map_from_set(isl_basic_set_get_dim(bset));
768 id = isl_basic_map_identity(idim);
769 id = isl_basic_map_remove_dims(id, isl_dim_out, dim.pos, 1);
770 bset = isl_basic_set_apply(bset, isl_basic_map_copy(id));
771 bset = isl_basic_set_apply(bset, isl_basic_map_reverse(id));
773 constraints_dim = isl_basic_set_dim(bset, isl_dim_set);
774 eq = isl_basic_set_remove_dims(eq, isl_dim_set, constraints_dim,
775 isl_basic_set_dim(eq, isl_dim_set) - constraints_dim);
776 bset = isl_basic_set_gist(bset, eq);
777 n_div = isl_basic_set_dim(bset, isl_dim_div);
778 if (n_div > 1) {
779 isl_basic_set_free(bset);
780 return cloog_constraint_set_from_isl_basic_set(orig);
782 if (n_div < 1) {
783 isl_basic_set_free(orig);
784 return cloog_constraint_set_from_isl_basic_set(bset);
787 div = isl_basic_set_div(isl_basic_set_copy(bset), 0);
788 c = isl_equality_alloc(isl_basic_set_get_dim(bset));
789 c = isl_constraint_add_div(c, div, &pos);
790 isl_constraint_set_coefficient_si(c, isl_dim_set, dim.pos, 1);
791 isl_constraint_set_coefficient_si(c, isl_dim_div, pos, -1);
792 bset = isl_basic_set_add_constraint(bset, c);
794 isl_int_set_si(*bound, 0);
795 constraints = cloog_constraint_set_from_isl_basic_set(bset);
796 cloog_constraint_set_foreach_constraint(constraints,
797 add_constant_term, bound);
799 isl_basic_set_free(orig);
800 return cloog_constraint_set_from_isl_basic_set(bset);
803 CloogConstraint *cloog_constraint_copy(CloogConstraint *constraint)
805 return cloog_constraint_from_isl_constraint(
806 isl_constraint_copy(cloog_constraint_to_isl(constraint)));
809 void cloog_constraint_release(CloogConstraint *constraint)
811 isl_constraint_free(cloog_constraint_to_isl(constraint));
814 struct cloog_isl_foreach {
815 int (*fn)(CloogConstraint *constraint, void *user);
816 void *user;
819 static int cloog_isl_foreach_cb(__isl_take isl_constraint *c, void *user)
821 struct cloog_isl_foreach *data = (struct cloog_isl_foreach *)user;
822 int ret;
824 if (isl_constraint_is_div_constraint(c)) {
825 isl_constraint_free(c);
826 return 0;
829 ret = data->fn(cloog_constraint_from_isl_constraint(c), data->user);
831 isl_constraint_free(c);
833 return ret;
836 int cloog_constraint_set_foreach_constraint(CloogConstraintSet *constraints,
837 int (*fn)(CloogConstraint *constraint, void *user), void *user)
839 struct cloog_isl_foreach data = { fn, user };
840 isl_basic_set *bset;
842 bset = cloog_constraints_set_to_isl(constraints);
843 return isl_basic_set_foreach_constraint(bset,
844 cloog_isl_foreach_cb, &data);
847 CloogConstraint *cloog_equal_constraint(CloogEqualities *equal, int j)
849 isl_constraint *c;
851 c = isl_constraint_copy(equal->constraints[j]);
852 return cloog_constraint_from_isl_constraint(c);
855 /* Given a stride constraint on iterator i (specified by level) of the form
857 * i = f(outer iterators) + stride * f(existentials)
859 * extract f as an isl_aff.
861 static isl_aff *extract_stride_offset(__isl_keep isl_constraint *c,
862 int level, CloogStride *stride)
864 int i;
865 isl_dim *dim = isl_constraint_get_dim(c);
866 isl_local_space *ls = isl_local_space_from_dim(dim);
867 isl_aff *offset = isl_aff_zero(ls);
868 isl_int u;
869 unsigned nparam, nvar;
871 isl_int_init(u);
873 nparam = isl_constraint_dim(c, isl_dim_param);
874 nvar = isl_constraint_dim(c, isl_dim_set);
876 for (i = 0; i < nparam; ++i) {
877 isl_constraint_get_coefficient(c, isl_dim_param, i, &u);
878 isl_int_mul(u, u, stride->factor);
879 offset = isl_aff_set_coefficient(offset, isl_dim_param, i, u);
881 for (i = 0; i < nvar; ++i) {
882 if (i == level - 1)
883 continue;
884 isl_constraint_get_coefficient(c, isl_dim_set, i, &u);
885 isl_int_mul(u, u, stride->factor);
886 offset = isl_aff_set_coefficient(offset, isl_dim_set, i, u);
888 isl_constraint_get_constant(c, &u);
889 isl_int_mul(u, u, stride->factor);
890 offset = isl_aff_set_constant(offset, u);
892 isl_int_clear(u);
894 return offset;
897 /* Update the given lower bound on level such that it satisfies the stride
898 * constraint. The computation performed here is essentially the same
899 * as that performed in constraint_stride_lower_c.
901 * We update the constraint
903 * a i + f >= 0
905 * to
907 * i >= s * ceil((-f/a - d)/s) + d
909 * with s the stride and d the offset encoded in the stride constraint.
911 CloogConstraint *cloog_constraint_stride_lower_bound(CloogConstraint *c,
912 int level, CloogStride *stride)
914 isl_constraint *stride_c = cloog_constraint_to_isl(stride->constraint);
915 isl_constraint *bound = cloog_constraint_to_isl(c);
916 isl_aff *offset;
917 isl_aff *lower;
919 lower = isl_constraint_get_bound(bound, isl_dim_set, level - 1);
920 isl_constraint_free(bound);
922 offset = extract_stride_offset(stride_c, level, stride);
924 lower = isl_aff_sub(lower, isl_aff_copy(offset));
925 lower = isl_aff_scale_down(lower, stride->stride);
926 lower = isl_aff_ceil(lower);
927 lower = isl_aff_scale(lower, stride->stride);
928 lower = isl_aff_add(lower, offset);
929 lower = isl_aff_neg(lower);
930 lower = isl_aff_add_coefficient_si(lower, isl_dim_set, level - 1, 1);
932 bound = isl_inequality_from_aff(lower);
934 return cloog_constraint_from_isl_constraint(bound);