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 * The maximal number of rays allowed to be allocated by PolyLib. In fact since
48 * version 5.20, PolyLib automatically tune the number of rays by multiplying
49 * by 2 this number each time the maximum is reached. For unknown reasons
50 * PolyLib makes a segmentation fault if this number is too small. If this
51 * number is too small, performances will be reduced, if it is too high, memory
52 * will be saturated. Note that the option "-rays X" set this number to X.
57 /******************************************************************************
58 * Memory leaks hunting *
59 ******************************************************************************/
63 * These functions and global variables are devoted to memory leaks hunting: we
64 * want to know at each moment how many Polyhedron structures had been allocated
65 * (cloog_domain_allocated) and how many had been freed (cloog_domain_freed).
66 * Each time a Polyhedron structure is allocated, a call to the function
67 * cloog_domain_leak_up() must be carried out, and respectively
68 * cloog_domain_leak_down() when a Polyhedron structure is freed. The special
69 * variable cloog_domain_max gives the maximal number of Polyhedron structures
70 * simultaneously alive (i.e. allocated and non-freed) in memory.
71 * - July 3rd->11th 2003: first version (memory leaks hunt and correction).
75 int cloog_domain_allocated
= 0 ;
76 int cloog_domain_freed
= 0 ;
77 int cloog_domain_max
= 0 ;
80 static void cloog_domain_leak_up()
81 { cloog_domain_allocated
++ ;
82 if ((cloog_domain_allocated
-cloog_domain_freed
) > cloog_domain_max
)
83 cloog_domain_max
= cloog_domain_allocated
- cloog_domain_freed
;
87 static void cloog_domain_leak_down()
88 { cloog_domain_freed
++ ;
92 /* The same for Value variables since in GMP mode they have to be freed. */
93 int cloog_value_allocated
= 0 ;
94 int cloog_value_freed
= 0 ;
95 int cloog_value_max
= 0 ;
98 void cloog_value_leak_up()
99 { cloog_value_allocated
++ ;
100 if ((cloog_value_allocated
-cloog_value_freed
) > cloog_value_max
)
101 cloog_value_max
= cloog_value_allocated
- cloog_value_freed
;
105 void cloog_value_leak_down()
106 { cloog_value_freed
++ ;
110 /******************************************************************************
111 * PolyLib interface *
112 ******************************************************************************/
115 /* CLooG makes an intensive use of polyhedral operations and the PolyLib do
116 * the job. Here are the interfaces to all the PolyLib calls (CLooG uses 19
117 * PolyLib functions), with or without some adaptations. If another polyhedral
118 * library can be used, only these functions have to be changed.
119 * - April 16th 2005: Since PolyLib 5.20, compacting is no more useful and have
120 * been removed. The direct use of the PolyLib's Polyhedron
121 * data structure is also replaced with the CloogDomain data
122 * structure that includes the Polyhedron and an additional
123 * counter on how many pointers point on this structure.
124 * This allows to save memory (cloog_domain_copy now only
125 * increment the counter) while memory leaks are avoided (the
126 * function cloog_domain_free decrements the counter and
127 * actually frees the data structure only when its value
133 * cloog_domain_matrix2domain function:
134 * Given a matrix of constraints (matrix), this function constructs and returns
135 * the corresponding domain (i.e. the CloogDomain structure including the
136 * polyhedron with its double representation: constraint matrix and the set of
139 static CloogDomain
* cloog_domain_matrix2domain(CloogMatrix
* matrix
)
140 { return (cloog_domain_alloc(Constraints2Polyhedron(matrix
,MAX_RAYS
))) ;
145 * cloog_domain_domain2matrix function:
146 * Given a polyhedron (in domain), this function returns its corresponding
147 * matrix of constraints.
149 static CloogMatrix
* cloog_domain_domain2matrix(CloogDomain
* domain
)
151 return cloog_matrix_matrix(Polyhedron2Constraints(cloog_domain_polyhedron (domain
)));
154 static inline int cloog_domain_references (CloogDomain
*d
)
156 return d
->_references
;
159 static inline void cloog_domain_set_references (CloogDomain
*d
, int i
)
165 * cloog_domain_print function:
166 * This function prints the content of a CloogDomain structure (domain) into
167 * a file (foo, possibly stdout).
169 void cloog_domain_print(FILE * foo
, CloogDomain
* domain
)
170 { Polyhedron_Print(foo
,P_VALUE_FMT
,cloog_domain_polyhedron (domain
)) ;
171 fprintf (foo
, "Number of active references: %d\n", cloog_domain_references (domain
));
176 * cloog_polyhedron_print function:
177 * This function prints the content of a Polyhedron structure (polyhedron) into
178 * a file (foo, possibly stdout). Just there as a development facility.
180 void cloog_polyhedron_print(FILE * foo
, Polyhedron
* polyhedron
)
181 { Polyhedron_Print(foo
,P_VALUE_FMT
,polyhedron
) ;
186 * cloog_domain_free function:
187 * This function frees the allocated memory for a CloogDomain structure
188 * (domain). It decrements the number of active references to this structure,
189 * if there are no more references on the structure, it frees it (with the
190 * included list of polyhedra).
192 void cloog_domain_free(CloogDomain
* domain
)
193 { if (domain
!= NULL
)
195 cloog_domain_set_references (domain
, cloog_domain_references (domain
) - 1);
197 if (cloog_domain_references (domain
) == 0)
199 if (cloog_domain_polyhedron (domain
) != NULL
)
201 cloog_domain_leak_down ();
202 Domain_Free(cloog_domain_polyhedron (domain
)) ;
212 * cloog_domain_copy function:
213 * This function returns a copy of a CloogDomain structure (domain). To save
214 * memory this is not a memory copy but we increment a counter of active
215 * references inside the structure, then return a pointer to that structure.
217 CloogDomain
* cloog_domain_copy(CloogDomain
* domain
)
219 cloog_domain_set_references (domain
, cloog_domain_references (domain
) + 1);
225 * cloog_domain_image function:
226 * This function returns a CloogDomain structure such that the included
227 * polyhedral domain is computed from the former one into another
228 * domain according to a given affine mapping function (mapping).
230 static CloogDomain
* cloog_domain_image(CloogDomain
* domain
, CloogMatrix
* mapping
)
231 { return (cloog_domain_alloc(DomainImage(cloog_domain_polyhedron (domain
),mapping
,MAX_RAYS
)));
236 * cloog_domain_preimage function:
237 * Given a polyhedral domain (polyhedron) inside a CloogDomain structure and a
238 * mapping function (mapping), this function returns a new CloogDomain structure
239 * with a polyhedral domain which when transformed by mapping function (mapping)
240 * gives (polyhedron).
242 static CloogDomain
* cloog_domain_preimage(CloogDomain
* domain
, CloogMatrix
* mapping
)
243 { return (cloog_domain_alloc(DomainPreimage(cloog_domain_polyhedron (domain
),
244 mapping
,MAX_RAYS
))) ;
249 * cloog_domain_convex function:
250 * Given a polyhedral domain (polyhedron), this function concatenates the lists
251 * of rays and lines of the two (or more) polyhedra in the domain into one
252 * combined list, and find the set of constraints which tightly bound all of
253 * those objects. It returns the corresponding polyhedron.
255 CloogDomain
* cloog_domain_convex(CloogDomain
* domain
)
256 { return (cloog_domain_alloc(DomainConvex(cloog_domain_polyhedron (domain
),MAX_RAYS
)));
259 static inline Polyhedron
* cloog_polyhedron_next (Polyhedron
*p
)
264 static inline void cloog_polyhedron_set_next (Polyhedron
*p
, Polyhedron
*n
)
269 static inline Polyhedron
* cloog_domain_polyhedron_next (CloogDomain
* domain
)
271 return cloog_polyhedron_next (cloog_domain_polyhedron (domain
));
274 static inline void cloog_domain_polyhedron_set_next (CloogDomain
*d
,
277 cloog_polyhedron_set_next (cloog_domain_polyhedron (d
), n
) ;
280 static inline unsigned cloog_polyhedron_nbc (Polyhedron
*p
)
282 return p
->NbConstraints
;
285 static inline Value
*cloog_polyhedron_c (Polyhedron
*p
, int i
)
287 return p
->Constraint
[i
];
290 static inline Value
cloog_polyhedron_cval (Polyhedron
*p
, int i
, int j
)
292 return p
->Constraint
[i
][j
];
295 static inline void cloog_polyhedron_cval_set_si (Polyhedron
*p
, int i
, int j
, int k
)
297 value_set_si (p
->Constraint
[i
][j
], k
);
300 static inline void cloog_polyhedron_cval_oppose (Polyhedron
*p
, int i
, int j
, int k
)
302 value_oppose (p
->Constraint
[i
][j
], k
);
305 static inline void cloog_polyhedron_c_gcd (Polyhedron
*p
, int i
, int j
, int k
, Value
*gcd
)
307 Vector_Gcd(&(p
->Constraint
[i
][1]), k
, gcd
);
310 static inline unsigned cloog_polyhedron_nbeq (Polyhedron
*p
)
315 static inline unsigned cloog_domain_nbeq (CloogDomain
*d
)
317 return cloog_polyhedron_nbeq (cloog_domain_polyhedron (d
));
320 static inline unsigned cloog_polyhedron_dim (Polyhedron
*p
)
326 int cloog_domain_isconvex (CloogDomain
*domain
)
328 return !cloog_domain_polyhedron_next (domain
);
331 unsigned cloog_domain_dim (CloogDomain
*d
)
333 return cloog_polyhedron_dim (cloog_domain_polyhedron (d
));
338 * cloog_domain_simplified_hull:
339 * Given a list (union) of polyhedra, this function returns a single
340 * polyhedron that contains this union and uses only contraints that
341 * appear in one or more of the polyhedra in the list.
343 * We simply iterate over all constraints of all polyhedra and test
344 * whether all rays of the other polyhedra satisfy/saturate the constraint.
346 static CloogDomain
*cloog_domain_simplified_hull(CloogDomain
* domain
)
348 int dim
= cloog_domain_dim (domain
);
350 int nb_pol
= 0, nb_constraints
= 0;
352 CloogMatrix
**rays
, *matrix
;
357 for (P
= cloog_domain_polyhedron (domain
); P
; P
= cloog_polyhedron_next (P
)) {
359 nb_constraints
+= cloog_polyhedron_nbc (P
);
361 matrix
= cloog_matrix_alloc(nb_constraints
, 1 + dim
+ 1);
363 rays
= (CloogMatrix
**)malloc(nb_pol
* sizeof(CloogMatrix
*));
364 for (P
= cloog_domain_polyhedron (domain
), i
= 0; P
; P
= cloog_polyhedron_next (P
), ++i
)
365 rays
[i
] = Polyhedron2Rays(P
);
367 for (P
= cloog_domain_polyhedron (domain
), i
= 0; P
; P
= cloog_polyhedron_next (P
), ++i
) {
368 CloogMatrix
*constraints
= Polyhedron2Constraints(P
);
369 for (j
= 0; j
< constraints
->NbRows
; ++j
) {
370 for (k
= 0; k
< nb_pol
; ++k
) {
373 for (l
= 0; l
< rays
[k
]->NbRows
; ++l
) {
374 Inner_Product(constraints
->p
[j
]+1, rays
[k
]->p
[l
]+1, dim
+1, &tmp
);
375 if (value_neg_p(tmp
))
377 if ((value_zero_p(cloog_matrix_element(constraints
, j
, 0)) ||
378 value_zero_p(cloog_matrix_element(rays
[k
], l
, 0))) && value_pos_p(tmp
))
381 if (l
< rays
[k
]->NbRows
)
385 Vector_Copy(constraints
->p
[j
], matrix
->p
[nb_constraints
++], 1+dim
+1);
387 Matrix_Free(constraints
);
390 for (P
= cloog_domain_polyhedron (domain
), i
= 0; P
; P
= cloog_polyhedron_next (P
), ++i
)
391 Matrix_Free(rays
[i
]);
395 matrix
->NbRows
= nb_constraints
;
396 bounds
= cloog_domain_matrix2domain(matrix
);
397 cloog_matrix_free(matrix
);
403 * cloog_domain_bounds:
404 * Given a list (union) of polyhedra "domain", this function returns a single
405 * polyhedron with constraints that reflect the (parametric) lower and
406 * upper bound on dimension "dim".
408 * nb_par is the number of parameters of the domain.
410 static CloogDomain
* cloog_domain_bounds(CloogDomain
* domain
, int dim
, int nb_par
)
412 int row
, nb_rows
, nb_columns
, difference
;
413 CloogDomain
* projected_domain
, *extended_domain
, *bounds
;
414 CloogMatrix
* matrix
;
416 nb_rows
= 1 + nb_par
+ 1;
417 nb_columns
= cloog_domain_dim (domain
) + 1 ;
418 difference
= nb_columns
- nb_rows
;
421 return(cloog_domain_convex(domain
));
423 matrix
= cloog_matrix_alloc(nb_rows
, nb_columns
);
425 cloog_matrix_element_set_si(matrix
, 0, dim
, 1);
426 for (row
= 1; row
< nb_rows
; row
++)
427 cloog_matrix_element_set_si(matrix
, row
, row
+difference
, 1);
429 projected_domain
= cloog_domain_image(domain
,matrix
) ;
430 extended_domain
= cloog_domain_preimage(projected_domain
, matrix
);
431 cloog_domain_free(projected_domain
);
432 cloog_matrix_free(matrix
) ;
433 bounds
= cloog_domain_convex(extended_domain
);
434 cloog_domain_free(extended_domain
);
440 * cloog_domain_simple_convex:
441 * Given a list (union) of polyhedra, this function returns a "simple"
442 * convex hull of this union. In particular, the constraints of the
443 * the returned polyhedron consist of (parametric) lower and upper
444 * bounds on individual variables and constraints that appear in the
445 * original polyhedra.
447 * nb_par is the number of parameters of the domain.
449 CloogDomain
* cloog_domain_simple_convex(CloogDomain
* domain
, int nb_par
)
452 int dim
= cloog_domain_dim (domain
) - nb_par
;
453 CloogDomain
*convex
= NULL
;
455 if (cloog_domain_isconvex(domain
))
456 return cloog_domain_copy(domain
);
458 for (i
= 0; i
< dim
; ++i
) {
459 CloogDomain
*bounds
= cloog_domain_bounds(domain
, i
, nb_par
);
464 CloogDomain
*temp
= cloog_domain_intersection(convex
, bounds
);
465 cloog_domain_free(bounds
);
466 cloog_domain_free(convex
);
471 CloogDomain
*temp
, *bounds
;
473 bounds
= cloog_domain_simplified_hull(domain
);
474 temp
= cloog_domain_intersection(convex
, bounds
);
475 cloog_domain_free(bounds
);
476 cloog_domain_free(convex
);
485 * cloog_domain_simplify function:
486 * Given two polyhedral domains (pol1) and (pol2) inside two CloogDomain
487 * structures, this function finds the largest domain set (or the smallest list
488 * of non-redundant constraints), that when intersected with polyhedral
489 * domain (pol2) equals (Pol1)intersect(Pol2). The output is a new CloogDomain
490 * structure with a polyhedral domain with the "redundant" constraints removed.
491 * NB: this function do not work as expected with unions of polyhedra...
493 CloogDomain
* cloog_domain_simplify(CloogDomain
* dom1
, CloogDomain
* dom2
)
497 Polyhedron
*P
= cloog_domain_polyhedron (dom1
);
499 /* DomainSimplify doesn't remove all redundant equalities,
500 * so we remove them here first in case both dom1 and dom2
501 * are single polyhedra (i.e., not unions of polyhedra).
503 if (cloog_domain_isconvex (dom1
)
504 && cloog_domain_isconvex (dom2
)
505 && cloog_polyhedron_nbeq (P
) && cloog_domain_nbeq (dom2
)) {
507 int rows
= cloog_polyhedron_nbeq (P
) + cloog_domain_nbeq (dom2
);
508 int cols
= cloog_polyhedron_dim (P
) + 2;
510 M
= cloog_matrix_alloc(rows
, cols
);
511 M2
= cloog_matrix_alloc(cloog_polyhedron_nbc (P
), cols
);
512 Vector_Copy(cloog_polyhedron_c (cloog_domain_polyhedron (dom2
), 0), M
->p
[0],
513 cloog_domain_nbeq (dom2
) * cols
);
514 rank
= cloog_domain_nbeq (dom2
);
516 for (i
= 0; i
< cloog_polyhedron_nbeq (P
); ++i
) {
517 Vector_Copy(cloog_polyhedron_c (P
, i
), M
->p
[rank
], cols
);
518 if (Gauss(M
, rank
+1, cols
-1) > rank
) {
519 Vector_Copy(cloog_polyhedron_c (P
, i
), M2
->p
[row
++], cols
);
523 if (row
< cloog_polyhedron_nbeq (P
)) {
524 Vector_Copy(cloog_polyhedron_c (P
, cloog_polyhedron_nbeq (P
)), M2
->p
[row
],
525 (cloog_polyhedron_nbc (P
) - cloog_polyhedron_nbeq (P
)) * cols
);
526 P
= Constraints2Polyhedron(M2
, MAX_RAYS
);
528 cloog_matrix_free(M2
);
529 cloog_matrix_free(M
);
531 dom
= cloog_domain_alloc(DomainSimplify(P
, cloog_domain_polyhedron (dom2
),MAX_RAYS
));
532 if (P
!= cloog_domain_polyhedron (dom1
))
539 * cloog_domain_union function:
540 * This function returns a new CloogDomain structure including a polyhedral
541 * domain which is the union of two polyhedral domains (pol1) U (pol2) inside
542 * two CloogDomain structures.
544 CloogDomain
* cloog_domain_union(CloogDomain
* dom1
, CloogDomain
* dom2
)
545 { return (cloog_domain_alloc(DomainUnion(cloog_domain_polyhedron (dom1
),
546 cloog_domain_polyhedron (dom2
),MAX_RAYS
))) ;
551 * cloog_domain_intersection function:
552 * This function returns a new CloogDomain structure including a polyhedral
553 * domain which is the intersection of two polyhedral domains (pol1)inter(pol2)
554 * inside two CloogDomain structures.
556 CloogDomain
* cloog_domain_intersection(CloogDomain
* dom1
, CloogDomain
* dom2
)
557 { return (cloog_domain_alloc(DomainIntersection(cloog_domain_polyhedron (dom1
),
558 cloog_domain_polyhedron (dom2
),MAX_RAYS
))) ;
563 * cloog_domain_difference function:
564 * This function returns a new CloogDomain structure including a polyhedral
565 * domain which is the difference of two polyhedral domains domain \ minus
566 * inside two CloogDomain structures.
567 * - November 8th 2001: first version.
569 CloogDomain
* cloog_domain_difference(CloogDomain
* domain
, CloogDomain
* minus
)
570 { if (cloog_domain_isempty(minus
))
571 return(cloog_domain_copy(domain
)) ;
573 return (cloog_domain_alloc(DomainDifference(cloog_domain_polyhedron (domain
),
574 cloog_domain_polyhedron (minus
),MAX_RAYS
))) ;
579 * cloog_domain_addconstraints function :
580 * This function adds source's polyhedron constraints to target polyhedron: for
581 * each element of the polyhedron inside 'target' (i.e. element of the union
582 * of polyhedra) it adds the constraints of the corresponding element in
584 * - August 10th 2002: first version.
585 * Nota bene for future : it is possible that source and target don't have the
586 * same number of elements (try iftest2 without non-shared constraint
587 * elimination in cloog_loop_separate !). This function is yet another part
588 * of the DomainSimplify patching problem...
590 CloogDomain
* cloog_domain_addconstraints(domain_source
, domain_target
)
591 CloogDomain
* domain_source
, * domain_target
;
592 { unsigned nb_constraint
;
593 Value
* constraints
;
594 Polyhedron
* source
, * target
, * new, * next
, * last
;
596 source
= cloog_domain_polyhedron (domain_source
) ;
597 target
= cloog_domain_polyhedron (domain_target
) ;
599 constraints
= source
->p_Init
;
600 nb_constraint
= cloog_polyhedron_nbc (source
) ;
601 source
= cloog_polyhedron_next (source
) ;
602 new = AddConstraints(constraints
,nb_constraint
,target
,MAX_RAYS
) ;
604 next
= cloog_polyhedron_next (target
) ;
607 { /* BUG !!! This is actually a bug. I don't know yet how to cleanly avoid
608 * the situation where source and target do not have the same number of
609 * elements. So this 'if' is an awful trick, waiting for better.
612 { constraints
= source
->p_Init
;
613 nb_constraint
= cloog_polyhedron_nbc (source
) ;
614 source
= cloog_polyhedron_next (source
) ;
616 cloog_polyhedron_set_next (last
, AddConstraints (constraints
, nb_constraint
,
618 last
= cloog_polyhedron_next (last
);
619 next
= cloog_polyhedron_next (next
);
622 return (cloog_domain_alloc(new)) ;
627 * cloog_domain_sort function:
628 * This function topologically sorts (nb_pols) polyhedra. Here (pols) is a an
629 * array of pointers to polyhedra, (nb_pols) is the number of polyhedra,
630 * (level) is the level to consider for partial ordering (nb_par) is the
631 * parameter space dimension, (permut) if not NULL, is an array of (nb_pols)
632 * integers that contains a permutation specification after call in order to
633 * apply the topological sorting.
635 void cloog_domain_sort(pols
, nb_pols
, level
, nb_par
, permut
)
637 unsigned nb_pols
, level
, nb_par
;
641 /* time is an array of (nb_pols) integers to store logical time values. We
642 * do not use it, but it is compulsory for PolyhedronTSort.
644 time
= (int *)malloc(nb_pols
*sizeof(int)) ;
646 /* PolyhedronTSort will fill up permut (and time). */
647 PolyhedronTSort(pols
,nb_pols
,level
,nb_par
,time
,permut
,MAX_RAYS
) ;
654 * cloog_domain_empty function:
655 * This function allocates the memory space for a CloogDomain structure and
656 * sets its polyhedron to an empty polyhedron with 'dimension' dimensions.
657 * Then it returns a pointer to the allocated space.
658 * - June 10th 2005: first version.
660 CloogDomain
* cloog_domain_empty(int dimension
)
661 { return (cloog_domain_alloc(Empty_Polyhedron(dimension
))) ;
665 /******************************************************************************
666 * Structure display function *
667 ******************************************************************************/
671 * cloog_domain_print_structure :
672 * this function is a more human-friendly way to display the CloogDomain data
673 * structure, it only shows the constraint system and includes an indentation
674 * level (level) in order to work with others print_structure functions.
675 * Written by Olivier Chorier, Luc Marchaud, Pierre Martin and Romain Tartiere.
676 * - April 24th 2005: Initial version.
677 * - May 26th 2005: Memory leak hunt.
678 * - June 16th 2005: (Ced) Integration in domain.c.
680 void cloog_domain_print_structure(FILE * file
, CloogDomain
* domain
, int level
)
682 CloogMatrix
* matrix
;
684 /* Go to the right level. */
685 for(i
=0; i
<level
; i
++)
686 fprintf(file
,"|\t") ;
689 { fprintf(file
,"+-- CloogDomain\n") ;
691 /* Print the matrix. */
692 matrix
= cloog_domain_domain2matrix(domain
) ;
693 cloog_matrix_print_structure(file
,matrix
,level
) ;
694 cloog_matrix_free(matrix
) ;
697 for (i
=0; i
<level
+1; i
++)
698 fprintf(file
,"|\t") ;
702 fprintf(file
,"+-- Null CloogDomain\n") ;
708 * cloog_domain_list_print function:
709 * This function prints the content of a CloogDomainList structure into a
710 * file (foo, possibly stdout).
711 * - November 6th 2001: first version.
713 void cloog_domain_list_print(FILE * foo
, CloogDomainList
* list
)
717 cloog_domain_print (foo
, cloog_domain (list
)) ;
718 list
= cloog_next_domain (list
) ;
723 /******************************************************************************
724 * Memory deallocation function *
725 ******************************************************************************/
729 * cloog_domain_list_free function:
730 * This function frees the allocated memory for a CloogDomainList structure.
731 * - November 6th 2001: first version.
733 void cloog_domain_list_free(CloogDomainList
* list
)
734 { CloogDomainList
* temp
;
738 temp
= cloog_next_domain (list
) ;
739 cloog_domain_free (cloog_domain (list
)) ;
746 /******************************************************************************
748 ******************************************************************************/
752 * cloog_domain_read function:
753 * Adaptation from the PolyLib. This function reads a matrix into a file (foo,
754 * posibly stdin) and returns a pointer to a polyhedron containing the read
756 * - October 18th 2001: first version.
758 CloogDomain
* cloog_domain_read(FILE * foo
)
759 { CloogMatrix
* matrix
;
760 CloogDomain
* domain
;
762 matrix
= cloog_matrix_read(foo
) ;
763 domain
= cloog_domain_matrix2domain(matrix
) ;
764 cloog_matrix_free(matrix
) ;
771 * cloog_domain_union_read function:
772 * This function reads a union of polyhedra into a file (foo, posibly stdin) and
773 * returns a pointer to a Polyhedron containing the read information.
774 * - September 9th 2002: first version.
775 * - October 29th 2005: (debug) removal of a leak counting "correction" that
776 * was just false since ages.
778 CloogDomain
* cloog_domain_union_read(FILE * foo
)
779 { int i
, nb_components
;
781 CloogDomain
* domain
, * temp
, * old
;
783 /* domain reading: nb_components (constraint matrices). */
784 while (fgets(s
,MAX_STRING
,foo
) == 0) ;
785 while ((*s
=='#' || *s
=='\n') || (sscanf(s
," %d",&nb_components
)<1))
786 fgets(s
,MAX_STRING
,foo
) ;
788 if (nb_components
> 0)
789 { /* 1. first part of the polyhedra union, */
790 domain
= cloog_domain_read(foo
) ;
791 /* 2. and the nexts. */
792 for (i
=1;i
<nb_components
;i
++)
793 { /* Leak counting is OK since next allocated domain is freed here. */
794 temp
= cloog_domain_read(foo
) ;
796 domain
= cloog_domain_union(temp
,old
) ;
797 cloog_domain_free(temp
) ;
798 cloog_domain_free(old
) ;
808 * cloog_domain_list_read function:
809 * This function reads a list of polyhedra into a file (foo, posibly stdin) and
810 * returns a pointer to a CloogDomainList containing the read information.
811 * - November 6th 2001: first version.
813 CloogDomainList
* cloog_domain_list_read(FILE * foo
)
816 CloogDomainList
* list
, * now
, * next
;
819 /* We read first the number of polyhedra in the list. */
820 while (fgets(s
,MAX_STRING
,foo
) == 0) ;
821 while ((*s
=='#' || *s
=='\n') || (sscanf(s
," %d",&nb_pols
)<1))
822 fgets(s
,MAX_STRING
,foo
) ;
824 /* Then we read the polyhedra. */
827 { list
= (CloogDomainList
*)malloc(sizeof(CloogDomainList
)) ;
828 cloog_set_domain (list
, cloog_domain_read (foo
));
829 cloog_set_next_domain (list
, NULL
);
831 for (i
=1;i
<nb_pols
;i
++)
832 { next
= (CloogDomainList
*)malloc(sizeof(CloogDomainList
)) ;
833 cloog_set_domain (next
, cloog_domain_read (foo
));
834 cloog_set_next_domain (next
, NULL
);
835 cloog_set_next_domain (now
, next
);
836 now
= cloog_next_domain (now
);
843 /******************************************************************************
844 * Processing functions *
845 ******************************************************************************/
849 * cloog_domain_malloc function:
850 * This function allocates the memory space for a CloogDomain structure and
851 * sets its fields with default values. Then it returns a pointer to the
853 * - November 21th 2005: first version.
855 static CloogDomain
* cloog_domain_malloc()
856 { CloogDomain
* domain
;
858 domain
= (CloogDomain
*)malloc(sizeof(CloogDomain
)) ;
860 { fprintf(stderr
, "[CLooG]ERROR: memory overflow.\n") ;
863 cloog_domain_leak_up() ;
865 /* We set the various fields with default values. */
866 cloog_domain_polyhedron_set (domain
, NULL
) ;
867 cloog_domain_set_references (domain
, 1);
874 * cloog_domain_alloc function:
875 * This function allocates the memory space for a CloogDomain structure and
876 * sets its fields with those given as input. Then it returns a pointer to the
878 * - April 19th 2005: first version.
879 * - November 21th 2005: cloog_domain_malloc use.
881 CloogDomain
* cloog_domain_alloc(Polyhedron
* polyhedron
)
882 { CloogDomain
* domain
;
884 if (polyhedron
== NULL
)
887 { domain
= cloog_domain_malloc() ;
888 cloog_domain_polyhedron_set (domain
, polyhedron
) ;
896 * cloog_domain_isempty function:
897 * This function returns 1 if the polyhedron given as input is empty, 0
899 * - October 28th 2001: first version.
901 int cloog_domain_isempty(CloogDomain
* domain
)
902 { if (cloog_domain_polyhedron (domain
) == NULL
)
905 if (cloog_domain_polyhedron_next (domain
))
908 return((cloog_domain_dim (domain
)
909 < cloog_domain_nbeq (domain
)) ? 1 : 0) ;
914 * cloog_domain_project function:
915 * From Quillere's LoopGen 0.4. This function returns the projection of
916 * (domain) on the (level) first dimensions (i.e. outer loops). It returns a
917 * pointer to the projected Polyhedron.
918 * - nb_par is the number of parameters.
920 * - October 27th 2001: first version.
921 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
924 CloogDomain
* cloog_domain_project(CloogDomain
* domain
, int level
, int nb_par
)
925 { int row
, column
, nb_rows
, nb_columns
, difference
;
926 CloogDomain
* projected_domain
;
927 CloogMatrix
* matrix
;
929 nb_rows
= level
+ nb_par
+ 1 ;
930 nb_columns
= cloog_domain_dim (domain
) + 1 ;
931 difference
= nb_columns
- nb_rows
;
934 return(cloog_domain_copy(domain
)) ;
936 matrix
= cloog_matrix_alloc(nb_rows
,nb_columns
) ;
938 for (row
=0;row
<level
;row
++)
939 for (column
=0;column
<nb_columns
; column
++)
940 cloog_matrix_element_set_si(matrix
, row
, column
, (row
== column
? 1 : 0)) ;
942 for (;row
<nb_rows
;row
++)
943 for (column
=0;column
<nb_columns
;column
++)
944 cloog_matrix_element_set_si (matrix
, row
, column
, (row
+difference
== column
? 1 : 0)) ;
946 projected_domain
= cloog_domain_image(domain
,matrix
) ;
947 cloog_matrix_free(matrix
) ;
949 return(projected_domain
) ;
953 * cloog_domain_extend function:
954 * From Quillere's LoopGen 0.4. This function returns the (domain) given as
955 * input with (dim)+(nb_par) dimensions. The new dimensions are added before
956 * the (nb_par) parameters. This function does not free (domain), and returns
958 * - nb_par is the number of parameters.
960 * - October 27th 2001: first version.
961 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
964 CloogDomain
* cloog_domain_extend(CloogDomain
* domain
, int dim
, int nb_par
)
965 { int row
, column
, nb_rows
, nb_columns
, difference
;
966 CloogDomain
* extended_domain
;
967 CloogMatrix
* matrix
;
969 nb_rows
= 1 + cloog_domain_dim (domain
) ;
970 nb_columns
= dim
+ nb_par
+ 1 ;
971 difference
= nb_columns
- nb_rows
;
974 return(cloog_domain_copy(domain
)) ;
976 matrix
= cloog_matrix_alloc(nb_rows
,nb_columns
) ;
978 for (row
=0;row
<cloog_domain_dim (domain
) - nb_par
;row
++)
979 for (column
=0;column
<nb_columns
;column
++)
980 cloog_matrix_element_set_si(matrix
, row
, column
, (row
== column
? 1 : 0)) ;
982 for (;row
<=cloog_domain_dim (domain
); row
++)
983 for (column
=0;column
<nb_columns
;column
++)
984 cloog_matrix_element_set_si(matrix
, row
, column
, (row
+difference
== column
? 1 : 0)) ;
986 extended_domain
= cloog_domain_preimage(domain
,matrix
) ;
987 cloog_matrix_free(matrix
) ;
989 return(extended_domain
) ;
994 * cloog_domain_never_integral function:
995 * For us, an equality like 3*i -4 = 0 is always false since 4%3 != 0. This
996 * function returns a boolean set to 1 if there is this kind of 'never true'
997 * constraint inside a polyhedron, 0 otherwise.
998 * - domain is the polyhedron to check,
1000 * - November 28th 2001: first version.
1001 * - June 26th 2003: for iterators, more 'never true' constraints are found
1002 * (compare cholesky2 and vivien with a previous version),
1003 * checking for the parameters created (compare using vivien).
1004 * - June 28th 2003: Previously in loop.c and called
1005 * cloog_loop_simplify_nevertrue, now here !
1006 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1008 * - October 14th 2005: Complete rewriting, not faster but code quite shorter.
1010 int cloog_domain_never_integral(CloogDomain
* domain
)
1011 { int i
, dimension
;
1013 Polyhedron
* polyhedron
;
1015 if ((domain
== NULL
) || (cloog_domain_polyhedron (domain
) == NULL
))
1019 value_init_c(modulo
) ;
1020 polyhedron
= cloog_domain_polyhedron (domain
) ;
1021 dimension
= cloog_domain_dim (domain
) + 2 ;
1023 /* For each constraint... */
1024 for (i
=0; i
<cloog_polyhedron_nbc (polyhedron
); i
++)
1025 { /* If we have an equality and the scalar part is not zero... */
1026 if (value_zero_p(cloog_polyhedron_cval (polyhedron
, i
, 0)) &&
1027 value_notzero_p(cloog_polyhedron_cval (polyhedron
, i
, dimension
-1)))
1028 { /* Then we check whether the scalar can be divided by the gcd of the
1029 * unknown vector (including iterators and parameters) or not. If not,
1030 * there is no integer point in the polyhedron and we return 1.
1032 cloog_polyhedron_c_gcd (polyhedron
, i
, 1, dimension
-2, &gcd
) ;
1033 value_modulus(modulo
,cloog_polyhedron_cval (polyhedron
, i
, dimension
- 1), gcd
) ;
1035 if (value_notzero_p(modulo
))
1036 { value_clear_c(gcd
) ;
1037 value_clear_c(modulo
) ;
1043 value_clear_c(gcd
) ;
1044 value_clear_c(modulo
) ;
1050 * cloog_domain_stride function:
1051 * This function finds the stride imposed to unknown with the column number
1052 * 'strided_level' in order to be integral. For instance, if we have a
1053 * constraint like -i - 2j + 2k = 0, and we consider k, then k can be integral
1054 * only if (i + 2j)%2 = 0. Then only if i%2 = 0. Then k imposes a stride 2 to
1055 * the unknown i. The function returns the imposed stride in a parameter field.
1056 * - domain is the set of constraint we have to consider,
1057 * - strided_level is the column number of the unknown for which a stride have
1059 * - looking_level is the column number of the unknown that impose a stride to
1060 * the first unknown.
1061 * - stride is the stride that is returned back as a function parameter.
1062 * - offset is the value of the constant c if the condition is of the shape
1063 * (i + c)%s = 0, s being the stride.
1065 * - June 28th 2003: first version.
1066 * - July 14th 2003: can now look for multiple striding constraints and returns
1067 * the GCD of the strides and the common offset.
1068 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1071 void cloog_domain_stride(domain
, strided_level
, nb_par
, stride
, offset
)
1072 CloogDomain
* domain
;
1073 int strided_level
, nb_par
;
1074 Value
* stride
, * offset
;
1076 Polyhedron
* polyhedron
;
1077 int n_col
, n_row
, rank
;
1082 polyhedron
= cloog_domain_polyhedron (domain
) ;
1083 dimension
= cloog_domain_dim (domain
);
1085 /* Look at all equalities involving strided_level and the inner
1086 * iterators. We can ignore the outer iterators and the parameters
1087 * here because the lower bound on strided_level is assumed to
1090 n_col
= (1+dimension
-nb_par
) - strided_level
;
1091 for (i
=0, n_row
=0; i
< cloog_polyhedron_nbeq (polyhedron
); i
++)
1092 if (First_Non_Zero(cloog_polyhedron_c (polyhedron
, i
) + strided_level
, n_col
) != -1)
1095 M
= cloog_matrix_alloc(n_row
+1, n_col
+1);
1096 for (i
=0, n_row
= 0; i
< cloog_polyhedron_nbeq (polyhedron
); i
++) {
1097 if (First_Non_Zero(cloog_polyhedron_c (polyhedron
, i
) + strided_level
, n_col
) == -1)
1099 Vector_Copy(cloog_polyhedron_c (polyhedron
, i
) + strided_level
, M
->p
[n_row
], n_col
);
1100 cloog_matrix_element_assign(M
, n_row
, n_col
, cloog_polyhedron_cval (polyhedron
, i
, 1 + dimension
));
1103 cloog_matrix_element_set_si(M
, n_row
, n_col
, 1);
1105 /* Then look at the general solution to the above equalities. */
1106 rank
= SolveDiophantine(M
, &U
, &V
);
1107 cloog_matrix_free(M
);
1110 /* There is no solution, so the body of this loop will
1111 * never execute. We just leave the constraints alone here so
1112 * that they will ensure the body will not be executed.
1113 * We should probably propagate this information up so that
1114 * the loop can be removed entirely.
1116 value_set_si(*offset
, 0);
1117 value_set_si(*stride
, 1);
1119 /* Compute the gcd of the coefficients defining strided_level. */
1120 Vector_Gcd(U
->p
[0], U
->NbColumns
, stride
);
1121 value_oppose(*offset
, V
->p
[0]);
1122 value_pmodulus(*offset
, *offset
, *stride
);
1132 * cloog_domain_integral_lowerbound function:
1133 * This function returns 1 if the lower bound of an iterator (such as its
1134 * column rank in the constraint set 'domain' is 'level') is integral,
1135 * 0 otherwise. If the lower bound is actually integral, the function fills
1136 * the 'lower' field with the lower bound value.
1137 * - June 29th 2003: first version.
1138 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1141 int cloog_domain_integral_lowerbound(domain
, level
, lower
)
1142 CloogDomain
* domain
;
1145 { int i
, first_lower
=1, dimension
, lower_constraint
=-1 ;
1146 Value iterator
, constant
, tmp
;
1147 Polyhedron
* polyhedron
;
1149 polyhedron
= cloog_domain_polyhedron (domain
) ;
1150 dimension
= cloog_domain_dim (domain
);
1152 /* We want one and only one lower bound (e.g. no equality, no maximum
1155 for (i
=0; i
<cloog_polyhedron_nbc (polyhedron
); i
++)
1156 if (value_zero_p(cloog_polyhedron_cval (polyhedron
, i
, 0))
1157 && value_notzero_p(cloog_polyhedron_cval (polyhedron
, i
, level
)))
1160 for (i
=0; i
<cloog_polyhedron_nbc (polyhedron
); i
++)
1161 if (value_pos_p (cloog_polyhedron_cval (polyhedron
, i
, level
)))
1166 lower_constraint
= i
;
1175 /* We want an integral lower bound: no other non-zero entry except the
1176 * iterator coefficient and the constant.
1178 for (i
=1; i
<level
; i
++)
1179 if (value_notzero_p(cloog_polyhedron_cval (polyhedron
, lower_constraint
, i
)))
1182 for (i
=level
+1; i
<= cloog_polyhedron_dim (polyhedron
); i
++)
1183 if (value_notzero_p(cloog_polyhedron_cval (polyhedron
, lower_constraint
, i
)))
1186 value_init_c(iterator
) ;
1187 value_init_c(constant
) ;
1190 /* If all is passed, then find the lower bound and return 1. */
1191 value_assign(iterator
, cloog_polyhedron_cval (polyhedron
, lower_constraint
, level
)) ;
1192 value_oppose(constant
, cloog_polyhedron_cval (polyhedron
, lower_constraint
, dimension
+ 1));
1194 value_modulus(tmp
, constant
, iterator
) ;
1195 value_division(*lower
, constant
, iterator
) ;
1197 if (!(value_zero_p(tmp
) || value_neg_p(constant
)))
1198 value_increment(*lower
, *lower
) ;
1200 value_clear_c(iterator
) ;
1201 value_clear_c(constant
) ;
1202 value_clear_c(tmp
) ;
1209 * cloog_domain_lowerbound_update function:
1210 * This function updates the integral lower bound of an iterator (such as its
1211 * column rank in the constraint set 'domain' is 'level') into 'lower'.
1212 * - Jun 29th 2003: first version.
1213 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1216 void cloog_domain_lowerbound_update(domain
, level
, lower
)
1217 CloogDomain
* domain
;
1221 Polyhedron
* polyhedron
;
1223 polyhedron
= cloog_domain_polyhedron (domain
) ;
1225 /* There is only one lower bound, the first one is the good one. */
1226 for (i
=0; i
<cloog_polyhedron_nbc (polyhedron
); i
++)
1227 if (value_pos_p(cloog_polyhedron_cval (polyhedron
, i
, level
)))
1229 cloog_polyhedron_cval_set_si (polyhedron
, i
, level
, 1) ;
1230 cloog_polyhedron_cval_oppose (polyhedron
, i
, cloog_polyhedron_dim (polyhedron
) + 1, lower
) ;
1237 * cloog_domain_lazy_equal function:
1238 * This function returns 1 if the domains given as input are the same, 0 if it
1239 * is unable to decide. This function makes an entry-to-entry comparison between
1240 * the constraint systems, if all the entries are the same, the domains are
1241 * obviously the same and it returns 1, at the first difference, it returns 0.
1242 * This is a very fast way to verify this property. It has been shown (with the
1243 * CLooG benchmarks) that operations on equal domains are 17% of all the
1244 * polyhedral computations. For 75% of the actually identical domains, this
1245 * function answer that they are the same and allow to give immediately the
1246 * trivial solution instead of calling the heavy general functions of PolyLib.
1247 * - August 22th 2003: first version.
1248 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1251 int cloog_domain_lazy_equal(CloogDomain
* d1
, CloogDomain
* d2
)
1252 { int i
, nb_elements
;
1253 Polyhedron
* p1
, * p2
;
1255 p1
= cloog_domain_polyhedron (d1
) ;
1256 p2
= cloog_domain_polyhedron (d2
) ;
1258 while ((p1
!= NULL
) && (p2
!= NULL
))
1259 { if ((cloog_polyhedron_nbc (p1
) != cloog_polyhedron_nbc (p2
)) ||
1260 (cloog_polyhedron_dim (p1
) != cloog_polyhedron_dim (p2
)))
1263 nb_elements
= cloog_polyhedron_nbc (p1
) * (cloog_polyhedron_dim (p1
) + 2) ;
1265 for (i
=0;i
<nb_elements
;i
++)
1266 if (value_ne(p1
->p_Init
[i
], p2
->p_Init
[i
]))
1269 p1
= cloog_polyhedron_next (p1
) ;
1270 p2
= cloog_polyhedron_next (p2
) ;
1273 if ((p1
!= NULL
) || (p2
!= NULL
))
1281 * cloog_domain_lazy_block function:
1282 * This function returns 1 if the two domains d1 and d2 given as input are the
1283 * same (possibly except for a dimension equal to a constant where we accept
1284 * a difference of 1) AND if we are sure that there are no other domain in
1285 * the code generation problem that may put integral points between those of
1286 * d1 and d2 (0 otherwise). In fact this function answers the question "can I
1287 * safely consider the two domains as only one with two statements (a block) ?".
1288 * This function is lazy: it asks for very standard scattering representation
1289 * (only one constraint per dimension which is an equality, and the constraints
1290 * are ordered per dimension depth: the left hand side of the constraint matrix
1291 * is the identity) and will answer NO at the very first problem.
1292 * - d1 and d2 are the two domains to check for blocking,
1293 * - scattering is the linked list of all domains,
1294 * - scattdims is the total number of scattering dimentions.
1296 * - April 30th 2005: beginning
1297 * - June 9th 2005: first working version.
1298 * - June 10th 2005: debugging.
1299 * - June 21rd 2005: Adaptation for GMP.
1300 * - October 16th 2005: (debug) some false blocks have been removed.
1302 int cloog_domain_lazy_block(d1
, d2
, scattering
, scattdims
)
1303 CloogDomain
* d1
, * d2
;
1304 CloogDomainList
* scattering
;
1306 { int i
, j
, difference
=0, different_constraint
=0 ;
1307 Value date1
, date2
, date3
, temp
;
1308 Polyhedron
* p1
, * p2
, * p3
;
1310 p1
= cloog_domain_polyhedron (d1
) ;
1311 p2
= cloog_domain_polyhedron (d2
) ;
1313 /* Some basic checks: we only accept convex domains, with same constraint
1314 * and dimension numbers.
1316 if (cloog_polyhedron_next (p1
) || cloog_polyhedron_next (p2
) ||
1317 (cloog_polyhedron_nbc (p1
) != cloog_polyhedron_nbc (p2
)) ||
1318 (cloog_polyhedron_dim (p1
) != cloog_polyhedron_dim (p2
)))
1321 /* There should be only one difference between the two domains, it
1322 * has to be at the constant level and the difference must be of +1,
1323 * moreover, after the difference all domain coefficient has to be 0.
1324 * The matrix shape is:
1326 * |===========|=====|<- 0 line
1327 * |===========|=====|
1328 * |===========|====?|<- different_constraint line (found here)
1329 * |===========|0000=|
1330 * |===========|0000=|<- pX->NbConstraints line
1333 * | | (pX->Dimension + 2) column
1334 * | scattdims column
1338 value_init_c(temp
) ;
1339 for (i
=0;i
<cloog_polyhedron_nbc (p1
);i
++)
1340 { if (difference
== 0)
1341 { /* All elements except scalar must be equal. */
1342 for (j
=0; j
< (cloog_polyhedron_dim (p1
) + 1); j
++)
1343 if (value_ne(cloog_polyhedron_cval (p1
, i
, j
),
1344 cloog_polyhedron_cval (p2
, i
, j
)))
1346 value_clear_c(temp
) ;
1349 /* The scalar may differ from +1 (now j=(p1->Dimension + 1)). */
1350 if (value_ne(cloog_polyhedron_cval (p1
, i
, j
),
1351 cloog_polyhedron_cval (p2
, i
, j
)))
1353 value_increment(temp
, cloog_polyhedron_cval (p2
, i
, j
)) ;
1354 if (value_ne (cloog_polyhedron_cval (p1
, i
, j
), temp
))
1356 value_clear_c(temp
) ;
1362 different_constraint
= i
;
1367 { /* Scattering coefficients must be equal. */
1368 for (j
=0;j
<(scattdims
+1);j
++)
1369 if (value_ne(cloog_polyhedron_cval (p1
, i
, j
),
1370 cloog_polyhedron_cval (p2
, i
, j
)))
1372 value_clear_c(temp
) ;
1376 /* Domain coefficients must be 0. */
1377 for (; j
< (cloog_polyhedron_dim (p1
) + 1);j
++)
1378 if (value_notzero_p (cloog_polyhedron_cval (p1
, i
, j
))
1379 || value_notzero_p (cloog_polyhedron_cval (p2
, i
, j
)))
1381 value_clear_c(temp
) ;
1385 /* Scalar must be equal. */
1386 if (value_ne(cloog_polyhedron_cval (p1
, i
, j
),
1387 cloog_polyhedron_cval (p2
, i
, j
)))
1389 value_clear_c(temp
) ;
1394 value_clear_c(temp
) ;
1396 /* If the domains are exactly the same, this is a block. */
1397 if (difference
== 0)
1400 /* Now a basic check that the constraint with the difference is an
1401 * equality of a dimension with a constant.
1403 for (i
=0;i
<=different_constraint
;i
++)
1404 if (value_notzero_p(cloog_polyhedron_cval (p1
, different_constraint
, i
)))
1407 if (value_notone_p(cloog_polyhedron_cval (p1
, different_constraint
,
1408 different_constraint
+ 1)))
1411 for (i
=different_constraint
+2;i
<(cloog_polyhedron_dim (p1
) + 1);i
++)
1412 if (value_notzero_p(cloog_polyhedron_cval (p1
, different_constraint
, i
)))
1415 /* For the moment, d1 and d2 are a block candidate. There remains to check
1416 * that there is no other domain that may put an integral point between
1417 * them. In our lazy test we ensure this property by verifying that the
1418 * constraint matrices have a very strict shape: let us consider that the
1419 * dimension with the difference is d. Then the first d dimensions are
1420 * defined in their depth order using equalities (thus the first column begins
1421 * with d zeroes, there is a d*d identity matrix and a zero-matrix for
1422 * the remaining simensions). If a domain can put integral points between the
1423 * domains of the block candidate, this means that the other entries on the
1424 * first d constraints are equal to those of d1 or d2. Thus we are looking for
1425 * such a constraint system, if it exists d1 and d2 is considered to not be
1426 * a block, it is a bock otherwise.
1428 * 1. Only equalities (for the first different_constraint+1 lines).
1429 * | 2. Must be the identity.
1430 * | | 3. Must be zero.
1431 * | | | 4. Elements are equal, the last one is either date1 or 2.
1434 * |0|100|00000|=====|<- 0 line
1435 * |0|010|00000|=====|
1436 * |0|001|00000|====?|<- different_constraint line
1437 * |*|***|*****|*****|
1438 * |*|***|*****|*****|<- pX->NbConstraints line
1441 * | | | (pX->Dimension + 2) column
1442 * | | scattdims column
1443 * | different_constraint+1 column
1447 /* Step 1 and 2. This is only necessary to check one domain because
1448 * we checked that they are equal on this part before.
1450 for (i
=0;i
<=different_constraint
;i
++)
1451 { for (j
=0;j
<i
+1;j
++)
1452 if (value_notzero_p (cloog_polyhedron_cval (p1
, i
, j
)))
1455 if (value_notone_p(cloog_polyhedron_cval (p1
, i
, i
+1)))
1458 for (j
=i
+2;j
<=different_constraint
+1;j
++)
1459 if (value_notzero_p(cloog_polyhedron_cval (p1
, i
, j
)))
1464 for (i
=0;i
<=different_constraint
;i
++)
1465 for (j
=different_constraint
+2;j
<=scattdims
;j
++)
1466 if (value_notzero_p(cloog_polyhedron_cval (p1
, i
, j
)))
1469 value_init_c(date1
) ;
1470 value_init_c(date2
) ;
1471 value_init_c(date3
) ;
1473 /* Now we have to check that the two different dates are unique. */
1474 value_assign (date1
, cloog_polyhedron_cval (p1
, different_constraint
,
1475 cloog_polyhedron_dim (p1
) + 1)) ;
1476 value_assign (date2
, cloog_polyhedron_cval (p2
, different_constraint
,
1477 cloog_polyhedron_dim (p2
) + 1)) ;
1479 /* Step 4. We check all domains except d1 and d2 and we look for at least
1480 * a difference with d1 or d2 on the first different_constraint+1 dimensions.
1482 while (scattering
!= NULL
)
1484 if ((cloog_domain (scattering
) != d1
) && (cloog_domain (scattering
) != d2
))
1486 p3
= cloog_domain_polyhedron (cloog_domain (scattering
)) ;
1487 value_assign (date3
, cloog_polyhedron_cval (p3
, different_constraint
,
1488 cloog_polyhedron_dim (p3
) + 1));
1491 if (value_ne(date3
,date2
) && value_ne(date3
,date1
))
1494 for (i
=0;(i
<different_constraint
)&&(!difference
);i
++)
1495 for (j
=0;(j
<(cloog_polyhedron_dim (p3
) + 2))&&(!difference
);j
++)
1496 if (value_ne (cloog_polyhedron_cval (p1
, i
, j
),
1497 cloog_polyhedron_cval (p3
, i
, j
)))
1500 for (j
=0;(j
<(cloog_polyhedron_dim (p3
) + 1))&&(!difference
);j
++)
1501 if (value_ne (cloog_polyhedron_cval (p1
, different_constraint
, j
),
1502 cloog_polyhedron_cval (p3
, different_constraint
, j
)))
1507 value_clear_c(date1
) ;
1508 value_clear_c(date2
) ;
1509 value_clear_c(date3
) ;
1514 scattering
= cloog_next_domain (scattering
);
1517 value_clear_c(date1
) ;
1518 value_clear_c(date2
) ;
1519 value_clear_c(date3
) ;
1525 * cloog_domain_lazy_disjoint function:
1526 * This function returns 1 if the domains given as input are disjoint, 0 if it
1527 * is unable to decide. This function finds the unknown with fixed values in
1528 * both domains (on a given constraint, their column entry is not zero and
1529 * only the constant coefficient can be different from zero) and verify that
1530 * their values are the same. If not, the domains are obviously disjoint and
1531 * it returns 1, if there is not such case it returns 0. This is a very fast
1532 * way to verify this property. It has been shown (with the CLooG benchmarks)
1533 * that operations on disjoint domains are 36% of all the polyhedral
1534 * computations. For 94% of the actually identical domains, this
1535 * function answer that they are disjoint and allow to give immediately the
1536 * trivial solution instead of calling the heavy general functions of PolyLib.
1537 * - August 22th 2003: first version.
1538 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1541 int cloog_domain_lazy_disjoint(CloogDomain
* d1
, CloogDomain
* d2
)
1543 int i1
, j1
, i2
, j2
, scat_dim
;
1545 Polyhedron
* p1
, * p2
;
1547 p1
= cloog_domain_polyhedron (d1
) ;
1548 p2
= cloog_domain_polyhedron (d2
) ;
1550 if (cloog_polyhedron_next (p1
) || cloog_polyhedron_next (p2
))
1553 value_init_c(scat_val
) ;
1555 for (i1
=0; i1
<cloog_polyhedron_nbc (p1
); i1
++)
1557 if (value_notzero_p (cloog_polyhedron_cval (p1
, i1
, 0)))
1561 while (value_zero_p(cloog_polyhedron_cval (p1
, i1
, scat_dim
)) &&
1562 (scat_dim
< cloog_polyhedron_dim (p1
)))
1565 if (value_notone_p(cloog_polyhedron_cval (p1
, i1
, scat_dim
)))
1569 for (j1
=scat_dim
+1; j1
<=cloog_polyhedron_dim (p1
); j1
++)
1570 if (value_notzero_p(cloog_polyhedron_cval (p1
, i1
, j1
)))
1573 if (j1
!= cloog_polyhedron_dim (p1
)+1)
1576 value_assign (scat_val
, cloog_polyhedron_cval (p1
, i1
, cloog_polyhedron_dim (p1
) + 1)) ;
1578 for (i2
=0; i2
<cloog_polyhedron_nbc (p2
); i2
++)
1580 for (j2
=0;j2
<scat_dim
;j2
++)
1581 if (value_notzero_p (cloog_polyhedron_cval (p2
, i2
, j2
)))
1584 if ((j2
!= scat_dim
)
1585 || value_notone_p(cloog_polyhedron_cval (p2
, i2
, scat_dim
)))
1588 for (j2
=scat_dim
+1; j2
< cloog_polyhedron_dim (p2
); j2
++)
1589 if (value_notzero_p(cloog_polyhedron_cval (p2
, i2
, j2
)))
1592 if (j2
!= cloog_polyhedron_dim (p2
))
1595 if (value_ne(cloog_polyhedron_cval (p2
, i2
, cloog_polyhedron_dim (p2
) + 1), scat_val
))
1597 value_clear_c(scat_val
) ;
1604 value_clear_c(scat_val
) ;
1610 * cloog_domain_list_lazy_same function:
1611 * This function returns 1 if two domains in the list are the same, 0 if it
1612 * is unable to decide.
1613 * - February 9th 2004: first version.
1615 int cloog_domain_list_lazy_same(CloogDomainList
* list
)
1616 { /*int i=1, j=1 ;*/
1617 CloogDomainList
* current
, * next
;
1620 while (current
!= NULL
)
1622 next
= cloog_next_domain (current
);
1624 while (next
!= NULL
)
1626 if (cloog_domain_lazy_equal (cloog_domain (current
),
1627 cloog_domain (next
)))
1628 { /*printf("Same domains: %d and %d\n",i,j) ;*/
1632 next
= cloog_next_domain (next
) ;
1635 current
= cloog_next_domain (current
) ;
1642 * cloog_domain_cut_first function:
1643 * this function returns a CloogDomain structure with everything except the
1644 * first part of the polyhedra union of the input domain as domain. After a call
1645 * to this function, there remains in the CloogDomain structure provided as
1646 * input only the first part of the original polyhedra union.
1647 * - April 20th 2005: first version, extracted from different part of loop.c.
1649 CloogDomain
* cloog_domain_cut_first(CloogDomain
* domain
)
1650 { CloogDomain
* rest
;
1652 if ((domain
!= NULL
) && (cloog_domain_polyhedron (domain
) != NULL
))
1653 { rest
= cloog_domain_alloc(cloog_domain_polyhedron_next (domain
)) ;
1654 cloog_domain_polyhedron_set_next (domain
, NULL
) ;
1664 * cloog_domain_lazy_isscalar function:
1665 * this function returns 1 if the dimension 'dimension' in the domain 'domain'
1666 * is scalar, this means that the only constraint on this dimension must have
1667 * the shape "x.dimension + scalar = 0" with x an integral variable. This
1668 * function is lazy since we only accept x=1 (further calculations are easier
1670 * - June 14th 2005: first version.
1671 * - June 21rd 2005: Adaptation for GMP.
1673 int cloog_domain_lazy_isscalar(CloogDomain
* domain
, int dimension
)
1675 Polyhedron
* polyhedron
;
1677 polyhedron
= cloog_domain_polyhedron (domain
) ;
1678 /* For each constraint... */
1679 for (i
=0;i
<cloog_polyhedron_nbc (polyhedron
);i
++)
1680 { /* ...if it is concerned by the potentially scalar dimension... */
1681 if (value_notzero_p (cloog_polyhedron_cval (polyhedron
, i
, dimension
+1)))
1682 { /* ...check that the constraint has the shape "dimension + scalar = 0". */
1683 for (j
=0;j
<=dimension
;j
++)
1684 if (value_notzero_p(cloog_polyhedron_cval (polyhedron
, i
, j
)))
1687 if (value_notone_p(cloog_polyhedron_cval (polyhedron
, i
, dimension
+ 1)))
1690 for (j
=dimension
+2;j
<(cloog_polyhedron_dim (polyhedron
) + 1);j
++)
1691 if (value_notzero_p(cloog_polyhedron_cval (polyhedron
, i
, j
)))
1701 * cloog_domain_scalar function:
1702 * when we call this function, we know that "dimension" is a scalar dimension,
1703 * this function finds the scalar value in "domain" and returns it in "value".
1704 * - June 30th 2005: first version.
1706 void cloog_domain_scalar(CloogDomain
* domain
, int dimension
, Value
* value
)
1708 Polyhedron
* polyhedron
;
1710 polyhedron
= cloog_domain_polyhedron (domain
) ;
1711 /* For each constraint... */
1712 for (i
=0;i
<cloog_polyhedron_nbc (polyhedron
);i
++)
1713 { /* ...if it is the equality defining the scalar dimension... */
1714 if (value_notzero_p(cloog_polyhedron_cval (polyhedron
, i
, dimension
+1)) &&
1715 value_zero_p(cloog_polyhedron_cval (polyhedron
, i
, 0)))
1716 { /* ...Then send the scalar value. */
1717 value_assign(*value
,cloog_polyhedron_cval (polyhedron
, i
,
1718 cloog_polyhedron_dim (polyhedron
) + 1)) ;
1719 value_oppose(*value
,*value
) ;
1724 /* We should have found a scalar value: if not, there is an error. */
1725 fprintf(stderr
, "[CLooG]ERROR: dimension %d is not scalar as expected.\n",
1732 * cloog_domain_erase_dimension function:
1733 * this function returns a CloogDomain structure builds from 'domain' where
1734 * we removed the dimension 'dimension' and every constraint considering this
1735 * dimension. This is not a projection ! Every data concerning the
1736 * considered dimension is simply erased.
1737 * - June 14th 2005: first version.
1738 * - June 21rd 2005: Adaptation for GMP.
1740 CloogDomain
* cloog_domain_erase_dimension(CloogDomain
* domain
, int dimension
)
1741 { int i
, j
, mi
, nb_dim
;
1742 CloogMatrix
* matrix
;
1743 CloogDomain
* erased
;
1744 Polyhedron
* polyhedron
;
1746 polyhedron
= cloog_domain_polyhedron (domain
) ;
1747 nb_dim
= cloog_domain_dim (domain
);
1749 /* The matrix is one column less and at least one constraint less. */
1750 matrix
= cloog_matrix_alloc(cloog_polyhedron_nbc (polyhedron
)-1,nb_dim
+1) ;
1752 /* mi is the constraint counter for the matrix. */
1754 for (i
=0;i
<cloog_polyhedron_nbc (polyhedron
);i
++)
1755 if (value_zero_p(cloog_polyhedron_cval (polyhedron
, i
, dimension
+1)))
1756 { for (j
=0;j
<=dimension
;j
++)
1757 cloog_matrix_element_assign(matrix
, mi
, j
, cloog_polyhedron_cval (polyhedron
, i
, j
)) ;
1759 for (j
=dimension
+2;j
<nb_dim
+2;j
++)
1760 cloog_matrix_element_assign(matrix
, mi
, j
-1, cloog_polyhedron_cval (polyhedron
, i
, j
)) ;
1765 erased
= cloog_domain_matrix2domain(matrix
) ;
1766 cloog_matrix_free(matrix
) ;
1772 cloog_simplify_domain_matrix_with_equalities (CloogDomain
*domain
, int level
,
1773 CloogMatrix
*equal
, int nb_parameters
)
1775 CloogMatrix
*temp
, *res
;
1777 temp
= cloog_domain_domain2matrix (domain
);
1778 cloog_matrix_normalize (temp
, level
);
1779 res
= cloog_matrix_simplify (temp
, equal
, level
, nb_parameters
);
1780 cloog_matrix_free(temp
);