isl backend: remove uses of isl_constraint_add_div
[cloog/uuh.git] / source / isl / constraints.c
blob873a0b93e1fc02f45b2b9e57ea82e01d50d7d6a1
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 struct cloog_isl_other {
107 int level;
108 int found;
109 isl_constraint *u;
110 isl_constraint *l;
114 /* Set other->found to 1 if the given constraint involves other->level
115 * and is different from other->u and other->l.
117 static int check_other_constraint(__isl_take isl_constraint *c, void *user)
119 struct cloog_isl_other *other = user;
120 CloogConstraint *cc;
122 if (!isl_constraint_is_equal(c, other->l) &&
123 !isl_constraint_is_equal(c, other->u)) {
124 cc = cloog_constraint_from_isl_constraint(c);
125 if (cloog_constraint_involves(cc, other->level - 1))
126 other->found = 1;
129 isl_constraint_free(c);
131 return other->found ? -1 : 0;
135 /* Check if the variable (e) at position level is defined by a
136 * pair of inequalities
137 * <a, i> + -m e + <b, p> + k1 >= 0
138 * <-a, i> + m e + <-b, p> + k2 >= 0
139 * with 0 <= k1 + k2 < m
140 * If so return the row number of the upper bound and set *lower
141 * to the row number of the lower bound. If not, return -1.
143 * If the variable at position level occurs in any other constraint,
144 * then we currently return -1. The modulo guard that we would generate
145 * would still be correct, but we would also need to generate
146 * guards corresponding to the other constraints, and this has not
147 * been implemented yet.
149 CloogConstraint *cloog_constraint_set_defining_inequalities(
150 CloogConstraintSet *constraints,
151 int level, CloogConstraint **lower, int nb_par)
153 struct isl_constraint *u;
154 struct isl_constraint *l;
155 struct cloog_isl_dim dim;
156 struct isl_basic_set *bset;
157 struct cloog_isl_other other;
159 bset = cloog_constraints_set_to_isl(constraints);
160 dim = set_cloog_dim_to_isl_dim(constraints, level - 1);
161 if (!isl_basic_set_has_defining_inequalities(bset, dim.type, dim.pos,
162 &l, &u))
163 return cloog_constraint_invalid();
165 other.l = l;
166 other.u = u;
167 other.found = 0;
168 other.level = level;
169 isl_basic_set_foreach_constraint(bset, &check_other_constraint, &other);
170 if (other.found) {
171 isl_constraint_free(l);
172 isl_constraint_free(u);
173 *lower = NULL;
174 return NULL;
176 *lower = cloog_constraint_from_isl_constraint(l);
177 return cloog_constraint_from_isl_constraint(u);
180 int cloog_constraint_set_total_dimension(CloogConstraintSet *constraints)
182 isl_basic_set *bset;
183 bset = cloog_constraints_set_to_isl(constraints);
184 return isl_basic_set_total_dim(bset);
187 int cloog_constraint_set_n_iterators(CloogConstraintSet *constraints, int n_par)
189 isl_basic_set *bset;
190 bset = cloog_constraints_set_to_isl(constraints);
191 return isl_basic_set_dim(bset, isl_dim_set);
195 /******************************************************************************
196 * Equalities spreading functions *
197 ******************************************************************************/
200 /* Equalities are stored inside a Matrix data structure called "equal".
201 * This matrix has (nb_scattering + nb_iterators + 1) rows (i.e. total
202 * dimensions + 1, the "+ 1" is because a statement can be included inside an
203 * external loop without iteration domain), and (nb_scattering + nb_iterators +
204 * nb_parameters + 2) columns (all unknowns plus the scalar plus the equality
205 * type). The ith row corresponds to the equality "= 0" for the ith dimension
206 * iterator. The first column gives the equality type (0: no equality, then
207 * EQTYPE_* -see pprint.h-). At each recursion of pprint, if an equality for
208 * the current level is found, the corresponding row is updated. Then the
209 * equality if it exists is used to simplify expressions (e.g. if we have
210 * "i+1" while we know that "i=2", we simplify it in "3"). At the end of
211 * the pprint call, the corresponding row is reset to zero.
214 CloogEqualities *cloog_equal_alloc(int n, int nb_levels, int nb_parameters)
216 int i;
217 CloogEqualities *equal = ALLOC(CloogEqualities);
219 equal->total_dim = nb_levels - 1 + nb_parameters;
220 equal->n = n;
221 equal->constraints = ALLOCN(isl_constraint *, n);
222 equal->types = ALLOCN(int, n);
223 for (i = 0; i < n; ++i) {
224 equal->constraints[i] = NULL;
225 equal->types[i] = EQTYPE_NONE;
227 return equal;
230 int cloog_equal_total_dimension(CloogEqualities *equal)
232 return equal->total_dim;
235 void cloog_equal_free(CloogEqualities *equal)
237 int i;
239 for (i = 0; i < equal->n; ++i)
240 isl_constraint_free(equal->constraints[i]);
241 free(equal->constraints);
242 free(equal->types);
243 free(equal);
246 int cloog_equal_count(CloogEqualities *equal)
248 return equal->n;
253 * cloog_constraint_equal_type function :
254 * This function returns the type of the equality in the constraint (line) of
255 * (constraints) for the element (level). An equality is 'constant' iff all
256 * other factors are null except the constant one. It is a 'pure item' iff
257 * it is equal or opposite to a single variable or parameter.
258 * Otherwise it is an 'affine expression'.
259 * For instance:
260 * i = -13 is constant, i = j, j = -M are pure items,
261 * j = 2*M, i = j+1, 2*j = M are affine expressions.
263 * - constraints is the matrix of constraints,
264 * - level is the column number in equal of the element which is 'equal to',
266 static int cloog_constraint_equal_type(CloogConstraint *cc, int level)
268 int i;
269 isl_int c;
270 int type = EQTYPE_NONE;
271 struct isl_constraint *constraint = cloog_constraint_to_isl(cc);
273 isl_int_init(c);
274 isl_constraint_get_constant(constraint, &c);
275 if (!isl_int_is_zero(c))
276 type = EQTYPE_CONSTANT;
277 isl_constraint_get_coefficient(constraint, isl_dim_set, level - 1, &c);
278 if (!isl_int_is_one(c) && !isl_int_is_negone(c))
279 type = EQTYPE_EXAFFINE;
280 for (i = 0; i < isl_constraint_dim(constraint, isl_dim_param); ++i) {
281 isl_constraint_get_coefficient(constraint, isl_dim_param, i, &c);
282 if (isl_int_is_zero(c))
283 continue;
284 if ((!isl_int_is_one(c) && !isl_int_is_negone(c)) ||
285 type != EQTYPE_NONE) {
286 type = EQTYPE_EXAFFINE;
287 break;
289 type = EQTYPE_PUREITEM;
291 for (i = 0; i < isl_constraint_dim(constraint, isl_dim_set); ++i) {
292 if (i == level - 1)
293 continue;
294 isl_constraint_get_coefficient(constraint, isl_dim_set, i, &c);
295 if (isl_int_is_zero(c))
296 continue;
297 if ((!isl_int_is_one(c) && !isl_int_is_negone(c)) ||
298 type != EQTYPE_NONE) {
299 type = EQTYPE_EXAFFINE;
300 break;
302 type = EQTYPE_PUREITEM;
304 for (i = 0; i < isl_constraint_dim(constraint, isl_dim_div); ++i) {
305 isl_constraint_get_coefficient(constraint, isl_dim_div, i, &c);
306 if (isl_int_is_zero(c))
307 continue;
308 if ((!isl_int_is_one(c) && !isl_int_is_negone(c)) ||
309 type != EQTYPE_NONE) {
310 type = EQTYPE_EXAFFINE;
311 break;
313 type = EQTYPE_PUREITEM;
315 isl_int_clear(c);
317 if (type == EQTYPE_NONE)
318 type = EQTYPE_CONSTANT;
320 return type;
324 int cloog_equal_type(CloogEqualities *equal, int level)
326 return equal->types[level-1];
331 * cloog_equal_add function:
332 * This function updates the row (level-1) of the equality matrix (equal) with
333 * the row that corresponds to the row (line) of the matrix (matrix).
334 * - equal is the matrix of equalities,
335 * - matrix is the matrix of constraints,
336 * - level is the column number in matrix of the element which is 'equal to',
337 * - line is the line number in matrix of the constraint we want to study,
338 * - the infos structure gives the user all options on code printing and more.
340 * line is set to an invalid constraint for equalities that CLooG itself has
341 * discovered because the lower and upper bound of a loop happened to be equal.
342 * This situation shouldn't happen in the isl port since isl should
343 * have found the equality itself.
345 void cloog_equal_add(CloogEqualities *equal, CloogConstraintSet *matrix,
346 int level, CloogConstraint *line, int nb_par)
348 isl_constraint *c;
349 assert(cloog_constraint_is_valid(line));
351 equal->types[level-1] = cloog_constraint_equal_type(line, level);
352 c = cloog_constraint_to_isl(line);
353 equal->constraints[level - 1] = isl_constraint_copy(c);
358 * cloog_equal_del function :
359 * This function reset the equality corresponding to the iterator (level)
360 * in the equality matrix (equal).
361 * - July 2nd 2002: first version.
363 void cloog_equal_del(CloogEqualities *equal, int level)
365 equal->types[level-1] = EQTYPE_NONE;
366 isl_constraint_free(equal->constraints[level - 1]);
367 equal->constraints[level-1] = NULL;
372 /******************************************************************************
373 * Processing functions *
374 ******************************************************************************/
377 * Function cloog_constraint_set_normalize:
378 * This function will modify the constraint system in such a way that when
379 * there is an equality depending on the element at level 'level', there are
380 * no more (in)equalities depending on this element.
382 * The simplified form of isl automatically satisfies this condition.
384 void cloog_constraint_set_normalize(CloogConstraintSet *matrix, int level)
391 * cloog_constraint_set_copy function:
392 * this functions builds and returns a "hard copy" (not a pointer copy) of a
393 * CloogConstraintSet data structure.
395 CloogConstraintSet *cloog_constraint_set_copy(CloogConstraintSet *constraints)
397 isl_basic_set *bset;
398 bset = cloog_constraints_set_to_isl(constraints);
399 return cloog_constraint_set_from_isl_basic_set(isl_basic_set_dup(bset));
404 * cloog_constraint_set_simplify function:
405 * this function simplify all constraints inside the matrix "matrix" thanks to
406 * an equality matrix "equal" that gives for some elements of the affine
407 * constraint an equality with other elements, preferably constants.
408 * For instance, if a row of the matrix contains i+j+3>=0 and the equality
409 * matrix gives i=n and j=2, the constraint is simplified to n+3>=0. The
410 * simplified constraints are returned back inside a new simplified matrix.
411 * - matrix is the set of constraints to simplify,
412 * - equal is the matrix of equalities,
413 * - level is a level we don't want to simplify (-1 if none),
414 * - nb_par is the number of parameters of the program.
416 * isl should have performed these simplifications already in isl_set_gist.
418 CloogConstraintSet *cloog_constraint_set_simplify(CloogConstraintSet *matrix,
419 CloogEqualities *equal, int level, int nb_par)
421 return cloog_constraint_set_copy(matrix);
425 static struct cloog_isl_dim constraint_cloog_dim_to_isl_dim(
426 CloogConstraint *constraint, int pos)
428 enum isl_dim_type types[] = { isl_dim_set, isl_dim_div, isl_dim_param };
429 int i;
430 struct cloog_isl_dim ci_dim;
432 for (i = 0; i < 3; ++i) {
433 isl_constraint *c = cloog_constraint_to_isl(constraint);
434 unsigned dim = isl_constraint_dim(c, types[i]);
435 if (pos < dim) {
436 ci_dim.type = types[i];
437 ci_dim.pos = pos;
438 return ci_dim;
440 pos -= dim;
442 assert(0);
445 static struct clast_expr *div_expr(CloogConstraint *constraint, int pos,
446 CloogNames *names)
448 int i, nb_elts;
449 unsigned dim = cloog_constraint_total_dimension(constraint);
450 cloog_int_t c;
451 struct clast_reduction *r;
452 struct clast_expr *e = NULL;
453 struct isl_div *div;
455 div = isl_constraint_div(cloog_constraint_to_isl(constraint), pos);
457 cloog_int_init(c);
458 for (i = 0, nb_elts = 0; i < dim; ++i) {
459 struct cloog_isl_dim dim;
461 dim = constraint_cloog_dim_to_isl_dim(constraint, i);
462 isl_div_get_coefficient(div, dim.type, dim.pos, &c);
463 if (!cloog_int_is_zero(c))
464 ++nb_elts;
466 isl_div_get_constant(div, &c);
467 if (!cloog_int_is_zero(c))
468 ++nb_elts;
470 r = new_clast_reduction(clast_red_sum, nb_elts);
471 for (i = 0, nb_elts = 0; i < dim; ++i) {
472 struct clast_expr *v;
473 struct cloog_isl_dim dim;
475 dim = constraint_cloog_dim_to_isl_dim(constraint, i);
476 isl_div_get_coefficient(div, dim.type, dim.pos, &c);
477 if (cloog_int_is_zero(c))
478 continue;
480 v = cloog_constraint_variable_expr(constraint, 1 + i, names);
482 r->elts[nb_elts++] = &new_clast_term(c, v)->expr;
484 isl_div_get_constant(div, &c);
485 if (!cloog_int_is_zero(c))
486 r->elts[nb_elts++] = &new_clast_term(c, NULL)->expr;
488 isl_div_get_denominator(div, &c);
489 e = &new_clast_binary(clast_bin_fdiv, &r->expr, c)->expr;
491 cloog_int_clear(c);
493 isl_div_free(div);
495 return e;
499 * Return clast_expr corresponding to the variable "level" (1 based) in
500 * the given constraint.
502 struct clast_expr *cloog_constraint_variable_expr(CloogConstraint *constraint,
503 int level, CloogNames *names)
505 struct cloog_isl_dim dim;
506 const char *name;
508 assert(constraint);
510 dim = constraint_cloog_dim_to_isl_dim(constraint, level - 1);
511 if (dim.type == isl_dim_div)
512 return div_expr(constraint, dim.pos, names);
514 if (dim.type == isl_dim_set)
515 name = cloog_names_name_at_level(names, level);
516 else
517 name = names->parameters[dim.pos];
519 return &new_clast_name(name)->expr;
524 * Return true if constraint c involves variable v (zero-based).
526 int cloog_constraint_involves(CloogConstraint *constraint, int v)
528 isl_int c;
529 int res;
531 isl_int_init(c);
532 cloog_constraint_coefficient_get(constraint, v, &c);
533 res = !isl_int_is_zero(c);
534 isl_int_clear(c);
535 return res;
538 int cloog_constraint_is_lower_bound(CloogConstraint *constraint, int v)
540 isl_int c;
541 int res;
543 isl_int_init(c);
544 cloog_constraint_coefficient_get(constraint, v, &c);
545 res = isl_int_is_pos(c);
546 isl_int_clear(c);
547 return res;
550 int cloog_constraint_is_upper_bound(CloogConstraint *constraint, int v)
552 isl_int c;
553 int res;
555 isl_int_init(c);
556 cloog_constraint_coefficient_get(constraint, v, &c);
557 res = isl_int_is_neg(c);
558 isl_int_clear(c);
559 return res;
562 int cloog_constraint_is_equality(CloogConstraint *constraint)
564 return isl_constraint_is_equality(cloog_constraint_to_isl(constraint));
567 CloogConstraintSet *cloog_constraint_set_drop_constraint(
568 CloogConstraintSet *constraints, CloogConstraint *constraint)
570 isl_basic_set *bset;
571 isl_constraint *c;
573 bset = cloog_constraints_set_to_isl(constraints);
574 c = cloog_constraint_to_isl(cloog_constraint_copy(constraint));
575 bset = isl_basic_set_drop_constraint(bset, c);
576 return cloog_constraint_set_from_isl_basic_set(bset);
579 void cloog_constraint_coefficient_get(CloogConstraint *constraint,
580 int var, cloog_int_t *val)
582 struct cloog_isl_dim dim;
583 isl_constraint *c;
585 if (!constraint)
586 return;
588 dim = constraint_cloog_dim_to_isl_dim(constraint, var);
589 c = cloog_constraint_to_isl(constraint);
590 isl_constraint_get_coefficient(c, dim.type, dim.pos, val);
593 void cloog_constraint_coefficient_set(CloogConstraint *constraint,
594 int var, cloog_int_t val)
596 struct cloog_isl_dim dim;
597 isl_constraint *c;
599 assert(constraint);
601 dim = constraint_cloog_dim_to_isl_dim(constraint, var);
602 c = cloog_constraint_to_isl(constraint);
603 isl_constraint_set_coefficient(c, dim.type, dim.pos, val);
606 void cloog_constraint_constant_get(CloogConstraint *constraint, cloog_int_t *val)
608 isl_constraint_get_constant(cloog_constraint_to_isl(constraint), val);
612 * Copy the coefficient of constraint c into dst in PolyLib order,
613 * i.e., first the coefficients of the variables, then the coefficients
614 * of the parameters and finally the constant.
616 void cloog_constraint_copy_coefficients(CloogConstraint *constraint,
617 cloog_int_t *dst)
619 int i;
620 unsigned dim;
622 dim = cloog_constraint_total_dimension(constraint);
624 for (i = 0; i < dim; ++i)
625 cloog_constraint_coefficient_get(constraint, i, dst+i);
626 cloog_constraint_constant_get(constraint, dst+dim);
629 CloogConstraint *cloog_constraint_invalid(void)
631 return NULL;
634 int cloog_constraint_is_valid(CloogConstraint *constraint)
636 return constraint != NULL;
639 int cloog_constraint_total_dimension(CloogConstraint *constraint)
641 isl_constraint *c;
642 c = cloog_constraint_to_isl(constraint);
643 return isl_constraint_dim(c, isl_dim_all);
648 * Check whether there is any need for the constraint "upper" on
649 * "level" to get reduced.
650 * In case of the isl backend, there should be no need to do so
651 * if the level corresponds to an existentially quantified variable.
652 * Moreover, the way reduction is performed does not work for such
653 * variables since its position might chance during the construction
654 * of a set for reduction.
656 int cloog_constraint_needs_reduction(CloogConstraint *upper, int level)
658 isl_basic_set *bset;
659 isl_constraint *c;
660 struct cloog_isl_dim dim;
662 c = cloog_constraint_to_isl(upper);
663 bset = isl_basic_set_from_constraint(isl_constraint_copy(c));
664 dim = basic_set_cloog_dim_to_isl_dim(bset, level - 1);
665 isl_basic_set_free(bset);
667 return dim.type == isl_dim_set;
672 * Create a CloogConstraintSet containing enough information to perform
673 * a reduction on the upper equality (in this case lower is an invalid
674 * CloogConstraint) or the pair of inequalities upper and lower
675 * from within insert_modulo_guard.
676 * In the isl backend, we return a CloogConstraintSet containing both
677 * bounds, as the stride may change during the reduction and we may
678 * need to recompute the bound on the modulo expression.
680 CloogConstraintSet *cloog_constraint_set_for_reduction(CloogConstraint *upper,
681 CloogConstraint *lower)
683 struct isl_basic_set *bset;
684 isl_constraint *c;
686 c = cloog_constraint_to_isl(upper);
687 bset = isl_basic_set_from_constraint(isl_constraint_copy(c));
688 if (cloog_constraint_is_valid(lower)) {
689 c = cloog_constraint_to_isl(lower);
690 bset = isl_basic_set_add_constraint(bset,
691 isl_constraint_copy(c));
693 return cloog_constraint_set_from_isl_basic_set(bset);
697 static int add_constant_term(CloogConstraint *c, void *user)
699 isl_int *bound = (isl_int *)user;
700 isl_int v;
702 isl_int_init(v);
704 cloog_constraint_constant_get(c, &v);
705 isl_int_add(*bound, *bound, v);
707 isl_int_clear(v);
709 return 0;
713 /* Return an isl_basic_set representation of the equality stored
714 * at position i in the given CloogEqualities.
716 static __isl_give isl_basic_set *equality_to_basic_set(CloogEqualities *equal,
717 int i)
719 isl_constraint *c;
720 isl_basic_set *bset;
721 unsigned nparam;
722 unsigned nvar;
724 c = isl_constraint_copy(equal->constraints[i]);
725 bset = isl_basic_set_from_constraint(c);
726 nparam = isl_basic_set_dim(bset, isl_dim_param);
727 nvar = isl_basic_set_dim(bset, isl_dim_set);
728 bset = isl_basic_set_add(bset, isl_dim_set,
729 equal->total_dim - (nparam + nvar));
730 return bset;
734 * Reduce the modulo guard expressed by "constraints" using equalities
735 * found in outer nesting levels (stored in "equal").
736 * The modulo guard may be an equality or a pair of inequalities.
737 * In case of a pair of inequalities, *bound contains the bound on the
738 * corresponding modulo expression. If any reduction is performed
739 * then this bound is recomputed.
741 * "level" may not correspond to an existentially quantified variable.
743 * We first check if there are any equalities we can use. If not,
744 * there is again nothing to reduce.
745 * For the actual reduction, we use isl_basic_set_gist, but this
746 * function will only perform the reduction we want here if the
747 * the variable that imposes the modulo constraint has been projected
748 * out (i.e., turned into an existentially quantified variable).
749 * After the call to isl_basic_set_gist, we need to move the
750 * existential variable back into the position where the calling
751 * function expects it (assuming there are any constraints left).
752 * We do this by adding an equality between the given dimension and
753 * the existentially quantified variable.
755 * If there are no existentially quantified variables left, then
756 * we don't need to add this equality.
757 * If, on the other hand, the resulting basic set involves more
758 * than one existentially quantified variable, then the caller
759 * will not be able to handle the result, so we just return the
760 * original input instead.
762 CloogConstraintSet *cloog_constraint_set_reduce(CloogConstraintSet *constraints,
763 int level, CloogEqualities *equal, int nb_par, cloog_int_t *bound)
765 int j;
766 isl_ctx *ctx;
767 isl_dim *idim;
768 struct isl_basic_set *eq;
769 struct isl_basic_map *id;
770 struct cloog_isl_dim dim;
771 struct isl_constraint *c;
772 struct isl_div *div;
773 unsigned constraints_dim;
774 unsigned n_div;
775 isl_basic_set *bset, *orig;
776 isl_aff *aff;
778 bset = cloog_constraints_set_to_isl(constraints);
779 orig = isl_basic_set_copy(bset);
780 ctx = isl_basic_set_get_ctx(bset);
781 dim = set_cloog_dim_to_isl_dim(constraints, level - 1);
782 assert(dim.type == isl_dim_set);
784 eq = NULL;
785 for (j = 0; j < level - 1; ++j) {
786 isl_basic_set *bset_j;
787 if (equal->types[j] != EQTYPE_EXAFFINE)
788 continue;
789 bset_j = equality_to_basic_set(equal, j);
790 if (!eq)
791 eq = bset_j;
792 else
793 eq = isl_basic_set_intersect(eq, bset_j);
795 if (!eq) {
796 isl_basic_set_free(orig);
797 return cloog_constraint_set_from_isl_basic_set(bset);
800 idim = isl_dim_map_from_set(isl_basic_set_get_dim(bset));
801 id = isl_basic_map_identity(idim);
802 id = isl_basic_map_remove_dims(id, isl_dim_out, dim.pos, 1);
803 bset = isl_basic_set_apply(bset, isl_basic_map_copy(id));
804 bset = isl_basic_set_apply(bset, isl_basic_map_reverse(id));
806 constraints_dim = isl_basic_set_dim(bset, isl_dim_set);
807 eq = isl_basic_set_remove_dims(eq, isl_dim_set, constraints_dim,
808 isl_basic_set_dim(eq, isl_dim_set) - constraints_dim);
809 bset = isl_basic_set_gist(bset, eq);
810 n_div = isl_basic_set_dim(bset, isl_dim_div);
811 if (n_div > 1) {
812 isl_basic_set_free(bset);
813 return cloog_constraint_set_from_isl_basic_set(orig);
815 if (n_div < 1) {
816 isl_basic_set_free(orig);
817 return cloog_constraint_set_from_isl_basic_set(bset);
820 div = isl_basic_set_div(isl_basic_set_copy(bset), 0);
821 aff = isl_aff_from_div(div);
822 aff = isl_aff_add_coefficient_si(aff, isl_dim_set, dim.pos, -1);
823 c = isl_equality_from_aff(aff);
824 bset = isl_basic_set_add_constraint(bset, c);
826 isl_int_set_si(*bound, 0);
827 constraints = cloog_constraint_set_from_isl_basic_set(bset);
828 cloog_constraint_set_foreach_constraint(constraints,
829 add_constant_term, bound);
831 isl_basic_set_free(orig);
832 return cloog_constraint_set_from_isl_basic_set(bset);
835 CloogConstraint *cloog_constraint_copy(CloogConstraint *constraint)
837 return cloog_constraint_from_isl_constraint(
838 isl_constraint_copy(cloog_constraint_to_isl(constraint)));
841 void cloog_constraint_release(CloogConstraint *constraint)
843 isl_constraint_free(cloog_constraint_to_isl(constraint));
846 struct cloog_isl_foreach {
847 int (*fn)(CloogConstraint *constraint, void *user);
848 void *user;
851 static int cloog_isl_foreach_cb(__isl_take isl_constraint *c, void *user)
853 struct cloog_isl_foreach *data = (struct cloog_isl_foreach *)user;
854 int ret;
856 if (isl_constraint_is_div_constraint(c)) {
857 isl_constraint_free(c);
858 return 0;
861 ret = data->fn(cloog_constraint_from_isl_constraint(c), data->user);
863 isl_constraint_free(c);
865 return ret;
868 int cloog_constraint_set_foreach_constraint(CloogConstraintSet *constraints,
869 int (*fn)(CloogConstraint *constraint, void *user), void *user)
871 struct cloog_isl_foreach data = { fn, user };
872 isl_basic_set *bset;
874 bset = cloog_constraints_set_to_isl(constraints);
875 return isl_basic_set_foreach_constraint(bset,
876 cloog_isl_foreach_cb, &data);
879 CloogConstraint *cloog_equal_constraint(CloogEqualities *equal, int j)
881 isl_constraint *c;
883 c = isl_constraint_copy(equal->constraints[j]);
884 return cloog_constraint_from_isl_constraint(c);
887 /* Given a stride constraint on iterator i (specified by level) of the form
889 * i = f(outer iterators) + stride * f(existentials)
891 * extract f as an isl_aff.
893 static isl_aff *extract_stride_offset(__isl_keep isl_constraint *c,
894 int level, CloogStride *stride)
896 int i;
897 isl_dim *dim = isl_constraint_get_dim(c);
898 isl_local_space *ls = isl_local_space_from_dim(dim);
899 isl_aff *offset = isl_aff_zero(ls);
900 isl_int u;
901 unsigned nparam, nvar;
903 isl_int_init(u);
905 nparam = isl_constraint_dim(c, isl_dim_param);
906 nvar = isl_constraint_dim(c, isl_dim_set);
908 for (i = 0; i < nparam; ++i) {
909 isl_constraint_get_coefficient(c, isl_dim_param, i, &u);
910 isl_int_mul(u, u, stride->factor);
911 offset = isl_aff_set_coefficient(offset, isl_dim_param, i, u);
913 for (i = 0; i < nvar; ++i) {
914 if (i == level - 1)
915 continue;
916 isl_constraint_get_coefficient(c, isl_dim_set, i, &u);
917 isl_int_mul(u, u, stride->factor);
918 offset = isl_aff_set_coefficient(offset, isl_dim_set, i, u);
920 isl_constraint_get_constant(c, &u);
921 isl_int_mul(u, u, stride->factor);
922 offset = isl_aff_set_constant(offset, u);
924 isl_int_clear(u);
926 return offset;
929 /* Update the given lower bound on level such that it satisfies the stride
930 * constraint. The computation performed here is essentially the same
931 * as that performed in constraint_stride_lower_c.
933 * We update the constraint
935 * a i + f >= 0
937 * to
939 * i >= s * ceil((-f/a - d)/s) + d
941 * with s the stride and d the offset encoded in the stride constraint.
943 CloogConstraint *cloog_constraint_stride_lower_bound(CloogConstraint *c,
944 int level, CloogStride *stride)
946 isl_constraint *stride_c = cloog_constraint_to_isl(stride->constraint);
947 isl_constraint *bound = cloog_constraint_to_isl(c);
948 isl_aff *offset;
949 isl_aff *lower;
951 lower = isl_constraint_get_bound(bound, isl_dim_set, level - 1);
952 isl_constraint_free(bound);
954 offset = extract_stride_offset(stride_c, level, stride);
956 lower = isl_aff_sub(lower, isl_aff_copy(offset));
957 lower = isl_aff_scale_down(lower, stride->stride);
958 lower = isl_aff_ceil(lower);
959 lower = isl_aff_scale(lower, stride->stride);
960 lower = isl_aff_add(lower, offset);
961 lower = isl_aff_neg(lower);
962 lower = isl_aff_add_coefficient_si(lower, isl_dim_set, level - 1, 1);
964 bound = isl_inequality_from_aff(lower);
966 return cloog_constraint_from_isl_constraint(bound);