6 #include <cloog/isl/cloog.h>
8 #include <isl/constraint.h>
14 #include <isl/val_gmp.h>
17 #include <osl/macros.h>
18 #include <osl/relation.h>
21 CloogDomain
*cloog_domain_from_isl_set(__isl_take isl_set
*set
)
23 if (isl_set_is_params(set
))
24 set
= isl_set_from_params(set
);
25 set
= isl_set_detect_equalities(set
);
26 set
= isl_set_compute_divs(set
);
27 return (CloogDomain
*)set
;
30 __isl_give isl_set
*isl_set_from_cloog_domain(CloogDomain
*domain
)
32 return (isl_set
*)domain
;
35 CloogScattering
*cloog_scattering_from_isl_map(__isl_take isl_map
*map
)
37 return (CloogScattering
*)map
;
40 __isl_give isl_map
*isl_map_from_cloog_scattering(CloogScattering
*scattering
)
42 return (isl_map
*)scattering
;
47 * Returns true if each scattering dimension is defined in terms
48 * of the original iterators.
50 int cloog_scattering_fully_specified(CloogScattering
*scattering
,
53 isl_map
*map
= isl_map_from_cloog_scattering(scattering
);
54 return isl_map_is_single_valued(map
);
58 CloogConstraintSet
*cloog_domain_constraints(CloogDomain
*domain
)
61 isl_set
*set
= isl_set_from_cloog_domain(domain
);
62 assert(isl_set_n_basic_set(set
) == 1);
63 bset
= isl_set_copy_basic_set(set
);
64 return cloog_constraint_set_from_isl_basic_set(bset
);
68 void cloog_domain_print_constraints(FILE *foo
, CloogDomain
*domain
,
73 isl_set
*set
= isl_set_from_cloog_domain(domain
);
75 p
= isl_printer_to_file(isl_set_get_ctx(set
), foo
);
77 p
= isl_printer_set_output_format(p
, ISL_FORMAT_EXT_POLYLIB
);
78 p
= isl_printer_print_set(p
, set
);
80 assert(isl_set_n_basic_set(set
) == 1);
81 bset
= isl_set_copy_basic_set(set
);
82 p
= isl_printer_set_output_format(p
, ISL_FORMAT_POLYLIB
);
83 p
= isl_printer_print_basic_set(p
, bset
);
84 isl_basic_set_free(bset
);
90 void cloog_scattering_print_constraints(FILE *foo
, CloogScattering
*scattering
)
92 isl_map
*map
= isl_map_from_cloog_scattering(scattering
);
95 p
= isl_printer_to_file(isl_map_get_ctx(map
), foo
);
96 p
= isl_printer_set_output_format(p
, ISL_FORMAT_EXT_POLYLIB
);
97 p
= isl_printer_print_map(p
, map
);
102 void cloog_domain_free(CloogDomain
* domain
)
104 isl_set
*set
= isl_set_from_cloog_domain(domain
);
109 void cloog_scattering_free(CloogScattering
*scatt
)
111 isl_map
*map
= isl_map_from_cloog_scattering(scatt
);
116 CloogDomain
* cloog_domain_copy(CloogDomain
* domain
)
118 isl_set
*set
= isl_set_from_cloog_domain(domain
);
119 return cloog_domain_from_isl_set(isl_set_copy(set
));
124 * cloog_domain_convex function:
125 * Computes the convex hull of domain.
127 CloogDomain
*cloog_domain_convex(CloogDomain
*domain
)
129 isl_set
*set
= isl_set_from_cloog_domain(domain
);
130 set
= isl_set_from_basic_set(isl_set_convex_hull(isl_set_copy(set
)));
131 return cloog_domain_from_isl_set(set
);
136 * cloog_domain_simple_convex:
137 * Given a list (union) of polyhedra, this function returns a "simple"
138 * convex hull of this union. In particular, the constraints of the
139 * the returned polyhedron consist of (parametric) lower and upper
140 * bounds on individual variables and constraints that appear in the
141 * original polyhedra.
143 CloogDomain
*cloog_domain_simple_convex(CloogDomain
*domain
)
145 struct isl_basic_set
*hull
;
146 isl_set
*set
= isl_set_from_cloog_domain(domain
);
148 if (cloog_domain_isconvex(domain
))
149 return cloog_domain_copy(domain
);
151 hull
= isl_set_bounded_simple_hull(isl_set_copy(set
));
152 return cloog_domain_from_isl_set(isl_set_from_basic_set(hull
));
157 * cloog_domain_simplify function:
158 * Given two polyhedral domains (dom1) and (dom2),
159 * this function finds the largest domain set (or the smallest list
160 * of non-redundant constraints), that when intersected with polyhedral
161 * domain (dom2) equals (dom1)intersect(dom2). The output is a new CloogDomain
162 * structure with a polyhedral domain with the "redundant" constraints removed.
163 * NB: the second domain is required not to be a union.
165 CloogDomain
*cloog_domain_simplify(CloogDomain
*dom1
, CloogDomain
*dom2
)
167 isl_set
*set1
= isl_set_from_cloog_domain(dom1
);
168 isl_set
*set2
= isl_set_from_cloog_domain(dom2
);
169 set1
= isl_set_gist(isl_set_copy(set1
), isl_set_copy(set2
));
170 return cloog_domain_from_isl_set(set1
);
175 * cloog_domain_union function:
176 * This function returns a new polyhedral domain which is the union of
177 * two polyhedral domains (dom1) U (dom2).
178 * Frees dom1 and dom2;
180 CloogDomain
*cloog_domain_union(CloogDomain
*dom1
, CloogDomain
*dom2
)
182 isl_set
*set1
= isl_set_from_cloog_domain(dom1
);
183 isl_set
*set2
= isl_set_from_cloog_domain(dom2
);
184 set1
= isl_set_union(set1
, set2
);
185 return cloog_domain_from_isl_set(set1
);
191 * cloog_domain_intersection function:
192 * This function returns a new polyhedral domain which is the intersection of
193 * two polyhedral domains (dom1) \cap (dom2).
195 CloogDomain
*cloog_domain_intersection(CloogDomain
*dom1
, CloogDomain
*dom2
)
197 isl_set
*set1
= isl_set_from_cloog_domain(dom1
);
198 isl_set
*set2
= isl_set_from_cloog_domain(dom2
);
199 set1
= isl_set_intersect(isl_set_copy(set1
), isl_set_copy(set2
));
200 return cloog_domain_from_isl_set(set1
);
205 * cloog_domain_difference function:
206 * Returns the set difference domain \ minus.
208 CloogDomain
*cloog_domain_difference(CloogDomain
*domain
, CloogDomain
*minus
)
210 isl_set
*set1
= isl_set_from_cloog_domain(domain
);
211 isl_set
*set2
= isl_set_from_cloog_domain(minus
);
212 set1
= isl_set_subtract(isl_set_copy(set1
), isl_set_copy(set2
));
213 return cloog_domain_from_isl_set(set1
);
218 * cloog_domain_sort function:
219 * This function topologically sorts (nb_doms) domains. Here (doms) is an
220 * array of pointers to CloogDomains, (nb_doms) is the number of domains,
221 * (level) is the level to consider for partial ordering (nb_par) is the
222 * parameter space dimension, (permut) if not NULL, is an array of (nb_doms)
223 * integers that contains a permutation specification after call in order to
224 * apply the topological sorting.
226 void cloog_domain_sort(CloogDomain
**doms
, unsigned nb_doms
, unsigned level
,
231 unsigned char **follows
;
232 isl_set
*set_i
, *set_j
;
233 isl_basic_set
*bset_i
, *bset_j
;
237 set_i
= isl_set_from_cloog_domain(doms
[0]);
238 ctx
= isl_set_get_ctx(set_i
);
239 for (i
= 0; i
< nb_doms
; i
++) {
240 set_i
= isl_set_from_cloog_domain(doms
[i
]);
241 assert(isl_set_n_basic_set(set_i
) == 1);
244 follows
= isl_alloc_array(ctx
, unsigned char *, nb_doms
);
246 for (i
= 0; i
< nb_doms
; ++i
) {
247 follows
[i
] = isl_alloc_array(ctx
, unsigned char, nb_doms
);
249 for (j
= 0; j
< nb_doms
; ++j
)
253 for (i
= 1; i
< nb_doms
; ++i
) {
254 for (j
= 0; j
< i
; ++j
) {
255 if (follows
[i
][j
] || follows
[j
][i
])
257 set_i
= isl_set_from_cloog_domain(doms
[i
]);
258 set_j
= isl_set_from_cloog_domain(doms
[j
]);
259 bset_i
= isl_set_copy_basic_set(set_i
);
260 bset_j
= isl_set_copy_basic_set(set_j
);
261 cmp
= isl_basic_set_compare_at(bset_i
, bset_j
, level
-1);
262 isl_basic_set_free(bset_i
);
263 isl_basic_set_free(bset_j
);
268 for (k
= 0; k
< i
; ++k
)
269 follows
[i
][k
] |= follows
[j
][k
];
272 for (k
= 0; k
< i
; ++k
)
273 follows
[k
][i
] |= follows
[k
][j
];
278 for (i
= 0, j
= 0; i
< nb_doms
; j
= (j
+ 1) % nb_doms
) {
279 for (k
= 0; k
< nb_doms
; ++k
)
284 for (k
= 0; k
< nb_doms
; ++k
)
291 for (i
= 0; i
< nb_doms
; ++i
)
298 * Check whether there is or may be any value of dom1 at the given level
299 * that is greater than or equal to a value of dom2 at the same level.
302 * 1 is there is or may be a greater-than pair.
303 * 0 if there is no greater-than pair, but there may be an equal-to pair
304 * -1 if there is definitely no such pair
306 int cloog_domain_follows(CloogDomain
*dom1
, CloogDomain
*dom2
, unsigned level
)
308 isl_set
*set1
= isl_set_from_cloog_domain(dom1
);
309 isl_set
*set2
= isl_set_from_cloog_domain(dom2
);
312 follows
= isl_set_follows_at(set1
, set2
, level
- 1);
313 assert(follows
>= -1);
320 * cloog_domain_empty function:
321 * Returns an empty domain of the same dimensions as template.
323 CloogDomain
*cloog_domain_empty(CloogDomain
*template)
325 isl_set
*set
= isl_set_from_cloog_domain(template);
326 isl_space
*space
= isl_set_get_space(set
);
327 return cloog_domain_from_isl_set(isl_set_empty(space
));
332 * Return 1 if the specified dimension has both an upper and a lower bound.
334 int cloog_domain_is_bounded(CloogDomain
*dom
, unsigned level
)
336 isl_set
*set
= isl_set_from_cloog_domain(dom
);
337 return isl_set_dim_is_bounded(set
, isl_dim_set
, level
- 1);
341 /******************************************************************************
342 * Structure display function *
343 ******************************************************************************/
347 * cloog_domain_print_structure :
348 * this function is a more human-friendly way to display the CloogDomain data
349 * structure, it only shows the constraint system and includes an indentation
350 * level (level) in order to work with others print_structure functions.
352 void cloog_domain_print_structure(FILE *file
, CloogDomain
*domain
, int level
,
356 isl_set
*set
= isl_set_from_cloog_domain(domain
);
359 /* Go to the right level. */
360 for (i
= 0; i
< level
; i
++)
361 fprintf(file
, "|\t");
364 fprintf(file
, "+-- Null CloogDomain\n");
367 fprintf(file
, "+-- %s\n", name
);
368 for (i
= 0; i
< level
+1; ++i
)
369 fprintf(file
, "|\t");
371 p
= isl_printer_to_file(isl_set_get_ctx(set
), file
);
372 p
= isl_printer_print_set(p
, set
);
379 /******************************************************************************
380 * Memory deallocation function *
381 ******************************************************************************/
384 void cloog_domain_list_free(CloogDomainList
*list
)
386 CloogDomainList
*next
;
388 for ( ; list
; list
= next
) {
390 cloog_domain_free(list
->domain
);
397 * cloog_scattering_list_free function:
398 * This function frees the allocated memory for a CloogScatteringList structure.
400 void cloog_scattering_list_free(CloogScatteringList
*list
)
402 while (list
!= NULL
) {
403 CloogScatteringList
*temp
= list
->next
;
404 isl_map
*map
= isl_map_from_cloog_scattering(list
->scatt
);
412 /******************************************************************************
414 ******************************************************************************/
418 * cloog_domain_read_context function:
419 * Read parameter domain.
421 CloogDomain
*cloog_domain_read_context(CloogState
*state
, FILE *input
)
423 struct isl_ctx
*ctx
= state
->backend
->ctx
;
426 set
= isl_set_read_from_file(ctx
, input
);
427 set
= isl_set_move_dims(set
, isl_dim_param
, 0,
428 isl_dim_set
, 0, isl_set_dim(set
, isl_dim_set
));
430 return cloog_domain_from_isl_set(set
);
435 * cloog_domain_from_context
436 * Reinterpret context by turning parameters into variables.
438 CloogDomain
*cloog_domain_from_context(CloogDomain
*context
)
440 isl_set
*set
= isl_set_from_cloog_domain(context
);
442 set
= isl_set_move_dims(set
, isl_dim_set
, 0,
443 isl_dim_param
, 0, isl_set_dim(set
, isl_dim_param
));
445 return cloog_domain_from_isl_set(set
);
450 * cloog_domain_union_read function:
451 * This function reads a union of polyhedra into a file (input) and
452 * returns a pointer to a CloogDomain containing the read information.
454 CloogDomain
*cloog_domain_union_read(CloogState
*state
,
455 FILE *input
, int nb_parameters
)
457 struct isl_ctx
*ctx
= state
->backend
->ctx
;
460 set
= isl_set_read_from_file(ctx
, input
);
461 if (isl_set_dim(set
, isl_dim_param
) != nb_parameters
) {
462 int dim
= isl_set_dim(set
, isl_dim_set
);
463 set
= isl_set_move_dims(set
, isl_dim_param
, 0,
464 isl_dim_set
, dim
- nb_parameters
, nb_parameters
);
466 return cloog_domain_from_isl_set(set
);
471 * cloog_domain_read_scattering function:
472 * This function reads in a scattering function from the file input.
474 * We try to read the scattering relation as a map, but if it is
475 * specified in the original PolyLib format, then isl_map_read_from_file
476 * will treat the input as a set return a map with zero input dimensions.
477 * In this case, we need to decompose the set into a map from
478 * scattering dimensions to domain dimensions and then invert the
481 CloogScattering
*cloog_domain_read_scattering(CloogDomain
*domain
, FILE *input
)
483 isl_set
*set
= isl_set_from_cloog_domain(domain
);
484 isl_ctx
*ctx
= isl_set_get_ctx(set
);
485 struct isl_map
*scat
;
490 dim
= isl_set_dim(set
, isl_dim_set
);
491 nparam
= isl_set_dim(set
, isl_dim_param
);
492 scat
= isl_map_read_from_file(ctx
, input
);
493 if (isl_map_dim(scat
, isl_dim_param
) != nparam
) {
494 int n_out
= isl_map_dim(scat
, isl_dim_out
);
495 scat
= isl_map_move_dims(scat
, isl_dim_param
, 0,
496 isl_dim_out
, n_out
- nparam
, nparam
);
498 if (isl_map_dim(scat
, isl_dim_in
) != dim
) {
499 n_scat
= isl_map_dim(scat
, isl_dim_out
) - dim
;
500 scat
= isl_map_move_dims(scat
, isl_dim_in
, 0,
501 isl_dim_out
, n_scat
, dim
);
503 return cloog_scattering_from_isl_map(scat
);
506 /******************************************************************************
507 * CloogMatrix Reading function *
508 ******************************************************************************/
511 * isl_constraint_read_from_matrix:
512 * Convert a single line of a matrix to a isl_constraint.
513 * Returns a pointer to the constraint if successful; NULL otherwise.
515 static struct isl_constraint
*isl_constraint_read_from_matrix(
516 struct isl_space
*dim
, cloog_int_t
*row
)
518 struct isl_constraint
*constraint
;
520 int nvariables
= isl_space_dim(dim
, isl_dim_set
);
521 int nparam
= isl_space_dim(dim
, isl_dim_param
);
522 isl_local_space
*ls
= isl_local_space_from_space(dim
);
524 if (cloog_int_is_zero(row
[0]))
525 constraint
= isl_equality_alloc(ls
);
527 constraint
= isl_inequality_alloc(ls
);
529 for (j
= 0; j
< nvariables
; ++j
) {
530 isl_val
*val
= cloog_int_to_isl_val(isl_constraint_get_ctx(constraint
), row
[1 + j
]);
531 isl_constraint_set_coefficient_val(constraint
, isl_dim_out
, j
, val
);
534 for (j
= 0; j
< nparam
; ++j
) {
535 isl_val
*val
= cloog_int_to_isl_val(isl_constraint_get_ctx(constraint
), row
[1 + nvariables
+ j
]);
536 isl_constraint_set_coefficient_val(constraint
, isl_dim_param
, j
, val
);
539 isl_val
*val
= cloog_int_to_isl_val(isl_constraint_get_ctx(constraint
), row
[1 + nvariables
+ nparam
]);
540 isl_constraint_set_constant_val(constraint
, val
);
546 * isl_basic_set_read_from_matrix:
547 * Convert matrix to basic_set. The matrix contains nparam parameter columns.
548 * Returns a pointer to the basic_set if successful; NULL otherwise.
550 static struct isl_basic_set
*isl_basic_set_read_from_matrix(struct isl_ctx
*ctx
,
551 CloogMatrix
* matrix
, int nparam
)
553 struct isl_space
*dim
;
554 struct isl_basic_set
*bset
;
556 unsigned nrows
, ncolumns
;
558 nrows
= matrix
->NbRows
;
559 ncolumns
= matrix
->NbColumns
;
560 int nvariables
= ncolumns
- 2 - nparam
;
562 dim
= isl_space_set_alloc(ctx
, nparam
, nvariables
);
564 bset
= isl_basic_set_universe(isl_space_copy(dim
));
566 for (i
= 0; i
< nrows
; ++i
) {
567 cloog_int_t
*row
= matrix
->p
[i
];
568 struct isl_constraint
*constraint
=
569 isl_constraint_read_from_matrix(isl_space_copy(dim
), row
);
570 bset
= isl_basic_set_add_constraint(bset
, constraint
);
579 * cloog_domain_from_cloog_matrix:
580 * Create a CloogDomain containing the constraints described in matrix.
581 * nparam is the number of parameters contained in the domain.
582 * Returns a pointer to the CloogDomain if successful; NULL otherwise.
584 CloogDomain
*cloog_domain_from_cloog_matrix(CloogState
*state
,
585 CloogMatrix
*matrix
, int nparam
)
587 struct isl_ctx
*ctx
= state
->backend
->ctx
;
588 struct isl_basic_set
*bset
;
590 bset
= isl_basic_set_read_from_matrix(ctx
, matrix
, nparam
);
592 return cloog_domain_from_isl_set(isl_set_from_basic_set(bset
));
596 * cloog_scattering_from_cloog_matrix:
597 * Create a CloogScattering containing the constraints described in matrix.
598 * nparam is the number of parameters contained in the domain.
599 * Returns a pointer to the CloogScattering if successful; NULL otherwise.
601 CloogScattering
*cloog_scattering_from_cloog_matrix(CloogState
*state
,
602 CloogMatrix
*matrix
, int nb_scat
, int nb_par
)
604 struct isl_ctx
*ctx
= state
->backend
->ctx
;
605 struct isl_basic_set
*bset
;
606 struct isl_basic_map
*scat
;
607 struct isl_space
*dims
;
610 bset
= isl_basic_set_read_from_matrix(ctx
, matrix
, nb_par
);
611 dim
= isl_basic_set_n_dim(bset
) - nb_scat
;
612 dims
= isl_space_alloc(ctx
, nb_par
, nb_scat
, dim
);
614 scat
= isl_basic_map_from_basic_set(bset
, dims
);
615 scat
= isl_basic_map_reverse(scat
);
616 return cloog_scattering_from_isl_map(isl_map_from_basic_map(scat
));
620 /******************************************************************************
621 * Processing functions *
622 ******************************************************************************/
627 * Converts an openscop relation to a CLooG domain.
628 * \param[in,out] state CLooG state.
629 * \param[in] relation OpenScop relation to convert.
630 * \return A new CloogDomain corresponding to the input OpenScop relation.
632 CloogDomain
*cloog_domain_from_osl_relation(CloogState
*state
,
633 osl_relation_p relation
) {
635 struct isl_ctx
*ctx
= state
->backend
->ctx
;
637 CloogDomain
*domain
= NULL
;
639 if (relation
!= NULL
) {
640 str
= osl_relation_spprint_polylib(relation
, NULL
);
641 set
= isl_set_read_from_str(ctx
, str
);
644 domain
= cloog_domain_from_isl_set(set
);
651 * Converts an openscop scattering relation to a CLooG scattering.
652 * \param[in,out] state CLooG state.
653 * \param[in] relation OpenScop relation to convert.
654 * \return A new CloogScattering corresponding to the input OpenScop relation.
656 CloogScattering
*cloog_scattering_from_osl_relation(CloogState
*state
,
657 osl_relation_p relation
) {
659 struct isl_ctx
*ctx
= state
->backend
->ctx
;
661 CloogScattering
*scattering
= NULL
;
663 if (relation
!= NULL
) {
664 if (relation
->type
!= OSL_TYPE_SCATTERING
)
665 cloog_die("Cannot convert a non-scattering relation to a scattering.\n");
667 str
= osl_relation_spprint_polylib(relation
, NULL
);
668 map
= isl_map_read_from_str(ctx
, str
);
671 scattering
= cloog_scattering_from_isl_map(map
);
679 * cloog_domain_isempty function:
681 int cloog_domain_isempty(CloogDomain
*domain
)
683 isl_set
*set
= isl_set_from_cloog_domain(domain
);
684 return isl_set_is_empty(set
);
689 * cloog_domain_universe function:
690 * This function returns the complete dim-dimensional space.
692 CloogDomain
*cloog_domain_universe(CloogState
*state
, unsigned dim
)
694 struct isl_space
*dims
;
695 struct isl_basic_set
*bset
;
697 dims
= isl_space_set_alloc(state
->backend
->ctx
, 0, dim
);
698 bset
= isl_basic_set_universe(dims
);
699 return cloog_domain_from_isl_set(isl_set_from_basic_set(bset
));
704 * cloog_domain_project function:
705 * This function returns the projection of
706 * (domain) on the (level) first dimensions (i.e. outer loops).
708 CloogDomain
*cloog_domain_project(CloogDomain
*domain
, int level
)
710 isl_set
*set
= isl_set_from_cloog_domain(domain
);
711 set
= isl_set_remove_dims(isl_set_copy(set
), isl_dim_set
,
712 level
, isl_set_n_dim(set
) - level
);
713 set
= isl_set_compute_divs(set
);
715 set
= isl_set_remove_divs_involving_dims(set
,
716 isl_dim_set
, level
- 1, 1);
717 return cloog_domain_from_isl_set(set
);
722 * cloog_domain_extend function:
723 * This function returns the (domain) given as input with (dim)
724 * dimensions and (nb_par) parameters.
725 * This function does not free (domain), and returns a new CloogDomain.
727 CloogDomain
*cloog_domain_extend(CloogDomain
*domain
, int dim
)
729 isl_set
*set
= isl_set_from_cloog_domain(domain
);
730 int n
= isl_set_dim(set
, isl_dim_set
);
731 set
= isl_set_add_dims(isl_set_copy(set
), isl_dim_set
, dim
- n
);
732 return cloog_domain_from_isl_set(set
);
737 * cloog_domain_never_integral function:
738 * For us, an equality like 3*i -4 = 0 is always false since 4%3 != 0.
739 * There is no need to check for such constraints explicitly for the isl
742 int cloog_domain_never_integral(CloogDomain
* domain
)
744 isl_set
*set
= isl_set_from_cloog_domain(domain
);
745 return isl_set_is_empty(set
);
750 * Check whether the loop at "level" is executed at most once.
751 * We construct a map that maps all remaining variables to this iterator
752 * and check whether this map is single valued.
754 * Alternatively, we could have mapped the domain through a mapping
755 * [p] -> { [..., i] -> [..., i'] : i' > i }
756 * and then taken the intersection of the original domain and the transformed
757 * domain. If this intersection is empty, then the corresponding
758 * loop is executed at most once.
760 int cloog_domain_is_otl(CloogDomain
*domain
, int level
)
763 isl_set
*set
= isl_set_from_cloog_domain(domain
);
766 map
= isl_map_from_domain(isl_set_copy(set
));
767 map
= isl_map_move_dims(map
, isl_dim_out
, 0, isl_dim_in
, level
- 1, 1);
768 otl
= isl_map_is_single_valued(map
);
776 * cloog_domain_stride function:
777 * This function finds the stride imposed to unknown with the column number
778 * 'strided_level' in order to be integral. For instance, if we have a
779 * constraint like -i - 2j + 2k = 0, and we consider k, then k can be integral
780 * only if (i + 2j)%2 = 0. Then only if i%2 = 0. Then k imposes a stride 2 to
781 * the unknown i. The function returns the imposed stride in a parameter field.
782 * - domain is the set of constraint we have to consider,
783 * - strided_level is the column number of the unknown for which a stride have
785 * - looking_level is the column number of the unknown that impose a stride to
787 * - stride is the stride that is returned back as a function parameter.
788 * - offset is the value of the constant c if the condition is of the shape
789 * (i + c)%s = 0, s being the stride.
791 void cloog_domain_stride(CloogDomain
*domain
, int strided_level
,
792 cloog_int_t
*stride
, cloog_int_t
*offset
)
795 isl_set
*set
= isl_set_from_cloog_domain(domain
);
796 isl_val
*stride_val
= NULL
;
797 isl_val
*offset_val
= NULL
;
798 ret
= isl_set_dim_residue_class_val(set
, strided_level
- 1, &stride_val
, &offset_val
);
800 cloog_die("failure to compute stride.\n");
801 isl_val_to_cloog_int(stride_val
, stride
);
802 isl_val_to_cloog_int(offset_val
, offset
);
804 if (!cloog_int_is_zero(*offset
))
805 cloog_int_sub(*offset
, *stride
, *offset
);
807 isl_val_free(stride_val
);
808 isl_val_free(offset_val
);
814 struct cloog_can_stride
{
819 static int constraint_can_stride(__isl_take isl_constraint
*c
, void *user
)
821 struct cloog_can_stride
*ccs
= (struct cloog_can_stride
*)user
;
826 if (isl_constraint_is_equality(c
)) {
827 isl_constraint_free(c
);
831 v
= isl_constraint_get_coefficient_val(c
, isl_dim_set
, ccs
->level
- 1);
832 if (isl_val_is_pos(v
)) {
833 n_div
= isl_constraint_dim(c
, isl_dim_div
);
835 for (i
= 0; i
< n_div
; ++i
) {
837 v
= isl_constraint_get_coefficient_val(c
, isl_dim_div
, i
);
838 if (!isl_val_is_zero(v
))
846 isl_constraint_free(c
);
850 static int basic_set_can_stride(__isl_take isl_basic_set
*bset
, void *user
)
852 struct cloog_can_stride
*ccs
= (struct cloog_can_stride
*)user
;
855 r
= isl_basic_set_foreach_constraint(bset
, constraint_can_stride
, ccs
);
856 isl_basic_set_free(bset
);
862 * Return 1 if CLooG is allowed to perform stride detection on level "level"
864 * Currently, stride detection is only allowed when none of the lower
865 * bound constraints involve any existentially quantified variables.
866 * The reason is that the current isl interface does not make it
867 * easy to construct an integer division that depends on other integer
869 * By not allowing existentially quantified variables in the constraints,
870 * we can ignore them in cloog_domain_stride_lower_bound.
872 int cloog_domain_can_stride(CloogDomain
*domain
, int level
)
874 struct cloog_can_stride ccs
= { level
, 1 };
875 isl_set
*set
= isl_set_from_cloog_domain(domain
);
877 r
= isl_set_foreach_basic_set(set
, basic_set_can_stride
, &ccs
);
879 return ccs
.can_stride
;
883 struct cloog_stride_lower
{
887 isl_basic_set
*bounds
;
890 /* If the given constraint is a lower bound on csl->level, then add
891 * a lower bound to csl->bounds that makes sure that the remainder
892 * of the smallest value on division by csl->stride is equal to csl->offset.
894 * In particular, the given lower bound is of the form
898 * where f may depend on the parameters and other iterators.
899 * The stride is s and the offset is d.
900 * The lower bound -f/a may not satisfy the above condition. In fact,
901 * it may not even be integral. We want to round this value of i up
902 * to the nearest value that satisfies the condition and add the corresponding
903 * lower bound constraint. This nearest value is obtained by rounding
904 * i - d up to the nearest multiple of s.
905 * That is, we first subtract d
909 * then we round up to the nearest multiple of s
911 * i'' = s * ceil(i'/s)
913 * and finally, we add d again
917 * and impose the constraint i >= i'''.
921 * i'' = s * ceil((-f - a * d)/(a * s)) = - s * floor((f + a * d)/(a * s))
923 * i >= - s * floor((f + a * d)/(a * s)) + d
926 * i + s * floor((f + a * d)/(a * s)) - d >= 0
928 static int constraint_stride_lower(__isl_take isl_constraint
*c
, void *user
)
930 struct cloog_stride_lower
*csl
= (struct cloog_stride_lower
*)user
;
932 isl_constraint
*bound
;
935 if (isl_constraint_is_equality(c
)) {
936 isl_constraint_free(c
);
940 v
= isl_constraint_get_coefficient_val(c
, isl_dim_set
, csl
->level
- 1);
941 if (!isl_val_is_pos(v
)) {
943 isl_constraint_free(c
);
949 b
= isl_constraint_get_bound(c
, isl_dim_set
, csl
->level
- 1);
952 b
= isl_aff_add_constant_val(b
, cloog_int_to_isl_val(isl_constraint_get_ctx(c
), csl
->stride
->offset
));
953 b
= isl_aff_scale_down_val(b
, cloog_int_to_isl_val(isl_constraint_get_ctx(c
), csl
->stride
->stride
));
954 b
= isl_aff_floor(b
);
955 b
= isl_aff_scale_val(b
, cloog_int_to_isl_val(isl_constraint_get_ctx(c
), csl
->stride
->stride
));
956 v
= cloog_int_to_isl_val(isl_constraint_get_ctx(c
), csl
->stride
->offset
);
958 b
= isl_aff_add_constant_val(b
, v
);
959 b
= isl_aff_add_coefficient_si(b
, isl_dim_in
, csl
->level
- 1, 1);
961 bound
= isl_inequality_from_aff(b
);
963 csl
->bounds
= isl_basic_set_add_constraint(csl
->bounds
, bound
);
965 isl_constraint_free(c
);
970 /* This functions performs essentially the same operation as
971 * constraint_stride_lower, the only difference being that the offset d
972 * is not a constant, but an affine expression in terms of the parameters
973 * and earlier variables. In particular the affine expression is equal
974 * to the coefficients of stride->constraint multiplied by stride->factor.
975 * As in constraint_stride_lower, we add an extra bound
977 * i + s * floor((f + a * d)/(a * s)) - d >= 0
979 * for each lower bound
983 * where d is not the aforementioned affine expression.
985 static int constraint_stride_lower_c(__isl_take isl_constraint
*c
, void *user
)
987 struct cloog_stride_lower
*csl
= (struct cloog_stride_lower
*)user
;
989 isl_constraint
*bound
;
990 isl_constraint
*csl_c
;
993 if (isl_constraint_is_equality(c
)) {
994 isl_constraint_free(c
);
998 v
= isl_constraint_get_coefficient_val(c
, isl_dim_set
, csl
->level
- 1);
999 if (!isl_val_is_pos(v
)) {
1001 isl_constraint_free(c
);
1006 csl_c
= cloog_constraint_to_isl(csl
->stride
->constraint
);
1008 d
= isl_constraint_get_aff(csl_c
);
1009 d
= isl_aff_drop_dims(d
, isl_dim_div
, 0, isl_aff_dim(d
, isl_dim_div
));
1010 d
= isl_aff_set_coefficient_si(d
, isl_dim_in
, csl
->level
- 1, 0);
1011 d
= isl_aff_scale_val(d
, cloog_int_to_isl_val(isl_constraint_get_ctx(csl_c
), csl
->stride
->factor
));
1013 b
= isl_constraint_get_bound(c
, isl_dim_set
, csl
->level
- 1);
1016 b
= isl_aff_add(b
, isl_aff_copy(d
));
1017 b
= isl_aff_scale_down_val(b
, cloog_int_to_isl_val(isl_constraint_get_ctx(csl_c
), csl
->stride
->stride
));
1018 b
= isl_aff_floor(b
);
1019 b
= isl_aff_scale_val(b
, cloog_int_to_isl_val(isl_constraint_get_ctx(csl_c
), csl
->stride
->stride
));
1020 b
= isl_aff_sub(b
, d
);
1021 b
= isl_aff_add_coefficient_si(b
, isl_dim_in
, csl
->level
- 1, 1);
1023 bound
= isl_inequality_from_aff(b
);
1025 csl
->bounds
= isl_basic_set_add_constraint(csl
->bounds
, bound
);
1028 isl_constraint_free(c
);
1033 static int basic_set_stride_lower(__isl_take isl_basic_set
*bset
, void *user
)
1035 struct cloog_stride_lower
*csl
= (struct cloog_stride_lower
*)user
;
1038 csl
->bounds
= isl_basic_set_universe(isl_basic_set_get_space(bset
));
1039 if (csl
->stride
->constraint
)
1040 r
= isl_basic_set_foreach_constraint(bset
,
1041 &constraint_stride_lower_c
, csl
);
1043 r
= isl_basic_set_foreach_constraint(bset
,
1044 &constraint_stride_lower
, csl
);
1045 bset
= isl_basic_set_intersect(bset
, csl
->bounds
);
1046 csl
->set
= isl_set_union(csl
->set
, isl_set_from_basic_set(bset
));
1052 * Update the lower bounds at level "level" to the given stride information.
1053 * That is, make sure that the remainder on division by "stride"
1054 * is equal to "offset".
1056 CloogDomain
*cloog_domain_stride_lower_bound(CloogDomain
*domain
, int level
,
1057 CloogStride
*stride
)
1059 struct cloog_stride_lower csl
;
1060 isl_set
*set
= isl_set_from_cloog_domain(domain
);
1063 csl
.stride
= stride
;
1065 csl
.set
= isl_set_empty(isl_set_get_space(set
));
1067 r
= isl_set_foreach_basic_set(set
, basic_set_stride_lower
, &csl
);
1070 cloog_domain_free(domain
);
1071 return cloog_domain_from_isl_set(csl
.set
);
1075 /* Add stride constraint, if any, to domain.
1077 CloogDomain
*cloog_domain_add_stride_constraint(CloogDomain
*domain
,
1078 CloogStride
*stride
)
1083 if (!stride
|| !stride
->constraint
)
1086 set
= isl_set_from_cloog_domain(domain
);
1087 c
= isl_constraint_copy(cloog_constraint_to_isl(stride
->constraint
));
1089 set
= isl_set_add_constraint(set
, c
);
1091 return cloog_domain_from_isl_set(set
);
1096 * cloog_domain_lazy_equal function:
1097 * This function returns 1 if the domains given as input are the same, 0 if it
1098 * is unable to decide.
1100 int cloog_domain_lazy_equal(CloogDomain
*d1
, CloogDomain
*d2
)
1102 isl_set
*set1
= isl_set_from_cloog_domain(d1
);
1103 isl_set
*set2
= isl_set_from_cloog_domain(d2
);
1104 return isl_set_plain_is_equal(set1
, set2
);
1107 struct cloog_bound_split
{
1114 static int constraint_bound_split(__isl_take isl_constraint
*c
, void *user
)
1116 struct cloog_bound_split
*cbs
= (struct cloog_bound_split
*)user
;
1121 v
= isl_constraint_get_coefficient_val(c
, isl_dim_set
, cbs
->level
- 1);
1122 if (!cbs
->lower
&& isl_val_is_pos(v
))
1123 cbs
->lower
= handle
= 1;
1124 else if (!cbs
->upper
&& isl_val_is_neg(v
))
1125 cbs
->upper
= handle
= 1;
1128 for (i
= 0; i
< isl_set_dim(cbs
->set
, isl_dim_param
); ++i
) {
1130 v
= isl_constraint_get_coefficient_val(c
, isl_dim_param
, i
);
1131 if (isl_val_is_zero(v
))
1134 cbs
->set
= isl_set_split_dims(cbs
->set
,
1135 isl_dim_param
, i
, 1);
1140 isl_constraint_free(c
);
1141 return (cbs
->lower
&& cbs
->upper
) ? -1 : 0;
1144 static int basic_set_bound_split(__isl_take isl_basic_set
*bset
, void *user
)
1146 struct cloog_bound_split
*cbs
= (struct cloog_bound_split
*)user
;
1151 r
= isl_basic_set_foreach_constraint(bset
, constraint_bound_split
, cbs
);
1152 isl_basic_set_free(bset
);
1153 return ((!cbs
->lower
|| !cbs
->upper
) && r
< 0) ? -1 : 0;
1157 * Return a union of sets S_i such that the convex hull of "dom",
1158 * when intersected with one the sets S_i, will have an upper and
1159 * lower bound for the dimension at "level" (provided "dom" itself
1160 * has such bounds for the dimensions).
1162 * We currently take a very simple approach. For each of the basic
1163 * sets in "dom" we pick a lower and an upper bound and split the
1164 * range of any parameter involved in these two bounds in a
1165 * nonnegative and a negative part. This ensures that the symbolic
1166 * constant in these two constraints are themselves bounded and
1167 * so there will be at least one upper and one lower bound
1168 * in the convex hull.
1170 CloogDomain
*cloog_domain_bound_splitter(CloogDomain
*dom
, int level
)
1172 struct cloog_bound_split cbs
;
1173 isl_set
*set
= isl_set_from_cloog_domain(dom
);
1176 cbs
.set
= isl_set_universe(isl_set_get_space(set
));
1177 r
= isl_set_foreach_basic_set(set
, basic_set_bound_split
, &cbs
);
1179 return cloog_domain_from_isl_set(cbs
.set
);
1183 /* Check whether the union of scattering functions over all domains
1184 * is obviously injective.
1186 static int injective_scattering(CloogScatteringList
*list
)
1189 isl_union_map
*umap
;
1197 map
= isl_map_copy(isl_map_from_cloog_scattering(list
->scatt
));
1198 snprintf(name
, sizeof(name
), "S%d", i
);
1199 map
= isl_map_set_tuple_name(map
, isl_dim_in
, name
);
1200 umap
= isl_union_map_from_map(map
);
1202 for (list
= list
->next
, ++i
; list
; list
= list
->next
, ++i
) {
1203 map
= isl_map_copy(isl_map_from_cloog_scattering(list
->scatt
));
1204 snprintf(name
, sizeof(name
), "S%d", i
);
1205 map
= isl_map_set_tuple_name(map
, isl_dim_in
, name
);
1206 umap
= isl_union_map_add_map(umap
, map
);
1209 injective
= isl_union_map_plain_is_injective(umap
);
1211 isl_union_map_free(umap
);
1218 * cloog_scattering_lazy_block function:
1219 * This function returns 1 if the two scattering functions s1 and s2 given
1220 * as input are the same (except possibly for the final dimension, where we
1221 * allow a difference of 1), assuming that the domains on which this
1222 * scatterings are applied are the same.
1223 * In fact this function answers the question "can I
1224 * safely consider the two domains as only one with two statements (a block) ?".
1225 * A difference of 1 in the final dimension is only allowed if the
1226 * entire scattering function is injective.
1227 * - s1 and s2 are the two domains to check for blocking,
1228 * - scattering is the linked list of all domains,
1229 * - scattdims is the total number of scattering dimentions.
1231 int cloog_scattering_lazy_block(CloogScattering
*s1
, CloogScattering
*s2
,
1232 CloogScatteringList
*scattering
, int scattdims
)
1235 struct isl_space
*dim
;
1236 struct isl_map
*rel
;
1237 struct isl_set
*delta
;
1238 isl_map
*map1
= isl_map_from_cloog_scattering(s1
);
1239 isl_map
*map2
= isl_map_from_cloog_scattering(s2
);
1244 n_scat
= isl_map_dim(map1
, isl_dim_out
);
1245 if (n_scat
!= isl_map_dim(map2
, isl_dim_out
))
1248 dim
= isl_map_get_space(map1
);
1249 dim
= isl_space_map_from_set(isl_space_domain(dim
));
1250 rel
= isl_map_identity(dim
);
1251 rel
= isl_map_apply_domain(rel
, isl_map_copy(map1
));
1252 rel
= isl_map_apply_range(rel
, isl_map_copy(map2
));
1253 delta
= isl_map_deltas(rel
);
1255 for (i
= 0; i
< n_scat
; ++i
) {
1256 cst
= isl_set_plain_get_val_if_fixed(delta
, isl_dim_set
, i
);
1261 if (isl_val_is_zero(cst
)){
1265 if (i
+ 1 < n_scat
){
1269 if (!isl_val_is_one(cst
)){
1273 if (!injective_scattering(scattering
)){
1280 block
= i
>= n_scat
;
1281 isl_set_free(delta
);
1287 * cloog_domain_lazy_disjoint function:
1288 * This function returns 1 if the domains given as input are disjoint, 0 if it
1289 * is unable to decide.
1291 int cloog_domain_lazy_disjoint(CloogDomain
*d1
, CloogDomain
*d2
)
1293 isl_set
*set1
= isl_set_from_cloog_domain(d1
);
1294 isl_set
*set2
= isl_set_from_cloog_domain(d2
);
1295 return isl_set_plain_is_disjoint(set1
, set2
);
1300 * cloog_scattering_list_lazy_same function:
1301 * This function returns 1 if two domains in the list are the same, 0 if it
1302 * is unable to decide.
1304 int cloog_scattering_list_lazy_same(CloogScatteringList
*list
)
1306 CloogScatteringList
*one
, *other
;
1307 isl_map
*one_map
, *other_map
;
1309 for (one
= list
; one
; one
= one
->next
) {
1310 one_map
= isl_map_from_cloog_scattering(one
->scatt
);
1311 for (other
= one
->next
; other
; other
= other
->next
) {
1312 other_map
= isl_map_from_cloog_scattering(other
->scatt
);
1313 if (isl_map_plain_is_equal(one_map
, other_map
))
1320 int cloog_domain_dimension(CloogDomain
* domain
)
1322 isl_set
*set
= isl_set_from_cloog_domain(domain
);
1323 return isl_set_dim(set
, isl_dim_set
);
1326 int cloog_domain_parameter_dimension(CloogDomain
*domain
)
1328 isl_set
*set
= isl_set_from_cloog_domain(domain
);
1329 return isl_set_dim(set
, isl_dim_param
);
1332 int cloog_scattering_dimension(CloogScattering
*scatt
, CloogDomain
*domain
)
1334 isl_map
*map
= isl_map_from_cloog_scattering(scatt
);
1335 return isl_map_dim(map
, isl_dim_out
);
1338 int cloog_domain_isconvex(CloogDomain
* domain
)
1340 isl_set
*set
= isl_set_from_cloog_domain(domain
);
1341 return isl_set_n_basic_set(set
) <= 1;
1346 * cloog_domain_cut_first function:
1347 * This function splits off and returns the first convex set in the
1348 * union "domain". The remainder of the union is returned in rest.
1349 * The original "domain" itself is destroyed and may not be used
1350 * after a call to this function.
1352 CloogDomain
*cloog_domain_cut_first(CloogDomain
*domain
, CloogDomain
**rest
)
1354 isl_set
*set
= isl_set_from_cloog_domain(domain
);
1355 struct isl_basic_set
*first
;
1357 first
= isl_set_copy_basic_set(set
);
1358 set
= isl_set_drop_basic_set(set
, first
);
1359 *rest
= cloog_domain_from_isl_set(set
);
1361 return cloog_domain_from_isl_set(isl_set_from_basic_set(first
));
1366 * Given a union domain, try to find a simpler representation
1367 * using fewer sets in the union.
1368 * The original "domain" itself is destroyed and may not be used
1369 * after a call to this function.
1371 CloogDomain
*cloog_domain_simplify_union(CloogDomain
*domain
)
1373 isl_set
*set
= isl_set_from_cloog_domain(domain
);
1374 return cloog_domain_from_isl_set(isl_set_coalesce(set
));
1379 * cloog_scattering_lazy_isscalar function:
1380 * this function returns 1 if the scattering dimension 'dimension' in the
1381 * scattering 'scatt' is constant.
1382 * If value is not NULL, then it is set to the constant value of dimension.
1384 int cloog_scattering_lazy_isscalar(CloogScattering
*scatt
, int dimension
,
1387 isl_map
*map
= isl_map_from_cloog_scattering(scatt
);
1388 isl_val
*v
= isl_map_plain_get_val_if_fixed(map
, isl_dim_out
, dimension
);
1390 if (!isl_val_is_nan(v
)){
1392 isl_val_to_cloog_int(v
, value
);
1408 * cloog_domain_lazy_isconstant function:
1409 * this function returns 1 if the dimension 'dimension' in the
1410 * domain 'domain' is constant.
1411 * If value is not NULL, then it is set to the constant value of dimension.
1413 int cloog_domain_lazy_isconstant(CloogDomain
*domain
, int dimension
,
1416 isl_set
*set
= isl_set_from_cloog_domain(domain
);
1417 isl_val
*cst
= isl_set_plain_get_val_if_fixed(set
, isl_dim_set
, dimension
);
1419 if (!isl_val_is_nan(cst
)){
1421 isl_val_to_cloog_int(cst
, value
);
1437 * cloog_scattering_erase_dimension function:
1438 * this function returns a CloogDomain structure builds from 'domain' where
1439 * we removed the dimension 'dimension' and every constraint involving this
1442 CloogScattering
*cloog_scattering_erase_dimension(CloogScattering
*scattering
,
1445 isl_map
*map
= isl_map_from_cloog_scattering(scattering
);
1446 map
= isl_map_remove_dims(isl_map_copy(map
), isl_dim_out
, dimension
, 1);
1447 return cloog_scattering_from_isl_map(map
);
1451 * cloog_domain_cube:
1452 * Construct and return a dim-dimensional cube, with values ranging
1453 * between min and max in each dimension.
1455 CloogDomain
*cloog_domain_cube(CloogState
*state
,
1456 int dim
, cloog_int_t min
, cloog_int_t max
)
1465 return cloog_domain_universe(state
, dim
);
1467 space
= isl_space_set_alloc(state
->backend
->ctx
, 0, dim
);
1468 cube
= isl_set_universe(space
);
1469 for (i
= 0; i
< dim
; ++i
) {
1470 min_v
= cloog_int_to_isl_val(isl_set_get_ctx(cube
), min
);
1471 max_v
= cloog_int_to_isl_val(isl_set_get_ctx(cube
), max
);
1472 cube
= isl_set_lower_bound_val(cube
, isl_dim_set
, i
, min_v
);
1473 cube
= isl_set_upper_bound_val(cube
, isl_dim_set
, i
, max_v
);
1476 return cloog_domain_from_isl_set(cube
);
1481 * cloog_domain_scatter function:
1482 * This function add the scattering (scheduling) informations to a domain.
1484 CloogDomain
*cloog_domain_scatter(CloogDomain
*domain
, CloogScattering
*scatt
)
1486 isl_set
*set
= isl_set_from_cloog_domain(domain
);
1487 isl_map
*map
= isl_map_from_cloog_scattering(scatt
);
1489 map
= isl_map_reverse(isl_map_copy(map
));
1490 map
= isl_map_intersect_range(map
, set
);
1491 set
= isl_set_flatten(isl_map_wrap(map
));
1492 return cloog_domain_from_isl_set(set
);
1495 static int add_domain_from_map(__isl_take isl_map
*map
, void *user
)
1499 CloogDomain
*domain
;
1500 CloogScattering
*scat
;
1501 CloogUnionDomain
**ud
= (CloogUnionDomain
**)user
;
1503 dim
= isl_map_get_space(map
);
1504 name
= isl_space_get_tuple_name(dim
, isl_dim_in
);
1505 domain
= cloog_domain_from_isl_set(isl_map_domain(isl_map_copy(map
)));
1506 scat
= cloog_scattering_from_isl_map(map
);
1507 *ud
= cloog_union_domain_add_domain(*ud
, name
, domain
, scat
, NULL
);
1508 isl_space_free(dim
);
1514 * Construct a CloogUnionDomain from an isl_union_map representing
1515 * a global scattering function. The input is a mapping from different
1516 * spaces (different tuple names and possibly different dimensions)
1517 * to a common space. The iteration domains are set to the domains
1518 * in each space. The statement names are set to the names of the
1519 * spaces. The parameter names of the result are set to those of
1520 * the input, but the iterator and scattering dimension names are
1523 CloogUnionDomain
*cloog_union_domain_from_isl_union_map(
1524 __isl_take isl_union_map
*umap
)
1529 CloogUnionDomain
*ud
;
1531 dim
= isl_union_map_get_space(umap
);
1532 nparam
= isl_space_dim(dim
, isl_dim_param
);
1534 ud
= cloog_union_domain_alloc(nparam
);
1536 for (i
= 0; i
< nparam
; ++i
) {
1537 const char *s
= isl_space_get_dim_name(dim
, isl_dim_param
, i
);
1538 ud
= cloog_union_domain_set_name(ud
, CLOOG_PARAM
, i
, s
);
1540 isl_space_free(dim
);
1542 if (isl_union_map_foreach_map(umap
, &add_domain_from_map
, &ud
) < 0) {
1543 isl_union_map_free(umap
);
1544 cloog_union_domain_free(ud
);
1548 isl_union_map_free(umap
);
1553 static int count_same_name(__isl_keep isl_space
*dim
,
1554 enum isl_dim_type type
, unsigned pos
, const char *name
)
1556 enum isl_dim_type t
;
1559 int len
= strlen(name
);
1561 for (t
= isl_dim_param
; t
<= type
&& t
<= isl_dim_out
; ++t
) {
1562 s
= t
== type
? pos
: isl_space_dim(dim
, t
);
1563 for (p
= 0; p
< s
; ++p
) {
1564 const char *n
= isl_space_get_dim_name(dim
, t
, p
);
1565 if (n
&& !strncmp(n
, name
, len
))
1572 static CloogUnionDomain
*add_domain(__isl_take isl_set
*set
, CloogUnionDomain
*ud
)
1579 CloogDomain
*domain
;
1581 ctx
= isl_set_get_ctx(set
);
1582 dim
= isl_set_get_space(set
);
1583 name
= isl_space_get_tuple_name(dim
, isl_dim_set
);
1584 set
= isl_set_flatten(set
);
1585 set
= isl_set_set_tuple_name(set
, NULL
);
1586 domain
= cloog_domain_from_isl_set(set
);
1587 ud
= cloog_union_domain_add_domain(ud
, name
, domain
, NULL
, NULL
);
1589 nvar
= isl_space_dim(dim
, isl_dim_set
);
1590 for (i
= 0; i
< nvar
; ++i
) {
1591 char *long_name
= NULL
;
1594 name
= isl_space_get_dim_name(dim
, isl_dim_set
, i
);
1596 snprintf(buffer
, sizeof(buffer
), "i%d", i
);
1599 n
= count_same_name(dim
, isl_dim_set
, i
, name
);
1601 int size
= strlen(name
) + 10;
1602 long_name
= isl_alloc_array(ctx
, char, size
);
1604 cloog_die("memory overflow.\n");
1605 snprintf(long_name
, size
, "%s_%d", name
, n
);
1608 ud
= cloog_union_domain_set_name(ud
, CLOOG_ITER
, i
, name
);
1611 isl_space_free(dim
);
1617 * Construct a CloogUnionDomain from an isl_set.
1618 * The statement names are set to the names of the
1619 * spaces. The parameter and iterator names of the result are set to those of
1620 * the input, but the scattering dimension names are left unspecified.
1622 CloogUnionDomain
*cloog_union_domain_from_isl_set(
1623 __isl_take isl_set
*set
)
1628 CloogUnionDomain
*ud
;
1630 dim
= isl_set_get_space(set
);
1631 nparam
= isl_space_dim(dim
, isl_dim_param
);
1633 ud
= cloog_union_domain_alloc(nparam
);
1635 for (i
= 0; i
< nparam
; ++i
) {
1636 const char *s
= isl_space_get_dim_name(dim
, isl_dim_param
, i
);
1637 ud
= cloog_union_domain_set_name(ud
, CLOOG_PARAM
, i
, s
);
1639 isl_space_free(dim
);
1641 ud
= add_domain(set
, ud
);
1646 /* Computes x, y and g such that g = gcd(a,b) and a*x+b*y = g */
1647 static void Euclid(cloog_int_t a
, cloog_int_t b
,
1648 cloog_int_t
*x
, cloog_int_t
*y
, cloog_int_t
*g
)
1650 cloog_int_t c
, d
, e
, f
, tmp
;
1656 cloog_int_init(tmp
);
1657 cloog_int_abs(c
, a
);
1658 cloog_int_abs(d
, b
);
1659 cloog_int_set_si(e
, 1);
1660 cloog_int_set_si(f
, 0);
1661 while (cloog_int_is_pos(d
)) {
1662 cloog_int_tdiv_q(tmp
, c
, d
);
1663 cloog_int_mul(tmp
, tmp
, f
);
1664 cloog_int_sub(e
, e
, tmp
);
1665 cloog_int_tdiv_q(tmp
, c
, d
);
1666 cloog_int_mul(tmp
, tmp
, d
);
1667 cloog_int_sub(c
, c
, tmp
);
1668 cloog_int_swap(c
, d
);
1669 cloog_int_swap(e
, f
);
1671 cloog_int_set(*g
, c
);
1672 if (cloog_int_is_zero(a
))
1673 cloog_int_set_si(*x
, 0);
1674 else if (cloog_int_is_pos(a
))
1675 cloog_int_set(*x
, e
);
1676 else cloog_int_neg(*x
, e
);
1677 if (cloog_int_is_zero(b
))
1678 cloog_int_set_si(*y
, 0);
1680 cloog_int_mul(tmp
, a
, *x
);
1681 cloog_int_sub(tmp
, c
, tmp
);
1682 cloog_int_divexact(*y
, tmp
, b
);
1688 cloog_int_clear(tmp
);
1691 /* Construct a CloogStride from the given constraint for the given level,
1693 * We first compute the gcd of the coefficients of the existentially
1694 * quantified variables and then remove any common factors it has
1695 * with the coefficient at the given level.
1696 * The result is the value of the stride and if it is not one,
1697 * then it is possible to construct a CloogStride.
1698 * The constraint leading to the stride is stored in the CloogStride
1699 * as well a value (factor) such that the product of this value
1700 * and the coefficient at the given level is equal to -1 modulo the stride.
1702 static CloogStride
*construct_stride(isl_constraint
*c
, int level
)
1705 isl_val
*v
, *m
, *gcd
, *stride
;
1706 isl_val
*v_copy
, *m_copy
, *gcd_copy
;
1707 cloog_int_t c_v
, c_m
, c_gcd
, c_stride
, c_factor
;
1709 isl_ctx
*ctx
= isl_constraint_get_ctx(c
);;
1714 v
= isl_constraint_get_coefficient_val(c
, isl_dim_set
, level
- 1);
1716 sign
= isl_val_sgn(v
);
1717 m
= isl_val_abs(v
); /* *takes* v. */
1719 gcd
= isl_val_int_from_si(ctx
, 0);
1720 n
= isl_constraint_dim(c
, isl_dim_div
);
1721 for (i
= 0; i
< n
; ++i
) {
1722 v
= isl_constraint_get_coefficient_val(c
, isl_dim_div
, i
);
1723 gcd
= isl_val_gcd(gcd
, v
);
1726 m_copy
= isl_val_copy(m
);
1727 gcd_copy
= isl_val_copy(gcd
);
1729 v
= isl_val_gcd(m
, gcd
);
1731 v_copy
= isl_val_copy(v
);
1732 gcd
= isl_val_copy(gcd_copy
);
1733 stride
= isl_val_div(gcd
, v
);
1735 if (isl_val_is_zero(stride
) || isl_val_is_one(stride
))
1738 cloog_int_init(c_m
);
1739 cloog_int_init(c_stride
);
1740 cloog_int_init(c_v
);
1741 cloog_int_init(c_gcd
);
1742 cloog_int_init(c_factor
);
1744 isl_val_to_cloog_int(m_copy
, &c_m
);
1745 isl_val_to_cloog_int(stride
, &c_stride
);
1746 isl_val_to_cloog_int(v_copy
, &c_v
);
1747 isl_val_to_cloog_int(gcd_copy
, &c_gcd
);
1749 Euclid(c_m
, c_stride
, &c_factor
, &c_v
, &c_gcd
);
1751 cloog_int_neg(c_factor
, c_factor
);
1753 c
= isl_constraint_copy(c
);
1754 s
= cloog_stride_alloc_from_constraint(c_stride
,
1755 cloog_constraint_from_isl_constraint(c
), c_factor
);
1758 cloog_int_clear(c_m
);
1759 cloog_int_clear(c_stride
);
1760 cloog_int_clear(c_v
);
1761 cloog_int_clear(c_gcd
);
1762 cloog_int_clear(c_factor
);
1765 isl_val_free(stride
);
1766 isl_val_free(gcd_copy
);
1767 isl_val_free(m_copy
);
1768 isl_val_free(v_copy
);
1773 struct cloog_isl_find_stride_data
{
1775 CloogStride
*stride
;
1778 /* Check if the given constraint can be used to derive
1779 * a stride on the iterator identified by data->level.
1780 * We first check that there are some existentially quantified variables
1781 * and that the coefficient at data->level is non-zero.
1782 * Then we call construct_stride for further checks and the actual
1783 * construction of the CloogStride.
1785 static int find_stride(__isl_take isl_constraint
*c
, void *user
)
1787 struct cloog_isl_find_stride_data
*data
;
1791 if (!isl_constraint_is_equality(c
)) {
1792 isl_constraint_free(c
);
1796 data
= (struct cloog_isl_find_stride_data
*)user
;
1799 isl_constraint_free(c
);
1803 n
= isl_constraint_dim(c
, isl_dim_div
);
1805 isl_constraint_free(c
);
1809 v
= isl_constraint_get_coefficient_val(c
, isl_dim_set
, data
->level
- 1);
1810 if (!isl_val_is_zero(v
))
1811 data
->stride
= construct_stride(c
, data
->level
);
1815 isl_constraint_free(c
);
1820 /* Check if the given list of domains has a common stride on the given level.
1821 * If so, return a pointer to a CloogStride object. If not, return NULL.
1823 * We project out all later variables, take the union and compute
1824 * the affine hull of the union. Then we check the (equality)
1825 * constraints in this affine hull for imposing a stride.
1827 CloogStride
*cloog_domain_list_stride(CloogDomainList
*list
, int level
)
1829 struct cloog_isl_find_stride_data data
= { level
, NULL
};
1836 set
= isl_set_from_cloog_domain(list
->domain
);
1837 n
= isl_set_dim(set
, isl_dim_set
) - first
;
1838 set
= isl_set_project_out(isl_set_copy(set
), isl_dim_set
, first
, n
);
1840 for (list
= list
->next
; list
; list
= list
->next
) {
1841 isl_set
*set_i
= isl_set_from_cloog_domain(list
->domain
);
1842 n
= isl_set_dim(set_i
, isl_dim_set
) - first
;
1843 set_i
= isl_set_project_out(isl_set_copy(set_i
),
1844 isl_dim_set
, first
, n
);
1845 set
= isl_set_union(set
, set_i
);
1847 aff
= isl_set_affine_hull(set
);
1849 r
= isl_basic_set_foreach_constraint(aff
, &find_stride
, &data
);
1852 isl_basic_set_free(aff
);
1857 struct cloog_can_unroll
{
1867 * Check if the given lower bound can be used for unrolling
1868 * and, if so, return the unrolling factor/trip count in *v.
1869 * If the lower bound involves any existentially quantified
1870 * variables, we currently punt.
1871 * Otherwise we compute the maximal value of (i - ceil(l) + 1),
1872 * with l the given lower bound and i the iterator identified by level.
1874 static int is_valid_unrolling_lower_bound(struct cloog_can_unroll
*ccu
,
1875 __isl_keep isl_constraint
*c
, isl_val
**v
)
1881 n_div
= isl_constraint_dim(c
, isl_dim_div
);
1882 if (isl_constraint_involves_dims(c
, isl_dim_div
, 0, n_div
))
1885 aff
= isl_constraint_get_bound(c
, isl_dim_set
, ccu
->level
- 1);
1886 aff
= isl_aff_ceil(aff
);
1887 aff
= isl_aff_neg(aff
);
1888 aff
= isl_aff_add_coefficient_si(aff
, isl_dim_in
, ccu
->level
- 1, 1);
1889 *v
= isl_set_max_val(ccu
->set
, aff
);
1892 if (!*v
|| isl_val_is_nan(*v
))
1893 cloog_die("Fail to decide about unrolling (cannot find max)");
1895 if (isl_val_is_infty(*v
) || isl_val_is_neginfty(*v
)){
1901 *v
= isl_val_add_ui(*v
, 1);
1907 /* Check if we can unroll based on the given constraint.
1908 * Only lower bounds can be used.
1909 * Record it if it turns out to be usable and if we haven't recorded
1910 * any other constraint already.
1912 static int constraint_can_unroll(__isl_take isl_constraint
*c
, void *user
)
1914 struct cloog_can_unroll
*ccu
= (struct cloog_can_unroll
*)user
;
1916 isl_val
*count
= NULL
;
1918 v
= isl_constraint_get_coefficient_val(c
, isl_dim_set
, ccu
->level
- 1);
1919 if (isl_val_is_pos(v
) &&
1920 is_valid_unrolling_lower_bound(ccu
, c
, &count
) &&
1921 (!ccu
->c
|| (isl_val_lt(count
, ccu
->n
))) ) {
1922 isl_constraint_free(ccu
->c
);
1923 ccu
->c
= isl_constraint_copy(c
);
1925 isl_val_free(ccu
->n
);
1926 ccu
->n
= isl_val_copy(count
);
1928 isl_val_free(count
);
1930 isl_constraint_free(c
);
1936 /* Check if we can unroll the domain at the current level.
1937 * If the domain is a union, we cannot. Otherwise, we check the
1940 static int basic_set_can_unroll(__isl_take isl_basic_set
*bset
, void *user
)
1942 struct cloog_can_unroll
*ccu
= (struct cloog_can_unroll
*)user
;
1945 if (ccu
->c
|| !ccu
->can_unroll
)
1946 ccu
->can_unroll
= 0;
1948 bset
= isl_basic_set_remove_redundancies(bset
);
1949 r
= isl_basic_set_foreach_constraint(bset
,
1950 &constraint_can_unroll
, ccu
);
1952 isl_basic_set_free(bset
);
1957 /* Check if we can unroll the given domain at the given level, and
1958 * if so, return the single lower bound in *lb and an upper bound
1959 * on the number of iterations in *n.
1960 * If we cannot unroll, return 0 and set *lb to NULL.
1962 * We can unroll, if we can identify a lower bound on level
1963 * such that the number of iterations is bounded by a constant.
1965 int cloog_domain_can_unroll(CloogDomain
*domain
, int level
, cloog_int_t
*n
,
1966 CloogConstraint
**lb
)
1968 isl_set
*set
= isl_set_from_cloog_domain(domain
);
1969 isl_val
*v
= cloog_int_to_isl_val(isl_set_get_ctx(set
), *n
);
1970 struct cloog_can_unroll ccu
= { 1, level
, NULL
, set
, v
};
1974 r
= isl_set_foreach_basic_set(set
, &basic_set_can_unroll
, &ccu
);
1978 if (!ccu
.can_unroll
) {
1979 isl_constraint_free(ccu
.c
);
1983 *lb
= cloog_constraint_from_isl_constraint(ccu
.c
);
1985 isl_val_to_cloog_int(ccu
.n
, n
);
1986 /* Note: we have to free ccu.n and not v because v has been
1987 * freed and replaced in ccu during isl_set_foreach_basic_set
1989 isl_val_free(ccu
.n
);
1990 return ccu
.can_unroll
;
1994 /* Fix the iterator i at the given level to l + o,
1995 * where l is prescribed by the constraint lb and o is equal to offset.
1996 * In particular, if lb is the constraint
2000 * then l = ceil(f(j)/a).
2002 CloogDomain
*cloog_domain_fixed_offset(CloogDomain
*domain
,
2003 int level
, CloogConstraint
*lb
, cloog_int_t offset
)
2006 isl_set
*set
= isl_set_from_cloog_domain(domain
);
2007 isl_ctx
*ctx
= isl_set_get_ctx(set
);
2011 c
= cloog_constraint_to_isl(lb
);
2012 aff
= isl_constraint_get_bound(c
, isl_dim_set
, level
- 1);
2013 aff
= isl_aff_ceil(aff
);
2014 aff
= isl_aff_add_coefficient_si(aff
, isl_dim_in
, level
- 1, -1);
2015 aff
= isl_aff_add_constant_val(aff
, cloog_int_to_isl_val(ctx
, offset
));
2016 eq
= isl_equality_from_aff(aff
);
2017 set
= isl_set_add_constraint(set
, eq
);
2019 return cloog_domain_from_isl_set(set
);