2 /**-------------------------------------------------------------------**
4 **-------------------------------------------------------------------**
6 **-------------------------------------------------------------------**
7 ** First version: april 17th 2005 **
8 **-------------------------------------------------------------------**/
11 /******************************************************************************
12 * CLooG : the Chunky Loop Generator (experimental) *
13 ******************************************************************************
15 * Copyright (C) 2005 Cedric Bastoul *
17 * This library is free software; you can redistribute it and/or *
18 * modify it under the terms of the GNU Lesser General Public *
19 * License as published by the Free Software Foundation; either *
20 * version 2.1 of the License, or (at your option) any later version. *
22 * This library is distributed in the hope that it will be useful, *
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
25 * Lesser General Public License for more details. *
27 * You should have received a copy of the GNU Lesser General Public *
28 * License along with this library; if not, write to the Free Software *
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
30 * Boston, MA 02110-1301 USA *
32 * CLooG, the Chunky Loop Generator *
33 * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr *
35 ******************************************************************************/
36 /* CAUTION: the english used for comments is probably the worst you ever read,
37 * please feel free to correct and improve it !
44 #include <cloog/cloog.h>
45 #include <cloog/matrix/constraintset.h>
48 #define ALLOC(type) (type*)malloc(sizeof(type))
49 #define ALLOCN(type,n) (type*)malloc((n)*sizeof(type))
52 CloogConstraint
*cloog_constraint_first(CloogConstraintSet
*constraints
);
53 CloogConstraint
*cloog_constraint_next(CloogConstraint
*constraint
);
56 CloogConstraintSet
*cloog_constraint_set_from_cloog_matrix(CloogMatrix
*M
)
58 return (CloogConstraintSet
*)M
;
62 void cloog_constraint_set_free(CloogConstraintSet
*constraints
)
64 cloog_matrix_free(&constraints
->M
);
67 int cloog_constraint_set_contains_level(CloogConstraintSet
*constraints
,
68 int level
, int nb_parameters
)
70 return constraints
->M
.NbColumns
- 2 - nb_parameters
>= level
;
73 /* Check if the variable at position level is defined by an
74 * equality. If so, return the row number. Otherwise, return -1.
76 * If there is an equality, we can print it directly -no ambiguity-.
77 * PolyLib can give more than one equality, we use just the first one
78 * (this is a PolyLib problem, but all equalities are equivalent).
80 CloogConstraint
*cloog_constraint_set_defining_equality(CloogConstraintSet
*constraints
, int level
)
82 CloogConstraint
*constraint
= ALLOC(CloogConstraint
);
85 constraint
->set
= constraints
;
86 for (i
= 0; i
< constraints
->M
.NbRows
; i
++)
87 if (cloog_int_is_zero(constraints
->M
.p
[i
][0]) &&
88 !cloog_int_is_zero(constraints
->M
.p
[i
][level
])) {
89 constraint
->line
= &constraints
->M
.p
[i
];
93 return cloog_constraint_invalid();
96 /* Check if the variable (e) at position level is defined by a
97 * pair of inequalities
98 * <a, i> + -m e + <b, p> + k1 >= 0
99 * <-a, i> + m e + <-b, p> + k2 >= 0
100 * with 0 <= k1 + k2 < m
101 * If so return the row number of the upper bound and set *lower
102 * to the row number of the lower bound. If not, return -1.
104 * If the variable at position level occurs in any other constraint,
105 * then we currently return -1. The modulo guard that we would generate
106 * would still be correct, but we would also need to generate
107 * guards corresponding to the other constraints, and this has not
108 * been implemented yet.
110 CloogConstraint
*cloog_constraint_set_defining_inequalities(CloogConstraintSet
*constraints
,
111 int level
, CloogConstraint
**lower
, int nb_par
)
115 CloogMatrix
*matrix
= &constraints
->M
;
116 unsigned len
= matrix
->NbColumns
- 2;
117 unsigned nb_iter
= len
- nb_par
;
118 CloogConstraint
*constraint
;
120 for (i
= 0; i
< matrix
->NbRows
; i
++) {
121 if (cloog_int_is_zero(matrix
->p
[i
][level
]))
123 if (cloog_int_is_zero(matrix
->p
[i
][0]))
124 return cloog_constraint_invalid();
125 if (cloog_int_is_one(matrix
->p
[i
][level
]))
126 return cloog_constraint_invalid();
127 if (cloog_int_is_neg_one(matrix
->p
[i
][level
]))
128 return cloog_constraint_invalid();
129 if (cloog_seq_first_non_zero(matrix
->p
[i
]+level
+1,
130 (1+nb_iter
)-(level
+1)) != -1)
131 return cloog_constraint_invalid();
132 for (j
= i
+1; j
< matrix
->NbRows
; ++j
) {
133 if (cloog_int_is_zero(matrix
->p
[j
][level
]))
135 if (cloog_int_is_zero(matrix
->p
[j
][0]))
136 return cloog_constraint_invalid();
137 if (cloog_int_is_one(matrix
->p
[j
][level
]))
138 return cloog_constraint_invalid();
139 if (cloog_int_is_neg_one(matrix
->p
[j
][level
]))
140 return cloog_constraint_invalid();
141 if (cloog_seq_first_non_zero(matrix
->p
[j
]+level
+1,
142 (1+nb_iter
)-(level
+1)) != -1)
143 return cloog_constraint_invalid();
146 cloog_int_add(m
, matrix
->p
[i
][1+len
], matrix
->p
[j
][1+len
]);
147 if (cloog_int_is_neg(m
) ||
148 cloog_int_abs_ge(m
, matrix
->p
[i
][level
])) {
150 return cloog_constraint_invalid();
154 if (!cloog_seq_is_neg(matrix
->p
[i
]+1, matrix
->p
[j
]+1,
156 return cloog_constraint_invalid();
157 for (k
= j
+1; k
< matrix
->NbRows
; ++k
)
158 if (!cloog_int_is_zero(matrix
->p
[k
][level
]))
159 return cloog_constraint_invalid();
160 *lower
= ALLOC(CloogConstraint
);
161 constraint
= ALLOC(CloogConstraint
);
162 (*lower
)->set
= constraints
;
163 constraint
->set
= constraints
;
164 if (cloog_int_is_pos(matrix
->p
[i
][level
])) {
165 (*lower
)->line
= &matrix
->p
[i
];
166 constraint
->line
= &matrix
->p
[j
];
168 (*lower
)->line
= &matrix
->p
[j
];
169 constraint
->line
= &matrix
->p
[i
];
174 return cloog_constraint_invalid();
177 int cloog_constraint_set_total_dimension(CloogConstraintSet
*constraints
)
179 return constraints
->M
.NbColumns
- 2;
182 int cloog_constraint_set_n_iterators(CloogConstraintSet
*constraint
, int nb_par
)
184 return cloog_constraint_set_total_dimension(constraint
) - nb_par
;
187 int cloog_equal_total_dimension(CloogEqualities
*equal
)
189 return cloog_constraint_set_total_dimension(equal
->constraints
);
192 int cloog_constraint_total_dimension(CloogConstraint
*constraint
)
194 return cloog_constraint_set_total_dimension(constraint
->set
);
199 /******************************************************************************
200 * Equalities spreading functions *
201 ******************************************************************************/
204 /* Equalities are stored inside a CloogMatrix data structure called "equal".
205 * This matrix has (nb_scattering + nb_iterators + 1) rows (i.e. total
206 * dimensions + 1, the "+ 1" is because a statement can be included inside an
207 * external loop without iteration domain), and (nb_scattering + nb_iterators +
208 * nb_parameters + 2) columns (all unknowns plus the scalar plus the equality
209 * type). The ith row corresponds to the equality "= 0" for the ith dimension
210 * iterator. The first column gives the equality type (0: no equality, then
211 * EQTYPE_* -see pprint.h-). At each recursion of pprint, if an equality for
212 * the current level is found, the corresponding row is updated. Then the
213 * equality if it exists is used to simplify expressions (e.g. if we have
214 * "i+1" while we know that "i=2", we simplify it in "3"). At the end of
215 * the pprint call, the corresponding row is reset to zero.
218 CloogEqualities
*cloog_equal_alloc(int n
, int nb_levels
,
222 CloogEqualities
*equal
= ALLOC(CloogEqualities
);
224 equal
->constraints
= cloog_constraint_set_from_cloog_matrix(
225 cloog_matrix_alloc(n
, nb_levels
+ nb_parameters
+ 1));
226 equal
->types
= ALLOCN(int, n
);
227 for (i
= 0; i
< n
; ++i
)
228 equal
->types
[i
] = EQTYPE_NONE
;
232 void cloog_equal_free(CloogEqualities
*equal
)
234 cloog_matrix_free(&equal
->constraints
->M
);
239 int cloog_equal_count(CloogEqualities
*equal
)
241 return equal
->constraints
->M
.NbRows
;
244 CloogConstraintSet
*cloog_equal_constraints(CloogEqualities
*equal
)
246 return equal
->constraints
;
251 * cloog_constraint_equal_type function :
252 * This function returns the type of the equality in the constraint (line) of
253 * (constraints) for the element (level). An equality is 'constant' iff all
254 * other factors are null except the constant one. It is a 'pure item' iff
255 * it is equal or opposite to a single variable or parameter.
256 * Otherwise it is an 'affine expression'.
258 * i = -13 is constant, i = j, j = -M are pure items,
259 * j = 2*M, i = j+1, 2*j = M are affine expressions.
261 * - constraints is the matrix of constraints,
262 * - level is the column number in equal of the element which is 'equal to',
264 * - July 3rd 2002: first version, called pprint_equal_isconstant.
265 * - July 6th 2002: adaptation for the 3 types.
266 * - June 15th 2005: (debug) expr = domain->Constraint[line] was evaluated
267 * before checking if line != ONE_TIME_LOOP. Since
268 * ONE_TIME_LOOP is -1, an invalid read was possible.
269 * - October 19th 2005: Removal of the once-time-loop specific processing.
271 static int cloog_constraint_equal_type(CloogConstraint
*constraint
, int level
)
276 expr
= *constraint
->line
;
278 if (!cloog_int_is_one(expr
[level
]) && !cloog_int_is_neg_one(expr
[level
]))
279 return EQTYPE_EXAFFINE
;
281 /* There is only one non null factor, and it must be +1 or -1 for
282 * iterators or parameters.
284 for (i
= 1;i
<= constraint
->set
->M
.NbColumns
-2; i
++)
285 if (!cloog_int_is_zero(expr
[i
]) && (i
!= level
)) {
286 if ((!cloog_int_is_one(expr
[i
]) && !cloog_int_is_neg_one(expr
[i
])) || (one
!= 0))
287 return EQTYPE_EXAFFINE
;
291 /* if the constant factor is non null, it must be alone. */
293 if (!cloog_int_is_zero(expr
[constraint
->set
->M
.NbColumns
-1]))
294 return EQTYPE_EXAFFINE
;
297 return EQTYPE_CONSTANT
;
299 return EQTYPE_PUREITEM
;
303 int cloog_equal_type(CloogEqualities
*equal
, int level
)
305 return equal
->types
[level
-1];
310 * cloog_equal_update function:
311 * this function updates a matrix of equalities where each row corresponds to
312 * the equality "=0" of an affine expression such that the entry at column
313 * "row" (="level") is not zero. This matrix is upper-triangular, except the
314 * row number "level-1" which has to be updated for the matrix to be triangular.
315 * This function achieves the processing.
316 * - equal is the matrix to be updated,
317 * - level gives the row that has to be updated (it is actually row "level-1"),
318 * - nb_par is the number of parameters of the program.
320 * - September 20th 2005: first version.
322 static void cloog_equal_update(CloogEqualities
*equal
, int level
, int nb_par
)
324 cloog_int_t gcd
, factor_level
, factor_outer
, temp_level
, temp_outer
;
327 cloog_int_init(temp_level
);
328 cloog_int_init(temp_outer
);
329 cloog_int_init(factor_level
);
330 cloog_int_init(factor_outer
);
332 /* For each previous level, */
333 for (i
=level
-2;i
>=0;i
--)
334 { /* if the corresponding iterator is inside the current equality and is equal
337 if (!cloog_int_is_zero(equal
->constraints
->M
.p
[level
-1][i
+1]) && equal
->types
[i
])
338 { /* Compute the Greatest Common Divisor. */
339 cloog_int_gcd(gcd
, equal
->constraints
->M
.p
[level
-1][i
+1],
340 equal
->constraints
->M
.p
[i
][i
+1]);
342 /* Compute the factors to apply to each row vector element. */
343 cloog_int_divexact(factor_level
, equal
->constraints
->M
.p
[i
][i
+1], gcd
);
344 cloog_int_divexact(factor_outer
, equal
->constraints
->M
.p
[level
-1][i
+1], gcd
);
346 /* Now update the row 'level'. */
347 /* - the iterators, up to level, */
348 for (j
= 1; j
<= level
; j
++) {
349 cloog_int_mul(temp_level
, factor_level
,
350 equal
->constraints
->M
.p
[level
-1][j
]);
351 cloog_int_mul(temp_outer
, factor_outer
, equal
->constraints
->M
.p
[i
][j
]);
352 cloog_int_sub(equal
->constraints
->M
.p
[level
-1][j
], temp_level
, temp_outer
);
354 /* - between last useful iterator (level) and the first parameter, the
355 * matrix is sparse (full of zeroes), we just do nothing there.
356 * - the parameters and the scalar.
358 for (j
= 0; j
< nb_par
+ 1; j
++) {
359 cloog_int_mul(temp_level
,factor_level
,
360 equal
->constraints
->M
.p
[level
-1]
361 [equal
->constraints
->M
.NbColumns
-j
-1]);
362 cloog_int_mul(temp_outer
,factor_outer
,
363 equal
->constraints
->M
.p
[i
][equal
->constraints
->M
.NbColumns
-j
-1]);
364 cloog_int_sub(equal
->constraints
->M
.p
[level
-1]
365 [equal
->constraints
->M
.NbColumns
-j
-1],
366 temp_level
,temp_outer
) ;
371 /* Normalize (divide by GCD of all elements) the updated equality. */
372 cloog_seq_normalize(&(equal
->constraints
->M
.p
[level
-1][1]),
373 equal
->constraints
->M
.NbColumns
-1);
375 cloog_int_clear(gcd
);
376 cloog_int_clear(temp_level
);
377 cloog_int_clear(temp_outer
);
378 cloog_int_clear(factor_level
);
379 cloog_int_clear(factor_outer
);
384 * cloog_equal_add function:
385 * This function updates the row (level-1) of the equality matrix (equal) with
386 * the row that corresponds to the row (line) of the matrix (matrix).
387 * - equal is the matrix of equalities,
388 * - matrix is the matrix of constraints,
389 * - level is the column number in matrix of the element which is 'equal to',
390 * - line is the line number in matrix of the constraint we want to study,
391 * - the infos structure gives the user all options on code printing and more.
393 * - July 2nd 2002: first version.
394 * - October 19th 2005: Addition of the once-time-loop specific processing.
396 void cloog_equal_add(CloogEqualities
*equal
, CloogConstraintSet
*constraints
,
397 int level
, CloogConstraint
*line
, int nb_par
)
400 CloogConstraint
*i
= cloog_constraint_invalid();
401 CloogMatrix
*matrix
= &constraints
->M
;
403 /* If we are in the case of a loop running once, this means that the equality
404 * comes from an inequality. Here we find this inequality.
406 if (!cloog_constraint_is_valid(line
))
407 { for (i
= cloog_constraint_first(constraints
);
408 cloog_constraint_is_valid(i
); i
= cloog_constraint_next(i
))
409 if ((!cloog_int_is_zero(i
->line
[0][0]))&& (!cloog_int_is_zero(i
->line
[0][level
])))
412 /* Since in once-time-loops, equalities derive from inequalities, we
413 * may have to offset the values. For instance if we have 2i>=3, the
414 * equality is in fact i=2. This may happen when the level coefficient is
415 * not 1 or -1 and the scalar value is not zero. In any other case (e.g.,
416 * if the inequality is an expression including outer loop counters or
417 * parameters) the once time loop would not have been detected
418 * because of floord and ceild functions.
420 if (cloog_int_ne_si(i
->line
[0][level
],1) &&
421 cloog_int_ne_si(i
->line
[0][level
],-1) &&
422 !cloog_int_is_zero(i
->line
[0][matrix
->NbColumns
-1])) {
423 cloog_int_t denominator
;
425 cloog_int_init(denominator
);
426 cloog_int_abs(denominator
, i
->line
[0][level
]);
427 cloog_int_fdiv_q(i
->line
[0][matrix
->NbColumns
-1],
428 i
->line
[0][matrix
->NbColumns
-1], denominator
);
429 cloog_int_set_si(i
->line
[0][level
], cloog_int_sgn(i
->line
[0][level
]));
430 cloog_int_clear(denominator
);
436 assert(cloog_constraint_is_valid(line
));
438 /* We update the line of equal corresponding to level:
439 * - the first element gives the equality type,
441 equal
->types
[level
-1] = cloog_constraint_equal_type(line
, level
);
442 /* - the other elements corresponding to the equality itself
443 * (the iterators up to level, then the parameters and the scalar).
445 for (j
=1;j
<=level
;j
++)
446 cloog_int_set(equal
->constraints
->M
.p
[level
-1][j
], line
->line
[0][j
]);
447 for (j
= 0; j
< nb_par
+ 1; j
++)
448 cloog_int_set(equal
->constraints
->M
.p
[level
-1][equal
->constraints
->M
.NbColumns
-j
-1],
449 line
->line
[0][line
->set
->M
.NbColumns
-j
-1]);
451 if (cloog_constraint_is_valid(i
))
452 cloog_constraint_release(line
);
453 cloog_equal_update(equal
, level
, nb_par
);
458 * cloog_equal_del function :
459 * This function reset the equality corresponding to the iterator (level)
460 * in the equality matrix (equal).
461 * - July 2nd 2002: first version.
463 void cloog_equal_del(CloogEqualities
*equal
, int level
)
465 equal
->types
[level
-1] = EQTYPE_NONE
;
470 /******************************************************************************
471 * Processing functions *
472 ******************************************************************************/
475 * Function cloog_constraint_set_normalize:
476 * This function will modify the constraint system in such a way that when
477 * there is an equality depending on the element at level 'level', there are
478 * no more (in)equalities depending on this element. For instance, try
479 * test/valilache.cloog with options -f 8 -l 9, with and without the call
480 * to this function. At a given moment, for the level L we will have
481 * 32*P=L && L>=1 (P is a lower level), this constraint system cannot be
482 * translated directly into a source code. Thus, we normalize the domain to
483 * remove L from the inequalities. In our example, this leads to
484 * 32*P=L && 32*P>=1, that can be transated to the code
485 * if (P>=1) { L=32*P ; ... }. This function solves the DaeGon Kim bug.
486 * WARNING: Remember that if there is another call to Polylib after a call to
487 * this function, we have to recall this function.
488 * -June 16th 2005: first version (adaptation from URGent June-7th-2005 by
490 * - June 21rd 2005: Adaptation for GMP.
491 * - November 4th 2005: Complete rewriting, simpler and faster. It is no more an
492 * adaptation from URGent.
494 void cloog_constraint_set_normalize(CloogConstraintSet
*constraints
, int level
)
496 cloog_int_t factor_i
, factor_ref
, temp_i
, temp_ref
, gcd
;
497 CloogMatrix
*matrix
= &constraints
->M
;
502 /* Don't "normalize" the constant term. */
503 if (level
== matrix
->NbColumns
-1)
506 /* Let us find an equality for the current level that can be propagated. */
507 for (ref
=0;ref
<matrix
->NbRows
;ref
++)
508 if (cloog_int_is_zero(matrix
->p
[ref
][0]) && !cloog_int_is_zero(matrix
->p
[ref
][level
])) {
510 cloog_int_init(temp_i
);
511 cloog_int_init(temp_ref
);
512 cloog_int_init(factor_i
);
513 cloog_int_init(factor_ref
);
515 /* Row "ref" is the reference equality, now let us find a row to simplify.*/
516 for (i
=ref
+1;i
<matrix
->NbRows
;i
++)
517 if (!cloog_int_is_zero(matrix
->p
[i
][level
])) {
518 /* Now let us set to 0 the "level" coefficient of row "j" using "ref".
519 * First we compute the factors to apply to each row vector element.
521 cloog_int_gcd(gcd
, matrix
->p
[ref
][level
], matrix
->p
[i
][level
]);
522 cloog_int_divexact(factor_i
, matrix
->p
[ref
][level
], gcd
);
523 cloog_int_divexact(factor_ref
, matrix
->p
[i
][level
], gcd
);
525 /* Maybe we are simplifying an inequality: factor_i must not be <0. */
526 if (cloog_int_is_neg(factor_i
)) {
527 cloog_int_abs(factor_i
, factor_i
);
528 cloog_int_neg(factor_ref
, factor_ref
);
531 /* Now update the vector. */
532 for (j
=1;j
<matrix
->NbColumns
;j
++) {
533 cloog_int_mul(temp_i
, factor_i
, matrix
->p
[i
][j
]);
534 cloog_int_mul(temp_ref
, factor_ref
, matrix
->p
[ref
][j
]);
535 cloog_int_sub(matrix
->p
[i
][j
], temp_i
, temp_ref
);
538 /* Normalize (divide by GCD of all elements) the updated vector. */
539 cloog_seq_normalize(&(matrix
->p
[i
][1]), matrix
->NbColumns
-1);
542 cloog_int_clear(gcd
);
543 cloog_int_clear(temp_i
);
544 cloog_int_clear(temp_ref
);
545 cloog_int_clear(factor_i
);
546 cloog_int_clear(factor_ref
);
554 * cloog_constraint_set_copy function:
555 * this functions builds and returns a "hard copy" (not a pointer copy) of a
556 * CloogMatrix data structure.
557 * - October 26th 2005: first version.
559 CloogConstraintSet
*cloog_constraint_set_copy(CloogConstraintSet
*constraints
)
562 CloogMatrix
*matrix
= &constraints
->M
;
564 copy
= cloog_matrix_alloc(matrix
->NbRows
, matrix
->NbColumns
);
566 for (i
=0;i
<matrix
->NbRows
;i
++)
567 for (j
=0;j
<matrix
->NbColumns
;j
++)
568 cloog_int_set(copy
->p
[i
][j
], matrix
->p
[i
][j
]);
570 return cloog_constraint_set_from_cloog_matrix(copy
);
575 * cloog_equal_vector_simplify function:
576 * this function simplify an affine expression with its coefficients in
577 * "vector" of length "length" thanks to an equality matrix "equal" that gives
578 * for some elements of the affine expression an equality with other elements,
579 * preferably constants. For instance, if the vector contains i+j+3 and the
580 * equality matrix gives i=n and j=2, the vector is simplified to n+3 and is
581 * returned in a new vector.
582 * - vector is the array of affine expression coefficients
583 * - equal is the matrix of equalities,
584 * - length is the vector length,
585 * - level is a level we don't want to simplify (-1 if none),
586 * - nb_par is the number of parameters of the program.
588 * - September 20th 2005: first version.
589 * - November 2nd 2005: (debug) we are simplifying inequalities, thus we are
590 * not allowed to multiply the vector by a negative
591 * constant.Problem found after a report of Michael
594 struct cloog_vec
*cloog_equal_vector_simplify(CloogEqualities
*equal
, cloog_int_t
*vector
,
595 int length
, int level
, int nb_par
)
597 cloog_int_t gcd
, factor_vector
, factor_equal
, temp_vector
, temp_equal
;
598 struct cloog_vec
*simplified
;
600 simplified
= cloog_vec_alloc(length
);
601 cloog_seq_cpy(simplified
->p
, vector
, length
);
604 cloog_int_init(temp_vector
);
605 cloog_int_init(temp_equal
);
606 cloog_int_init(factor_vector
);
607 cloog_int_init(factor_equal
);
609 /* For each non-null coefficient in the vector, */
610 for (i
=length
-nb_par
-2;i
>0;i
--)
612 { /* if the coefficient in not null, and there exists a useful equality */
613 if ((!cloog_int_is_zero(simplified
->p
[i
])) && equal
->types
[i
-1])
614 { /* Compute the Greatest Common Divisor. */
615 cloog_int_gcd(gcd
, simplified
->p
[i
], equal
->constraints
->M
.p
[i
-1][i
]);
617 /* Compute the factors to apply to each row vector element. */
618 cloog_int_divexact(factor_vector
, equal
->constraints
->M
.p
[i
-1][i
], gcd
);
619 cloog_int_divexact(factor_equal
, simplified
->p
[i
], gcd
);
621 /* We are simplifying an inequality: factor_vector must not be <0. */
622 if (cloog_int_is_neg(factor_vector
)) {
623 cloog_int_abs(factor_vector
, factor_vector
);
624 cloog_int_neg(factor_equal
, factor_equal
);
627 /* Now update the vector. */
628 /* - the iterators, up to the current level, */
629 for (j
=1;j
<=length
-nb_par
-2;j
++) {
630 cloog_int_mul(temp_vector
, factor_vector
, simplified
->p
[j
]);
631 cloog_int_mul(temp_equal
, factor_equal
, equal
->constraints
->M
.p
[i
-1][j
]);
632 cloog_int_sub(simplified
->p
[j
], temp_vector
, temp_equal
);
634 /* - between last useful iterator (i) and the first parameter, the equal
635 * matrix is sparse (full of zeroes), we just do nothing there.
636 * - the parameters and the scalar.
638 for (j
= 0; j
< nb_par
+ 1; j
++) {
639 cloog_int_mul(temp_vector
, factor_vector
, simplified
->p
[length
-1-j
]);
640 cloog_int_mul(temp_equal
,factor_equal
,
641 equal
->constraints
->M
.p
[i
-1][equal
->constraints
->M
.NbColumns
-j
-1]);
642 cloog_int_sub(simplified
->p
[length
-1-j
],temp_vector
,temp_equal
) ;
647 /* Normalize (divide by GCD of all elements) the updated vector. */
648 cloog_seq_normalize(&simplified
->p
[1], length
- 1);
650 cloog_int_clear(gcd
);
651 cloog_int_clear(temp_vector
);
652 cloog_int_clear(temp_equal
);
653 cloog_int_clear(factor_vector
);
654 cloog_int_clear(factor_equal
);
661 * cloog_constraint_set_simplify function:
662 * this function simplify all constraints inside the matrix "matrix" thanks to
663 * an equality matrix "equal" that gives for some elements of the affine
664 * constraint an equality with other elements, preferably constants.
665 * For instance, if a row of the matrix contains i+j+3>=0 and the equality
666 * matrix gives i=n and j=2, the constraint is simplified to n+3>=0. The
667 * simplified constraints are returned back inside a new simplified matrix.
668 * - matrix is the set of constraints to simplify,
669 * - equal is the matrix of equalities,
670 * - level is a level we don't want to simplify (-1 if none),
671 * - nb_par is the number of parameters of the program.
673 * - November 4th 2005: first version.
675 CloogConstraintSet
*cloog_constraint_set_simplify(CloogConstraintSet
*constraints
,
676 CloogEqualities
*equal
, int level
, int nb_par
)
678 struct cloog_vec
*vector
;
679 CloogMatrix
*simplified
;
680 CloogMatrix
*matrix
= &constraints
->M
;
685 /* The simplified matrix is such that each row has been simplified thanks
686 * tho the "equal" matrix. We allocate the memory for the simplified matrix,
687 * then for each row of the original matrix, we compute the simplified
688 * vector and we copy its content into the according simplified row.
690 simplified
= cloog_matrix_alloc(matrix
->NbRows
, matrix
->NbColumns
);
691 for (i
=0;i
<matrix
->NbRows
;i
++)
692 { vector
= cloog_equal_vector_simplify(equal
, matrix
->p
[i
],
693 matrix
->NbColumns
, level
, nb_par
);
694 for (j
=0;j
<matrix
->NbColumns
;j
++)
695 cloog_int_set(simplified
->p
[i
][j
], vector
->p
[j
]);
697 cloog_vec_free(vector
);
700 /* After simplification, it may happen that few constraints are the same,
701 * we remove them here by replacing them with 0=0 constraints.
703 for (i
=0;i
<simplified
->NbRows
;i
++)
704 for (j
=i
+1;j
<simplified
->NbRows
;j
++)
705 { for (k
=0;k
<simplified
->NbColumns
;k
++)
706 if (cloog_int_ne(simplified
->p
[i
][k
],simplified
->p
[j
][k
]))
709 if (k
== matrix
->NbColumns
)
710 { for (k
=0;k
<matrix
->NbColumns
;k
++)
711 cloog_int_set_si(simplified
->p
[j
][k
],0);
715 return cloog_constraint_set_from_cloog_matrix(simplified
);
720 * Return clast_expr corresponding to the variable "level" (1 based) in
721 * the given constraint.
723 struct clast_expr
*cloog_constraint_variable_expr(CloogConstraint
*constraint
,
724 int level
, CloogNames
*names
)
726 int total_dim
, nb_iter
;
729 total_dim
= cloog_constraint_total_dimension(constraint
);
730 nb_iter
= total_dim
- names
->nb_parameters
;
732 if (level
<= nb_iter
)
733 name
= cloog_names_name_at_level(names
, level
);
735 name
= names
->parameters
[level
- (nb_iter
+1)] ;
737 return &new_clast_name(name
)->expr
;
742 * Return true if constraint c involves variable v (zero-based).
744 int cloog_constraint_involves(CloogConstraint
*constraint
, int v
)
746 return !cloog_int_is_zero(constraint
->line
[0][1+v
]);
749 int cloog_constraint_is_lower_bound(CloogConstraint
*constraint
, int v
)
751 return cloog_int_is_pos(constraint
->line
[0][1+v
]);
754 int cloog_constraint_is_upper_bound(CloogConstraint
*constraint
, int v
)
756 return cloog_int_is_neg(constraint
->line
[0][1+v
]);
759 int cloog_constraint_is_equality(CloogConstraint
*constraint
)
761 return cloog_int_is_zero(constraint
->line
[0][0]);
764 void cloog_constraint_clear(CloogConstraint
*constraint
)
768 for (k
= 1; k
<= constraint
->set
->M
.NbColumns
- 2; k
++)
769 cloog_int_set_si(constraint
->line
[0][k
], 0);
772 CloogConstraintSet
*cloog_constraint_set_drop_constraint(
773 CloogConstraintSet
*constraints
, CloogConstraint
*constraint
)
775 cloog_constraint_clear(constraint
);
779 void cloog_constraint_coefficient_get(CloogConstraint
*constraint
,
780 int var
, cloog_int_t
*val
)
782 cloog_int_set(*val
, constraint
->line
[0][1+var
]);
785 void cloog_constraint_coefficient_set(CloogConstraint
*constraint
,
786 int var
, cloog_int_t val
)
788 cloog_int_set(constraint
->line
[0][1+var
], val
);
791 void cloog_constraint_constant_get(CloogConstraint
*constraint
, cloog_int_t
*val
)
793 cloog_int_set(*val
, constraint
->line
[0][constraint
->set
->M
.NbColumns
-1]);
797 * Copy the coefficient of constraint c into dst in PolyLib order,
798 * i.e., first the coefficients of the variables, then the coefficients
799 * of the parameters and finally the constant.
801 void cloog_constraint_copy_coefficients(CloogConstraint
*constraint
,
804 cloog_seq_cpy(dst
, constraint
->line
[0]+1, constraint
->set
->M
.NbColumns
-1);
807 CloogConstraint
*cloog_constraint_invalid(void)
812 int cloog_constraint_is_valid(CloogConstraint
*constraint
)
814 return constraint
!= NULL
;
819 * Check whether there is any need for the constraint "upper" on
820 * "level" to get reduced.
823 int cloog_constraint_needs_reduction(CloogConstraint
*upper
, int level
)
830 * Create a CloogConstraintSet containing enough information to perform
831 * a reduction on the upper equality (in this case lower is an invalid
832 * CloogConstraint) or the pair of inequalities upper and lower
833 * from within insert_modulo_guard.
834 * In the PolyLib backend, we return a CloogConstraintSet containting only
835 * the upper bound. The reduction will not change the stride so there
836 * will be no need to recompute the bound on the modulo expression.
838 CloogConstraintSet
*cloog_constraint_set_for_reduction(CloogConstraint
*upper
,
839 CloogConstraint
*lower
)
841 CloogConstraintSet
*set
;
843 set
= cloog_constraint_set_from_cloog_matrix(
844 cloog_matrix_alloc(1, upper
->set
->M
.NbColumns
));
845 cloog_seq_cpy(set
->M
.p
[0], upper
->line
[0], set
->M
.NbColumns
);
850 /* Computes x, y and g such that g = gcd(a,b) and a*x+b*y = g */
851 static void Euclid(cloog_int_t a
, cloog_int_t b
,
852 cloog_int_t
*x
, cloog_int_t
*y
, cloog_int_t
*g
)
854 cloog_int_t c
, d
, e
, f
, tmp
;
863 cloog_int_set_si(e
, 1);
864 cloog_int_set_si(f
, 0);
865 while (cloog_int_is_pos(d
)) {
866 cloog_int_tdiv_q(tmp
, c
, d
);
867 cloog_int_mul(tmp
, tmp
, f
);
868 cloog_int_sub(e
, e
, tmp
);
869 cloog_int_tdiv_q(tmp
, c
, d
);
870 cloog_int_mul(tmp
, tmp
, d
);
871 cloog_int_sub(c
, c
, tmp
);
872 cloog_int_swap(c
, d
);
873 cloog_int_swap(e
, f
);
875 cloog_int_set(*g
, c
);
876 if (cloog_int_is_zero(a
))
877 cloog_int_set_si(*x
, 0);
878 else if (cloog_int_is_pos(a
))
879 cloog_int_set(*x
, e
);
880 else cloog_int_neg(*x
, e
);
881 if (cloog_int_is_zero(b
))
882 cloog_int_set_si(*y
, 0);
884 cloog_int_mul(tmp
, a
, *x
);
885 cloog_int_sub(tmp
, c
, tmp
);
886 cloog_int_divexact(*y
, tmp
, b
);
892 cloog_int_clear(tmp
);
896 * Reduce the modulo guard expressed by "contraints" using equalities
897 * found in outer nesting levels (stored in "equal").
898 * The modulo guard may be an equality or a pair of inequalities.
899 * In case of a pair of inequalities, "constraints" only contains the
900 * upper bound and *bound contains the bound on the
901 * corresponding modulo expression. The bound is left untouched by
904 CloogConstraintSet
*cloog_constraint_set_reduce(CloogConstraintSet
*constraints
,
905 int level
, CloogEqualities
*equal
, int nb_par
, cloog_int_t
*bound
)
907 int i
, j
, k
, len
, len2
, nb_iter
;
908 struct cloog_vec
*line_vector2
;
909 cloog_int_t
*line
, *line2
, val
, x
, y
, g
;
911 len
= constraints
->M
.NbColumns
;
912 len2
= cloog_equal_total_dimension(equal
) + 2;
913 nb_iter
= len
- 2 - nb_par
;
920 line_vector2
= cloog_vec_alloc(len2
);
921 line2
= line_vector2
->p
;
923 line
= constraints
->M
.p
[0];
924 if (cloog_int_is_pos(line
[level
]))
925 cloog_seq_neg(line
+1, line
+1, len
-1);
926 cloog_int_neg(line
[level
], line
[level
]);
927 assert(cloog_int_is_pos(line
[level
]));
929 for (i
= nb_iter
; i
>= 1; --i
) {
932 cloog_int_fdiv_r(line
[i
], line
[i
], line
[level
]);
933 if (cloog_int_is_zero(line
[i
]))
936 /* Look for an earlier variable that is also a multiple of line[level]
937 * and check whether we can use the corresponding affine expression
938 * to "reduce" the modulo guard, where reduction means that we eliminate
939 * a variable, possibly at the expense of introducing other variables
940 * with smaller index.
942 for (j
= level
-1; j
>= 0; --j
) {
943 CloogConstraint
*equal_constraint
;
944 if (cloog_equal_type(equal
, j
+1) != EQTYPE_EXAFFINE
)
946 equal_constraint
= cloog_equal_constraint(equal
, j
);
947 cloog_constraint_coefficient_get(equal_constraint
, j
, &val
);
948 if (!cloog_int_is_divisible_by(val
, line
[level
])) {
949 cloog_constraint_release(equal_constraint
);
952 cloog_constraint_coefficient_get(equal_constraint
, i
-1, &val
);
953 if (cloog_int_is_divisible_by(val
, line
[level
])) {
954 cloog_constraint_release(equal_constraint
);
957 for (k
= j
; k
> i
; --k
) {
958 cloog_constraint_coefficient_get(equal_constraint
, k
-1, &val
);
959 if (cloog_int_is_zero(val
))
961 if (!cloog_int_is_divisible_by(val
, line
[level
]))
965 cloog_constraint_release(equal_constraint
);
968 cloog_constraint_coefficient_get(equal_constraint
, i
-1, &val
);
969 Euclid(val
, line
[level
], &x
, &y
, &g
);
970 if (!cloog_int_is_divisible_by(val
, line
[i
])) {
971 cloog_constraint_release(equal_constraint
);
974 cloog_int_divexact(val
, line
[i
], g
);
975 cloog_int_neg(val
, val
);
976 cloog_int_mul(val
, val
, x
);
977 cloog_int_set_si(y
, 1);
978 /* Add (equal->p[j][i])^{-1} * line[i] times the equality */
979 cloog_constraint_copy_coefficients(equal_constraint
, line2
+1);
980 cloog_seq_combine(line
+1, y
, line
+1, val
, line2
+1, i
);
981 cloog_seq_combine(line
+len
-nb_par
-1, y
, line
+len
-nb_par
-1,
982 val
, line2
+len2
-nb_par
-1, nb_par
+1);
983 cloog_constraint_release(equal_constraint
);
988 cloog_vec_free(line_vector2
);
990 cloog_int_clear(val
);
995 /* Make sure the line is not inverted again in the calling function. */
996 cloog_int_neg(line
[level
], line
[level
]);
1001 CloogConstraint
*cloog_constraint_first(CloogConstraintSet
*constraints
)
1004 if (constraints
->M
.NbRows
== 0)
1005 return cloog_constraint_invalid();
1006 c
= ALLOC(CloogConstraint
);
1007 c
->set
= constraints
;
1008 c
->line
= &constraints
->M
.p
[0];
1012 CloogConstraint
*cloog_constraint_next(CloogConstraint
*constraint
)
1015 if (constraint
->line
== constraint
->set
->M
.p
+ constraint
->set
->M
.NbRows
) {
1016 cloog_constraint_release(constraint
);
1022 CloogConstraint
*cloog_constraint_copy(CloogConstraint
*constraint
)
1024 CloogConstraint
*c
= ALLOC(CloogConstraint
);
1025 c
->set
= constraint
->set
;
1026 c
->line
= constraint
->line
;
1030 void cloog_constraint_release(CloogConstraint
*constraint
)
1035 int cloog_constraint_set_foreach_constraint(CloogConstraintSet
*constraints
,
1036 int (*fn
)(CloogConstraint
*constraint
, void *user
), void *user
)
1040 for (c
= cloog_constraint_first(constraints
);
1041 cloog_constraint_is_valid(c
); c
= cloog_constraint_next(c
))
1042 if (fn(c
, user
) < 0) {
1043 cloog_constraint_release(c
);
1050 CloogConstraint
*cloog_equal_constraint(CloogEqualities
*equal
, int j
)
1052 CloogConstraint
*c
= ALLOC(CloogConstraint
);
1053 c
->set
= equal
->constraints
;
1054 c
->line
= &equal
->constraints
->M
.p
[j
];