2 /**-------------------------------------------------------------------**
4 **-------------------------------------------------------------------**
6 **-------------------------------------------------------------------**
7 ** First version: october 28th 2001 **
8 **-------------------------------------------------------------------**/
11 /******************************************************************************
12 * CLooG : the Chunky Loop Generator (experimental) *
13 ******************************************************************************
15 * Copyright (C) 2001-2005 Cedric Bastoul *
17 * This is free software; you can redistribute it and/or modify it under the *
18 * terms of the GNU General Public License as published by the Free Software *
19 * Foundation; either version 2 of the License, or (at your option) any later *
22 * This software is distributed in the hope that it will be useful, but *
23 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
24 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
27 * You should have received a copy of the GNU General Public License along *
28 * with software; if not, write to the Free Software Foundation, Inc., *
29 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
31 * CLooG, the Chunky Loop Generator *
32 * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr *
34 ******************************************************************************/
35 /* CAUTION: the english used for comments is probably the worst you ever read,
36 * please feel free to correct and improve it !
42 # include "../../include/cloog/cloog.h"
45 static int cloog_check_polyhedral_ops
= 1;
46 static int cloog_return_ppl_result
= 0;
47 static int cloog_print_debug
= 0;
50 print_result (char *s
, CloogDomain
*d
)
52 if (cloog_print_debug
)
54 fprintf (stderr
, "%s \n", s
);
55 debug_cloog_domain (d
);
60 /* Variables names for pretty printing. */
61 static char wild_name
[200][40];
63 static inline const char*
64 variable_output_function (ppl_dimension_type var
)
67 return wild_name
[var
+ 1];
73 error_handler (enum ppl_enum_error_code code
, const char* description
)
75 fprintf (stderr
, "PPL error code %d\n%s", code
, description
);
80 cloog_initialize (void)
82 sprintf (wild_name
[0], "1");
83 sprintf (wild_name
[1], "a");
84 sprintf (wild_name
[2], "b");
85 sprintf (wild_name
[3], "c");
86 sprintf (wild_name
[4], "d");
87 sprintf (wild_name
[5], "e");
88 sprintf (wild_name
[6], "f");
89 sprintf (wild_name
[7], "g");
90 sprintf (wild_name
[8], "h");
91 sprintf (wild_name
[9], "i");
92 sprintf (wild_name
[10], "j");
93 sprintf (wild_name
[11], "k");
94 sprintf (wild_name
[12], "l");
95 sprintf (wild_name
[13], "m");
96 sprintf (wild_name
[14], "n");
97 sprintf (wild_name
[15], "o");
98 sprintf (wild_name
[16], "p");
99 sprintf (wild_name
[17], "q");
100 sprintf (wild_name
[18], "r");
101 sprintf (wild_name
[19], "s");
102 sprintf (wild_name
[20], "t");
103 sprintf (wild_name
[21], "alpha");
104 sprintf (wild_name
[22], "beta");
105 sprintf (wild_name
[23], "gamma");
106 sprintf (wild_name
[24], "delta");
107 sprintf (wild_name
[25], "tau");
108 sprintf (wild_name
[26], "sigma");
109 sprintf (wild_name
[27], "chi");
110 sprintf (wild_name
[28], "omega");
111 sprintf (wild_name
[29], "pi");
112 sprintf (wild_name
[30], "ni");
113 sprintf (wild_name
[31], "Alpha");
114 sprintf (wild_name
[32], "Beta");
115 sprintf (wild_name
[33], "Gamma");
116 sprintf (wild_name
[34], "Delta");
117 sprintf (wild_name
[35], "Tau");
118 sprintf (wild_name
[36], "Sigma");
119 sprintf (wild_name
[37], "Chi");
120 sprintf (wild_name
[38], "Omega");
121 sprintf (wild_name
[39], "xxx");
123 if (ppl_initialize() < 0)
125 fprintf (stderr
, "Cannot initialize the Parma Polyhedra Library.\n");
129 if (ppl_set_error_handler (error_handler
) < 0)
131 fprintf (stderr
, "Cannot install the custom error handler.\n");
135 if (ppl_io_set_variable_output_function (variable_output_function
) < 0)
137 fprintf (stderr
, "Cannot install the PPL custom variable output function. \n");
142 static inline Polyhedron
*
143 u2p (ppl_polyhedra_union
* upol
)
145 Polyhedron
*res
= Polyhedron_Copy (cloog_upol_polyhedron (upol
));
150 ppl_polyhedra_union
*next
= cloog_upol_next (upol
);
154 n
= Polyhedron_Copy (cloog_upol_polyhedron (next
));
166 static inline Polyhedron
*
167 d2p (CloogDomain
* d
)
169 return u2p (cloog_domain_upol (d
));
173 static inline ppl_polyhedra_union
*
176 ppl_polyhedra_union
*u
= cloog_new_upol (p
);
177 ppl_polyhedra_union
*res
= u
;
181 Polyhedron
*next
= p
->next
;
182 ppl_polyhedra_union
*n
;
185 n
= cloog_new_upol (next
);
189 cloog_upol_set_next (u
, n
);
199 * The maximal number of rays allowed to be allocated by PolyLib. In fact since
200 * version 5.20, PolyLib automatically tune the number of rays by multiplying
201 * by 2 this number each time the maximum is reached. For unknown reasons
202 * PolyLib makes a segmentation fault if this number is too small. If this
203 * number is too small, performances will be reduced, if it is too high, memory
204 * will be saturated. Note that the option "-rays X" set this number to X.
208 /* Unused in this backend. */
210 int cloog_domain_allocated
= 0;
211 int cloog_domain_freed
= 0;
212 int cloog_domain_max
= 0;
214 /* The same for Value variables since in GMP mode they have to be freed. */
215 int cloog_value_allocated
= 0;
216 int cloog_value_freed
= 0;
217 int cloog_value_max
= 0;
221 cloog_value_leak_up ()
223 cloog_value_allocated
++;
224 if ((cloog_value_allocated
- cloog_value_freed
) > cloog_value_max
)
225 cloog_value_max
= cloog_value_allocated
- cloog_value_freed
;
230 cloog_value_leak_down ()
236 cloog_domain_polyhedron_set (CloogDomain
* d
, ppl_polyhedra_union
* p
)
242 cloog_domain_set_references (CloogDomain
* d
, int i
)
248 cloog_new_domain (ppl_polyhedra_union
*p
)
250 CloogDomain
*domain
= (CloogDomain
*) malloc (sizeof (CloogDomain
));
251 domain
->_polyhedron
= p
;
252 cloog_domain_set_references (domain
, 1);
257 cloog_domain_alloc (Polyhedron
*p
)
259 return print_result ("cloog_domain_alloc", cloog_new_domain (p2u (p
)));
262 static inline CloogDomain
*
263 cloog_check_domain_id (CloogDomain
*dom
)
268 static inline CloogDomain
*
269 cloog_check_domain (CloogDomain
*dom
)
274 /* FIXME: Remove this check. */
275 if (cloog_domain_polyhedron (dom
)->next
)
277 fprintf (stderr
, "polyhedra of domains should be convex.\n");
285 * cloog_domain_matrix2domain function:
286 * Given a matrix of constraints (matrix), this function constructs and returns
287 * the corresponding domain (i.e. the CloogDomain structure including the
288 * polyhedron with its double representation: constraint matrix and the set of
292 cloog_domain_matrix2domain (CloogMatrix
* matrix
)
294 return print_result ("cloog_domain_matrix2domain", cloog_check_domain (cloog_domain_alloc (Constraints2Polyhedron (matrix
, MAX_RAYS
))));
297 static inline CloogMatrix
*
298 cloog_upol_domain2matrix (ppl_polyhedra_union
* upol
)
300 return Polyhedron2Constraints (cloog_upol_polyhedron (upol
));
303 /* In the matrix representation an equality has a 0 in the first
304 column. When the value of the first column is 1, the row
305 represents an inequality. */
308 cloog_matrix_row_is_eq_p (CloogMatrix
*matrix
, int row
)
310 return value_zero_p (matrix
->p
[row
][0]);
313 static ppl_Polyhedron_t
314 cloog_translate_constraint_matrix (CloogMatrix
*matrix
)
317 ppl_Polyhedron_t res
;
318 ppl_Constraint_t cstr
;
319 ppl_Linear_Expression_t expr
;
320 ppl_Coefficient_t coef
;
321 ppl_dimension_type dim
= matrix
->NbColumns
- 2;
323 ppl_new_Coefficient (&coef
);
324 ppl_new_NNC_Polyhedron_from_dimension (&res
, dim
);
326 for (i
= 0; i
< matrix
->NbRows
; i
++)
328 ppl_new_Linear_Expression_with_dimension (&expr
, dim
);
330 for (j
= 1; j
< matrix
->NbColumns
- 1; j
++)
332 ppl_assign_Coefficient_from_mpz_t (coef
, matrix
->p
[i
][j
]);
333 ppl_Linear_Expression_add_to_coefficient (expr
, j
- 1, coef
);
336 ppl_assign_Coefficient_from_mpz_t
337 (coef
, matrix
->p
[i
][matrix
->NbColumns
- 1]);
338 ppl_Linear_Expression_add_to_inhomogeneous (expr
, coef
);
340 if (cloog_matrix_row_is_eq_p (matrix
, i
))
341 ppl_new_Constraint (&cstr
, expr
, PPL_CONSTRAINT_TYPE_EQUAL
);
343 ppl_new_Constraint (&cstr
, expr
, PPL_CONSTRAINT_TYPE_GREATER_THAN_OR_EQUAL
);
345 ppl_Polyhedron_add_constraint (res
, cstr
);
348 if (cloog_check_polyhedral_ops
)
349 ppl_Polyhedron_OK (res
);
355 cloog_translate_ppl_polyhedron (ppl_Polyhedron_t pol
)
358 CloogMatrix
*matrix
;
359 ppl_dimension_type dim
;
360 ppl_const_Constraint_System_t pcs
;
361 ppl_Constraint_System_const_iterator_t cit
, end
;
364 ppl_Polyhedron_constraints (pol
, &pcs
);
365 ppl_new_Constraint_System_const_iterator (&cit
);
366 ppl_new_Constraint_System_const_iterator (&end
);
368 for (row
= 0, ppl_Constraint_System_begin (pcs
, cit
), ppl_Constraint_System_end (pcs
, end
);
369 !ppl_Constraint_System_const_iterator_equal_test (cit
, end
);
370 ppl_Constraint_System_const_iterator_increment (cit
), row
++);
372 ppl_Polyhedron_space_dimension (pol
, &dim
);
373 matrix
= cloog_matrix_alloc (row
, dim
+ 2);
375 for (row
= 0, ppl_Constraint_System_begin (pcs
, cit
), ppl_Constraint_System_end (pcs
, end
);
376 !ppl_Constraint_System_const_iterator_equal_test (cit
, end
);
377 ppl_Constraint_System_const_iterator_increment (cit
), row
++)
379 ppl_const_Constraint_t pc
;
380 ppl_Coefficient_t coef
;
381 ppl_dimension_type col
;
386 ppl_new_Coefficient (&coef
);
387 ppl_Constraint_System_const_iterator_dereference (cit
, &pc
);
389 neg
= (ppl_Constraint_type (pc
) == PPL_CONSTRAINT_TYPE_LESS_THAN
390 || ppl_Constraint_type (pc
) == PPL_CONSTRAINT_TYPE_LESS_THAN_OR_EQUAL
) ? 1 : 0;
392 for (col
= 0; col
< dim
; col
++)
394 ppl_Constraint_coefficient (pc
, col
, coef
);
395 ppl_Coefficient_to_mpz_t (coef
, val
);
398 value_oppose (val
, val
);
400 value_assign (matrix
->p
[row
][col
+1], val
);
403 ppl_Constraint_inhomogeneous_term (pc
, coef
);
404 ppl_Coefficient_to_mpz_t (coef
, val
);
405 value_assign (matrix
->p
[row
][dim
+ 1], val
);
407 switch (ppl_Constraint_type (pc
))
409 case PPL_CONSTRAINT_TYPE_EQUAL
:
410 value_set_si (matrix
->p
[row
][0], 0);
413 case PPL_CONSTRAINT_TYPE_LESS_THAN
:
414 case PPL_CONSTRAINT_TYPE_GREATER_THAN
:
415 value_decrement (matrix
->p
[row
][dim
+ 1], matrix
->p
[row
][dim
+ 1]);
416 value_set_si (matrix
->p
[row
][0], 1);
419 case PPL_CONSTRAINT_TYPE_LESS_THAN_OR_EQUAL
:
420 case PPL_CONSTRAINT_TYPE_GREATER_THAN_OR_EQUAL
:
421 value_set_si (matrix
->p
[row
][0], 1);
425 fprintf (stderr
, "PPL_CONSTRAINT_TYPE_%d not implemented yet\n",
426 ppl_Constraint_type (pc
));
431 res
= cloog_domain_matrix2domain (matrix
);
432 return print_result ("cloog_translate_ppl_polyhedron", cloog_check_domain (res
));
436 cloog_domain_references (CloogDomain
* d
)
438 return d
->_references
;
442 * cloog_domain_print function:
443 * This function prints the content of a CloogDomain structure (domain) into
444 * a file (foo, possibly stdout).
447 cloog_domain_print (FILE * foo
, CloogDomain
* domain
)
449 ppl_polyhedra_union
*upol
= cloog_domain_upol (domain
);
453 Polyhedron_Print (foo
, P_VALUE_FMT
, cloog_upol_polyhedron (upol
));
454 upol
= cloog_upol_next (upol
);
457 fprintf (foo
, "Number of active references: %d\n",
458 cloog_domain_references (domain
));
462 * cloog_domain_free function:
463 * This function frees the allocated memory for a CloogDomain structure
464 * (domain). It decrements the number of active references to this structure,
465 * if there are no more references on the structure, it frees it (with the
466 * included list of polyhedra).
469 cloog_domain_free (CloogDomain
* domain
)
473 cloog_domain_set_references (domain
,
474 cloog_domain_references (domain
) - 1);
476 if (cloog_domain_references (domain
) == 0)
479 ppl_polyhedra_union
*upol
= cloog_domain_upol (domain
);
483 Polyhedron_Free (cloog_upol_polyhedron (upol
));
484 upol
= cloog_upol_next (upol
);
494 * cloog_domain_copy function:
495 * This function returns a copy of a CloogDomain structure (domain). To save
496 * memory this is not a memory copy but we increment a counter of active
497 * references inside the structure, then return a pointer to that structure.
500 cloog_domain_copy (CloogDomain
* domain
)
502 cloog_domain_set_references (domain
, cloog_domain_references (domain
) + 1);
503 return print_result ("cloog_domain_copy", domain
);
508 * cloog_domain_image function:
509 * This function returns a CloogDomain structure such that the included
510 * polyhedral domain is computed from the former one into another
511 * domain according to a given affine mapping function (mapping).
514 cloog_domain_image (CloogDomain
* domain
, CloogMatrix
* mapping
)
516 Polyhedron
*p
= d2p (domain
);
518 cloog_check_domain (cloog_domain_alloc
519 (DomainImage (p
, mapping
, MAX_RAYS
)));
521 return print_result ("cloog_domain_image", res
);
526 * cloog_domain_preimage function:
527 * Given a polyhedral domain (polyhedron) inside a CloogDomain structure and a
528 * mapping function (mapping), this function returns a new CloogDomain structure
529 * with a polyhedral domain which when transformed by mapping function (mapping)
530 * gives (polyhedron).
533 cloog_domain_preimage (CloogDomain
* domain
, CloogMatrix
* mapping
)
535 Polyhedron
*p
= d2p (domain
);
537 cloog_check_domain (cloog_domain_alloc
538 (DomainPreimage (p
, mapping
, MAX_RAYS
)));
540 return print_result ("cloog_domain_preimage", res
);
545 * cloog_domain_convex function:
546 * Given a polyhedral domain (polyhedron), this function concatenates the lists
547 * of rays and lines of the two (or more) polyhedra in the domain into one
548 * combined list, and find the set of constraints which tightly bound all of
549 * those objects. It returns the corresponding polyhedron.
552 cloog_domain_convex (CloogDomain
* domain
)
554 Polyhedron
*p
= d2p (domain
);
556 cloog_check_domain (cloog_domain_alloc
557 (DomainConvex (p
, MAX_RAYS
)));
559 return print_result ("cloog_domain_convex", res
);
562 static inline unsigned
563 cloog_upol_nbc (ppl_polyhedra_union
* p
)
565 return cloog_upol_polyhedron (p
)->NbConstraints
;
569 cloog_domain_nbconstraints (CloogDomain
* domain
)
571 return cloog_domain_polyhedron (domain
)->NbConstraints
;
574 static inline unsigned
575 cloog_upol_nbeq (ppl_polyhedra_union
* d
)
577 return cloog_upol_polyhedron (d
)->NbEq
;
580 static inline unsigned
581 cloog_domain_nbeq (CloogDomain
* d
)
583 return cloog_domain_polyhedron (d
)->NbEq
;
586 static inline unsigned
587 cloog_upol_dim (ppl_polyhedra_union
* p
)
589 return cloog_upol_polyhedron (p
)->Dimension
;
593 cloog_domain_isconvex (CloogDomain
* domain
)
595 if (cloog_domain_polyhedron (domain
))
596 return !cloog_upol_next (cloog_domain_upol (domain
));
602 cloog_domain_dim (CloogDomain
* d
)
604 return cloog_domain_polyhedron (d
)->Dimension
;
608 cloog_check_domains (CloogDomain
*ppl
, CloogDomain
*polylib
)
610 /* Cannot use cloog_domain_lazy_equal (polylib, ppl) here as this
611 function is too dumb: it does not detect permutations of
613 if (!cloog_domain_isempty (cloog_domain_difference (ppl
, polylib
))
614 || !cloog_domain_isempty (cloog_domain_difference (polylib
, ppl
)))
616 fprintf (stderr
, "different domains ( \n ppl (\n");
617 cloog_domain_print (stderr
, ppl
);
618 fprintf (stderr
, ") \n polylib (\n");
619 cloog_domain_print (stderr
, polylib
);
620 fprintf (stderr
, "))\n");
624 if (cloog_return_ppl_result
)
631 * cloog_domain_simple_convex:
632 * Given a list (union) of polyhedra, this function returns a "simple"
633 * convex hull of this union. In particular, the constraints of the
634 * the returned polyhedron consist of (parametric) lower and upper
635 * bounds on individual variables and constraints that appear in the
636 * original polyhedra.
638 * nb_par is the number of parameters of the domain.
641 cloog_domain_simple_convex (CloogDomain
* domain
, int nb_par
)
643 fprintf (stderr
, "cloog_domain_simple_convex is not implemented yet.\n");
649 * cloog_domain_simplify function:
650 * Given two polyhedral domains (pol1) and (pol2) inside two CloogDomain
651 * structures, this function finds the largest domain set (or the smallest list
652 * of non-redundant constraints), that when intersected with polyhedral
653 * domain (pol2) equals (Pol1)intersect(Pol2). The output is a new CloogDomain
654 * structure with a polyhedral domain with the "redundant" constraints removed.
655 * NB: this function do not work as expected with unions of polyhedra...
658 cloog_domain_simplify (CloogDomain
* dom1
, CloogDomain
* dom2
)
662 Polyhedron
*d2
, *P
= d2p (dom1
);
663 int nbc
= cloog_domain_nbconstraints (dom1
);
665 /* DomainSimplify doesn't remove all redundant equalities,
666 * so we remove them here first in case both dom1 and dom2
667 * are single polyhedra (i.e., not unions of polyhedra).
669 if (cloog_domain_isconvex (dom1
) && cloog_domain_isconvex (dom2
)
670 && cloog_domain_nbeq (dom1
) && cloog_domain_nbeq (dom2
))
673 int rows
= cloog_domain_nbeq (dom1
) + cloog_domain_nbeq (dom2
);
674 int cols
= cloog_domain_dim (dom1
) + 2;
676 M
= cloog_matrix_alloc (rows
, cols
);
677 M2
= cloog_matrix_alloc (nbc
, cols
);
678 Vector_Copy (cloog_domain_polyhedron (dom2
)->Constraint
[0],
679 M
->p
[0], cloog_domain_nbeq (dom2
) * cols
);
680 rank
= cloog_domain_nbeq (dom2
);
682 for (i
= 0; i
< cloog_domain_nbeq (dom1
); ++i
)
684 Vector_Copy (P
->Constraint
[i
], M
->p
[rank
], cols
);
685 if (Gauss (M
, rank
+ 1, cols
- 1) > rank
)
687 Vector_Copy (P
->Constraint
[i
], M2
->p
[row
++], cols
);
691 if (row
< cloog_domain_nbeq (dom1
))
693 Vector_Copy (P
->Constraint
[cloog_domain_nbeq (dom1
)],
694 M2
->p
[row
], (nbc
- cloog_domain_nbeq (dom1
)) * cols
);
695 P
= Constraints2Polyhedron (M2
, MAX_RAYS
);
697 cloog_matrix_free (M2
);
698 cloog_matrix_free (M
);
701 dom
= cloog_domain_alloc (DomainSimplify (P
, d2
, MAX_RAYS
));
702 Polyhedron_Free (d2
);
704 return print_result ("cloog_domain_simplify", cloog_check_domain (dom
));
707 static ppl_polyhedra_union
*
708 cloog_upol_copy (ppl_polyhedra_union
*p
)
710 ppl_polyhedra_union
*res
= cloog_new_upol (Polyhedron_Copy (cloog_upol_polyhedron (p
)));
711 ppl_polyhedra_union
*upol
= res
;
713 while (cloog_upol_next (p
))
715 cloog_upol_set_next (upol
, cloog_new_upol (Polyhedron_Copy (cloog_upol_polyhedron (p
))));
716 upol
= cloog_upol_next (upol
);
717 p
= cloog_upol_next (p
);
723 /* Adds to D1 the union of polyhedra from D2, with no checks of
724 redundancies between polyhedra. */
727 cloog_domain_add_domain (CloogDomain
*d1
, CloogDomain
*d2
)
729 ppl_polyhedra_union
*upol
;
737 upol
= cloog_domain_upol (d1
);
738 while (cloog_upol_next (upol
))
739 upol
= cloog_upol_next (upol
);
741 cloog_upol_set_next (upol
, cloog_domain_upol (d2
));
746 * cloog_domain_union function:
747 * This function returns a new CloogDomain structure including a polyhedral
748 * domain which is the union of two polyhedral domains (pol1) U (pol2) inside
749 * two CloogDomain structures.
752 cloog_domain_union (CloogDomain
* dom1
, CloogDomain
* dom2
)
755 ppl_polyhedra_union
*head1
, *head2
, *tail1
, *tail2
;
756 ppl_polyhedra_union
*d1
, *d2
;
764 if (cloog_domain_dim (dom1
) != cloog_domain_dim (dom2
))
766 fprintf (stderr
, "cloog_domain_union should not be called on domains of different dimensions.\n");
772 for (d1
= cloog_domain_upol (dom1
); d1
; d1
= cloog_upol_next (d1
))
775 ppl_Polyhedron_t ppl1
= cloog_translate_constraint_matrix (cloog_upol_domain2matrix (d1
));
777 for (d2
= cloog_domain_upol (dom2
); d2
; d2
= cloog_upol_next (d2
))
779 ppl_Polyhedron_t ppl2
= cloog_translate_constraint_matrix (cloog_upol_domain2matrix (d2
));
781 if (ppl_Polyhedron_contains_Polyhedron (ppl2
, ppl1
))
792 head1
= cloog_upol_copy (d1
);
797 cloog_upol_set_next (tail1
, cloog_upol_copy (d1
));
798 tail1
= cloog_upol_next (tail1
);
805 for (d2
= cloog_domain_upol (dom2
); d2
; d2
= cloog_upol_next (d2
))
808 ppl_Polyhedron_t ppl2
= cloog_translate_constraint_matrix (cloog_upol_domain2matrix (d2
));
810 for (d1
= head1
; d1
; d1
= cloog_upol_next (d1
))
812 ppl_Polyhedron_t ppl1
= cloog_translate_constraint_matrix (cloog_upol_domain2matrix (d1
));
814 if (ppl_Polyhedron_contains_Polyhedron (ppl1
, ppl2
))
825 head2
= cloog_upol_copy (d2
);
830 cloog_upol_set_next (tail2
, cloog_upol_copy (d2
));
831 tail2
= cloog_upol_next (tail2
);
837 res
= cloog_new_domain (head2
);
840 cloog_upol_set_next (tail1
, head2
);
841 res
= cloog_new_domain (head1
);
844 if (cloog_check_polyhedral_ops
)
846 Polyhedron
*p1
= d2p (dom1
);
847 Polyhedron
*p2
= d2p (dom2
);
849 cloog_check_domains (res
, cloog_domain_alloc (DomainUnion (p1
, p2
, MAX_RAYS
)));
851 Polyhedron_Free (p1
);
852 Polyhedron_Free (p2
);
855 return print_result ("cloog_domain_union", cloog_check_domain (res
));
859 * cloog_domain_intersection function:
860 * This function returns a new CloogDomain structure including a polyhedral
861 * domain which is the intersection of two polyhedral domains (pol1)inter(pol2)
862 * inside two CloogDomain structures.
865 cloog_domain_intersection (CloogDomain
* dom1
, CloogDomain
* dom2
)
868 ppl_polyhedra_union
*p1
, *p2
;
869 ppl_Polyhedron_t ppl1
, ppl2
;
871 res
= cloog_domain_empty (cloog_domain_dim (dom1
));
873 for (p1
= cloog_domain_upol (dom1
); p1
; p1
= cloog_upol_next (p1
))
875 ppl1
= cloog_translate_constraint_matrix (Polyhedron2Constraints (cloog_upol_polyhedron (p1
)));
877 for (p2
= cloog_domain_upol (dom2
); p2
; p2
= cloog_upol_next (p2
))
879 ppl2
= cloog_translate_constraint_matrix (Polyhedron2Constraints (cloog_upol_polyhedron (p2
)));
880 ppl_Polyhedron_intersection_assign (ppl2
, ppl1
);
882 res
= cloog_domain_union (res
, cloog_translate_ppl_polyhedron (ppl2
));
886 if (cloog_check_polyhedral_ops
)
888 Polyhedron
*a1
= d2p (dom1
);
889 Polyhedron
*a2
= d2p (dom2
);
891 res
= cloog_check_domains (res
, cloog_domain_alloc (DomainIntersection (a1
, a2
, MAX_RAYS
)));
893 Polyhedron_Free (a1
);
894 Polyhedron_Free (a2
);
897 return print_result ("cloog_domain_intersection", res
);
902 * cloog_domain_difference function:
903 * This function returns a new CloogDomain structure including a polyhedral
904 * domain which is the difference of two polyhedral domains domain \ minus
905 * inside two CloogDomain structures.
906 * - November 8th 2001: first version.
909 cloog_domain_difference (CloogDomain
* domain
, CloogDomain
* minus
)
911 if (cloog_domain_isempty (minus
))
912 return print_result ("cloog_domain_difference", cloog_domain_copy (domain
));
915 Polyhedron
*p1
= d2p (domain
);
916 Polyhedron
*p2
= d2p (minus
);
917 CloogDomain
*res
= cloog_domain_alloc (DomainDifference (p1
, p2
, MAX_RAYS
));
918 Polyhedron_Free (p1
);
919 Polyhedron_Free (p2
);
920 return print_result ("cloog_domain_difference", res
);
926 * cloog_domain_addconstraints function :
927 * This function adds source's polyhedron constraints to target polyhedron: for
928 * each element of the polyhedron inside 'target' (i.e. element of the union
929 * of polyhedra) it adds the constraints of the corresponding element in
931 * - August 10th 2002: first version.
932 * Nota bene for future : it is possible that source and target don't have the
933 * same number of elements (try iftest2 without non-shared constraint
934 * elimination in cloog_loop_separate !). This function is yet another part
935 * of the DomainSimplify patching problem...
938 cloog_domain_addconstraints (domain_source
, domain_target
)
939 CloogDomain
*domain_source
, *domain_target
;
941 unsigned nb_constraint
;
943 ppl_polyhedra_union
*source
, *target
, *new, *next
, *last
;
945 source
= cloog_domain_upol (domain_source
);
946 target
= cloog_domain_upol (domain_target
);
948 constraints
= cloog_upol_polyhedron (source
)->p_Init
;
949 nb_constraint
= cloog_upol_nbc (source
);
950 last
= new = cloog_new_upol (AddConstraints (constraints
, nb_constraint
,
951 u2p (target
), MAX_RAYS
));
952 source
= cloog_upol_next (source
);
953 next
= cloog_upol_next (target
);
956 { /* BUG !!! This is actually a bug. I don't know yet how to cleanly avoid
957 * the situation where source and target do not have the same number of
958 * elements. So this 'if' is an awful trick, waiting for better.
962 constraints
= cloog_upol_polyhedron (source
)->p_Init
;
963 nb_constraint
= cloog_upol_nbc (source
);
964 source
= cloog_upol_next (source
);
967 (last
, cloog_new_upol (AddConstraints (constraints
, nb_constraint
,
968 u2p (next
), MAX_RAYS
)));
969 last
= cloog_upol_next (last
);
970 next
= cloog_upol_next (next
);
973 return print_result ("cloog_domain_addconstraints", cloog_check_domain (cloog_new_domain (new)));
978 * cloog_domain_sort function:
979 * This function topologically sorts (nb_pols) polyhedra. Here (pols) is a an
980 * array of pointers to polyhedra, (nb_pols) is the number of polyhedra,
981 * (level) is the level to consider for partial ordering (nb_par) is the
982 * parameter space dimension, (permut) if not NULL, is an array of (nb_pols)
983 * integers that contains a permutation specification after call in order to
984 * apply the topological sorting.
987 cloog_domain_sort (doms
, nb_pols
, level
, nb_par
, permut
)
989 unsigned nb_pols
, level
, nb_par
;
993 Polyhedron
**pols
= (Polyhedron
**) malloc (nb_pols
* sizeof (Polyhedron
*));
995 for (i
= 0; i
< nb_pols
; i
++)
996 pols
[i
] = cloog_domain_polyhedron (doms
[i
]);
998 /* time is an array of (nb_pols) integers to store logical time values. We
999 * do not use it, but it is compulsory for PolyhedronTSort.
1001 time
= (int *) malloc (nb_pols
* sizeof (int));
1003 /* PolyhedronTSort will fill up permut (and time). */
1004 PolyhedronTSort (pols
, nb_pols
, level
, nb_par
, time
, permut
, MAX_RAYS
);
1012 * cloog_domain_empty function:
1013 * This function allocates the memory space for a CloogDomain structure and
1014 * sets its polyhedron to an empty polyhedron with 'dimension' dimensions.
1015 * Then it returns a pointer to the allocated space.
1016 * - June 10th 2005: first version.
1019 cloog_domain_empty (int dimension
)
1021 return (cloog_domain_alloc (Empty_Polyhedron (dimension
)));
1025 /******************************************************************************
1026 * Structure display function *
1027 ******************************************************************************/
1031 * cloog_domain_print_structure :
1032 * this function is a more human-friendly way to display the CloogDomain data
1033 * structure, it only shows the constraint system and includes an indentation
1034 * level (level) in order to work with others print_structure functions.
1035 * Written by Olivier Chorier, Luc Marchaud, Pierre Martin and Romain Tartiere.
1036 * - April 24th 2005: Initial version.
1037 * - May 26th 2005: Memory leak hunt.
1038 * - June 16th 2005: (Ced) Integration in domain.c.
1041 cloog_domain_print_structure (FILE * file
, CloogDomain
* domain
, int level
)
1044 CloogMatrix
*matrix
;
1046 /* Go to the right level. */
1047 for (i
= 0; i
< level
; i
++)
1048 fprintf (file
, "|\t");
1052 fprintf (file
, "+-- CloogDomain\n");
1054 /* Print the matrix. */
1055 matrix
= cloog_upol_domain2matrix (cloog_domain_upol (domain
));
1056 cloog_matrix_print_structure (file
, matrix
, level
);
1057 cloog_matrix_free (matrix
);
1060 for (i
= 0; i
< level
+ 1; i
++)
1061 fprintf (file
, "|\t");
1062 fprintf (file
, "\n");
1065 fprintf (file
, "+-- Null CloogDomain\n");
1071 * cloog_domain_list_print function:
1072 * This function prints the content of a CloogDomainList structure into a
1073 * file (foo, possibly stdout).
1074 * - November 6th 2001: first version.
1077 cloog_domain_list_print (FILE * foo
, CloogDomainList
* list
)
1079 while (list
!= NULL
)
1081 cloog_domain_print (foo
, cloog_domain (list
));
1082 list
= cloog_next_domain (list
);
1087 /******************************************************************************
1088 * Memory deallocation function *
1089 ******************************************************************************/
1093 * cloog_domain_list_free function:
1094 * This function frees the allocated memory for a CloogDomainList structure.
1095 * - November 6th 2001: first version.
1098 cloog_domain_list_free (CloogDomainList
* list
)
1100 CloogDomainList
*temp
;
1102 while (list
!= NULL
)
1104 temp
= cloog_next_domain (list
);
1105 cloog_domain_free (cloog_domain (list
));
1112 /******************************************************************************
1113 * Reading function *
1114 ******************************************************************************/
1118 * cloog_domain_read function:
1119 * Adaptation from the PolyLib. This function reads a matrix into a file (foo,
1120 * posibly stdin) and returns a pointer to a polyhedron containing the read
1122 * - October 18th 2001: first version.
1125 cloog_domain_read (FILE * foo
)
1127 CloogMatrix
*matrix
;
1128 CloogDomain
*domain
;
1130 matrix
= cloog_matrix_read (foo
);
1131 domain
= cloog_domain_matrix2domain (matrix
);
1132 cloog_matrix_free (matrix
);
1134 return print_result ("cloog_domain_read", domain
);
1139 * cloog_domain_union_read function:
1140 * This function reads a union of polyhedra into a file (foo, posibly stdin) and
1141 * returns a pointer to a Polyhedron containing the read information.
1142 * - September 9th 2002: first version.
1143 * - October 29th 2005: (debug) removal of a leak counting "correction" that
1144 * was just false since ages.
1147 cloog_domain_union_read (FILE * foo
)
1149 int i
, nb_components
;
1151 CloogDomain
*domain
, *temp
, *old
;
1153 /* domain reading: nb_components (constraint matrices). */
1154 while (fgets (s
, MAX_STRING
, foo
) == 0);
1155 while ((*s
== '#' || *s
== '\n') || (sscanf (s
, " %d", &nb_components
) < 1))
1156 fgets (s
, MAX_STRING
, foo
);
1158 if (nb_components
> 0)
1159 { /* 1. first part of the polyhedra union, */
1160 domain
= cloog_domain_read (foo
);
1161 /* 2. and the nexts. */
1162 for (i
= 1; i
< nb_components
; i
++)
1163 { /* Leak counting is OK since next allocated domain is freed here. */
1164 temp
= cloog_domain_read (foo
);
1166 domain
= cloog_domain_union (temp
, old
);
1167 cloog_domain_free (temp
);
1168 cloog_domain_free (old
);
1170 return print_result ("cloog_domain_union_read", cloog_check_domain (domain
));
1178 * cloog_domain_list_read function:
1179 * This function reads a list of polyhedra into a file (foo, posibly stdin) and
1180 * returns a pointer to a CloogDomainList containing the read information.
1181 * - November 6th 2001: first version.
1184 cloog_domain_list_read (FILE * foo
)
1188 CloogDomainList
*list
, *now
, *next
;
1191 /* We read first the number of polyhedra in the list. */
1192 while (fgets (s
, MAX_STRING
, foo
) == 0);
1193 while ((*s
== '#' || *s
== '\n') || (sscanf (s
, " %d", &nb_pols
) < 1))
1194 fgets (s
, MAX_STRING
, foo
);
1196 /* Then we read the polyhedra. */
1200 list
= (CloogDomainList
*) malloc (sizeof (CloogDomainList
));
1201 cloog_set_domain (list
, cloog_domain_read (foo
));
1202 cloog_set_next_domain (list
, NULL
);
1204 for (i
= 1; i
< nb_pols
; i
++)
1206 next
= (CloogDomainList
*) malloc (sizeof (CloogDomainList
));
1207 cloog_set_domain (next
, cloog_domain_read (foo
));
1208 cloog_set_next_domain (next
, NULL
);
1209 cloog_set_next_domain (now
, next
);
1210 now
= cloog_next_domain (now
);
1217 /******************************************************************************
1218 * Processing functions *
1219 ******************************************************************************/
1222 * cloog_domain_isempty function:
1223 * This function returns 1 if the polyhedron given as input is empty, 0
1225 * - October 28th 2001: first version.
1228 cloog_domain_isempty (CloogDomain
* domain
)
1230 if (cloog_domain_polyhedron (domain
) == NULL
)
1233 if (cloog_upol_next (cloog_domain_upol (domain
)))
1236 return ((cloog_domain_dim (domain
) < cloog_domain_nbeq (domain
)) ? 1 : 0);
1240 * cloog_domain_project function:
1241 * From Quillere's LoopGen 0.4. This function returns the projection of
1242 * (domain) on the (level) first dimensions (i.e. outer loops). It returns a
1243 * pointer to the projected Polyhedron.
1244 * - nb_par is the number of parameters.
1246 * - October 27th 2001: first version.
1247 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1251 cloog_domain_project_1 (CloogDomain
* domain
, int level
, int nb_par
)
1253 int row
, column
, nb_rows
, nb_columns
, difference
;
1254 CloogDomain
*projected_domain
;
1255 CloogMatrix
*matrix
;
1257 nb_rows
= level
+ nb_par
+ 1;
1258 nb_columns
= cloog_domain_dim (domain
) + 1;
1259 difference
= nb_columns
- nb_rows
;
1261 if (difference
== 0)
1262 return print_result ("cloog_domain_project", cloog_domain_copy (domain
));
1264 matrix
= cloog_matrix_alloc (nb_rows
, nb_columns
);
1266 for (row
= 0; row
< level
; row
++)
1267 for (column
= 0; column
< nb_columns
; column
++)
1268 value_set_si (matrix
->p
[row
][column
], (row
== column
? 1 : 0));
1270 for (; row
< nb_rows
; row
++)
1271 for (column
= 0; column
< nb_columns
; column
++)
1272 value_set_si (matrix
->p
[row
][column
],
1273 (row
+ difference
== column
? 1 : 0));
1275 projected_domain
= cloog_domain_image (domain
, matrix
);
1276 cloog_matrix_free (matrix
);
1278 return print_result ("cloog_domain_project_1", cloog_check_domain (projected_domain
));
1282 cloog_domain_project (CloogDomain
* domain
, int level
, int nb_par
)
1284 return print_result ("cloog_domain_project",
1285 cloog_domain_project_1 (domain
, level
, nb_par
));
1289 cloog_domain_project_ported (CloogDomain
* domain
, int level
, int nb_par
)
1291 CloogDomain
*res
= NULL
;
1292 ppl_polyhedra_union
*upol
= cloog_domain_upol (domain
);
1293 int i
, diff
= cloog_domain_dim (domain
) - level
- nb_par
;
1295 ppl_dimension_type
*to_remove
;
1298 return print_result ("cloog_domain_project", domain
);
1301 to_remove
= (ppl_dimension_type
*) malloc (n
* sizeof (ppl_dimension_type
));
1303 for (i
= 0; i
< n
; i
++)
1304 to_remove
[i
] = i
+ level
;
1308 ppl_Polyhedron_t ppl
= cloog_translate_constraint_matrix (cloog_upol_domain2matrix (upol
));
1310 ppl_Polyhedron_remove_space_dimensions (ppl
, to_remove
, n
);
1311 res
= cloog_domain_add_domain (res
, cloog_translate_ppl_polyhedron (ppl
));
1312 upol
= cloog_upol_next (upol
);
1315 if (cloog_check_polyhedral_ops
)
1316 return print_result ("cloog_domain_project",
1318 (res
, cloog_domain_project_1 (domain
, level
, nb_par
)));
1320 return print_result ("cloog_domain_project", res
);
1324 * cloog_domain_extend function:
1325 * From Quillere's LoopGen 0.4. This function returns the (domain) given as
1326 * input with (dim)+(nb_par) dimensions. The new dimensions are added before
1327 * the (nb_par) parameters. This function does not free (domain), and returns
1329 * - nb_par is the number of parameters.
1331 * - October 27th 2001: first version.
1332 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1336 cloog_domain_extend (CloogDomain
* domain
, int dim
, int nb_par
)
1338 int row
, column
, nb_rows
, nb_columns
, difference
;
1339 CloogDomain
*extended_domain
;
1340 CloogMatrix
*matrix
;
1342 nb_rows
= 1 + cloog_domain_dim (domain
);
1343 nb_columns
= dim
+ nb_par
+ 1;
1344 difference
= nb_columns
- nb_rows
;
1346 if (difference
== 0)
1347 return print_result ("cloog_domain_extend", cloog_domain_copy (domain
));
1349 matrix
= cloog_matrix_alloc (nb_rows
, nb_columns
);
1351 for (row
= 0; row
< cloog_domain_dim (domain
) - nb_par
; row
++)
1352 for (column
= 0; column
< nb_columns
; column
++)
1353 value_set_si (matrix
->p
[row
][column
], (row
== column
? 1 : 0));
1355 for (; row
<= cloog_domain_dim (domain
); row
++)
1356 for (column
= 0; column
< nb_columns
; column
++)
1357 value_set_si (matrix
->p
[row
][column
],
1358 (row
+ difference
== column
? 1 : 0));
1360 extended_domain
= cloog_domain_preimage (domain
, matrix
);
1361 cloog_matrix_free (matrix
);
1363 return print_result ("cloog_domain_extend", cloog_check_domain (extended_domain
));
1368 * cloog_domain_never_integral function:
1369 * For us, an equality like 3*i -4 = 0 is always false since 4%3 != 0. This
1370 * function returns a boolean set to 1 if there is this kind of 'never true'
1371 * constraint inside a polyhedron, 0 otherwise.
1372 * - domain is the polyhedron to check,
1374 * - November 28th 2001: first version.
1375 * - June 26th 2003: for iterators, more 'never true' constraints are found
1376 * (compare cholesky2 and vivien with a previous version),
1377 * checking for the parameters created (compare using vivien).
1378 * - June 28th 2003: Previously in loop.c and called
1379 * cloog_loop_simplify_nevertrue, now here !
1380 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1382 * - October 14th 2005: Complete rewriting, not faster but code quite shorter.
1385 cloog_domain_never_integral (CloogDomain
* domain
)
1387 int i
, dimension
, nbc
;
1389 Polyhedron
*polyhedron
;
1391 if ((domain
== NULL
) || (cloog_domain_polyhedron (domain
) == NULL
))
1395 value_init_c (modulo
);
1396 polyhedron
= d2p (domain
);
1397 dimension
= cloog_domain_dim (domain
) + 2;
1398 nbc
= cloog_domain_nbconstraints (domain
);
1400 /* For each constraint... */
1401 for (i
= 0; i
< nbc
; i
++)
1402 { /* If we have an equality and the scalar part is not zero... */
1403 if (value_zero_p (polyhedron
->Constraint
[i
][0]) &&
1404 value_notzero_p (polyhedron
->Constraint
[i
][dimension
- 1]))
1405 { /* Then we check whether the scalar can be divided by the gcd of the
1406 * unknown vector (including iterators and parameters) or not. If not,
1407 * there is no integer point in the polyhedron and we return 1.
1409 Vector_Gcd (&(polyhedron
->Constraint
[i
][1]), dimension
- 2, &gcd
);
1410 value_modulus (modulo
,
1411 polyhedron
->Constraint
[i
][dimension
- 1],
1414 if (value_notzero_p (modulo
))
1416 value_clear_c (gcd
);
1417 value_clear_c (modulo
);
1418 Polyhedron_Free (polyhedron
);
1424 value_clear_c (gcd
);
1425 value_clear_c (modulo
);
1426 Polyhedron_Free (polyhedron
);
1432 * cloog_domain_stride function:
1433 * This function finds the stride imposed to unknown with the column number
1434 * 'strided_level' in order to be integral. For instance, if we have a
1435 * constraint like -i - 2j + 2k = 0, and we consider k, then k can be integral
1436 * only if (i + 2j)%2 = 0. Then only if i%2 = 0. Then k imposes a stride 2 to
1437 * the unknown i. The function returns the imposed stride in a parameter field.
1438 * - domain is the set of constraint we have to consider,
1439 * - strided_level is the column number of the unknown for which a stride have
1441 * - looking_level is the column number of the unknown that impose a stride to
1442 * the first unknown.
1443 * - stride is the stride that is returned back as a function parameter.
1444 * - offset is the value of the constant c if the condition is of the shape
1445 * (i + c)%s = 0, s being the stride.
1447 * - June 28th 2003: first version.
1448 * - July 14th 2003: can now look for multiple striding constraints and returns
1449 * the GCD of the strides and the common offset.
1450 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1454 cloog_domain_stride (domain
, strided_level
, nb_par
, stride
, offset
)
1455 CloogDomain
*domain
;
1456 int strided_level
, nb_par
;
1457 Value
*stride
, *offset
;
1460 int n_col
, n_row
, rank
;
1464 Polyhedron
*polyhedron
= d2p (domain
);
1465 int dimension
= cloog_domain_dim (domain
);
1466 int nbeq
= cloog_domain_nbeq (domain
);
1468 /* Look at all equalities involving strided_level and the inner
1469 * iterators. We can ignore the outer iterators and the parameters
1470 * here because the lower bound on strided_level is assumed to
1473 n_col
= (1 + dimension
- nb_par
) - strided_level
;
1474 for (i
= 0, n_row
= 0; i
< nbeq
; i
++)
1476 (polyhedron
->Constraint
[i
] + strided_level
, n_col
) != -1)
1479 M
= cloog_matrix_alloc (n_row
+ 1, n_col
+ 1);
1480 for (i
= 0, n_row
= 0; i
< nbeq
; i
++)
1483 (polyhedron
->Constraint
[i
] + strided_level
, n_col
) == -1)
1485 Vector_Copy (polyhedron
->Constraint
[i
] + strided_level
,
1486 M
->p
[n_row
], n_col
);
1487 value_assign (M
->p
[n_row
][n_col
],
1488 polyhedron
->Constraint
[i
][1 + dimension
]);
1491 value_set_si (M
->p
[n_row
][n_col
], 1);
1493 /* Then look at the general solution to the above equalities. */
1494 rank
= SolveDiophantine (M
, &U
, &V
);
1495 cloog_matrix_free (M
);
1499 /* There is no solution, so the body of this loop will
1500 * never execute. We just leave the constraints alone here so
1501 * that they will ensure the body will not be executed.
1502 * We should probably propagate this information up so that
1503 * the loop can be removed entirely.
1505 value_set_si (*offset
, 0);
1506 value_set_si (*stride
, 1);
1510 /* Compute the gcd of the coefficients defining strided_level. */
1511 Vector_Gcd (U
->p
[0], U
->NbColumns
, stride
);
1512 value_oppose (*offset
, V
->p
[0]);
1513 value_pmodulus (*offset
, *offset
, *stride
);
1517 Polyhedron_Free (polyhedron
);
1523 * cloog_domain_integral_lowerbound function:
1524 * This function returns 1 if the lower bound of an iterator (such as its
1525 * column rank in the constraint set 'domain' is 'level') is integral,
1526 * 0 otherwise. If the lower bound is actually integral, the function fills
1527 * the 'lower' field with the lower bound value.
1528 * - June 29th 2003: first version.
1529 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1533 cloog_domain_integral_lowerbound (domain
, level
, lower
)
1534 CloogDomain
*domain
;
1538 int i
, first_lower
= 1, dimension
, lower_constraint
= -1, nbc
;
1539 Value iterator
, constant
, tmp
;
1540 Polyhedron
*polyhedron
;
1542 polyhedron
= d2p (domain
);
1543 dimension
= cloog_domain_dim (domain
);
1544 nbc
= cloog_domain_nbconstraints (domain
);
1546 /* We want one and only one lower bound (e.g. no equality, no maximum
1549 for (i
= 0; i
< nbc
; i
++)
1550 if (value_zero_p (polyhedron
->Constraint
[i
][0])
1551 && value_notzero_p (polyhedron
->Constraint
[i
][level
]))
1553 Polyhedron_Free (polyhedron
);
1557 for (i
= 0; i
< nbc
; i
++)
1558 if (value_pos_p (polyhedron
->Constraint
[i
][level
]))
1563 lower_constraint
= i
;
1567 Polyhedron_Free (polyhedron
);
1574 Polyhedron_Free (polyhedron
);
1578 /* We want an integral lower bound: no other non-zero entry except the
1579 * iterator coefficient and the constant.
1581 for (i
= 1; i
< level
; i
++)
1583 (polyhedron
->Constraint
[lower_constraint
][i
]))
1585 Polyhedron_Free (polyhedron
);
1589 for (i
= level
+ 1; i
<= dimension
; i
++)
1591 (polyhedron
->Constraint
[lower_constraint
][i
]))
1593 Polyhedron_Free (polyhedron
);
1597 value_init_c (iterator
);
1598 value_init_c (constant
);
1601 /* If all is passed, then find the lower bound and return 1. */
1602 value_assign (iterator
,
1603 polyhedron
->Constraint
[lower_constraint
][level
]);
1604 value_oppose (constant
,
1605 polyhedron
->Constraint
[lower_constraint
][dimension
+ 1]);
1607 value_modulus (tmp
, constant
, iterator
);
1608 value_division (*lower
, constant
, iterator
);
1610 if (!(value_zero_p (tmp
) || value_neg_p (constant
)))
1611 value_increment (*lower
, *lower
);
1613 value_clear_c (iterator
);
1614 value_clear_c (constant
);
1615 value_clear_c (tmp
);
1616 Polyhedron_Free (polyhedron
);
1622 * cloog_domain_lowerbound_update function:
1623 * This function updates the integral lower bound of an iterator (such as its
1624 * column rank in the constraint set 'domain' is 'level') into 'lower'.
1625 * - Jun 29th 2003: first version.
1626 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1630 cloog_domain_lowerbound_update (domain
, level
, lower
)
1631 CloogDomain
*domain
;
1636 int nbc
= cloog_domain_nbconstraints (domain
);
1637 int dim
= cloog_domain_dim (domain
);
1638 Polyhedron
*polyhedron
= cloog_domain_polyhedron (domain
);
1640 /* There is only one lower bound, the first one is the good one. */
1641 for (i
= 0; i
< nbc
; i
++)
1642 if (value_pos_p (polyhedron
->Constraint
[i
][level
]))
1644 value_set_si (polyhedron
->Constraint
[i
][level
], 1);
1645 value_oppose (polyhedron
->Constraint
[i
][dim
+ 1], lower
);
1652 * cloog_domain_lazy_equal function:
1653 * This function returns 1 if the domains given as input are the same, 0 if it
1654 * is unable to decide. This function makes an entry-to-entry comparison between
1655 * the constraint systems, if all the entries are the same, the domains are
1656 * obviously the same and it returns 1, at the first difference, it returns 0.
1657 * This is a very fast way to verify this property. It has been shown (with the
1658 * CLooG benchmarks) that operations on equal domains are 17% of all the
1659 * polyhedral computations. For 75% of the actually identical domains, this
1660 * function answer that they are the same and allow to give immediately the
1661 * trivial solution instead of calling the heavy general functions of PolyLib.
1662 * - August 22th 2003: first version.
1663 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1667 cloog_domain_lazy_equal (CloogDomain
* d1
, CloogDomain
* d2
)
1670 ppl_polyhedra_union
*u1
= cloog_domain_upol (d1
);
1671 ppl_polyhedra_union
*u2
= cloog_domain_upol (d2
);
1675 if ((cloog_upol_nbc (u1
) != cloog_upol_nbc (u2
)) ||
1676 (cloog_upol_dim (u1
) != cloog_upol_dim (u2
)))
1680 cloog_upol_nbc (u1
) * (cloog_upol_dim (u1
) + 2);
1682 for (i
= 0; i
< nb_elements
; i
++)
1683 if (value_ne (cloog_upol_polyhedron (u1
)->p_Init
[i
],
1684 cloog_upol_polyhedron (u2
)->p_Init
[i
]))
1687 u1
= cloog_upol_next (u1
);
1688 u2
= cloog_upol_next (u2
);
1699 * cloog_domain_lazy_block function:
1700 * This function returns 1 if the two domains d1 and d2 given as input are the
1701 * same (possibly except for a dimension equal to a constant where we accept
1702 * a difference of 1) AND if we are sure that there are no other domain in
1703 * the code generation problem that may put integral points between those of
1704 * d1 and d2 (0 otherwise). In fact this function answers the question "can I
1705 * safely consider the two domains as only one with two statements (a block) ?".
1706 * This function is lazy: it asks for very standard scattering representation
1707 * (only one constraint per dimension which is an equality, and the constraints
1708 * are ordered per dimension depth: the left hand side of the constraint matrix
1709 * is the identity) and will answer NO at the very first problem.
1710 * - d1 and d2 are the two domains to check for blocking,
1711 * - scattering is the linked list of all domains,
1712 * - scattdims is the total number of scattering dimentions.
1714 * - April 30th 2005: beginning
1715 * - June 9th 2005: first working version.
1716 * - June 10th 2005: debugging.
1717 * - June 21rd 2005: Adaptation for GMP.
1718 * - October 16th 2005: (debug) some false blocks have been removed.
1721 cloog_domain_lazy_block (d1
, d2
, scattering
, scattdims
)
1722 CloogDomain
*d1
, *d2
;
1723 CloogDomainList
*scattering
;
1726 int i
, j
, difference
= 0, different_constraint
= 0, nbc
;
1728 Value date1
, date2
, date3
, temp
;
1729 Polyhedron
*p1
, *p2
;
1731 /* Some basic checks: we only accept convex domains, with same constraint
1732 * and dimension numbers.
1734 if (!cloog_domain_isconvex (d1
) || !cloog_domain_isconvex (d2
) ||
1735 (cloog_domain_nbconstraints (d1
) != cloog_domain_nbconstraints (d2
)) ||
1736 (cloog_domain_dim (d1
) != cloog_domain_dim (d2
)))
1741 nbc
= cloog_domain_nbconstraints (d1
);
1742 dim1
= cloog_domain_dim (d1
);
1743 dim2
= cloog_domain_dim (d2
);
1745 /* There should be only one difference between the two domains, it
1746 * has to be at the constant level and the difference must be of +1,
1747 * moreover, after the difference all domain coefficient has to be 0.
1748 * The matrix shape is:
1750 * |===========|=====|<- 0 line
1751 * |===========|=====|
1752 * |===========|====?|<- different_constraint line (found here)
1753 * |===========|0000=|
1754 * |===========|0000=|<- pX->NbConstraints line
1757 * | | (pX->Dimension + 2) column
1758 * | scattdims column
1762 value_init_c (temp
);
1763 for (i
= 0; i
< nbc
; i
++)
1765 if (difference
== 0)
1766 { /* All elements except scalar must be equal. */
1767 for (j
= 0; j
< dim1
+ 1; j
++)
1768 if (value_ne (p1
->Constraint
[i
][j
],
1769 p2
->Constraint
[i
][j
]))
1771 value_clear_c (temp
);
1772 Polyhedron_Free (p1
);
1773 Polyhedron_Free (p2
);
1776 /* The scalar may differ from +1 (now j=(p1->Dimension + 1)). */
1777 if (value_ne (p1
->Constraint
[i
][j
],
1778 p2
->Constraint
[i
][j
]))
1780 value_increment (temp
, p2
->Constraint
[i
][j
]);
1781 if (value_ne (p1
->Constraint
[i
][j
], temp
))
1783 value_clear_c (temp
);
1784 Polyhedron_Free (p1
);
1785 Polyhedron_Free (p2
);
1791 different_constraint
= i
;
1796 { /* Scattering coefficients must be equal. */
1797 for (j
= 0; j
< (scattdims
+ 1); j
++)
1798 if (value_ne (p1
->Constraint
[i
][j
],
1799 p2
->Constraint
[i
][j
]))
1801 value_clear_c (temp
);
1802 Polyhedron_Free (p1
);
1803 Polyhedron_Free (p2
);
1807 /* Domain coefficients must be 0. */
1808 for (; j
< dim1
+ 1; j
++)
1809 if (value_notzero_p (p1
->Constraint
[i
][j
])
1810 || value_notzero_p (p2
->Constraint
[i
][j
]))
1812 value_clear_c (temp
);
1813 Polyhedron_Free (p1
);
1814 Polyhedron_Free (p2
);
1818 /* Scalar must be equal. */
1819 if (value_ne (p1
->Constraint
[i
][j
],
1820 p2
->Constraint
[i
][j
]))
1822 value_clear_c (temp
);
1823 Polyhedron_Free (p1
);
1824 Polyhedron_Free (p2
);
1829 value_clear_c (temp
);
1831 /* If the domains are exactly the same, this is a block. */
1832 if (difference
== 0)
1834 Polyhedron_Free (p1
);
1835 Polyhedron_Free (p2
);
1839 /* Now a basic check that the constraint with the difference is an
1840 * equality of a dimension with a constant.
1842 for (i
= 0; i
<= different_constraint
; i
++)
1843 if (value_notzero_p (p1
->Constraint
[different_constraint
][i
]))
1845 Polyhedron_Free (p1
);
1846 Polyhedron_Free (p2
);
1850 if (value_notone_p (p1
->Constraint
[different_constraint
][different_constraint
+ 1]))
1852 Polyhedron_Free (p1
);
1853 Polyhedron_Free (p2
);
1857 for (i
= different_constraint
+ 2; i
< dim1
+ 1; i
++)
1858 if (value_notzero_p (p1
->Constraint
[different_constraint
][i
]))
1860 Polyhedron_Free (p1
);
1861 Polyhedron_Free (p2
);
1865 /* For the moment, d1 and d2 are a block candidate. There remains to check
1866 * that there is no other domain that may put an integral point between
1867 * them. In our lazy test we ensure this property by verifying that the
1868 * constraint matrices have a very strict shape: let us consider that the
1869 * dimension with the difference is d. Then the first d dimensions are
1870 * defined in their depth order using equalities (thus the first column begins
1871 * with d zeroes, there is a d*d identity matrix and a zero-matrix for
1872 * the remaining simensions). If a domain can put integral points between the
1873 * domains of the block candidate, this means that the other entries on the
1874 * first d constraints are equal to those of d1 or d2. Thus we are looking for
1875 * such a constraint system, if it exists d1 and d2 is considered to not be
1876 * a block, it is a bock otherwise.
1878 * 1. Only equalities (for the first different_constraint+1 lines).
1879 * | 2. Must be the identity.
1880 * | | 3. Must be zero.
1881 * | | | 4. Elements are equal, the last one is either date1 or 2.
1884 * |0|100|00000|=====|<- 0 line
1885 * |0|010|00000|=====|
1886 * |0|001|00000|====?|<- different_constraint line
1887 * |*|***|*****|*****|
1888 * |*|***|*****|*****|<- pX->NbConstraints line
1891 * | | | (pX->Dimension + 2) column
1892 * | | scattdims column
1893 * | different_constraint+1 column
1897 /* Step 1 and 2. This is only necessary to check one domain because
1898 * we checked that they are equal on this part before.
1900 for (i
= 0; i
<= different_constraint
; i
++)
1902 for (j
= 0; j
< i
+ 1; j
++)
1903 if (value_notzero_p (p1
->Constraint
[i
][j
]))
1905 Polyhedron_Free (p1
);
1906 Polyhedron_Free (p2
);
1910 if (value_notone_p (p1
->Constraint
[i
][i
+ 1]))
1912 Polyhedron_Free (p1
);
1913 Polyhedron_Free (p2
);
1917 for (j
= i
+ 2; j
<= different_constraint
+ 1; j
++)
1918 if (value_notzero_p (p1
->Constraint
[i
][j
]))
1920 Polyhedron_Free (p1
);
1921 Polyhedron_Free (p2
);
1927 for (i
= 0; i
<= different_constraint
; i
++)
1928 for (j
= different_constraint
+ 2; j
<= scattdims
; j
++)
1929 if (value_notzero_p (p1
->Constraint
[i
][j
]))
1931 Polyhedron_Free (p1
);
1932 Polyhedron_Free (p2
);
1936 value_init_c (date1
);
1937 value_init_c (date2
);
1938 value_init_c (date3
);
1940 /* Now we have to check that the two different dates are unique. */
1941 value_assign (date1
, p1
->Constraint
[different_constraint
][dim1
+ 1]);
1942 value_assign (date2
, p2
->Constraint
[different_constraint
][dim2
+ 1]);
1944 /* Step 4. We check all domains except d1 and d2 and we look for at least
1945 * a difference with d1 or d2 on the first different_constraint+1 dimensions.
1947 while (scattering
!= NULL
)
1949 if ((cloog_domain (scattering
) != d1
)
1950 && (cloog_domain (scattering
) != d2
))
1952 CloogDomain
*d3
= cloog_domain (scattering
);
1953 Polyhedron
*p3
= d2p (d3
);
1954 int dim3
= cloog_domain_dim (d3
);
1956 value_assign (date3
,
1957 p3
->Constraint
[different_constraint
][dim3
+ 1]);
1960 if (value_ne (date3
, date2
) && value_ne (date3
, date1
))
1963 for (i
= 0; (i
< different_constraint
) && (!difference
); i
++)
1964 for (j
= 0; (j
< dim3
+ 2) && !difference
; j
++)
1966 (p1
->Constraint
[i
][j
],
1967 p3
->Constraint
[i
][j
]))
1970 for (j
= 0; (j
< dim3
+ 1) && !difference
; j
++)
1972 (p1
->Constraint
[different_constraint
][j
],
1973 p3
->Constraint
[different_constraint
][j
]))
1976 Polyhedron_Free (p3
);
1979 value_clear_c (date1
);
1980 value_clear_c (date2
);
1981 value_clear_c (date3
);
1982 Polyhedron_Free (p1
);
1983 Polyhedron_Free (p2
);
1988 scattering
= cloog_next_domain (scattering
);
1991 Polyhedron_Free (p1
);
1992 Polyhedron_Free (p2
);
1993 value_clear_c (date1
);
1994 value_clear_c (date2
);
1995 value_clear_c (date3
);
2001 * cloog_domain_lazy_disjoint function:
2002 * This function returns 1 if the domains given as input are disjoint, 0 if it
2003 * is unable to decide. This function finds the unknown with fixed values in
2004 * both domains (on a given constraint, their column entry is not zero and
2005 * only the constant coefficient can be different from zero) and verify that
2006 * their values are the same. If not, the domains are obviously disjoint and
2007 * it returns 1, if there is not such case it returns 0. This is a very fast
2008 * way to verify this property. It has been shown (with the CLooG benchmarks)
2009 * that operations on disjoint domains are 36% of all the polyhedral
2010 * computations. For 94% of the actually identical domains, this
2011 * function answer that they are disjoint and allow to give immediately the
2012 * trivial solution instead of calling the heavy general functions of PolyLib.
2013 * - August 22th 2003: first version.
2014 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
2018 cloog_domain_lazy_disjoint (CloogDomain
* d1
, CloogDomain
* d2
)
2020 int i1
, j1
, i2
, j2
, scat_dim
, nbc1
, nbc2
;
2023 Polyhedron
*p1
, *p2
;
2025 if (!cloog_domain_isconvex (d1
) || !cloog_domain_isconvex (d2
))
2030 nbc1
= cloog_domain_nbconstraints (d1
);
2031 nbc2
= cloog_domain_nbconstraints (d2
);
2032 dim1
= cloog_domain_dim (d1
);
2033 dim2
= cloog_domain_dim (d2
);
2034 value_init_c (scat_val
);
2036 for (i1
= 0; i1
< nbc1
; i1
++)
2038 if (value_notzero_p (p1
->Constraint
[i1
][0]))
2042 while (value_zero_p (p1
->Constraint
[i1
][scat_dim
]) &&
2046 if (value_notone_p (p1
->Constraint
[i1
][scat_dim
]))
2050 for (j1
= scat_dim
+ 1; j1
<= dim1
; j1
++)
2051 if (value_notzero_p (p1
->Constraint
[i1
][j1
]))
2057 value_assign (scat_val
,
2058 p1
->Constraint
[i1
][dim1
+ 1]);
2060 for (i2
= 0; i2
< nbc2
; i2
++)
2062 for (j2
= 0; j2
< scat_dim
; j2
++)
2063 if (value_notzero_p (p2
->Constraint
[i2
][j2
]))
2066 if ((j2
!= scat_dim
)
2068 value_notone_p (p2
->Constraint
[i2
][scat_dim
]))
2071 for (j2
= scat_dim
+ 1; j2
< dim2
; j2
++)
2072 if (value_notzero_p (p2
->Constraint
[i2
][j2
]))
2079 (p2
->Constraint
[i2
][dim2
+ 1], scat_val
))
2081 value_clear_c (scat_val
);
2088 value_clear_c (scat_val
);
2089 Polyhedron_Free (p1
);
2090 Polyhedron_Free (p2
);
2096 * cloog_domain_list_lazy_same function:
2097 * This function returns 1 if two domains in the list are the same, 0 if it
2098 * is unable to decide.
2099 * - February 9th 2004: first version.
2102 cloog_domain_list_lazy_same (CloogDomainList
* list
)
2103 { /*int i=1, j=1 ; */
2104 CloogDomainList
*current
, *next
;
2107 while (current
!= NULL
)
2109 next
= cloog_next_domain (current
);
2111 while (next
!= NULL
)
2113 if (cloog_domain_lazy_equal (cloog_domain (current
),
2114 cloog_domain (next
)))
2115 { /*printf("Same domains: %d and %d\n",i,j) ; */
2119 next
= cloog_next_domain (next
);
2122 current
= cloog_next_domain (current
);
2129 * cloog_domain_cut_first function:
2130 * this function returns a CloogDomain structure with everything except the
2131 * first part of the polyhedra union of the input domain as domain. After a call
2132 * to this function, there remains in the CloogDomain structure provided as
2133 * input only the first part of the original polyhedra union.
2134 * - April 20th 2005: first version, extracted from different part of loop.c.
2137 cloog_domain_cut_first (CloogDomain
* domain
)
2141 if (domain
&& cloog_domain_polyhedron (domain
))
2143 if (!cloog_upol_next (cloog_domain_upol (domain
)))
2146 rest
= cloog_new_domain (cloog_upol_next (cloog_domain_upol (domain
)));
2147 cloog_upol_set_next (cloog_domain_upol (domain
), NULL
);
2152 return print_result ("cloog_domain_cut_first", cloog_check_domain (rest
));
2157 * cloog_domain_lazy_isscalar function:
2158 * this function returns 1 if the dimension 'dimension' in the domain 'domain'
2159 * is scalar, this means that the only constraint on this dimension must have
2160 * the shape "x.dimension + scalar = 0" with x an integral variable. This
2161 * function is lazy since we only accept x=1 (further calculations are easier
2163 * - June 14th 2005: first version.
2164 * - June 21rd 2005: Adaptation for GMP.
2167 cloog_domain_lazy_isscalar (CloogDomain
* domain
, int dimension
)
2170 Polyhedron
*polyhedron
= d2p (domain
);
2171 int nbc
= cloog_domain_nbconstraints (domain
);
2172 int dim
= cloog_domain_dim (domain
);
2174 /* For each constraint... */
2175 for (i
= 0; i
< nbc
; i
++)
2176 { /* ...if it is concerned by the potentially scalar dimension... */
2178 (polyhedron
->Constraint
[i
][dimension
+ 1]))
2179 { /* ...check that the constraint has the shape "dimension + scalar = 0". */
2180 for (j
= 0; j
<= dimension
; j
++)
2181 if (value_notzero_p (polyhedron
->Constraint
[i
][j
]))
2183 Polyhedron_Free (polyhedron
);
2188 (polyhedron
->Constraint
[i
][dimension
+ 1]))
2190 Polyhedron_Free (polyhedron
);
2194 for (j
= dimension
+ 2; j
< dim
+ 1; j
++)
2195 if (value_notzero_p (polyhedron
->Constraint
[i
][j
]))
2197 Polyhedron_Free (polyhedron
);
2203 Polyhedron_Free (polyhedron
);
2209 * cloog_domain_scalar function:
2210 * when we call this function, we know that "dimension" is a scalar dimension,
2211 * this function finds the scalar value in "domain" and returns it in "value".
2212 * - June 30th 2005: first version.
2215 cloog_domain_scalar (CloogDomain
* domain
, int dimension
, Value
* value
)
2218 Polyhedron
*polyhedron
= d2p (domain
);
2219 int nbc
= cloog_domain_nbconstraints (domain
);
2220 int dim
= cloog_domain_dim (domain
);
2222 /* For each constraint... */
2223 for (i
= 0; i
< nbc
; i
++)
2224 { /* ...if it is the equality defining the scalar dimension... */
2226 (polyhedron
->Constraint
[i
][dimension
+ 1])
2227 && value_zero_p (polyhedron
->Constraint
[i
][0]))
2228 { /* ...Then send the scalar value. */
2229 value_assign (*value
, polyhedron
->Constraint
[i
][dim
+ 1]);
2230 value_oppose (*value
, *value
);
2231 Polyhedron_Free (polyhedron
);
2236 /* We should have found a scalar value: if not, there is an error. */
2237 fprintf (stderr
, "[CLooG]ERROR: dimension %d is not scalar as expected.\n",
2239 Polyhedron_Free (polyhedron
);
2245 * cloog_domain_erase_dimension function:
2246 * this function returns a CloogDomain structure builds from 'domain' where
2247 * we removed the dimension 'dimension' and every constraint considering this
2248 * dimension. This is not a projection ! Every data concerning the
2249 * considered dimension is simply erased.
2250 * - June 14th 2005: first version.
2251 * - June 21rd 2005: Adaptation for GMP.
2254 cloog_domain_erase_dimension (CloogDomain
* domain
, int dimension
)
2256 int i
, j
, mi
, nb_dim
, nbc
;
2257 CloogMatrix
*matrix
;
2258 CloogDomain
*erased
;
2259 Polyhedron
*polyhedron
;
2261 polyhedron
= d2p (domain
);
2262 nb_dim
= cloog_domain_dim (domain
);
2263 nbc
= cloog_domain_nbconstraints (domain
);
2265 /* The matrix is one column less and at least one constraint less. */
2266 matrix
= cloog_matrix_alloc (nbc
- 1, nb_dim
+ 1);
2268 /* mi is the constraint counter for the matrix. */
2270 for (i
= 0; i
< nbc
; i
++)
2271 if (value_zero_p (polyhedron
->Constraint
[i
][dimension
+ 1]))
2273 for (j
= 0; j
<= dimension
; j
++)
2274 value_assign (matrix
->p
[mi
][j
],
2275 polyhedron
->Constraint
[i
][j
]);
2277 for (j
= dimension
+ 2; j
< nb_dim
+ 2; j
++)
2278 value_assign (matrix
->p
[mi
][j
- 1],
2279 polyhedron
->Constraint
[i
][j
]);
2284 erased
= cloog_domain_matrix2domain (matrix
);
2285 cloog_matrix_free (matrix
);
2287 Polyhedron_Free (polyhedron
);
2288 return print_result ("cloog_domain_erase_dimension", cloog_check_domain (erased
));
2291 /* Number of polyhedra inside the union of disjoint polyhedra. */
2294 cloog_domain_nb_polyhedra (CloogDomain
* domain
)
2297 ppl_polyhedra_union
*upol
= cloog_domain_upol (domain
);
2302 upol
= cloog_upol_next (upol
);
2309 cloog_domain_print_polyhedra (FILE * foo
, CloogDomain
* domain
)
2311 ppl_polyhedra_union
*upol
= cloog_domain_upol (domain
);
2313 while (upol
!= NULL
)
2315 CloogMatrix
*matrix
= cloog_upol_domain2matrix (upol
);
2316 cloog_matrix_print (foo
, matrix
);
2317 cloog_matrix_free (matrix
);
2318 upol
= cloog_upol_next (upol
);
2323 debug_cloog_domain (CloogDomain
*domain
)
2325 cloog_domain_print_polyhedra (stderr
, domain
);
2329 debug_cloog_matrix (CloogMatrix
*m
)
2331 cloog_matrix_print (stderr
, m
);