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 !
43 # include "../../include/cloog/cloog.h"
47 static int cloog_check_polyhedral_ops
= 1;
48 static int cloog_return_ppl_result
= 0;
50 /* Variables names for pretty printing. */
51 static char wild_name
[200][40];
53 static inline const char*
54 variable_output_function (ppl_dimension_type var
)
57 return wild_name
[var
+ 1];
63 error_handler (enum ppl_enum_error_code code
, const char* description
)
65 fprintf (stderr
, "PPL error code %d\n%s", code
, description
);
70 cloog_initialize (void)
72 sprintf (wild_name
[0], "1");
73 sprintf (wild_name
[1], "a");
74 sprintf (wild_name
[2], "b");
75 sprintf (wild_name
[3], "c");
76 sprintf (wild_name
[4], "d");
77 sprintf (wild_name
[5], "e");
78 sprintf (wild_name
[6], "f");
79 sprintf (wild_name
[7], "g");
80 sprintf (wild_name
[8], "h");
81 sprintf (wild_name
[9], "i");
82 sprintf (wild_name
[10], "j");
83 sprintf (wild_name
[11], "k");
84 sprintf (wild_name
[12], "l");
85 sprintf (wild_name
[13], "m");
86 sprintf (wild_name
[14], "n");
87 sprintf (wild_name
[15], "o");
88 sprintf (wild_name
[16], "p");
89 sprintf (wild_name
[17], "q");
90 sprintf (wild_name
[18], "r");
91 sprintf (wild_name
[19], "s");
92 sprintf (wild_name
[20], "t");
93 sprintf (wild_name
[21], "alpha");
94 sprintf (wild_name
[22], "beta");
95 sprintf (wild_name
[23], "gamma");
96 sprintf (wild_name
[24], "delta");
97 sprintf (wild_name
[25], "tau");
98 sprintf (wild_name
[26], "sigma");
99 sprintf (wild_name
[27], "chi");
100 sprintf (wild_name
[28], "omega");
101 sprintf (wild_name
[29], "pi");
102 sprintf (wild_name
[30], "ni");
103 sprintf (wild_name
[31], "Alpha");
104 sprintf (wild_name
[32], "Beta");
105 sprintf (wild_name
[33], "Gamma");
106 sprintf (wild_name
[34], "Delta");
107 sprintf (wild_name
[35], "Tau");
108 sprintf (wild_name
[36], "Sigma");
109 sprintf (wild_name
[37], "Chi");
110 sprintf (wild_name
[38], "Omega");
111 sprintf (wild_name
[39], "xxx");
113 if (ppl_initialize() < 0)
115 fprintf (stderr
, "Cannot initialize the Parma Polyhedra Library.\n");
119 if (ppl_set_error_handler (error_handler
) < 0)
121 fprintf (stderr
, "Cannot install the custom error handler.\n");
125 if (ppl_io_set_variable_output_function (variable_output_function
) < 0)
127 fprintf (stderr
, "Cannot install the PPL custom variable output function. \n");
133 * The maximal number of rays allowed to be allocated by PolyLib. In fact since
134 * version 5.20, PolyLib automatically tune the number of rays by multiplying
135 * by 2 this number each time the maximum is reached. For unknown reasons
136 * PolyLib makes a segmentation fault if this number is too small. If this
137 * number is too small, performances will be reduced, if it is too high, memory
138 * will be saturated. Note that the option "-rays X" set this number to X.
142 /* Unused in this backend. */
144 int cloog_domain_allocated
= 0;
145 int cloog_domain_freed
= 0;
146 int cloog_domain_max
= 0;
148 /* The same for Value variables since in GMP mode they have to be freed. */
149 int cloog_value_allocated
= 0;
150 int cloog_value_freed
= 0;
151 int cloog_value_max
= 0;
155 cloog_value_leak_up ()
157 cloog_value_allocated
++;
158 if ((cloog_value_allocated
- cloog_value_freed
) > cloog_value_max
)
159 cloog_value_max
= cloog_value_allocated
- cloog_value_freed
;
164 cloog_value_leak_down ()
169 static inline Polyhedron
*
170 cloog_domain_polyhedron_set (CloogDomain
* d
, Polyhedron
* p
)
172 return d
->_polyhedron
= p
;
176 cloog_domain_set_references (CloogDomain
* d
, int i
)
182 * cloog_domain_malloc function:
183 * This function allocates the memory space for a CloogDomain structure and
184 * sets its fields with default values. Then it returns a pointer to the
186 * - November 21th 2005: first version.
189 cloog_domain_malloc ()
193 domain
= (CloogDomain
*) malloc (sizeof (CloogDomain
));
196 fprintf (stderr
, "[CLooG]ERROR: memory overflow.\n");
200 /* We set the various fields with default values. */
201 cloog_domain_polyhedron_set (domain
, NULL
);
202 cloog_domain_set_references (domain
, 1);
209 * cloog_domain_alloc function:
210 * This function allocates the memory space for a CloogDomain structure and
211 * sets its fields with those given as input. Then it returns a pointer to the
213 * - April 19th 2005: first version.
214 * - November 21th 2005: cloog_domain_malloc use.
217 cloog_domain_alloc (Polyhedron
* polyhedron
)
221 if (polyhedron
== NULL
)
225 domain
= cloog_domain_malloc ();
226 cloog_domain_polyhedron_set (domain
, polyhedron
);
234 * cloog_domain_matrix2domain function:
235 * Given a matrix of constraints (matrix), this function constructs and returns
236 * the corresponding domain (i.e. the CloogDomain structure including the
237 * polyhedron with its double representation: constraint matrix and the set of
241 cloog_domain_matrix2domain (CloogMatrix
* matrix
)
243 return (cloog_domain_alloc (Constraints2Polyhedron (matrix
, MAX_RAYS
)));
247 static inline Polyhedron
*
248 cloog_domain_polyhedron (CloogDomain
* domain
)
250 return domain
->_polyhedron
;
254 * cloog_domain_domain2matrix function:
255 * Given a polyhedron (in domain), this function returns its corresponding
256 * matrix of constraints.
259 cloog_domain_domain2matrix (CloogDomain
* domain
)
261 return Polyhedron2Constraints (cloog_domain_polyhedron (domain
));
264 /* In the matrix representation an equality has a 0 in the first
265 column. When the value of the first column is 1, the row
266 represents an inequality. */
269 cloog_matrix_row_is_eq_p (CloogMatrix
*matrix
, int row
)
271 return value_zero_p (matrix
->p
[row
][0]);
274 static ppl_Polyhedron_t
275 cloog_translate_constraint_matrix (CloogMatrix
*matrix
)
278 ppl_Polyhedron_t res
;
279 ppl_Constraint_t cstr
;
280 ppl_Linear_Expression_t expr
;
281 ppl_Coefficient_t coef
;
282 ppl_dimension_type dim
= matrix
->NbColumns
- 2;
284 ppl_new_Coefficient (&coef
);
285 ppl_new_NNC_Polyhedron_from_dimension (&res
, dim
);
287 for (i
= 0; i
< matrix
->NbRows
; i
++)
289 ppl_new_Linear_Expression_with_dimension (&expr
, dim
);
291 for (j
= 1; j
< matrix
->NbColumns
- 1; j
++)
293 ppl_assign_Coefficient_from_mpz_t (coef
, matrix
->p
[i
][j
]);
294 ppl_Linear_Expression_add_to_coefficient (expr
, j
- 1, coef
);
297 ppl_assign_Coefficient_from_mpz_t
298 (coef
, matrix
->p
[i
][matrix
->NbColumns
- 1]);
299 ppl_Linear_Expression_add_to_inhomogeneous (expr
, coef
);
301 if (cloog_matrix_row_is_eq_p (matrix
, i
))
302 ppl_new_Constraint (&cstr
, expr
, PPL_CONSTRAINT_TYPE_EQUAL
);
304 ppl_new_Constraint (&cstr
, expr
, PPL_CONSTRAINT_TYPE_GREATER_THAN_OR_EQUAL
);
306 ppl_Polyhedron_add_constraint (res
, cstr
);
309 if (cloog_check_polyhedral_ops
)
310 ppl_Polyhedron_OK (res
);
316 cloog_translate_ppl_polyhedron (ppl_Polyhedron_t pol
)
319 CloogMatrix
*matrix
;
320 ppl_dimension_type dim
;
321 ppl_const_Constraint_System_t pcs
;
322 ppl_Constraint_System_const_iterator_t cit
, end
;
325 ppl_Polyhedron_constraints (pol
, &pcs
);
326 ppl_new_Constraint_System_const_iterator (&cit
);
327 ppl_new_Constraint_System_const_iterator (&end
);
329 for (row
= 0, ppl_Constraint_System_begin (pcs
, cit
), ppl_Constraint_System_end (pcs
, end
);
330 !ppl_Constraint_System_const_iterator_equal_test (cit
, end
);
331 ppl_Constraint_System_const_iterator_increment (cit
), row
++);
333 ppl_Polyhedron_space_dimension (pol
, &dim
);
334 matrix
= cloog_matrix_alloc (row
, dim
+ 2);
336 for (row
= 0, ppl_Constraint_System_begin (pcs
, cit
), ppl_Constraint_System_end (pcs
, end
);
337 !ppl_Constraint_System_const_iterator_equal_test (cit
, end
);
338 ppl_Constraint_System_const_iterator_increment (cit
), row
++)
340 ppl_const_Constraint_t pc
;
341 ppl_Coefficient_t coef
;
342 ppl_dimension_type col
;
347 ppl_new_Coefficient (&coef
);
348 ppl_Constraint_System_const_iterator_dereference (cit
, &pc
);
350 neg
= (ppl_Constraint_type (pc
) == PPL_CONSTRAINT_TYPE_LESS_THAN
351 || ppl_Constraint_type (pc
) == PPL_CONSTRAINT_TYPE_LESS_THAN_OR_EQUAL
) ? 1 : 0;
353 for (col
= 0; col
< dim
; col
++)
355 ppl_Constraint_coefficient (pc
, col
, coef
);
356 ppl_Coefficient_to_mpz_t (coef
, val
);
359 value_oppose (val
, val
);
361 value_assign (matrix
->p
[row
][col
+1], val
);
364 ppl_Constraint_inhomogeneous_term (pc
, coef
);
365 ppl_Coefficient_to_mpz_t (coef
, val
);
366 value_assign (matrix
->p
[row
][dim
+ 1], val
);
368 switch (ppl_Constraint_type (pc
))
370 case PPL_CONSTRAINT_TYPE_EQUAL
:
371 value_set_si (matrix
->p
[row
][0], 0);
374 case PPL_CONSTRAINT_TYPE_LESS_THAN
:
375 case PPL_CONSTRAINT_TYPE_GREATER_THAN
:
376 value_decrement (matrix
->p
[row
][dim
+ 1], matrix
->p
[row
][dim
+ 1]);
377 value_set_si (matrix
->p
[row
][0], 1);
380 case PPL_CONSTRAINT_TYPE_LESS_THAN_OR_EQUAL
:
381 case PPL_CONSTRAINT_TYPE_GREATER_THAN_OR_EQUAL
:
382 value_set_si (matrix
->p
[row
][0], 1);
386 fprintf (stderr
, "PPL_CONSTRAINT_TYPE_%d not implemented yet\n",
387 ppl_Constraint_type (pc
));
392 res
= cloog_domain_matrix2domain (matrix
);
397 cloog_domain_references (CloogDomain
* d
)
399 return d
->_references
;
403 * cloog_domain_print function:
404 * This function prints the content of a CloogDomain structure (domain) into
405 * a file (foo, possibly stdout).
408 cloog_domain_print (FILE * foo
, CloogDomain
* domain
)
410 Polyhedron_Print (foo
, P_VALUE_FMT
, cloog_domain_polyhedron (domain
));
411 fprintf (foo
, "Number of active references: %d\n",
412 cloog_domain_references (domain
));
416 * cloog_domain_free function:
417 * This function frees the allocated memory for a CloogDomain structure
418 * (domain). It decrements the number of active references to this structure,
419 * if there are no more references on the structure, it frees it (with the
420 * included list of polyhedra).
423 cloog_domain_free (CloogDomain
* domain
)
427 cloog_domain_set_references (domain
,
428 cloog_domain_references (domain
) - 1);
430 if (cloog_domain_references (domain
) == 0)
432 if (cloog_domain_polyhedron (domain
) != NULL
)
433 Domain_Free (cloog_domain_polyhedron (domain
));
442 * cloog_domain_copy function:
443 * This function returns a copy of a CloogDomain structure (domain). To save
444 * memory this is not a memory copy but we increment a counter of active
445 * references inside the structure, then return a pointer to that structure.
448 cloog_domain_copy (CloogDomain
* domain
)
450 cloog_domain_set_references (domain
, cloog_domain_references (domain
) + 1);
456 * cloog_domain_image function:
457 * This function returns a CloogDomain structure such that the included
458 * polyhedral domain is computed from the former one into another
459 * domain according to a given affine mapping function (mapping).
462 cloog_domain_image (CloogDomain
* domain
, CloogMatrix
* mapping
)
464 return (cloog_domain_alloc
466 (cloog_domain_polyhedron (domain
), mapping
, MAX_RAYS
)));
471 * cloog_domain_preimage function:
472 * Given a polyhedral domain (polyhedron) inside a CloogDomain structure and a
473 * mapping function (mapping), this function returns a new CloogDomain structure
474 * with a polyhedral domain which when transformed by mapping function (mapping)
475 * gives (polyhedron).
478 cloog_domain_preimage (CloogDomain
* domain
, CloogMatrix
* mapping
)
480 return (cloog_domain_alloc
482 (cloog_domain_polyhedron (domain
), mapping
, MAX_RAYS
)));
487 * cloog_domain_convex function:
488 * Given a polyhedral domain (polyhedron), this function concatenates the lists
489 * of rays and lines of the two (or more) polyhedra in the domain into one
490 * combined list, and find the set of constraints which tightly bound all of
491 * those objects. It returns the corresponding polyhedron.
494 cloog_domain_convex (CloogDomain
* domain
)
496 return (cloog_domain_alloc
497 (DomainConvex (cloog_domain_polyhedron (domain
), MAX_RAYS
)));
500 static inline Polyhedron
*
501 cloog_polyhedron_next (Polyhedron
* p
)
507 cloog_polyhedron_set_next (Polyhedron
* p
, Polyhedron
* n
)
512 static inline Polyhedron
*
513 cloog_domain_polyhedron_next (CloogDomain
* domain
)
515 return cloog_polyhedron_next (cloog_domain_polyhedron (domain
));
519 cloog_domain_polyhedron_set_next (CloogDomain
* d
, Polyhedron
* n
)
521 cloog_polyhedron_set_next (cloog_domain_polyhedron (d
), n
);
524 static inline unsigned
525 cloog_polyhedron_nbc (Polyhedron
* p
)
527 return p
->NbConstraints
;
531 cloog_domain_nbconstraints (CloogDomain
* domain
)
533 return cloog_domain_polyhedron (domain
)->NbConstraints
;
536 static inline unsigned
537 cloog_polyhedron_nbeq (Polyhedron
* p
)
542 static inline unsigned
543 cloog_domain_nbeq (CloogDomain
* d
)
545 return cloog_polyhedron_nbeq (cloog_domain_polyhedron (d
));
548 static inline unsigned
549 cloog_polyhedron_dim (Polyhedron
* p
)
556 cloog_domain_isconvex (CloogDomain
* domain
)
558 return !cloog_domain_polyhedron_next (domain
);
562 cloog_domain_dim (CloogDomain
* d
)
564 return cloog_polyhedron_dim (cloog_domain_polyhedron (d
));
568 cloog_check_domains (CloogDomain
*ppl
, CloogDomain
*polylib
)
570 /* Cannot use cloog_domain_lazy_equal (polylib, ppl) here as this
571 function is too dumb: it does not detect permutations of
573 if (!cloog_domain_isempty (cloog_domain_difference (ppl
, polylib
))
574 || !cloog_domain_isempty (cloog_domain_difference (polylib
, ppl
)))
576 fprintf (stderr
, "different domains ((\n");
577 cloog_domain_print (stderr
, ppl
);
578 fprintf (stderr
, ")(\n");
579 cloog_domain_print (stderr
, polylib
);
580 fprintf (stderr
, "))\n");
584 if (cloog_return_ppl_result
)
591 * cloog_domain_simple_convex:
592 * Given a list (union) of polyhedra, this function returns a "simple"
593 * convex hull of this union. In particular, the constraints of the
594 * the returned polyhedron consist of (parametric) lower and upper
595 * bounds on individual variables and constraints that appear in the
596 * original polyhedra.
598 * nb_par is the number of parameters of the domain.
601 cloog_domain_simple_convex (CloogDomain
* domain
, int nb_par
)
603 fprintf (stderr
, "cloog_domain_simple_convex is not implemented yet.\n");
609 * cloog_domain_simplify function:
610 * Given two polyhedral domains (pol1) and (pol2) inside two CloogDomain
611 * structures, this function finds the largest domain set (or the smallest list
612 * of non-redundant constraints), that when intersected with polyhedral
613 * domain (pol2) equals (Pol1)intersect(Pol2). The output is a new CloogDomain
614 * structure with a polyhedral domain with the "redundant" constraints removed.
615 * NB: this function do not work as expected with unions of polyhedra...
618 cloog_domain_simplify (CloogDomain
* dom1
, CloogDomain
* dom2
)
622 Polyhedron
*P
= cloog_domain_polyhedron (dom1
);
624 /* DomainSimplify doesn't remove all redundant equalities,
625 * so we remove them here first in case both dom1 and dom2
626 * are single polyhedra (i.e., not unions of polyhedra).
628 if (cloog_domain_isconvex (dom1
)
629 && cloog_domain_isconvex (dom2
)
630 && cloog_polyhedron_nbeq (P
) && cloog_domain_nbeq (dom2
))
633 int rows
= cloog_polyhedron_nbeq (P
) + cloog_domain_nbeq (dom2
);
634 int cols
= cloog_polyhedron_dim (P
) + 2;
636 M
= cloog_matrix_alloc (rows
, cols
);
637 M2
= cloog_matrix_alloc (cloog_polyhedron_nbc (P
), cols
);
638 Vector_Copy (cloog_domain_polyhedron (dom2
)->Constraint
[0],
639 M
->p
[0], cloog_domain_nbeq (dom2
) * cols
);
640 rank
= cloog_domain_nbeq (dom2
);
642 for (i
= 0; i
< cloog_polyhedron_nbeq (P
); ++i
)
644 Vector_Copy (P
->Constraint
[i
], M
->p
[rank
], cols
);
645 if (Gauss (M
, rank
+ 1, cols
- 1) > rank
)
647 Vector_Copy (P
->Constraint
[i
], M2
->p
[row
++], cols
);
651 if (row
< cloog_polyhedron_nbeq (P
))
653 Vector_Copy (P
->Constraint
[cloog_polyhedron_nbeq (P
)],
655 (cloog_polyhedron_nbc (P
) -
656 cloog_polyhedron_nbeq (P
)) * cols
);
657 P
= Constraints2Polyhedron (M2
, MAX_RAYS
);
659 cloog_matrix_free (M2
);
660 cloog_matrix_free (M
);
663 cloog_domain_alloc (DomainSimplify
664 (P
, cloog_domain_polyhedron (dom2
), MAX_RAYS
));
665 if (P
!= cloog_domain_polyhedron (dom1
))
672 * cloog_domain_union function:
673 * This function returns a new CloogDomain structure including a polyhedral
674 * domain which is the union of two polyhedral domains (pol1) U (pol2) inside
675 * two CloogDomain structures.
678 cloog_domain_union (CloogDomain
* dom1
, CloogDomain
* dom2
)
680 if (!cloog_domain_polyhedron (dom1
))
681 return cloog_domain_alloc (cloog_domain_polyhedron (dom2
));
683 if (!cloog_domain_polyhedron (dom2
))
684 return cloog_domain_alloc (cloog_domain_polyhedron (dom1
));
686 return (cloog_domain_alloc (DomainUnion (cloog_domain_polyhedron (dom1
),
687 cloog_domain_polyhedron (dom2
),
692 * cloog_domain_intersection function:
693 * This function returns a new CloogDomain structure including a polyhedral
694 * domain which is the intersection of two polyhedral domains (pol1)inter(pol2)
695 * inside two CloogDomain structures.
698 cloog_domain_intersection (CloogDomain
* dom1
, CloogDomain
* dom2
)
702 ppl_Polyhedron_t ppl1
, ppl2
;
704 res
= cloog_domain_malloc ();
706 for (p1
= cloog_domain_polyhedron (dom1
); p1
; p1
= p1
->next
)
708 ppl1
= cloog_translate_constraint_matrix (Polyhedron2Constraints (p1
));
710 for (p2
= cloog_domain_polyhedron (dom2
); p2
; p2
= p2
->next
)
712 ppl2
= cloog_translate_constraint_matrix (Polyhedron2Constraints (p2
));
713 ppl_Polyhedron_intersection_assign (ppl2
, ppl1
);
715 res
= cloog_domain_union (res
, cloog_translate_ppl_polyhedron (ppl2
));
719 return cloog_check_domains (res
, cloog_domain_alloc (DomainIntersection (cloog_domain_polyhedron (dom1
),
720 cloog_domain_polyhedron (dom2
),
726 * cloog_domain_difference function:
727 * This function returns a new CloogDomain structure including a polyhedral
728 * domain which is the difference of two polyhedral domains domain \ minus
729 * inside two CloogDomain structures.
730 * - November 8th 2001: first version.
733 cloog_domain_difference (CloogDomain
* domain
, CloogDomain
* minus
)
735 if (cloog_domain_isempty (minus
))
736 return (cloog_domain_copy (domain
));
738 return (cloog_domain_alloc
740 (cloog_domain_polyhedron (domain
),
741 cloog_domain_polyhedron (minus
), MAX_RAYS
)));
746 * cloog_domain_addconstraints function :
747 * This function adds source's polyhedron constraints to target polyhedron: for
748 * each element of the polyhedron inside 'target' (i.e. element of the union
749 * of polyhedra) it adds the constraints of the corresponding element in
751 * - August 10th 2002: first version.
752 * Nota bene for future : it is possible that source and target don't have the
753 * same number of elements (try iftest2 without non-shared constraint
754 * elimination in cloog_loop_separate !). This function is yet another part
755 * of the DomainSimplify patching problem...
758 cloog_domain_addconstraints (domain_source
, domain_target
)
759 CloogDomain
*domain_source
, *domain_target
;
761 unsigned nb_constraint
;
763 Polyhedron
*source
, *target
, *new, *next
, *last
;
765 source
= cloog_domain_polyhedron (domain_source
);
766 target
= cloog_domain_polyhedron (domain_target
);
768 constraints
= source
->p_Init
;
769 nb_constraint
= cloog_polyhedron_nbc (source
);
770 source
= cloog_polyhedron_next (source
);
771 new = AddConstraints (constraints
, nb_constraint
, target
, MAX_RAYS
);
773 next
= cloog_polyhedron_next (target
);
776 { /* BUG !!! This is actually a bug. I don't know yet how to cleanly avoid
777 * the situation where source and target do not have the same number of
778 * elements. So this 'if' is an awful trick, waiting for better.
782 constraints
= source
->p_Init
;
783 nb_constraint
= cloog_polyhedron_nbc (source
);
784 source
= cloog_polyhedron_next (source
);
786 cloog_polyhedron_set_next (last
,
787 AddConstraints (constraints
, nb_constraint
,
789 last
= cloog_polyhedron_next (last
);
790 next
= cloog_polyhedron_next (next
);
793 return (cloog_domain_alloc (new));
798 * cloog_domain_sort function:
799 * This function topologically sorts (nb_pols) polyhedra. Here (pols) is a an
800 * array of pointers to polyhedra, (nb_pols) is the number of polyhedra,
801 * (level) is the level to consider for partial ordering (nb_par) is the
802 * parameter space dimension, (permut) if not NULL, is an array of (nb_pols)
803 * integers that contains a permutation specification after call in order to
804 * apply the topological sorting.
807 cloog_domain_sort (doms
, nb_pols
, level
, nb_par
, permut
)
809 unsigned nb_pols
, level
, nb_par
;
814 (Polyhedron
**) malloc (nb_pols
* sizeof (Polyhedron
*));
816 for (i
= 0; i
< nb_pols
; i
++)
817 pols
[i
] = cloog_domain_polyhedron (doms
[i
]);
819 /* time is an array of (nb_pols) integers to store logical time values. We
820 * do not use it, but it is compulsory for PolyhedronTSort.
822 time
= (int *) malloc (nb_pols
* sizeof (int));
824 /* PolyhedronTSort will fill up permut (and time). */
825 PolyhedronTSort (pols
, nb_pols
, level
, nb_par
, time
, permut
, MAX_RAYS
);
833 * cloog_domain_empty function:
834 * This function allocates the memory space for a CloogDomain structure and
835 * sets its polyhedron to an empty polyhedron with 'dimension' dimensions.
836 * Then it returns a pointer to the allocated space.
837 * - June 10th 2005: first version.
840 cloog_domain_empty (int dimension
)
842 return (cloog_domain_alloc (Empty_Polyhedron (dimension
)));
846 /******************************************************************************
847 * Structure display function *
848 ******************************************************************************/
852 * cloog_domain_print_structure :
853 * this function is a more human-friendly way to display the CloogDomain data
854 * structure, it only shows the constraint system and includes an indentation
855 * level (level) in order to work with others print_structure functions.
856 * Written by Olivier Chorier, Luc Marchaud, Pierre Martin and Romain Tartiere.
857 * - April 24th 2005: Initial version.
858 * - May 26th 2005: Memory leak hunt.
859 * - June 16th 2005: (Ced) Integration in domain.c.
862 cloog_domain_print_structure (FILE * file
, CloogDomain
* domain
, int level
)
867 /* Go to the right level. */
868 for (i
= 0; i
< level
; i
++)
869 fprintf (file
, "|\t");
873 fprintf (file
, "+-- CloogDomain\n");
875 /* Print the matrix. */
876 matrix
= cloog_domain_domain2matrix (domain
);
877 cloog_matrix_print_structure (file
, matrix
, level
);
878 cloog_matrix_free (matrix
);
881 for (i
= 0; i
< level
+ 1; i
++)
882 fprintf (file
, "|\t");
883 fprintf (file
, "\n");
886 fprintf (file
, "+-- Null CloogDomain\n");
892 * cloog_domain_list_print function:
893 * This function prints the content of a CloogDomainList structure into a
894 * file (foo, possibly stdout).
895 * - November 6th 2001: first version.
898 cloog_domain_list_print (FILE * foo
, CloogDomainList
* list
)
902 cloog_domain_print (foo
, cloog_domain (list
));
903 list
= cloog_next_domain (list
);
908 /******************************************************************************
909 * Memory deallocation function *
910 ******************************************************************************/
914 * cloog_domain_list_free function:
915 * This function frees the allocated memory for a CloogDomainList structure.
916 * - November 6th 2001: first version.
919 cloog_domain_list_free (CloogDomainList
* list
)
921 CloogDomainList
*temp
;
925 temp
= cloog_next_domain (list
);
926 cloog_domain_free (cloog_domain (list
));
933 /******************************************************************************
935 ******************************************************************************/
939 * cloog_domain_read function:
940 * Adaptation from the PolyLib. This function reads a matrix into a file (foo,
941 * posibly stdin) and returns a pointer to a polyhedron containing the read
943 * - October 18th 2001: first version.
946 cloog_domain_read (FILE * foo
)
951 matrix
= cloog_matrix_read (foo
);
952 domain
= cloog_domain_matrix2domain (matrix
);
953 cloog_matrix_free (matrix
);
960 * cloog_domain_union_read function:
961 * This function reads a union of polyhedra into a file (foo, posibly stdin) and
962 * returns a pointer to a Polyhedron containing the read information.
963 * - September 9th 2002: first version.
964 * - October 29th 2005: (debug) removal of a leak counting "correction" that
965 * was just false since ages.
968 cloog_domain_union_read (FILE * foo
)
970 int i
, nb_components
;
972 CloogDomain
*domain
, *temp
, *old
;
974 /* domain reading: nb_components (constraint matrices). */
975 while (fgets (s
, MAX_STRING
, foo
) == 0);
976 while ((*s
== '#' || *s
== '\n') || (sscanf (s
, " %d", &nb_components
) < 1))
977 fgets (s
, MAX_STRING
, foo
);
979 if (nb_components
> 0)
980 { /* 1. first part of the polyhedra union, */
981 domain
= cloog_domain_read (foo
);
982 /* 2. and the nexts. */
983 for (i
= 1; i
< nb_components
; i
++)
984 { /* Leak counting is OK since next allocated domain is freed here. */
985 temp
= cloog_domain_read (foo
);
987 domain
= cloog_domain_union (temp
, old
);
988 cloog_domain_free (temp
);
989 cloog_domain_free (old
);
999 * cloog_domain_list_read function:
1000 * This function reads a list of polyhedra into a file (foo, posibly stdin) and
1001 * returns a pointer to a CloogDomainList containing the read information.
1002 * - November 6th 2001: first version.
1005 cloog_domain_list_read (FILE * foo
)
1009 CloogDomainList
*list
, *now
, *next
;
1012 /* We read first the number of polyhedra in the list. */
1013 while (fgets (s
, MAX_STRING
, foo
) == 0);
1014 while ((*s
== '#' || *s
== '\n') || (sscanf (s
, " %d", &nb_pols
) < 1))
1015 fgets (s
, MAX_STRING
, foo
);
1017 /* Then we read the polyhedra. */
1021 list
= (CloogDomainList
*) malloc (sizeof (CloogDomainList
));
1022 cloog_set_domain (list
, cloog_domain_read (foo
));
1023 cloog_set_next_domain (list
, NULL
);
1025 for (i
= 1; i
< nb_pols
; i
++)
1027 next
= (CloogDomainList
*) malloc (sizeof (CloogDomainList
));
1028 cloog_set_domain (next
, cloog_domain_read (foo
));
1029 cloog_set_next_domain (next
, NULL
);
1030 cloog_set_next_domain (now
, next
);
1031 now
= cloog_next_domain (now
);
1038 /******************************************************************************
1039 * Processing functions *
1040 ******************************************************************************/
1043 * cloog_domain_isempty function:
1044 * This function returns 1 if the polyhedron given as input is empty, 0
1046 * - October 28th 2001: first version.
1049 cloog_domain_isempty (CloogDomain
* domain
)
1051 if (cloog_domain_polyhedron (domain
) == NULL
)
1054 if (cloog_domain_polyhedron_next (domain
))
1057 return ((cloog_domain_dim (domain
) < cloog_domain_nbeq (domain
)) ? 1 : 0);
1062 * cloog_domain_project function:
1063 * From Quillere's LoopGen 0.4. This function returns the projection of
1064 * (domain) on the (level) first dimensions (i.e. outer loops). It returns a
1065 * pointer to the projected Polyhedron.
1066 * - nb_par is the number of parameters.
1068 * - October 27th 2001: first version.
1069 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1073 cloog_domain_project (CloogDomain
* domain
, int level
, int nb_par
)
1075 int row
, column
, nb_rows
, nb_columns
, difference
;
1076 CloogDomain
*projected_domain
;
1077 CloogMatrix
*matrix
;
1079 nb_rows
= level
+ nb_par
+ 1;
1080 nb_columns
= cloog_domain_dim (domain
) + 1;
1081 difference
= nb_columns
- nb_rows
;
1083 if (difference
== 0)
1084 return (cloog_domain_copy (domain
));
1086 matrix
= cloog_matrix_alloc (nb_rows
, nb_columns
);
1088 for (row
= 0; row
< level
; row
++)
1089 for (column
= 0; column
< nb_columns
; column
++)
1090 value_set_si (matrix
->p
[row
][column
], (row
== column
? 1 : 0));
1092 for (; row
< nb_rows
; row
++)
1093 for (column
= 0; column
< nb_columns
; column
++)
1094 value_set_si (matrix
->p
[row
][column
],
1095 (row
+ difference
== column
? 1 : 0));
1097 projected_domain
= cloog_domain_image (domain
, matrix
);
1098 cloog_matrix_free (matrix
);
1100 return (projected_domain
);
1104 * cloog_domain_extend function:
1105 * From Quillere's LoopGen 0.4. This function returns the (domain) given as
1106 * input with (dim)+(nb_par) dimensions. The new dimensions are added before
1107 * the (nb_par) parameters. This function does not free (domain), and returns
1109 * - nb_par is the number of parameters.
1111 * - October 27th 2001: first version.
1112 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1116 cloog_domain_extend (CloogDomain
* domain
, int dim
, int nb_par
)
1118 int row
, column
, nb_rows
, nb_columns
, difference
;
1119 CloogDomain
*extended_domain
;
1120 CloogMatrix
*matrix
;
1122 nb_rows
= 1 + cloog_domain_dim (domain
);
1123 nb_columns
= dim
+ nb_par
+ 1;
1124 difference
= nb_columns
- nb_rows
;
1126 if (difference
== 0)
1127 return (cloog_domain_copy (domain
));
1129 matrix
= cloog_matrix_alloc (nb_rows
, nb_columns
);
1131 for (row
= 0; row
< cloog_domain_dim (domain
) - nb_par
; row
++)
1132 for (column
= 0; column
< nb_columns
; column
++)
1133 value_set_si (matrix
->p
[row
][column
], (row
== column
? 1 : 0));
1135 for (; row
<= cloog_domain_dim (domain
); row
++)
1136 for (column
= 0; column
< nb_columns
; column
++)
1137 value_set_si (matrix
->p
[row
][column
],
1138 (row
+ difference
== column
? 1 : 0));
1140 extended_domain
= cloog_domain_preimage (domain
, matrix
);
1141 cloog_matrix_free (matrix
);
1143 return (extended_domain
);
1148 * cloog_domain_never_integral function:
1149 * For us, an equality like 3*i -4 = 0 is always false since 4%3 != 0. This
1150 * function returns a boolean set to 1 if there is this kind of 'never true'
1151 * constraint inside a polyhedron, 0 otherwise.
1152 * - domain is the polyhedron to check,
1154 * - November 28th 2001: first version.
1155 * - June 26th 2003: for iterators, more 'never true' constraints are found
1156 * (compare cholesky2 and vivien with a previous version),
1157 * checking for the parameters created (compare using vivien).
1158 * - June 28th 2003: Previously in loop.c and called
1159 * cloog_loop_simplify_nevertrue, now here !
1160 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1162 * - October 14th 2005: Complete rewriting, not faster but code quite shorter.
1165 cloog_domain_never_integral (CloogDomain
* domain
)
1169 Polyhedron
*polyhedron
;
1171 if ((domain
== NULL
) || (cloog_domain_polyhedron (domain
) == NULL
))
1175 value_init_c (modulo
);
1176 polyhedron
= cloog_domain_polyhedron (domain
);
1177 dimension
= cloog_domain_dim (domain
) + 2;
1179 /* For each constraint... */
1180 for (i
= 0; i
< cloog_polyhedron_nbc (polyhedron
); i
++)
1181 { /* If we have an equality and the scalar part is not zero... */
1182 if (value_zero_p (polyhedron
->Constraint
[i
][0]) &&
1183 value_notzero_p (polyhedron
->Constraint
[i
][dimension
- 1]))
1184 { /* Then we check whether the scalar can be divided by the gcd of the
1185 * unknown vector (including iterators and parameters) or not. If not,
1186 * there is no integer point in the polyhedron and we return 1.
1188 Vector_Gcd (&(polyhedron
->Constraint
[i
][1]), dimension
- 2, &gcd
);
1189 value_modulus (modulo
,
1190 polyhedron
->Constraint
[i
][dimension
- 1],
1193 if (value_notzero_p (modulo
))
1195 value_clear_c (gcd
);
1196 value_clear_c (modulo
);
1202 value_clear_c (gcd
);
1203 value_clear_c (modulo
);
1209 * cloog_domain_stride function:
1210 * This function finds the stride imposed to unknown with the column number
1211 * 'strided_level' in order to be integral. For instance, if we have a
1212 * constraint like -i - 2j + 2k = 0, and we consider k, then k can be integral
1213 * only if (i + 2j)%2 = 0. Then only if i%2 = 0. Then k imposes a stride 2 to
1214 * the unknown i. The function returns the imposed stride in a parameter field.
1215 * - domain is the set of constraint we have to consider,
1216 * - strided_level is the column number of the unknown for which a stride have
1218 * - looking_level is the column number of the unknown that impose a stride to
1219 * the first unknown.
1220 * - stride is the stride that is returned back as a function parameter.
1221 * - offset is the value of the constant c if the condition is of the shape
1222 * (i + c)%s = 0, s being the stride.
1224 * - June 28th 2003: first version.
1225 * - July 14th 2003: can now look for multiple striding constraints and returns
1226 * the GCD of the strides and the common offset.
1227 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1231 cloog_domain_stride (domain
, strided_level
, nb_par
, stride
, offset
)
1232 CloogDomain
*domain
;
1233 int strided_level
, nb_par
;
1234 Value
*stride
, *offset
;
1237 Polyhedron
*polyhedron
;
1238 int n_col
, n_row
, rank
;
1243 polyhedron
= cloog_domain_polyhedron (domain
);
1244 dimension
= cloog_domain_dim (domain
);
1246 /* Look at all equalities involving strided_level and the inner
1247 * iterators. We can ignore the outer iterators and the parameters
1248 * here because the lower bound on strided_level is assumed to
1251 n_col
= (1 + dimension
- nb_par
) - strided_level
;
1252 for (i
= 0, n_row
= 0; i
< cloog_polyhedron_nbeq (polyhedron
); i
++)
1254 (polyhedron
->Constraint
[i
] + strided_level
, n_col
) != -1)
1257 M
= cloog_matrix_alloc (n_row
+ 1, n_col
+ 1);
1258 for (i
= 0, n_row
= 0; i
< cloog_polyhedron_nbeq (polyhedron
); i
++)
1261 (polyhedron
->Constraint
[i
] + strided_level
, n_col
) == -1)
1263 Vector_Copy (polyhedron
->Constraint
[i
] + strided_level
,
1264 M
->p
[n_row
], n_col
);
1265 value_assign (M
->p
[n_row
][n_col
],
1266 polyhedron
->Constraint
[i
][1 + dimension
]);
1269 value_set_si (M
->p
[n_row
][n_col
], 1);
1271 /* Then look at the general solution to the above equalities. */
1272 rank
= SolveDiophantine (M
, &U
, &V
);
1273 cloog_matrix_free (M
);
1277 /* There is no solution, so the body of this loop will
1278 * never execute. We just leave the constraints alone here so
1279 * that they will ensure the body will not be executed.
1280 * We should probably propagate this information up so that
1281 * the loop can be removed entirely.
1283 value_set_si (*offset
, 0);
1284 value_set_si (*stride
, 1);
1288 /* Compute the gcd of the coefficients defining strided_level. */
1289 Vector_Gcd (U
->p
[0], U
->NbColumns
, stride
);
1290 value_oppose (*offset
, V
->p
[0]);
1291 value_pmodulus (*offset
, *offset
, *stride
);
1301 * cloog_domain_integral_lowerbound function:
1302 * This function returns 1 if the lower bound of an iterator (such as its
1303 * column rank in the constraint set 'domain' is 'level') is integral,
1304 * 0 otherwise. If the lower bound is actually integral, the function fills
1305 * the 'lower' field with the lower bound value.
1306 * - June 29th 2003: first version.
1307 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1311 cloog_domain_integral_lowerbound (domain
, level
, lower
)
1312 CloogDomain
*domain
;
1316 int i
, first_lower
= 1, dimension
, lower_constraint
= -1;
1317 Value iterator
, constant
, tmp
;
1318 Polyhedron
*polyhedron
;
1320 polyhedron
= cloog_domain_polyhedron (domain
);
1321 dimension
= cloog_domain_dim (domain
);
1323 /* We want one and only one lower bound (e.g. no equality, no maximum
1326 for (i
= 0; i
< cloog_polyhedron_nbc (polyhedron
); i
++)
1327 if (value_zero_p (polyhedron
->Constraint
[i
][0])
1328 && value_notzero_p (polyhedron
->Constraint
[i
][level
]))
1331 for (i
= 0; i
< cloog_polyhedron_nbc (polyhedron
); i
++)
1332 if (value_pos_p (polyhedron
->Constraint
[i
][level
]))
1337 lower_constraint
= i
;
1346 /* We want an integral lower bound: no other non-zero entry except the
1347 * iterator coefficient and the constant.
1349 for (i
= 1; i
< level
; i
++)
1351 (polyhedron
->Constraint
[lower_constraint
][i
]))
1354 for (i
= level
+ 1; i
<= cloog_polyhedron_dim (polyhedron
); i
++)
1356 (polyhedron
->Constraint
[lower_constraint
][i
]))
1359 value_init_c (iterator
);
1360 value_init_c (constant
);
1363 /* If all is passed, then find the lower bound and return 1. */
1364 value_assign (iterator
,
1365 polyhedron
->Constraint
[lower_constraint
][level
]);
1366 value_oppose (constant
,
1367 polyhedron
->Constraint
[lower_constraint
][dimension
+ 1]);
1369 value_modulus (tmp
, constant
, iterator
);
1370 value_division (*lower
, constant
, iterator
);
1372 if (!(value_zero_p (tmp
) || value_neg_p (constant
)))
1373 value_increment (*lower
, *lower
);
1375 value_clear_c (iterator
);
1376 value_clear_c (constant
);
1377 value_clear_c (tmp
);
1384 * cloog_domain_lowerbound_update function:
1385 * This function updates the integral lower bound of an iterator (such as its
1386 * column rank in the constraint set 'domain' is 'level') into 'lower'.
1387 * - Jun 29th 2003: first version.
1388 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1392 cloog_domain_lowerbound_update (domain
, level
, lower
)
1393 CloogDomain
*domain
;
1398 Polyhedron
*polyhedron
;
1400 polyhedron
= cloog_domain_polyhedron (domain
);
1402 /* There is only one lower bound, the first one is the good one. */
1403 for (i
= 0; i
< cloog_polyhedron_nbc (polyhedron
); i
++)
1404 if (value_pos_p (polyhedron
->Constraint
[i
][level
]))
1406 value_set_si (polyhedron
->Constraint
[i
][level
], 1);
1407 value_oppose (polyhedron
->Constraint
[i
][cloog_polyhedron_dim (polyhedron
) + 1], lower
);
1414 * cloog_domain_lazy_equal function:
1415 * This function returns 1 if the domains given as input are the same, 0 if it
1416 * is unable to decide. This function makes an entry-to-entry comparison between
1417 * the constraint systems, if all the entries are the same, the domains are
1418 * obviously the same and it returns 1, at the first difference, it returns 0.
1419 * This is a very fast way to verify this property. It has been shown (with the
1420 * CLooG benchmarks) that operations on equal domains are 17% of all the
1421 * polyhedral computations. For 75% of the actually identical domains, this
1422 * function answer that they are the same and allow to give immediately the
1423 * trivial solution instead of calling the heavy general functions of PolyLib.
1424 * - August 22th 2003: first version.
1425 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1429 cloog_domain_lazy_equal (CloogDomain
* d1
, CloogDomain
* d2
)
1432 Polyhedron
*p1
, *p2
;
1434 p1
= cloog_domain_polyhedron (d1
);
1435 p2
= cloog_domain_polyhedron (d2
);
1437 while ((p1
!= NULL
) && (p2
!= NULL
))
1439 if ((cloog_polyhedron_nbc (p1
) != cloog_polyhedron_nbc (p2
)) ||
1440 (cloog_polyhedron_dim (p1
) != cloog_polyhedron_dim (p2
)))
1444 cloog_polyhedron_nbc (p1
) * (cloog_polyhedron_dim (p1
) + 2);
1446 for (i
= 0; i
< nb_elements
; i
++)
1447 if (value_ne (p1
->p_Init
[i
], p2
->p_Init
[i
]))
1450 p1
= cloog_polyhedron_next (p1
);
1451 p2
= cloog_polyhedron_next (p2
);
1454 if ((p1
!= NULL
) || (p2
!= NULL
))
1462 * cloog_domain_lazy_block function:
1463 * This function returns 1 if the two domains d1 and d2 given as input are the
1464 * same (possibly except for a dimension equal to a constant where we accept
1465 * a difference of 1) AND if we are sure that there are no other domain in
1466 * the code generation problem that may put integral points between those of
1467 * d1 and d2 (0 otherwise). In fact this function answers the question "can I
1468 * safely consider the two domains as only one with two statements (a block) ?".
1469 * This function is lazy: it asks for very standard scattering representation
1470 * (only one constraint per dimension which is an equality, and the constraints
1471 * are ordered per dimension depth: the left hand side of the constraint matrix
1472 * is the identity) and will answer NO at the very first problem.
1473 * - d1 and d2 are the two domains to check for blocking,
1474 * - scattering is the linked list of all domains,
1475 * - scattdims is the total number of scattering dimentions.
1477 * - April 30th 2005: beginning
1478 * - June 9th 2005: first working version.
1479 * - June 10th 2005: debugging.
1480 * - June 21rd 2005: Adaptation for GMP.
1481 * - October 16th 2005: (debug) some false blocks have been removed.
1484 cloog_domain_lazy_block (d1
, d2
, scattering
, scattdims
)
1485 CloogDomain
*d1
, *d2
;
1486 CloogDomainList
*scattering
;
1489 int i
, j
, difference
= 0, different_constraint
= 0;
1490 Value date1
, date2
, date3
, temp
;
1491 Polyhedron
*p1
, *p2
, *p3
;
1493 p1
= cloog_domain_polyhedron (d1
);
1494 p2
= cloog_domain_polyhedron (d2
);
1496 /* Some basic checks: we only accept convex domains, with same constraint
1497 * and dimension numbers.
1499 if (cloog_polyhedron_next (p1
) || cloog_polyhedron_next (p2
) ||
1500 (cloog_polyhedron_nbc (p1
) != cloog_polyhedron_nbc (p2
)) ||
1501 (cloog_polyhedron_dim (p1
) != cloog_polyhedron_dim (p2
)))
1504 /* There should be only one difference between the two domains, it
1505 * has to be at the constant level and the difference must be of +1,
1506 * moreover, after the difference all domain coefficient has to be 0.
1507 * The matrix shape is:
1509 * |===========|=====|<- 0 line
1510 * |===========|=====|
1511 * |===========|====?|<- different_constraint line (found here)
1512 * |===========|0000=|
1513 * |===========|0000=|<- pX->NbConstraints line
1516 * | | (pX->Dimension + 2) column
1517 * | scattdims column
1521 value_init_c (temp
);
1522 for (i
= 0; i
< cloog_polyhedron_nbc (p1
); i
++)
1524 if (difference
== 0)
1525 { /* All elements except scalar must be equal. */
1526 for (j
= 0; j
< (cloog_polyhedron_dim (p1
) + 1); j
++)
1527 if (value_ne (p1
->Constraint
[i
][j
],
1528 p2
->Constraint
[i
][j
]))
1530 value_clear_c (temp
);
1533 /* The scalar may differ from +1 (now j=(p1->Dimension + 1)). */
1534 if (value_ne (p1
->Constraint
[i
][j
],
1535 p2
->Constraint
[i
][j
]))
1537 value_increment (temp
, p2
->Constraint
[i
][j
]);
1538 if (value_ne (p1
->Constraint
[i
][j
], temp
))
1540 value_clear_c (temp
);
1546 different_constraint
= i
;
1551 { /* Scattering coefficients must be equal. */
1552 for (j
= 0; j
< (scattdims
+ 1); j
++)
1553 if (value_ne (p1
->Constraint
[i
][j
],
1554 p2
->Constraint
[i
][j
]))
1556 value_clear_c (temp
);
1560 /* Domain coefficients must be 0. */
1561 for (; j
< (cloog_polyhedron_dim (p1
) + 1); j
++)
1562 if (value_notzero_p (p1
->Constraint
[i
][j
])
1563 || value_notzero_p (p2
->Constraint
[i
][j
]))
1565 value_clear_c (temp
);
1569 /* Scalar must be equal. */
1570 if (value_ne (p1
->Constraint
[i
][j
],
1571 p2
->Constraint
[i
][j
]))
1573 value_clear_c (temp
);
1578 value_clear_c (temp
);
1580 /* If the domains are exactly the same, this is a block. */
1581 if (difference
== 0)
1584 /* Now a basic check that the constraint with the difference is an
1585 * equality of a dimension with a constant.
1587 for (i
= 0; i
<= different_constraint
; i
++)
1588 if (value_notzero_p (p1
->Constraint
[different_constraint
][i
]))
1591 if (value_notone_p (p1
->Constraint
[different_constraint
][different_constraint
+ 1]))
1594 for (i
= different_constraint
+ 2; i
< (cloog_polyhedron_dim (p1
) + 1); i
++)
1595 if (value_notzero_p (p1
->Constraint
[different_constraint
][i
]))
1598 /* For the moment, d1 and d2 are a block candidate. There remains to check
1599 * that there is no other domain that may put an integral point between
1600 * them. In our lazy test we ensure this property by verifying that the
1601 * constraint matrices have a very strict shape: let us consider that the
1602 * dimension with the difference is d. Then the first d dimensions are
1603 * defined in their depth order using equalities (thus the first column begins
1604 * with d zeroes, there is a d*d identity matrix and a zero-matrix for
1605 * the remaining simensions). If a domain can put integral points between the
1606 * domains of the block candidate, this means that the other entries on the
1607 * first d constraints are equal to those of d1 or d2. Thus we are looking for
1608 * such a constraint system, if it exists d1 and d2 is considered to not be
1609 * a block, it is a bock otherwise.
1611 * 1. Only equalities (for the first different_constraint+1 lines).
1612 * | 2. Must be the identity.
1613 * | | 3. Must be zero.
1614 * | | | 4. Elements are equal, the last one is either date1 or 2.
1617 * |0|100|00000|=====|<- 0 line
1618 * |0|010|00000|=====|
1619 * |0|001|00000|====?|<- different_constraint line
1620 * |*|***|*****|*****|
1621 * |*|***|*****|*****|<- pX->NbConstraints line
1624 * | | | (pX->Dimension + 2) column
1625 * | | scattdims column
1626 * | different_constraint+1 column
1630 /* Step 1 and 2. This is only necessary to check one domain because
1631 * we checked that they are equal on this part before.
1633 for (i
= 0; i
<= different_constraint
; i
++)
1635 for (j
= 0; j
< i
+ 1; j
++)
1636 if (value_notzero_p (p1
->Constraint
[i
][j
]))
1639 if (value_notone_p (p1
->Constraint
[i
][i
+ 1]))
1642 for (j
= i
+ 2; j
<= different_constraint
+ 1; j
++)
1643 if (value_notzero_p (p1
->Constraint
[i
][j
]))
1648 for (i
= 0; i
<= different_constraint
; i
++)
1649 for (j
= different_constraint
+ 2; j
<= scattdims
; j
++)
1650 if (value_notzero_p (p1
->Constraint
[i
][j
]))
1653 value_init_c (date1
);
1654 value_init_c (date2
);
1655 value_init_c (date3
);
1657 /* Now we have to check that the two different dates are unique. */
1658 value_assign (date1
, p1
->Constraint
[different_constraint
][cloog_polyhedron_dim (p1
) + 1]);
1659 value_assign (date2
, p2
->Constraint
[different_constraint
][cloog_polyhedron_dim (p2
) + 1]);
1661 /* Step 4. We check all domains except d1 and d2 and we look for at least
1662 * a difference with d1 or d2 on the first different_constraint+1 dimensions.
1664 while (scattering
!= NULL
)
1666 if ((cloog_domain (scattering
) != d1
)
1667 && (cloog_domain (scattering
) != d2
))
1669 p3
= cloog_domain_polyhedron (cloog_domain (scattering
));
1670 value_assign (date3
,
1671 p3
->Constraint
[different_constraint
][cloog_polyhedron_dim (p3
) + 1]);
1674 if (value_ne (date3
, date2
) && value_ne (date3
, date1
))
1677 for (i
= 0; (i
< different_constraint
) && (!difference
); i
++)
1679 (j
< (cloog_polyhedron_dim (p3
) + 2)) && (!difference
); j
++)
1681 (p1
->Constraint
[i
][j
],
1682 p3
->Constraint
[i
][j
]))
1685 for (j
= 0; (j
< (cloog_polyhedron_dim (p3
) + 1)) && (!difference
);
1688 (p1
->Constraint
[different_constraint
][j
],
1689 p3
->Constraint
[different_constraint
][j
]))
1694 value_clear_c (date1
);
1695 value_clear_c (date2
);
1696 value_clear_c (date3
);
1701 scattering
= cloog_next_domain (scattering
);
1704 value_clear_c (date1
);
1705 value_clear_c (date2
);
1706 value_clear_c (date3
);
1712 * cloog_domain_lazy_disjoint function:
1713 * This function returns 1 if the domains given as input are disjoint, 0 if it
1714 * is unable to decide. This function finds the unknown with fixed values in
1715 * both domains (on a given constraint, their column entry is not zero and
1716 * only the constant coefficient can be different from zero) and verify that
1717 * their values are the same. If not, the domains are obviously disjoint and
1718 * it returns 1, if there is not such case it returns 0. This is a very fast
1719 * way to verify this property. It has been shown (with the CLooG benchmarks)
1720 * that operations on disjoint domains are 36% of all the polyhedral
1721 * computations. For 94% of the actually identical domains, this
1722 * function answer that they are disjoint and allow to give immediately the
1723 * trivial solution instead of calling the heavy general functions of PolyLib.
1724 * - August 22th 2003: first version.
1725 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1729 cloog_domain_lazy_disjoint (CloogDomain
* d1
, CloogDomain
* d2
)
1731 int i1
, j1
, i2
, j2
, scat_dim
;
1733 Polyhedron
*p1
, *p2
;
1735 p1
= cloog_domain_polyhedron (d1
);
1736 p2
= cloog_domain_polyhedron (d2
);
1738 if (cloog_polyhedron_next (p1
) || cloog_polyhedron_next (p2
))
1741 value_init_c (scat_val
);
1743 for (i1
= 0; i1
< cloog_polyhedron_nbc (p1
); i1
++)
1745 if (value_notzero_p (p1
->Constraint
[i1
][0]))
1749 while (value_zero_p (p1
->Constraint
[i1
][scat_dim
]) &&
1750 (scat_dim
< cloog_polyhedron_dim (p1
)))
1753 if (value_notone_p (p1
->Constraint
[i1
][scat_dim
]))
1757 for (j1
= scat_dim
+ 1; j1
<= cloog_polyhedron_dim (p1
); j1
++)
1758 if (value_notzero_p (p1
->Constraint
[i1
][j1
]))
1761 if (j1
!= cloog_polyhedron_dim (p1
) + 1)
1764 value_assign (scat_val
,
1765 p1
->Constraint
[i1
][cloog_polyhedron_dim (p1
) + 1]);
1767 for (i2
= 0; i2
< cloog_polyhedron_nbc (p2
); i2
++)
1769 for (j2
= 0; j2
< scat_dim
; j2
++)
1770 if (value_notzero_p (p2
->Constraint
[i2
][j2
]))
1773 if ((j2
!= scat_dim
)
1775 value_notone_p (p2
->Constraint
[i2
][scat_dim
]))
1778 for (j2
= scat_dim
+ 1; j2
< cloog_polyhedron_dim (p2
); j2
++)
1779 if (value_notzero_p (p2
->Constraint
[i2
][j2
]))
1782 if (j2
!= cloog_polyhedron_dim (p2
))
1786 (p2
->Constraint
[i2
][cloog_polyhedron_dim (p2
) + 1], scat_val
))
1788 value_clear_c (scat_val
);
1795 value_clear_c (scat_val
);
1801 * cloog_domain_list_lazy_same function:
1802 * This function returns 1 if two domains in the list are the same, 0 if it
1803 * is unable to decide.
1804 * - February 9th 2004: first version.
1807 cloog_domain_list_lazy_same (CloogDomainList
* list
)
1808 { /*int i=1, j=1 ; */
1809 CloogDomainList
*current
, *next
;
1812 while (current
!= NULL
)
1814 next
= cloog_next_domain (current
);
1816 while (next
!= NULL
)
1818 if (cloog_domain_lazy_equal (cloog_domain (current
),
1819 cloog_domain (next
)))
1820 { /*printf("Same domains: %d and %d\n",i,j) ; */
1824 next
= cloog_next_domain (next
);
1827 current
= cloog_next_domain (current
);
1834 * cloog_domain_cut_first function:
1835 * this function returns a CloogDomain structure with everything except the
1836 * first part of the polyhedra union of the input domain as domain. After a call
1837 * to this function, there remains in the CloogDomain structure provided as
1838 * input only the first part of the original polyhedra union.
1839 * - April 20th 2005: first version, extracted from different part of loop.c.
1842 cloog_domain_cut_first (CloogDomain
* domain
)
1846 if ((domain
!= NULL
) && (cloog_domain_polyhedron (domain
) != NULL
))
1848 rest
= cloog_domain_alloc (cloog_domain_polyhedron_next (domain
));
1849 cloog_domain_polyhedron_set_next (domain
, NULL
);
1859 * cloog_domain_lazy_isscalar function:
1860 * this function returns 1 if the dimension 'dimension' in the domain 'domain'
1861 * is scalar, this means that the only constraint on this dimension must have
1862 * the shape "x.dimension + scalar = 0" with x an integral variable. This
1863 * function is lazy since we only accept x=1 (further calculations are easier
1865 * - June 14th 2005: first version.
1866 * - June 21rd 2005: Adaptation for GMP.
1869 cloog_domain_lazy_isscalar (CloogDomain
* domain
, int dimension
)
1872 Polyhedron
*polyhedron
;
1874 polyhedron
= cloog_domain_polyhedron (domain
);
1875 /* For each constraint... */
1876 for (i
= 0; i
< cloog_polyhedron_nbc (polyhedron
); i
++)
1877 { /* ...if it is concerned by the potentially scalar dimension... */
1879 (polyhedron
->Constraint
[i
][dimension
+ 1]))
1880 { /* ...check that the constraint has the shape "dimension + scalar = 0". */
1881 for (j
= 0; j
<= dimension
; j
++)
1882 if (value_notzero_p (polyhedron
->Constraint
[i
][j
]))
1886 (polyhedron
->Constraint
[i
][dimension
+ 1]))
1889 for (j
= dimension
+ 2; j
< (cloog_polyhedron_dim (polyhedron
) + 1);
1891 if (value_notzero_p (polyhedron
->Constraint
[i
][j
]))
1901 * cloog_domain_scalar function:
1902 * when we call this function, we know that "dimension" is a scalar dimension,
1903 * this function finds the scalar value in "domain" and returns it in "value".
1904 * - June 30th 2005: first version.
1907 cloog_domain_scalar (CloogDomain
* domain
, int dimension
, Value
* value
)
1910 Polyhedron
*polyhedron
;
1912 polyhedron
= cloog_domain_polyhedron (domain
);
1913 /* For each constraint... */
1914 for (i
= 0; i
< cloog_polyhedron_nbc (polyhedron
); i
++)
1915 { /* ...if it is the equality defining the scalar dimension... */
1917 (polyhedron
->Constraint
[i
][dimension
+ 1])
1918 && value_zero_p (polyhedron
->Constraint
[i
][0]))
1919 { /* ...Then send the scalar value. */
1920 value_assign (*value
, polyhedron
->Constraint
[i
][cloog_polyhedron_dim (polyhedron
) + 1]);
1921 value_oppose (*value
, *value
);
1926 /* We should have found a scalar value: if not, there is an error. */
1927 fprintf (stderr
, "[CLooG]ERROR: dimension %d is not scalar as expected.\n",
1934 * cloog_domain_erase_dimension function:
1935 * this function returns a CloogDomain structure builds from 'domain' where
1936 * we removed the dimension 'dimension' and every constraint considering this
1937 * dimension. This is not a projection ! Every data concerning the
1938 * considered dimension is simply erased.
1939 * - June 14th 2005: first version.
1940 * - June 21rd 2005: Adaptation for GMP.
1943 cloog_domain_erase_dimension (CloogDomain
* domain
, int dimension
)
1945 int i
, j
, mi
, nb_dim
;
1946 CloogMatrix
*matrix
;
1947 CloogDomain
*erased
;
1948 Polyhedron
*polyhedron
;
1950 polyhedron
= cloog_domain_polyhedron (domain
);
1951 nb_dim
= cloog_domain_dim (domain
);
1953 /* The matrix is one column less and at least one constraint less. */
1955 cloog_matrix_alloc (cloog_polyhedron_nbc (polyhedron
) - 1, nb_dim
+ 1);
1957 /* mi is the constraint counter for the matrix. */
1959 for (i
= 0; i
< cloog_polyhedron_nbc (polyhedron
); i
++)
1960 if (value_zero_p (polyhedron
->Constraint
[i
][dimension
+ 1]))
1962 for (j
= 0; j
<= dimension
; j
++)
1963 value_assign (matrix
->p
[mi
][j
],
1964 polyhedron
->Constraint
[i
][j
]);
1966 for (j
= dimension
+ 2; j
< nb_dim
+ 2; j
++)
1967 value_assign (matrix
->p
[mi
][j
- 1],
1968 polyhedron
->Constraint
[i
][j
]);
1973 erased
= cloog_domain_matrix2domain (matrix
);
1974 cloog_matrix_free (matrix
);
1979 /* Number of polyhedra inside the union of disjoint polyhedra. */
1982 cloog_domain_nb_polyhedra (CloogDomain
* domain
)
1985 Polyhedron
*polyhedron
= cloog_domain_polyhedron (domain
);
1987 while (polyhedron
!= NULL
)
1990 polyhedron
= polyhedron
->next
;
1997 cloog_domain_print_polyhedra (FILE * foo
, CloogDomain
* domain
)
1999 Polyhedron
*polyhedron
= cloog_domain_polyhedron (domain
);
2001 while (polyhedron
!= NULL
)
2003 CloogMatrix
*matrix
;
2004 matrix
= Polyhedron2Constraints (polyhedron
);
2005 cloog_matrix_print (foo
, matrix
);
2006 cloog_matrix_free (matrix
);
2007 polyhedron
= polyhedron
->next
;