2 /**-------------------------------------------------------------------**
4 **-------------------------------------------------------------------**
6 **-------------------------------------------------------------------**
7 ** First version: october 26th 2001 **
8 **-------------------------------------------------------------------**/
11 /******************************************************************************
12 * CLooG : the Chunky Loop Generator (experimental) *
13 ******************************************************************************
15 * Copyright (C) 2001-2005 Cedric Bastoul *
17 * This library is free software; you can redistribute it and/or *
18 * modify it under the terms of the GNU Lesser General Public *
19 * License as published by the Free Software Foundation; either *
20 * version 2.1 of the License, or (at your option) any later version. *
22 * This library is distributed in the hope that it will be useful, *
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
25 * Lesser General Public License for more details. *
27 * You should have received a copy of the GNU Lesser General Public *
28 * License along with this library; if not, write to the Free Software *
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
30 * Boston, MA 02110-1301 USA *
32 * CLooG, the Chunky Loop Generator *
33 * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr *
35 ******************************************************************************/
36 /* CAUTION: the english used for comments is probably the worst you ever read,
37 * please feel free to correct and improve it !
42 # include "../include/cloog/cloog.h"
44 #define ALLOC(type) (type*)malloc(sizeof(type))
47 /******************************************************************************
48 * Memory leaks hunting *
49 ******************************************************************************/
53 * These functions and global variables are devoted to memory leaks hunting: we
54 * want to know at each moment how many CloogLoop structures had been allocated
55 * (cloog_loop_allocated) and how many had been freed (cloog_loop_freed).
56 * Each time a CloogLoog structure is allocated, a call to the function
57 * cloog_loop_leak_up() must be carried out, and respectively
58 * cloog_loop_leak_down() when a CloogLoop structure is freed. The special
59 * variable cloog_loop_max gives the maximal number of CloogLoop structures
60 * simultaneously alive (i.e. allocated and non-freed) in memory.
61 * - July 3rd->11th 2003: first version (memory leaks hunt and correction).
65 static void cloog_loop_leak_up(CloogState
*state
)
67 state
->loop_allocated
++;
68 if ((state
->loop_allocated
- state
->loop_freed
) > state
->loop_max
)
69 state
->loop_max
= state
->loop_allocated
- state
->loop_freed
;
73 static void cloog_loop_leak_down(CloogState
*state
)
79 /******************************************************************************
80 * Structure display function *
81 ******************************************************************************/
85 * cloog_loop_print_structure function:
86 * Displays a loop structure in a way that trends to be understandable without
87 * falling in a deep depression or, for the lucky ones, getting a headache...
88 * Written by Olivier Chorier, Luc Marchaud, Pierre Martin and Romain Tartiere.
89 * - April 24th 2005: Initial version.
90 * - May 21rd 2005: - New parameter `F' for destination file (ie stdout),
92 * - May 26th 2005: Memory leak hunt.
93 * - June 2nd 2005: (Ced) Integration and minor fixes.
94 * -June 22nd 2005: (Ced) Adaptation for GMP.
96 void cloog_loop_print_structure(FILE * file
, CloogLoop
* loop
, int level
)
100 { /* Go to the right level. */
101 for (i
=0; i
<level
; i
++)
102 fprintf(file
,"|\t") ;
104 fprintf(file
,"+-- CloogLoop\n") ;
110 { /* Go to the right level. */
111 for (i
=0; i
<level
; i
++)
112 fprintf(file
,"|\t") ;
114 fprintf(file
,"| CloogLoop\n") ;
120 for(j
=0; j
<=level
+1; j
++)
121 fprintf(file
,"|\t") ;
124 /* Print the domain. */
125 cloog_domain_print_structure(file
, loop
->domain
, level
+1, "CloogDomain");
127 /* Print the stride. */
128 for(j
=0; j
<=level
; j
++)
129 fprintf(file
,"|\t") ;
131 fprintf(file
, "Stride: ");
132 cloog_int_print(file
, loop
->stride
->stride
);
134 fprintf(file
, "Offset: ");
135 cloog_int_print(file
, loop
->stride
->offset
);
140 for(j
=0; j
<=level
+1; j
++)
141 fprintf(file
,"|\t") ;
144 /* Print the block. */
145 cloog_block_print_structure(file
,loop
->block
,level
+1) ;
148 for (i
=0; i
<=level
+1; i
++)
149 fprintf(file
,"|\t") ;
152 /* Print inner if any. */
154 cloog_loop_print_structure(file
,loop
->inner
,level
+1) ;
156 /* And let's go for the next one. */
159 /* One more time something that is here only for a better look. */
161 { /* Two blank lines if this is the end of the linked list. */
163 { for (i
=0; i
<=level
; i
++)
164 fprintf(file
,"|\t") ;
170 { /* A special blank line if the is a next loop. */
171 for (i
=0; i
<=level
; i
++)
172 fprintf(file
,"|\t") ;
173 fprintf(file
,"V\n") ;
180 * cloog_loop_print function:
181 * This function prints the content of a CloogLoop structure (start) into a
182 * file (file, possibly stdout).
183 * - June 2nd 2005: Now this very old function (probably as old as CLooG) is
184 * only a frontend to cloog_loop_print_structure, with a quite
185 * better human-readable representation.
187 void cloog_loop_print(FILE * file
, CloogLoop
* loop
)
188 { cloog_loop_print_structure(file
,loop
,0) ;
192 /******************************************************************************
193 * Memory deallocation function *
194 ******************************************************************************/
198 * cloog_loop_free function:
199 * This function frees the allocated memory for a CloogLoop structure (loop),
200 * and frees its inner loops and its next loops.
201 * - June 22nd 2005: Adaptation for GMP.
203 void cloog_loop_free(CloogLoop
* loop
)
206 while (loop
!= NULL
) {
207 cloog_loop_leak_down(loop
->state
);
210 cloog_domain_free(loop
->domain
) ;
211 cloog_domain_free(loop
->unsimplified
);
212 cloog_block_free(loop
->block
) ;
213 if (loop
->inner
!= NULL
)
214 cloog_loop_free(loop
->inner
) ;
216 cloog_stride_free(loop
->stride
);
224 * cloog_loop_free_parts function:
225 * This function frees the allocated memory for some parts of a CloogLoop
226 * structure (loop), each other argument is a boolean having to be set to 1 if
227 * we want to free the corresponding part, 0 otherwise. This function applies
228 * the same freeing policy to its inner ans next loops recursively.
229 * - July 3rd 2003: first version.
230 * - June 22nd 2005: Adaptation for GMP.
232 void cloog_loop_free_parts(loop
, domain
, block
, inner
, next
)
234 int domain
, block
, inner
, next
;
235 { CloogLoop
* follow
;
237 while (loop
!= NULL
) {
238 cloog_loop_leak_down(loop
->state
);
239 follow
= loop
->next
;
242 cloog_domain_free(loop
->domain
) ;
245 cloog_block_free(loop
->block
) ;
247 if ((inner
) && (loop
->inner
!= NULL
))
248 cloog_loop_free_parts(loop
->inner
,domain
,block
,inner
,1) ;
250 cloog_domain_free(loop
->unsimplified
);
251 cloog_stride_free(loop
->stride
);
261 /******************************************************************************
262 * Reading functions *
263 ******************************************************************************/
267 * Construct a CloogLoop structure from a given iteration domain
268 * and statement number.
270 CloogLoop
*cloog_loop_from_domain(CloogState
*state
, CloogDomain
*domain
,
275 CloogStatement
* statement
;
277 /* Memory allocation and information reading for the first domain: */
278 loop
= cloog_loop_malloc(state
);
280 loop
->domain
= domain
;
281 if (loop
->domain
!= NULL
)
282 nb_iterators
= cloog_domain_dimension(loop
->domain
);
285 /* included statement block. */
286 statement
= cloog_statement_alloc(state
, number
+ 1);
287 loop
->block
= cloog_block_alloc(statement
, 0, NULL
, nb_iterators
);
294 * cloog_loop_read function:
295 * This function reads loop data from a file (foo, possibly stdin) and
296 * returns a pointer to a CloogLoop structure containing the read information.
297 * This function can be used only for input file reading, when one loop is
298 * associated with one statement.
299 * - number is the statement block number carried by the loop (-1 if none).
300 * - nb_parameters is the number of parameters.
302 * - September 9th 2002: first version.
303 * - April 16th 2005: adaptation to new CloogStatement struct (with number).
304 * - June 11th 2005: adaptation to new CloogBlock structure.
305 * - June 22nd 2005: Adaptation for GMP.
307 CloogLoop
*cloog_loop_read(CloogState
*state
,
308 FILE *foo
, int number
, int nb_parameters
)
314 domain
= cloog_domain_union_read(state
, foo
, nb_parameters
);
316 /* To read that stupid "0 0 0" line. */
317 while (fgets(s
,MAX_STRING
,foo
) == 0) ;
318 while ((*s
=='#' || *s
=='\n') || (sscanf(s
," %d %d %d",&op1
,&op2
,&op3
)<3))
319 fgets(s
,MAX_STRING
,foo
) ;
321 return cloog_loop_from_domain(state
, domain
, number
);
325 /******************************************************************************
326 * Processing functions *
327 ******************************************************************************/
331 * cloog_loop_malloc function:
332 * This function allocates the memory space for a CloogLoop structure and
333 * sets its fields with default values. Then it returns a pointer to the
335 * - November 21th 2005: first version.
337 CloogLoop
*cloog_loop_malloc(CloogState
*state
)
340 /* Memory allocation for the CloogLoop structure. */
341 loop
= (CloogLoop
*)malloc(sizeof(CloogLoop
)) ;
343 cloog_die("memory overflow.\n");
344 cloog_loop_leak_up(state
);
347 /* We set the various fields with default values. */
349 loop
->domain
= NULL
;
350 loop
->unsimplified
= NULL
;
363 * cloog_loop_alloc function:
364 * This function allocates the memory space for a CloogLoop structure and
365 * sets its fields with those given as input. Then it returns a pointer to the
367 * - October 27th 2001: first version.
368 * - June 22nd 2005: Adaptation for GMP.
369 * - November 21th 2005: use of cloog_loop_malloc.
371 CloogLoop
*cloog_loop_alloc(CloogState
*state
,
372 CloogDomain
*domain
, int otl
, CloogStride
*stride
,
373 CloogBlock
*block
, CloogLoop
*inner
, CloogLoop
*next
)
376 loop
= cloog_loop_malloc(state
);
378 loop
->domain
= domain
;
379 loop
->block
= block
;
380 loop
->inner
= inner
;
383 loop
->stride
= cloog_stride_copy(stride
);
390 * cloog_loop_add function:
391 * This function adds a CloogLoop structure (loop) at a given place (now) of a
392 * NULL terminated list of CloogLoop structures. The beginning of this list
393 * is (start). This function updates (now) to (loop), and updates (start) if the
394 * added element is the first one -that is when (start) is NULL-.
395 * - October 28th 2001: first version.
397 void cloog_loop_add(CloogLoop
** start
, CloogLoop
** now
, CloogLoop
* loop
)
398 { if (*start
== NULL
)
403 { (*now
)->next
= loop
;
404 *now
= (*now
)->next
;
410 * cloog_loop_add function:
411 * This function adds a CloogLoop structure (loop) at a given place (now) of a
412 * NULL terminated list of CloogLoop structures. The beginning of this list
413 * is (start). This function updates (now) to the end of the loop list (loop),
414 * and updates (start) if the added element is the first one -that is when
416 * - September 9th 2005: first version.
418 void cloog_loop_add_list(CloogLoop
** start
, CloogLoop
** now
, CloogLoop
* loop
)
419 { if (*start
== NULL
)
424 { (*now
)->next
= loop
;
425 *now
= (*now
)->next
;
428 while ((*now
)->next
!= NULL
)
429 *now
= (*now
)->next
;
434 * cloog_loop_copy function:
435 * This function returns a copy of the CloogLoop structure given as input. In
436 * fact, there is just new allocations for the CloogLoop structures, but their
437 * contents are the same.
438 * - October 28th 2001: first version.
439 * - July 3rd->11th 2003: memory leaks hunt and correction.
441 CloogLoop
* cloog_loop_copy(CloogLoop
* source
)
444 CloogDomain
* domain
;
448 { domain
= cloog_domain_copy(source
->domain
) ;
449 block
= cloog_block_copy(source
->block
) ;
450 loop
= cloog_loop_alloc(source
->state
, domain
, source
->otl
,
451 source
->stride
, block
, NULL
, NULL
);
452 loop
->usr
= source
->usr
;
453 loop
->inner
= cloog_loop_copy(source
->inner
) ;
454 loop
->next
= cloog_loop_copy(source
->next
) ;
461 * cloog_loop_add_disjoint function:
462 * This function adds some CloogLoop structures at a given place (now) of a
463 * NULL terminated list of CloogLoop structures. The beginning of this list
464 * is (start). (loop) can be an union of polyhedra, this function separates the
465 * union into a list of *disjoint* polyhedra then adds the list. This function
466 * updates (now) to the end of the list and updates (start) if first added
467 * element is the first of the principal list -that is when (start) is NULL-.
468 * (loop) can be freed by this function, basically when its domain is actually
469 * a union of polyhedra, but don't worry, all the useful data are now stored
470 * inside the list (start). We do not use PolyLib's Domain_Disjoint function,
471 * since the number of union components is often higher (thus code size too).
472 * - October 28th 2001: first version.
473 * - November 14th 2001: bug correction (this one was hard to find !).
474 * - July 3rd->11th 2003: memory leaks hunt and correction.
475 * - June 22nd 2005: Adaptation for GMP.
476 * - October 27th 2005: (debug) included blocks were not copied for new loops.
478 void cloog_loop_add_disjoint(start
, now
, loop
)
479 CloogLoop
** start
, ** now
, * loop
;
481 CloogLoop
* sep
, * inner
;
482 CloogDomain
*domain
, *seen
, *temp
, *rest
;
485 if (cloog_domain_isconvex(loop
->domain
))
486 cloog_loop_add(start
,now
,loop
) ;
488 domain
= cloog_domain_simplify_union(loop
->domain
);
489 loop
->domain
= NULL
;
491 /* We separate the first element of the rest of the union. */
492 domain
= cloog_domain_cut_first(domain
, &rest
);
494 /* This first element is the first of the list of disjoint polyhedra. */
495 sep
= cloog_loop_alloc(loop
->state
, domain
, 0, NULL
,
496 loop
->block
, loop
->inner
, NULL
);
497 cloog_loop_add(start
,now
,sep
) ;
499 seen
= cloog_domain_copy(domain
);
500 while (!cloog_domain_isempty(domain
= rest
)) {
501 temp
= cloog_domain_cut_first(domain
, &rest
);
502 domain
= cloog_domain_difference(temp
, seen
);
503 cloog_domain_free(temp
);
505 if (cloog_domain_isempty(domain
)) {
506 cloog_domain_free(domain
);
510 /* Each new loop will have its own life, for instance we can free its
511 * inner loop and included block. Then each one must have its own copy
512 * of both 'inner' and 'block'.
514 inner
= cloog_loop_copy(loop
->inner
) ;
515 block
= cloog_block_copy(loop
->block
) ;
517 sep
= cloog_loop_alloc(loop
->state
, cloog_domain_copy(domain
),
518 0, NULL
, block
, inner
, NULL
);
519 /* domain can be an union too. If so: recursion. */
520 if (cloog_domain_isconvex(domain
))
521 cloog_loop_add(start
,now
,sep
) ;
523 cloog_loop_add_disjoint(start
,now
,sep
) ;
525 if (cloog_domain_isempty(rest
)) {
526 cloog_domain_free(domain
);
530 seen
= cloog_domain_union(seen
, domain
);
532 cloog_domain_free(rest
);
533 cloog_domain_free(seen
);
534 cloog_loop_free_parts(loop
,0,0,0,0) ;
540 * cloog_loop_disjoint function:
541 * This function returns a list of loops such that each loop with non-convex
542 * domain in the input list (loop) is separated into several loops where the
543 * domains are the components of the union of *disjoint* polyhedra equivalent
544 * to the original non-convex domain. See cloog_loop_add_disjoint comments
546 * - September 16th 2005: first version.
548 CloogLoop
* cloog_loop_disjoint(CloogLoop
* loop
)
549 { CloogLoop
*res
=NULL
, * now
=NULL
, * next
;
551 /* Because this is often the case, don't waste time ! */
552 if (loop
&& !loop
->next
&& cloog_domain_isconvex(loop
->domain
))
556 { next
= loop
->next
;
558 cloog_loop_add_disjoint(&res
,&now
,loop
) ;
567 * cloog_loop_restrict function:
568 * This function returns the (loop) in the context of (context): it makes the
569 * intersection between the (loop) domain and the (context), then it returns
570 * a pointer to a new loop, with this intersection as domain.
572 * - October 27th 2001: first version.
573 * - June 15th 2005: a memory leak fixed (domain was not freed when empty).
574 * - June 22nd 2005: Adaptation for GMP.
576 CloogLoop
*cloog_loop_restrict(CloogLoop
*loop
, CloogDomain
*context
)
577 { int new_dimension
;
578 CloogDomain
* domain
, * extended_context
, * new_domain
;
579 CloogLoop
* new_loop
;
581 domain
= loop
->domain
;
582 if (cloog_domain_dimension(domain
) > cloog_domain_dimension(context
))
584 new_dimension
= cloog_domain_dimension(domain
);
585 extended_context
= cloog_domain_extend(context
, new_dimension
);
586 new_domain
= cloog_domain_intersection(extended_context
,loop
->domain
) ;
587 cloog_domain_free(extended_context
) ;
590 new_domain
= cloog_domain_intersection(context
,loop
->domain
) ;
592 if (cloog_domain_isempty(new_domain
))
593 { cloog_domain_free(new_domain
) ;
597 new_loop
= cloog_loop_alloc(loop
->state
, new_domain
,
598 0, NULL
, loop
->block
, loop
->inner
, NULL
);
605 * Call cloog_loop_restrict on each loop in the list "loop" and return
606 * the concatenated result.
608 CloogLoop
*cloog_loop_restrict_all(CloogLoop
*loop
, CloogDomain
*context
)
611 CloogLoop
*res
= NULL
;
612 CloogLoop
**res_next
= &res
;
614 for (; loop
; loop
= next
) {
617 *res_next
= cloog_loop_restrict(loop
, context
);
619 res_next
= &(*res_next
)->next
;
620 cloog_loop_free_parts(loop
, 1, 0, 0, 0);
623 cloog_loop_free(loop
);
632 * Restrict the domains of the inner loops of each loop l in the given
633 * list of loops to the domain of the loop l. If the domains of all
634 * inner loops of a given loop l turn out to be empty, then remove l
637 CloogLoop
*cloog_loop_restrict_inner(CloogLoop
*loop
)
641 CloogLoop
**res_next
= &res
;
643 for (; loop
; loop
= next
) {
646 loop
->inner
= cloog_loop_restrict_all(loop
->inner
, loop
->domain
);
649 res_next
= &(*res_next
)->next
;
652 cloog_loop_free(loop
);
662 * cloog_loop_project function:
663 * This function returns the projection of (loop) on the (level) first
664 * dimensions (outer loops). It makes the projection of the (loop) domain,
665 * then it returns a pointer to a new loop, with this projection as domain.
667 * - October 27th 2001: first version.
668 * - July 3rd->11th 2003: memory leaks hunt and correction.
669 * - June 22nd 2005: Adaptation for GMP.
671 CloogLoop
* cloog_loop_project(CloogLoop
* loop
, int level
)
673 CloogDomain
* new_domain
;
674 CloogLoop
* new_loop
, * copy
;
676 copy
= cloog_loop_alloc(loop
->state
, loop
->domain
, loop
->otl
, loop
->stride
,
677 loop
->block
, loop
->inner
, NULL
);
679 if (cloog_domain_dimension(loop
->domain
) == level
)
680 new_domain
= cloog_domain_copy(loop
->domain
) ;
682 new_domain
= cloog_domain_project(loop
->domain
, level
);
684 new_loop
= cloog_loop_alloc(loop
->state
, new_domain
, 0, NULL
,
692 * Call cloog_loop_project on each loop in the list "loop" and return
693 * the concatenated result.
695 CloogLoop
*cloog_loop_project_all(CloogLoop
*loop
, int level
)
698 CloogLoop
*res
= NULL
;
699 CloogLoop
**res_next
= &res
;
701 for (; loop
; loop
= next
) {
704 *res_next
= cloog_loop_project(loop
, level
);
705 res_next
= &(*res_next
)->next
;
706 cloog_loop_free_parts(loop
, 0, 0, 0, 0);
714 * cloog_loop_concat function:
715 * This function returns a pointer to the concatenation of the
716 * CloogLoop lists given as input.
717 * - October 28th 2001: first version.
719 CloogLoop
* cloog_loop_concat(CloogLoop
* a
, CloogLoop
* b
)
720 { CloogLoop
* loop
, * temp
;
725 { while (temp
->next
!= NULL
)
737 * cloog_loop_combine:
738 * Combine consecutive loops with identical domains into
739 * a single loop with the concatenation of their inner loops
742 CloogLoop
*cloog_loop_combine(CloogLoop
*loop
)
744 CloogLoop
*first
, *second
;
746 for (first
= loop
; first
; first
= first
->next
) {
747 while (first
->next
) {
748 if (!cloog_domain_lazy_equal(first
->domain
, first
->next
->domain
))
750 second
= first
->next
;
751 first
->inner
= cloog_loop_concat(first
->inner
, second
->inner
);
752 first
->next
= second
->next
;
753 cloog_loop_free_parts(second
, 1, 0, 0, 0);
761 * Remove loops from list that have an empty domain.
763 CloogLoop
*cloog_loop_remove_empty_domain_loops(CloogLoop
*loop
)
765 CloogLoop
*l
, *res
, *next
, **res_next
;
769 for (l
= loop
; l
; l
= next
) {
771 if (cloog_domain_isempty(l
->domain
))
772 cloog_loop_free_parts(l
, 1, 1, 1, 0);
775 res_next
= &(*res_next
)->next
;
783 CloogLoop
*cloog_loop_decompose_inner(CloogLoop
*loop
,
784 int level
, int scalar
, int *scaldims
, int nb_scattdims
);
786 /* For each loop with only one inner loop, replace the domain
787 * of the loop with the projection of the domain of the inner
788 * loop. To increase the number of loops with a single inner
789 * we first decompose the inner loops into strongly connected
792 CloogLoop
*cloog_loop_specialize(CloogLoop
*loop
,
793 int level
, int scalar
, int *scaldims
, int nb_scattdims
)
799 loop
= cloog_loop_decompose_inner(loop
, level
, scalar
,
800 scaldims
, nb_scattdims
);
802 for (l
= loop
; l
; l
= l
->next
) {
805 if (!cloog_domain_isconvex(l
->inner
->domain
))
808 dim
= cloog_domain_dimension(l
->domain
);
809 domain
= cloog_domain_project(l
->inner
->domain
, dim
);
810 if (cloog_domain_isconvex(domain
)) {
811 cloog_domain_free(l
->domain
);
814 cloog_domain_free(domain
);
818 return cloog_loop_remove_empty_domain_loops(loop
);
821 /* For each loop with only one inner loop, propagate the bounds from
822 * the inner loop domain to the outer loop domain. This is especially
823 * useful if the inner loop domain has a non-trivial stride which
824 * results in an update of the lower bound.
826 CloogLoop
*cloog_loop_propagate_lower_bound(CloogLoop
*loop
, int level
)
829 CloogDomain
*domain
, *t
;
832 for (l
= loop
; l
; l
= l
->next
) {
835 if (!cloog_domain_isconvex(l
->inner
->domain
))
838 dim
= cloog_domain_dimension(l
->domain
);
839 domain
= cloog_domain_project(l
->inner
->domain
, dim
);
840 if (cloog_domain_isconvex(domain
)) {
841 t
= cloog_domain_intersection(domain
, l
->domain
);
842 cloog_domain_free(l
->domain
);
845 cloog_domain_free(domain
);
852 * cloog_loop_separate function:
853 * This function implements the Quillere algorithm for separation of multiple
854 * loops: for a given set of polyhedra (loop), it computes a set of disjoint
855 * polyhedra such that the unions of these sets are equal, and returns this set.
856 * - October 28th 2001: first version.
857 * - November 14th 2001: elimination of some unused blocks.
858 * - August 13th 2002: (debug) in the case of union of polyhedra for one
859 * loop, redundant constraints are fired.
860 * - July 3rd->11th 2003: memory leaks hunt and correction.
861 * - June 22nd 2005: Adaptation for GMP.
862 * - October 16th 2005: Removal of the non-shared constraint elimination when
863 * there is only one loop in the list (seems to work
864 * without now, DomainSimplify may have been improved).
865 * The problem was visible with test/iftest2.cloog.
867 CloogLoop
* cloog_loop_separate(CloogLoop
* loop
)
868 { int lazy_equal
=0, disjoint
= 0;
869 CloogLoop
* new_loop
, * new_inner
, * res
, * now
, * temp
, * Q
,
870 * inner
, * old
/*, * previous, * next*/ ;
871 CloogDomain
*UQ
, *domain
;
876 loop
= cloog_loop_combine(loop
);
878 if (loop
->next
== NULL
)
879 return cloog_loop_disjoint(loop
) ;
881 UQ
= cloog_domain_copy(loop
->domain
) ;
882 domain
= cloog_domain_copy(loop
->domain
) ;
883 res
= cloog_loop_alloc(loop
->state
, domain
, 0, NULL
,
884 loop
->block
, loop
->inner
, NULL
);
887 while((loop
= loop
->next
) != NULL
)
890 /* For all Q, add Q-loop associated with the blocks of Q alone,
891 * and Q inter loop associated with the blocks of Q and loop.
893 for (Q
= res
; Q
; Q
= Q
->next
) {
894 /* Add (Q inter loop). */
895 if ((disjoint
= cloog_domain_lazy_disjoint(Q
->domain
,loop
->domain
)))
898 { if ((lazy_equal
= cloog_domain_lazy_equal(Q
->domain
,loop
->domain
)))
899 domain
= cloog_domain_copy(Q
->domain
) ;
901 domain
= cloog_domain_intersection(Q
->domain
,loop
->domain
) ;
903 if (!cloog_domain_isempty(domain
))
904 { new_inner
= cloog_loop_concat(cloog_loop_copy(Q
->inner
),
905 cloog_loop_copy(loop
->inner
)) ;
906 new_loop
= cloog_loop_alloc(loop
->state
, domain
, 0, NULL
,
907 NULL
, new_inner
, NULL
);
908 cloog_loop_add_disjoint(&temp
,&now
,new_loop
) ;
912 cloog_domain_free(domain
);
916 /* Add (Q - loop). */
918 domain
= cloog_domain_copy(Q
->domain
) ;
921 domain
= cloog_domain_empty(Q
->domain
);
923 domain
= cloog_domain_difference(Q
->domain
,loop
->domain
) ;
926 if (!cloog_domain_isempty(domain
)) {
927 new_loop
= cloog_loop_alloc(loop
->state
, domain
, 0, NULL
,
928 NULL
, Q
->inner
, NULL
);
929 cloog_loop_add_disjoint(&temp
,&now
,new_loop
) ;
932 { cloog_domain_free(domain
) ;
933 /* If Q->inner is no more useful, we can free it. */
936 cloog_loop_free(inner
) ;
940 /* Add loop-UQ associated with the blocks of loop alone.*/
941 if (cloog_domain_lazy_disjoint(loop
->domain
,UQ
))
942 domain
= cloog_domain_copy(loop
->domain
) ;
944 { if (cloog_domain_lazy_equal(loop
->domain
,UQ
))
945 domain
= cloog_domain_empty(UQ
);
947 domain
= cloog_domain_difference(loop
->domain
,UQ
) ;
950 if (!cloog_domain_isempty(domain
)) {
951 new_loop
= cloog_loop_alloc(loop
->state
, domain
, 0, NULL
,
952 NULL
, loop
->inner
, NULL
);
953 cloog_loop_add_disjoint(&temp
,&now
,new_loop
) ;
956 { cloog_domain_free(domain
) ;
957 /* If loop->inner is no more useful, we can free it. */
958 cloog_loop_free(loop
->inner
) ;
963 if (loop
->next
!= NULL
)
964 UQ
= cloog_domain_union(UQ
, cloog_domain_copy(loop
->domain
));
966 cloog_domain_free(UQ
);
968 cloog_loop_free_parts(res
,1,0,0,1) ;
972 cloog_loop_free_parts(old
,1,0,0,1) ;
978 static CloogDomain
*bounding_domain(CloogDomain
*dom
, CloogOptions
*options
)
981 return cloog_domain_simple_convex(dom
);
983 return cloog_domain_convex(dom
);
988 * cloog_loop_merge function:
989 * This function is the 'soft' version of loop_separate if we are looking for
990 * a code much simpler (and less efficicient). This function returns the new
992 * - October 29th 2001: first version.
993 * - July 3rd->11th 2003: memory leaks hunt and correction.
994 * - June 22nd 2005: Adaptation for GMP.
996 CloogLoop
*cloog_loop_merge(CloogLoop
*loop
, int level
, CloogOptions
*options
)
998 CloogLoop
*res
, *new_inner
, *old
;
999 CloogDomain
*new_domain
, *temp
;
1004 if (loop
->next
== NULL
&& cloog_domain_isconvex(loop
->domain
))
1008 temp
= loop
->domain
;
1009 loop
->domain
= NULL
;
1010 new_inner
= loop
->inner
;
1012 for (loop
= loop
->next
; loop
; loop
= loop
->next
) {
1013 temp
= cloog_domain_union(temp
, loop
->domain
);
1014 loop
->domain
= NULL
;
1015 new_inner
= cloog_loop_concat(new_inner
, loop
->inner
);
1018 new_domain
= bounding_domain(temp
, options
);
1020 if (level
> 0 && !cloog_domain_is_bounded(new_domain
, level
) &&
1021 cloog_domain_is_bounded(temp
, level
)) {
1022 CloogDomain
*splitter
, *t2
;
1024 cloog_domain_free(new_domain
);
1025 splitter
= cloog_domain_bound_splitter(temp
, level
);
1028 while (!cloog_domain_isconvex(splitter
)) {
1029 CloogDomain
*first
, *rest
;
1030 first
= cloog_domain_cut_first(splitter
, &rest
);
1032 t2
= cloog_domain_intersection(first
, temp
);
1033 cloog_domain_free(first
);
1035 new_domain
= bounding_domain(t2
, options
);
1036 cloog_domain_free(t2
);
1038 if (cloog_domain_isempty(new_domain
)) {
1039 cloog_domain_free(new_domain
);
1042 res
= cloog_loop_alloc(old
->state
, new_domain
, 0, NULL
,
1043 NULL
, cloog_loop_copy(new_inner
), res
);
1046 t2
= cloog_domain_intersection(splitter
, temp
);
1047 cloog_domain_free(splitter
);
1049 new_domain
= bounding_domain(t2
, options
);
1050 cloog_domain_free(t2
);
1052 if (cloog_domain_isempty(new_domain
)) {
1053 cloog_domain_free(new_domain
);
1054 cloog_loop_free(new_inner
);
1056 res
= cloog_loop_alloc(old
->state
, new_domain
, 0, NULL
,
1057 NULL
, new_inner
, res
);
1059 res
= cloog_loop_alloc(old
->state
, new_domain
, 0, NULL
,
1060 NULL
, new_inner
, NULL
);
1062 cloog_domain_free(temp
);
1064 cloog_loop_free_parts(old
, 0, 0, 0, 1);
1070 static int cloog_loop_count(CloogLoop
*loop
)
1074 for (nb_loops
= 0; loop
; loop
= loop
->next
)
1082 * cloog_loop_sort function:
1083 * Adaptation from LoopGen 0.4 by F. Quillere. This function sorts a list of
1084 * parameterized disjoint polyhedra, in order to not have lexicographic order
1085 * violation (see Quillere paper).
1086 * - September 16th 2005: inclusion of cloog_loop_number (October 29th 2001).
1088 CloogLoop
*cloog_loop_sort(CloogLoop
*loop
, int level
)
1090 CloogLoop
*res
, *now
, **loop_array
;
1092 int i
, nb_loops
=0, * permut
;
1094 /* There is no need to sort the parameter domains. */
1098 /* We will need to know how many loops are in the list. */
1099 nb_loops
= cloog_loop_count(loop
);
1101 /* If there is only one loop, it's the end. */
1105 /* We have to allocate memory for some useful components:
1106 * - loop_array: the loop array,
1107 * - doms: the array of domains to sort,
1108 * - permut: will give us a possible sort (maybe not the only one).
1110 loop_array
= (CloogLoop
**)malloc(nb_loops
*sizeof(CloogLoop
*)) ;
1111 doms
= (CloogDomain
**)malloc(nb_loops
*sizeof(CloogDomain
*));
1112 permut
= (int *)malloc(nb_loops
*sizeof(int)) ;
1114 /* We fill up the loop and domain arrays. */
1115 for (i
=0;i
<nb_loops
;i
++,loop
=loop
->next
)
1116 { loop_array
[i
] = loop
;
1117 doms
[i
] = loop_array
[i
]->domain
;
1120 /* cloog_domain_sort will fill up permut. */
1121 cloog_domain_sort(doms
, nb_loops
, level
, permut
);
1123 /* With permut and loop_array we build the sorted list. */
1125 for (i
=0;i
<nb_loops
;i
++)
1126 { /* To avoid pointer looping... loop_add will rebuild the list. */
1127 loop_array
[permut
[i
]-1]->next
= NULL
;
1128 cloog_loop_add(&res
,&now
,loop_array
[permut
[i
]-1]) ;
1140 * cloog_loop_nest function:
1141 * This function changes the loop list in such a way that we have no more than
1142 * one dimension added by level. It returns an equivalent loop list with
1144 * - October 29th 2001: first version.
1145 * - July 3rd->11th 2003: memory leaks hunt and correction.
1146 * - June 22nd 2005: Adaptation for GMP.
1147 * - November 21th 2005: (debug) now OK when cloog_loop_restrict returns NULL.
1149 CloogLoop
*cloog_loop_nest(CloogLoop
*loop
, CloogDomain
*context
, int level
)
1151 CloogLoop
* p
, * temp
, * res
, * now
, * next
;
1152 CloogDomain
* new_domain
;
1154 loop
= cloog_loop_disjoint(loop
);
1157 /* Each domain is changed by its intersection with the context. */
1158 while (loop
!= NULL
)
1159 { p
= cloog_loop_restrict(loop
, context
);
1163 { cloog_loop_free_parts(loop
,1,0,0,0) ;
1165 temp
= cloog_loop_alloc(p
->state
, p
->domain
, 0, NULL
,
1166 p
->block
, p
->inner
, NULL
);
1168 /* If the intersection dimension is too big, we make projections smaller
1169 * and smaller, and each projection includes the preceding projection
1170 * (thus, in the target list, dimensions are added one by one).
1172 if (cloog_domain_dimension(p
->domain
) >= level
)
1173 for (l
= cloog_domain_dimension(p
->domain
); l
>= level
; l
--) {
1174 new_domain
= cloog_domain_project(p
->domain
, l
);
1175 temp
= cloog_loop_alloc(p
->state
, new_domain
, 0, NULL
,
1179 /* p is no more useful (but its content yes !). */
1180 cloog_loop_free_parts(p
,0,0,0,0) ;
1182 cloog_loop_add(&res
,&now
,temp
) ;
1185 cloog_loop_free_parts(loop
,1,1,1,0) ;
1194 /* Check if the domains of the inner loops impose a stride constraint
1195 * on the given level.
1196 * The core of the search is implemented in cloog_domain_list_stride.
1197 * Here, we simply construct a list of domains to pass to this function
1198 * and if a stride is found, we adjust the lower bounds by calling
1199 * cloog_domain_stride_lower_bound.
1201 static int cloog_loop_variable_offset_stride(CloogLoop
*loop
, int level
)
1203 CloogDomainList
*list
= NULL
;
1205 CloogStride
*stride
;
1207 for (inner
= loop
->inner
; inner
; inner
= inner
->next
) {
1208 CloogDomainList
*entry
= ALLOC(CloogDomainList
);
1209 entry
->domain
= cloog_domain_copy(inner
->domain
);
1214 stride
= cloog_domain_list_stride(list
, level
);
1216 cloog_domain_list_free(list
);
1221 loop
->stride
= stride
;
1222 loop
->domain
= cloog_domain_stride_lower_bound(loop
->domain
, level
, stride
);
1229 * cloog_loop_stride function:
1230 * This function will find the stride of a loop for the iterator at the column
1231 * number 'level' in the constraint matrix. It will update the lower bound of
1232 * the iterator accordingly. Basically, the function will try to find in the
1233 * inner loops a common condition on this iterator for the inner loop iterators
1234 * to be integral. For instance, let us consider a loop with the iterator i,
1235 * the iteration domain -4<=i<=n, and its two inner loops with the iterator j.
1236 * The first inner loop has the constraint 3j=i, and the second one has the
1237 * constraint 6j=i. Then the common constraint on i for j to be integral is
1238 * i%3=0, the stride for i is 3. Lastly, we have to find the new lower bound
1239 * for i: the first value satisfying the common constraint: -3. At the end, the
1240 * iteration domain for i is -3<=i<=n and the stride for i is 3.
1242 * The algorithm implemented in this function only allows for strides
1243 * on loops with a lower bound that has a constant remainder on division
1244 * by the stride. Before initiating this procedure, we first check
1245 * if we can find a stride with a lower bound with a variable offset in
1246 * cloog_loop_variable_offset_stride.
1248 * - loop is the loop including the iteration domain of the considered iterator,
1249 * - level is the column number of the iterator in the matrix of contraints.
1251 * - June 29th 2003: first version (work in progress since June 26th 2003).
1252 * - July 14th 2003: simpler version.
1253 * - June 22nd 2005: Adaptation for GMP (from S. Verdoolaege's 0.12.1 version).
1255 void cloog_loop_stride(CloogLoop
* loop
, int level
)
1256 { int first_search
;
1257 cloog_int_t stride
, ref_offset
, offset
, potential
;
1260 if (!cloog_domain_can_stride(loop
->domain
, level
))
1263 if (cloog_loop_variable_offset_stride(loop
, level
))
1266 cloog_int_init(stride
);
1267 cloog_int_init(ref_offset
);
1268 cloog_int_init(offset
);
1269 cloog_int_init(potential
);
1271 cloog_int_set_si(ref_offset
, 0);
1272 cloog_int_set_si(offset
, 0);
1274 /* Default stride. */
1275 cloog_int_set_si(stride
, 1);
1277 inner
= loop
->inner
;
1279 while (inner
!= NULL
)
1280 { /* If the minimun stride has not been found yet, find the stride. */
1281 if ((first_search
) || (!cloog_int_is_one(stride
)))
1283 cloog_domain_stride(inner
->domain
, level
, &potential
, &offset
);
1284 if (!cloog_int_is_one(potential
) && (!first_search
))
1285 { /* Offsets must be the same for common stride. */
1286 cloog_int_gcd(stride
, potential
, stride
);
1287 if (!cloog_int_is_zero(stride
)) {
1288 cloog_int_fdiv_r(offset
, offset
, stride
);
1289 cloog_int_fdiv_r(ref_offset
, ref_offset
, stride
);
1291 if (cloog_int_ne(offset
,ref_offset
))
1292 cloog_int_set_si(stride
, 1);
1295 cloog_int_set(stride
, potential
);
1296 cloog_int_set(ref_offset
, offset
);
1302 inner
= inner
->next
;
1305 if (cloog_int_is_zero(stride
))
1306 cloog_int_set_si(stride
, 1);
1308 /* Update the values if necessary. */
1309 if (!cloog_int_is_one(stride
))
1310 { /* Update the stride value. */
1311 if (!cloog_int_is_zero(offset
))
1312 cloog_int_sub(offset
, stride
, offset
);
1313 loop
->stride
= cloog_stride_alloc(stride
, offset
);
1314 loop
->domain
= cloog_domain_stride_lower_bound(loop
->domain
, level
,
1318 cloog_int_clear(stride
);
1319 cloog_int_clear(ref_offset
);
1320 cloog_int_clear(offset
);
1321 cloog_int_clear(potential
);
1325 void cloog_loop_otl(CloogLoop
*loop
, int level
)
1327 if (cloog_domain_is_otl(loop
->domain
, level
))
1333 * cloog_loop_stop function:
1334 * This function implements the 'stop' option : each domain of each loop
1335 * in the list 'loop' is replaced by 'context'. 'context' should be the
1336 * domain of the outer loop. By using this method, there are no more dimensions
1337 * to scan and the simplification step will automaticaly remove the domains
1338 * since they are the same as the corresponding contexts. The effect of this
1339 * function is to stop the code generation at the level this function is called,
1340 * the resulting code do not consider the next dimensions.
1341 * - January 11th 2005: first version.
1343 CloogLoop
* cloog_loop_stop(CloogLoop
* loop
, CloogDomain
* context
)
1347 { cloog_domain_free(loop
->domain
) ;
1348 loop
->domain
= cloog_domain_copy(context
) ;
1349 loop
->next
= cloog_loop_stop(loop
->next
, context
) ;
1356 static int level_is_constant(int level
, int scalar
, int *scaldims
, int nb_scattdims
)
1358 return level
&& (level
+scalar
<= nb_scattdims
) && (scaldims
[level
+scalar
-1]);
1363 * Compare the constant dimensions of loops 'l1' and 'l2' starting at 'scalar'
1364 * and return -1 if the vector of constant dimensions of 'l1' is smaller
1365 * than that of 'l2', 0 if they are the same and +1 if that of 'l1' is
1366 * greater than that of 'l2'.
1367 * This function should be called on the innermost loop (the loop
1368 * containing a block).
1369 * \param l1 Loop to be compared with l2.
1370 * \param l2 Loop to be compared with l1.
1371 * \param level Current non-scalar dimension.
1372 * \param scaldims Boolean array saying whether a dimension is scalar or not.
1373 * \param nb_scattdims Size of the scaldims array.
1374 * \param scalar Current scalar dimension.
1375 * \return -1 if (l1 < l2), 0 if (l1 == l2) and +1 if (l1 > l2)
1377 int cloog_loop_constant_cmp(CloogLoop
*l1
, CloogLoop
*l2
, int level
,
1378 int *scaldims
, int nb_scattdims
, int scalar
)
1380 CloogBlock
*b1
, *b2
;
1383 while (level_is_constant(level
, scalar
, scaldims
, nb_scattdims
)) {
1384 int cmp
= cloog_int_cmp(b1
->scaldims
[scalar
], b2
->scaldims
[scalar
]);
1394 * cloog_loop_scalar_gt function:
1395 * This function returns 1 if loop 'l1' is greater than loop 'l2' for the
1396 * scalar dimension vector that begins at dimension 'scalar', 0 otherwise. What
1397 * we want to know is whether a loop is scheduled before another one or not.
1398 * This function solves the problem when the considered dimension for scheduling
1399 * is a scalar dimension. Since there may be a succession of scalar dimensions,
1400 * this function will reason about the vector of scalar dimension that begins
1401 * at dimension 'level+scalar' and finish to the first non-scalar dimension.
1402 * \param l1 Loop to be compared with l2.
1403 * \param l2 Loop to be compared with l1.
1404 * \param level Current non-scalar dimension.
1405 * \param scaldims Boolean array saying whether a dimension is scalar or not.
1406 * \param nb_scattdims Size of the scaldims array.
1407 * \param scalar Current scalar dimension.
1408 * \return 1 if (l1 > l2), 0 otherwise.
1410 * - September 9th 2005: first version.
1411 * - October 15nd 2007: now "greater than" instead of "greater or equal".
1413 int cloog_loop_scalar_gt(l1
, l2
, level
, scaldims
, nb_scattdims
, scalar
)
1414 CloogLoop
* l1
, * l2
;
1415 int level
, * scaldims
, nb_scattdims
, scalar
;
1417 return cloog_loop_constant_cmp(l1
, l2
, level
, scaldims
, nb_scattdims
, scalar
) > 0;
1422 * cloog_loop_scalar_eq function:
1423 * This function returns 1 if loop 'l1' is equal to loop 'l2' for the scalar
1424 * dimension vector that begins at dimension 'scalar', 0 otherwise. What we want
1425 * to know is whether two loops are scheduled for the same time or not.
1426 * This function solves the problem when the considered dimension for scheduling
1427 * is a scalar dimension. Since there may be a succession of scalar dimensions,
1428 * this function will reason about the vector of scalar dimension that begins
1429 * at dimension 'level+scalar' and finish to the first non-scalar dimension.
1430 * - l1 and l2 are the loops to compare,
1431 * - level is the current non-scalar dimension,
1432 * - scaldims is the boolean array saying whether a dimension is scalar or not,
1433 * - nb_scattdims is the size of the scaldims array,
1434 * - scalar is the current scalar dimension.
1436 * - September 9th 2005 : first version.
1438 int cloog_loop_scalar_eq(l1
, l2
, level
, scaldims
, nb_scattdims
, scalar
)
1439 CloogLoop
* l1
, * l2
;
1440 int level
, * scaldims
, nb_scattdims
, scalar
;
1442 return cloog_loop_constant_cmp(l1
, l2
, level
, scaldims
, nb_scattdims
, scalar
) == 0;
1447 * cloog_loop_scalar_sort function:
1448 * This function sorts a linked list of loops (loop) with respect to the
1449 * scalar dimension vector that begins at dimension 'scalar'. Since there may
1450 * be a succession of scalar dimensions, this function will reason about the
1451 * vector of scalar dimension that begins at dimension 'level+scalar' and
1452 * finish to the first non-scalar dimension.
1453 * \param loop Loop list to sort.
1454 * \param level Current non-scalar dimension.
1455 * \param scaldims Boolean array saying whether a dimension is scalar or not.
1456 * \param nb_scattdims Size of the scaldims array.
1457 * \param scalar Current scalar dimension.
1458 * \return A pointer to the sorted list.
1460 * - July 2nd 2005: first developments.
1461 * - September 2nd 2005: first version.
1462 * - October 15nd 2007: complete rewrite to remove bugs, now a bubble sort.
1464 CloogLoop
* cloog_loop_scalar_sort(loop
, level
, scaldims
, nb_scattdims
, scalar
)
1466 int level
, * scaldims
, nb_scattdims
, scalar
;
1468 CloogLoop
**current
;
1472 for (current
= &loop
; (*current
)->next
; current
= &(*current
)->next
) {
1473 CloogLoop
*next
= (*current
)->next
;
1474 if (cloog_loop_scalar_gt(*current
,next
,level
,scaldims
,nb_scattdims
,scalar
)) {
1476 (*current
)->next
= next
->next
;
1477 next
->next
= *current
;
1488 * cloog_loop_generate_backtrack function:
1489 * adaptation from LoopGen 0.4 by F. Quillere. This function implements the
1490 * backtrack of the Quillere et al. algorithm (see the Quillere paper).
1491 * It eliminates unused iterations of the current level for the new one. See the
1492 * example called linearity-1-1 example with and without this part for an idea.
1493 * - October 26th 2001: first version in cloog_loop_generate_general.
1494 * - July 31th 2002: (debug) no more parasite loops (REALLY hard !).
1495 * - October 30th 2005: extraction from cloog_loop_generate_general.
1497 CloogLoop
*cloog_loop_generate_backtrack(CloogLoop
*loop
,
1498 int level
, CloogOptions
*options
)
1500 CloogDomain
* domain
;
1501 CloogLoop
* now
, * now2
, * next
, * next2
, * end
, * temp
, * l
, * inner
,
1507 while (temp
!= NULL
)
1509 inner
= temp
->inner
;
1511 while (inner
!= NULL
)
1512 { next
= inner
->next
;
1513 /* This 'if' and its first part is the debug of july 31th 2002. */
1514 if (inner
->block
!= NULL
) {
1515 end
= cloog_loop_alloc(temp
->state
, inner
->domain
, 0, NULL
,
1516 inner
->block
, NULL
, NULL
);
1517 domain
= cloog_domain_copy(temp
->domain
) ;
1518 new_loop
= cloog_loop_alloc(temp
->state
, domain
, 0, NULL
,
1522 new_loop
= cloog_loop_project(inner
, level
);
1524 cloog_loop_free_parts(inner
,0,0,0,0) ;
1525 cloog_loop_add(&l
,&now2
,new_loop
) ;
1529 temp
->inner
= NULL
;
1532 { l
= cloog_loop_separate(l
) ;
1533 l
= cloog_loop_sort(l
, level
);
1535 l
->stride
= cloog_stride_copy(l
->stride
);
1536 cloog_loop_add(&loop
,&now
,l
) ;
1540 next2
= temp
->next
;
1541 cloog_loop_free_parts(temp
,1,0,0,0) ;
1550 * Return 1 if we need to continue recursing to the specified level.
1552 int cloog_loop_more(CloogLoop
*loop
, int level
, int scalar
, int nb_scattdims
)
1554 return level
+ scalar
<= nb_scattdims
||
1555 cloog_domain_dimension(loop
->domain
) >= level
;
1559 * Return 1 if the domains of all loops in the given linked list
1560 * have a fixed value at the given level.
1561 * In principle, there would be no need to check that the fixed value is
1562 * the same for each of these loops because this function is only
1563 * called on a component. However, not all backends perform a proper
1564 * decomposition into components.
1566 int cloog_loop_is_constant(CloogLoop
*loop
, int level
)
1574 if (!cloog_domain_lazy_isconstant(loop
->domain
, level
- 1, &c1
))
1577 for (loop
= loop
->next
; r
&& loop
; loop
= loop
->next
) {
1578 if (!cloog_domain_lazy_isconstant(loop
->domain
, level
- 1, &c2
))
1580 else if (cloog_int_ne(c1
, c2
))
1584 cloog_int_clear(c1
);
1585 cloog_int_clear(c2
);
1591 * Assuming all domains in the given linked list of loop
1592 * have a fixed values at level, return a single loop with
1593 * a domain corresponding to this fixed value and with as
1594 * list of inner loops the concatenation of all inner loops
1595 * in the original list.
1597 CloogLoop
*cloog_loop_constant(CloogLoop
*loop
, int level
)
1599 CloogLoop
*res
, *inner
, *tmp
;
1600 CloogDomain
*domain
, *t
;
1605 inner
= loop
->inner
;
1606 domain
= loop
->domain
;
1607 for (tmp
= loop
->next
; tmp
; tmp
= tmp
->next
) {
1608 inner
= cloog_loop_concat(inner
, tmp
->inner
);
1609 domain
= cloog_domain_union(domain
, tmp
->domain
);
1612 domain
= cloog_domain_simple_convex(t
= domain
);
1613 cloog_domain_free(t
);
1615 res
= cloog_loop_alloc(loop
->state
, domain
, 0, NULL
, NULL
, inner
, NULL
);
1617 cloog_loop_free_parts(loop
, 0, 0, 0, 1);
1623 /* Unroll the given loop at the given level, provided it is allowed
1624 * by cloog_domain_can_unroll.
1625 * If so, we return a list of loops, one for each iteration of the original
1626 * loop. Otherwise, we simply return the original loop.
1628 static CloogLoop
*loop_unroll(CloogLoop
*loop
, int level
)
1633 CloogConstraint
*lb
;
1634 CloogLoop
*res
= NULL
;
1635 CloogLoop
**next_res
= &res
;
1636 CloogDomain
*domain
;
1640 can_unroll
= cloog_domain_can_unroll(loop
->domain
, level
, &n
, &lb
);
1648 for (cloog_int_set_si(i
, 0); cloog_int_lt(i
, n
); cloog_int_add_ui(i
, i
, 1)) {
1649 domain
= cloog_domain_copy(loop
->domain
);
1650 domain
= cloog_domain_fixed_offset(domain
, level
, lb
, i
);
1651 inner
= cloog_loop_copy(loop
->inner
);
1652 inner
= cloog_loop_restrict_all(inner
, domain
);
1654 cloog_domain_free(domain
);
1657 *next_res
= cloog_loop_alloc(loop
->state
, domain
, 1, NULL
, NULL
,
1659 next_res
= &(*next_res
)->next
;
1664 cloog_constraint_release(lb
);
1666 cloog_loop_free(loop
);
1672 /* Unroll all loops in the given list at the given level, provided
1673 * they can be unrolled.
1675 CloogLoop
*cloog_loop_unroll(CloogLoop
*loop
, int level
)
1677 CloogLoop
*now
, *next
;
1678 CloogLoop
*res
= NULL
;
1679 CloogLoop
**next_res
= &res
;
1681 for (now
= loop
; now
; now
= next
) {
1685 *next_res
= loop_unroll(now
, level
);
1688 next_res
= &(*next_res
)->next
;
1694 CloogLoop
*cloog_loop_generate_restricted_or_stop(CloogLoop
*loop
,
1695 CloogDomain
*context
,
1696 int level
, int scalar
, int *scaldims
, int nb_scattdims
,
1697 CloogOptions
*options
);
1699 CloogLoop
*cloog_loop_recurse(CloogLoop
*loop
,
1700 int level
, int scalar
, int *scaldims
, int nb_scattdims
,
1701 int constant
, CloogOptions
*options
);
1705 * Recurse on the inner loops of the given single loop.
1707 * - loop is the loop for which we have to generate scanning code,
1708 * - level is the current non-scalar dimension,
1709 * - scalar is the current scalar dimension,
1710 * - scaldims is the boolean array saying whether a dimension is scalar or not,
1711 * - nb_scattdims is the size of the scaldims array,
1712 * - constant is true if the loop is known to be executed at most once
1713 * - options are the general code generation options.
1715 static CloogLoop
*loop_recurse(CloogLoop
*loop
,
1716 int level
, int scalar
, int *scaldims
, int nb_scattdims
,
1717 int constant
, CloogOptions
*options
)
1719 CloogLoop
*inner
, *into
, *end
, *next
, *l
, *now
;
1720 CloogDomain
*domain
;
1722 if (level
&& options
->strides
&& !constant
)
1723 cloog_loop_stride(loop
, level
);
1726 options
->first_unroll
>= 0 && level
+ scalar
>= options
->first_unroll
) {
1727 loop
= cloog_loop_unroll(loop
, level
);
1729 return cloog_loop_recurse(loop
, level
, scalar
, scaldims
,
1730 nb_scattdims
, 1, options
);
1733 if (level
&& options
->otl
)
1734 cloog_loop_otl(loop
, level
);
1735 inner
= loop
->inner
;
1736 domain
= cloog_domain_copy(loop
->domain
);
1737 domain
= cloog_domain_add_stride_constraint(domain
, loop
->stride
);
1739 while (inner
!= NULL
)
1740 { /* 4b. -ced- recurse for each sub-list of non terminal loops. */
1741 if (cloog_loop_more(inner
, level
+ 1, scalar
, nb_scattdims
)) {
1743 while ((end
->next
!= NULL
) &&
1744 cloog_loop_more(end
->next
, level
+ 1, scalar
, nb_scattdims
))
1750 l
= cloog_loop_generate_restricted_or_stop(inner
, domain
,
1751 level
+ 1, scalar
, scaldims
, nb_scattdims
, options
);
1754 cloog_loop_add_list(&into
,&now
,l
) ;
1759 { cloog_loop_add(&into
,&now
,inner
) ;
1760 inner
= inner
->next
;
1764 cloog_domain_free(domain
);
1771 * Recurse on the inner loops of each of the loops in the loop list.
1773 * - loop is the loop list for which we have to generate scanning code,
1774 * - level is the current non-scalar dimension,
1775 * - scalar is the current scalar dimension,
1776 * - scaldims is the boolean array saying whether a dimension is scalar or not,
1777 * - nb_scattdims is the size of the scaldims array,
1778 * - constant is true if the loop is known to be executed at most once
1779 * - options are the general code generation options.
1781 CloogLoop
*cloog_loop_recurse(CloogLoop
*loop
,
1782 int level
, int scalar
, int *scaldims
, int nb_scattdims
,
1783 int constant
, CloogOptions
*options
)
1785 CloogLoop
*now
, *next
;
1786 CloogLoop
*res
= NULL
;
1787 CloogLoop
**next_res
= &res
;
1789 for (now
= loop
; now
; now
= next
) {
1793 *next_res
= loop_recurse(now
, level
, scalar
, scaldims
, nb_scattdims
,
1797 next_res
= &(*next_res
)->next
;
1804 * cloog_loop_generate_general function:
1805 * Adaptation from LoopGen 0.4 by F. Quillere. This function implements the
1806 * Quillere algorithm for polyhedron scanning from step 3 to 5.
1807 * (see the Quillere paper).
1808 * - loop is the loop for which we have to generate a scanning code,
1809 * - level is the current non-scalar dimension,
1810 * - scalar is the current scalar dimension,
1811 * - scaldims is the boolean array saying whether a dimension is scalar or not,
1812 * - nb_scattdims is the size of the scaldims array,
1813 * - options are the general code generation options.
1815 * - October 26th 2001: first version.
1816 * - July 3rd->11th 2003: memory leaks hunt and correction.
1817 * - June 22nd 2005: Adaptation for GMP.
1818 * - September 2nd 2005: The function have been cutted out in two pieces:
1819 * cloog_loop_generate and this one, in order to handle
1820 * the scalar dimension case more efficiently with
1821 * cloog_loop_generate_scalar.
1822 * - November 15th 2005: (debug) the result of the cloog_loop_generate call may
1823 * be a list of polyhedra (especially if stop option is
1824 * used): cloog_loop_add_list instead of cloog_loop_add.
1826 CloogLoop
*cloog_loop_generate_general(CloogLoop
*loop
,
1827 int level
, int scalar
, int *scaldims
, int nb_scattdims
,
1828 CloogOptions
*options
)
1830 CloogLoop
*res
, *now
, *temp
, *l
, *new_loop
, *next
;
1834 /* 3. Separate all projections into disjoint polyhedra. */
1835 if (level
> 0 && cloog_loop_is_constant(loop
, level
)) {
1836 res
= cloog_loop_constant(loop
, level
);
1838 } else if ((options
->f
> level
+scalar
) || (options
->f
< 0))
1839 res
= cloog_loop_merge(loop
, level
, options
);
1841 res
= cloog_loop_separate(loop
);
1845 /* 3b. -correction- sort the loops to determine their textual order. */
1846 res
= cloog_loop_sort(res
, level
);
1848 res
= cloog_loop_restrict_inner(res
);
1851 res
= cloog_loop_specialize(res
, level
, scalar
, scaldims
, nb_scattdims
);
1853 /* 4. Recurse for each loop with the current domain as context. */
1856 if (!level
|| (level
+scalar
< options
->l
) || (options
->l
< 0))
1857 res
= cloog_loop_recurse(temp
, level
, scalar
, scaldims
, nb_scattdims
,
1860 while (temp
!= NULL
)
1861 { next
= temp
->next
;
1862 l
= cloog_loop_nest(temp
->inner
, temp
->domain
, level
+1);
1863 new_loop
= cloog_loop_alloc(temp
->state
, temp
->domain
, 0, NULL
,
1865 temp
->inner
= NULL
;
1867 cloog_loop_free_parts(temp
,0,0,0,0) ;
1868 cloog_loop_add(&res
,&now
,new_loop
) ;
1872 if (options
->strides
)
1873 res
= cloog_loop_propagate_lower_bound(res
, level
);
1875 /* 5. eliminate unused iterations of the current level for the new one. See
1876 * the example called linearity-1-1 example with and without this part
1879 if (options
->backtrack
&& level
&&
1880 ((level
+scalar
< options
->l
) || (options
->l
< 0)) &&
1881 ((options
->f
<= level
+scalar
) && !(options
->f
< 0)))
1882 res
= cloog_loop_generate_backtrack(res
, level
, options
);
1884 /* Pray for my new paper to be accepted somewhere since the following stuff
1885 * is really amazing :-) !
1886 * Far long later: The paper has been accepted to PACT 2004 :-))). But there
1887 * are still some bugs and I have no time to fix them. Thus now you have to
1888 * pray for me to get an academic position for that really amazing stuff :-) !
1889 * Later again: OK, I get my academic position, but still I have not enough
1890 * time to fix and clean this part... Pray again :-) !!!
1892 /* res = cloog_loop_unisolate(res,level) ;*/
1898 CloogLoop
*cloog_loop_generate_restricted(CloogLoop
*loop
,
1899 int level
, int scalar
, int *scaldims
, int nb_scattdims
,
1900 CloogOptions
*options
);
1904 * cloog_loop_generate_scalar function:
1905 * This function applies the simplified code generation scheme in the trivial
1906 * case of scalar dimensions. When dealing with scalar dimensions, there is
1907 * no need of costly polyhedral operations for separation or sorting: sorting
1908 * is a question of comparing scalar vectors and separation amounts to consider
1909 * only loops with the same scalar vector for the next step of the code
1910 * generation process. This function achieves the separation/sorting process
1911 * for the vector of scalar dimension that begins at dimension 'level+scalar'
1912 * and finish to the first non-scalar dimension.
1913 * - loop is the loop for which we have to generate a scanning code,
1914 * - level is the current non-scalar dimension,
1915 * - scalar is the current scalar dimension,
1916 * - scaldims is the boolean array saying whether a dimension is scalar or not,
1917 * - nb_scattdims is the size of the scaldims array,
1918 * - options are the general code generation options.
1920 * - September 2nd 2005: First version.
1922 CloogLoop
*cloog_loop_generate_scalar(CloogLoop
*loop
,
1923 int level
, int scalar
, int *scaldims
, int nb_scattdims
,
1924 CloogOptions
*options
)
1925 { CloogLoop
* res
, * now
, * temp
, * l
, * end
, * next
, * ref
;
1928 /* We sort the loop list with respect to the current scalar vector. */
1929 res
= cloog_loop_scalar_sort(loop
,level
,scaldims
,nb_scattdims
,scalar
) ;
1931 scalar_new
= scalar
+ scaldims
[level
+ scalar
- 1];
1935 while (temp
!= NULL
)
1936 { /* Then we will appy the general code generation process to each sub-list
1937 * of loops with the same scalar vector.
1942 while((end
->next
!= NULL
) &&
1943 cloog_loop_more(end
->next
, level
, scalar_new
, nb_scattdims
) &&
1944 cloog_loop_scalar_eq(ref
,end
->next
,level
,scaldims
,nb_scattdims
,scalar
))
1950 /* For the next dimension, scalar value is updated by adding the scalar
1951 * vector size, which is stored at scaldims[level+scalar-1].
1953 if (cloog_loop_more(temp
, level
, scalar_new
, nb_scattdims
)) {
1954 l
= cloog_loop_generate_restricted(temp
, level
, scalar_new
,
1955 scaldims
, nb_scattdims
, options
);
1958 cloog_loop_add_list(&res
, &now
, l
);
1960 cloog_loop_add(&res
, &now
, temp
);
1969 /* Compare loop with the next loop based on their constant dimensions.
1970 * The result is < 0, == 0 or > 0 depending on whether the constant
1971 * dimensions of loop are lexicographically smaller, equal or greater
1972 * than those of loop->next.
1973 * If loop is the last in the list, then it is assumed to be smaller
1974 * than the "next" one.
1976 static int cloog_loop_next_scal_cmp(CloogLoop
*loop
)
1984 nb_scaldims
= loop
->block
->nb_scaldims
;
1985 if (loop
->next
->block
->nb_scaldims
< nb_scaldims
)
1986 nb_scaldims
= loop
->next
->block
->nb_scaldims
;
1988 for (i
= 0; i
< nb_scaldims
; ++i
) {
1989 int cmp
= cloog_int_cmp(loop
->block
->scaldims
[i
],
1990 loop
->next
->block
->scaldims
[i
]);
1994 return loop
->block
->nb_scaldims
- loop
->next
->block
->nb_scaldims
;
1998 /* Check whether the globally constant dimensions of a and b
1999 * have the same value for all globally constant dimensions
2000 * that are situated before any (locally) non-constant dimension.
2002 static int cloog_loop_equal_prefix(CloogLoop
*a
, CloogLoop
*b
,
2003 int *scaldims
, int nb_scattdims
)
2009 for (i
= 0; i
< nb_scattdims
; ++i
) {
2014 if (!cloog_int_eq(a
->block
->scaldims
[cst
], b
->block
->scaldims
[cst
]))
2018 for (i
= i
+ 1; i
< nb_scattdims
; ++i
) {
2021 if (!cloog_domain_lazy_isconstant(a
->domain
, dim
, NULL
))
2023 /* No need to check that dim is also constant in b and that the
2024 * constant values are equal. That will happen during the check
2025 * whether the two domains are equal.
2033 /* Try to block adjacent loops in the loop list "loop".
2034 * We only attempt blocking if the constant dimensions of the loops
2035 * in the least are (not necessarily strictly) increasing.
2036 * Then we look for a sublist such that the first (begin) has constant
2037 * dimensions strictly larger than the previous loop in the complete
2038 * list and such that the loop (end) after the last loop in the sublist
2039 * has constant dimensions strictly larger than the last loop in the sublist.
2040 * Furthermore, all loops in the sublist should have the same domain
2041 * (with globally constant dimensions removed) and the difference
2042 * (if any) in constant dimensions may only occur after all the
2043 * (locally) constant dimensions.
2044 * If we find such a sublist, then the blocks of all but the first
2045 * are merged into the block of the first.
2047 * Note that this function can only be called before the global
2048 * blocklist has been created because it may otherwise modify and destroy
2049 * elements on that list.
2051 CloogLoop
*cloog_loop_block(CloogLoop
*loop
, int *scaldims
, int nb_scattdims
)
2053 CloogLoop
*begin
, *end
, *l
;
2054 int begin_after_previous
;
2055 int end_after_previous
;
2059 for (begin
= loop
; begin
; begin
= begin
->next
) {
2060 if (!begin
->block
|| !begin
->block
->scaldims
)
2062 if (cloog_loop_next_scal_cmp(begin
) > 0)
2066 begin_after_previous
= 1;
2067 for (begin
= loop
; begin
; begin
= begin
->next
) {
2068 if (!begin_after_previous
) {
2069 begin_after_previous
= cloog_loop_next_scal_cmp(begin
) < 0;
2073 end_after_previous
= cloog_loop_next_scal_cmp(begin
) < 0;
2074 for (end
= begin
->next
; end
; end
= end
->next
) {
2075 if (!cloog_loop_equal_prefix(begin
, end
, scaldims
, nb_scattdims
))
2077 if (!cloog_domain_lazy_equal(begin
->domain
, end
->domain
))
2079 end_after_previous
= cloog_loop_next_scal_cmp(end
) < 0;
2081 if (end
!= begin
->next
&& end_after_previous
) {
2082 for (l
= begin
->next
; l
!= end
; l
= begin
->next
) {
2083 cloog_block_merge(begin
->block
, l
->block
);
2084 begin
->next
= l
->next
;
2085 cloog_loop_free_parts(l
, 1, 0, 1, 0);
2089 begin_after_previous
= cloog_loop_next_scal_cmp(begin
) < 0;
2097 * Check whether for any fixed iteration of the outer loops,
2098 * there is an iteration of loop1 that is lexicographically greater
2099 * than an iteration of loop2.
2100 * Return 1 if there exists (or may exist) such a pair.
2101 * Return 0 if all iterations of loop1 are lexicographically smaller
2102 * than the iterations of loop2.
2103 * If no iteration is lexicographically greater, but if there are
2104 * iterations that are equal to iterations of loop2, then return "def".
2105 * This is useful for ensuring that such statements are not reordered.
2106 * Some users, including the test_run target in test, expect
2107 * the statements at a given point to be run in the original order.
2108 * Passing the value "0" for "def" would allow such statements to be reordered
2109 * and would allow for the detection of more components.
2111 int cloog_loop_follows(CloogLoop
*loop1
, CloogLoop
*loop2
,
2112 int level
, int scalar
, int *scaldims
, int nb_scattdims
, int def
)
2116 dim1
= cloog_domain_dimension(loop1
->domain
);
2117 dim2
= cloog_domain_dimension(loop2
->domain
);
2118 while ((level
<= dim1
&& level
<= dim2
) ||
2119 level_is_constant(level
, scalar
, scaldims
, nb_scattdims
)) {
2120 if (level_is_constant(level
, scalar
, scaldims
, nb_scattdims
)) {
2121 int cmp
= cloog_loop_constant_cmp(loop1
, loop2
, level
, scaldims
,
2122 nb_scattdims
, scalar
);
2127 scalar
+= scaldims
[level
+ scalar
- 1];
2129 int follows
= cloog_domain_follows(loop1
->domain
, loop2
->domain
,
2143 /* Structure for representing the nodes in the graph being traversed
2144 * using Tarjan's algorithm.
2145 * index represents the order in which nodes are visited.
2146 * min_index is the index of the root of a (sub)component.
2147 * on_stack indicates whether the node is currently on the stack.
2149 struct cloog_loop_sort_node
{
2154 /* Structure for representing the graph being traversed
2155 * using Tarjan's algorithm.
2156 * len is the number of nodes
2157 * node is an array of nodes
2158 * stack contains the nodes on the path from the root to the current node
2159 * sp is the stack pointer
2160 * index is the index of the last node visited
2161 * order contains the elements of the components separated by -1
2162 * op represents the current position in order
2164 struct cloog_loop_sort
{
2166 struct cloog_loop_sort_node
*node
;
2174 /* Allocate and initialize cloog_loop_sort structure.
2176 static struct cloog_loop_sort
*cloog_loop_sort_alloc(int len
)
2178 struct cloog_loop_sort
*s
;
2181 s
= (struct cloog_loop_sort
*)malloc(sizeof(struct cloog_loop_sort
));
2184 s
->node
= (struct cloog_loop_sort_node
*)
2185 malloc(len
* sizeof(struct cloog_loop_sort_node
));
2187 for (i
= 0; i
< len
; ++i
)
2188 s
->node
[i
].index
= -1;
2189 s
->stack
= (int *)malloc(len
* sizeof(int));
2191 s
->order
= (int *)malloc(2 * len
* sizeof(int));
2201 /* Free cloog_loop_sort structure.
2203 static void cloog_loop_sort_free(struct cloog_loop_sort
*s
)
2212 /* Check whether for any fixed iteration of the outer loops,
2213 * there is an iteration of loop1 that is lexicographically greater
2214 * than an iteration of loop2, where the iteration domains are
2215 * available in the inner loops of the arguments.
2217 * By using this functions to detect components, we ensure that
2218 * two CloogLoops appear in the same component if some iterations of
2219 * each loop should be executed before some iterations of the other loop.
2220 * Since we also want two CloogLoops that have exactly the same
2221 * iteration domain at the current level to be placed in the same component,
2222 * we first check if these domains are indeed the same.
2224 static int inner_loop_follows(CloogLoop
*loop1
, CloogLoop
*loop2
,
2225 int level
, int scalar
, int *scaldims
, int nb_scattdims
, int def
)
2229 f
= cloog_domain_lazy_equal(loop1
->domain
, loop2
->domain
);
2231 f
= cloog_loop_follows(loop1
->inner
, loop2
->inner
,
2232 level
, scalar
, scaldims
, nb_scattdims
, def
);
2238 /* Perform Tarjan's algorithm for computing the strongly connected components
2239 * in the graph with the individual CloogLoops as vertices.
2240 * Two CloopLoops appear in the same component if they both (indirectly)
2241 * "follow" each other, where the following relation is determined
2242 * by the follows function.
2244 static void cloog_loop_components_tarjan(struct cloog_loop_sort
*s
,
2245 CloogLoop
**loop_array
, int i
, int level
, int scalar
, int *scaldims
,
2247 int (*follows
)(CloogLoop
*loop1
, CloogLoop
*loop2
,
2248 int level
, int scalar
, int *scaldims
, int nb_scattdims
, int def
))
2252 s
->node
[i
].index
= s
->index
;
2253 s
->node
[i
].min_index
= s
->index
;
2254 s
->node
[i
].on_stack
= 1;
2256 s
->stack
[s
->sp
++] = i
;
2258 for (j
= s
->len
- 1; j
>= 0; --j
) {
2263 if (s
->node
[j
].index
>= 0 &&
2264 (!s
->node
[j
].on_stack
||
2265 s
->node
[j
].index
> s
->node
[i
].min_index
))
2268 f
= follows(loop_array
[i
], loop_array
[j
],
2269 level
, scalar
, scaldims
, nb_scattdims
, i
> j
);
2273 if (s
->node
[j
].index
< 0) {
2274 cloog_loop_components_tarjan(s
, loop_array
, j
, level
, scalar
,
2275 scaldims
, nb_scattdims
, follows
);
2276 if (s
->node
[j
].min_index
< s
->node
[i
].min_index
)
2277 s
->node
[i
].min_index
= s
->node
[j
].min_index
;
2278 } else if (s
->node
[j
].index
< s
->node
[i
].min_index
)
2279 s
->node
[i
].min_index
= s
->node
[j
].index
;
2282 if (s
->node
[i
].index
!= s
->node
[i
].min_index
)
2286 j
= s
->stack
[--s
->sp
];
2287 s
->node
[j
].on_stack
= 0;
2288 s
->order
[s
->op
++] = j
;
2290 s
->order
[s
->op
++] = -1;
2294 static int qsort_index_cmp(const void *p1
, const void *p2
)
2296 return *(int *)p1
- *(int *)p2
;
2299 /* Sort the elements of the component starting at list.
2300 * The list is terminated by a -1.
2302 static void sort_component(int *list
)
2306 for (len
= 0; list
[len
] != -1; ++len
)
2309 qsort(list
, len
, sizeof(int), qsort_index_cmp
);
2312 /* Given an array of indices "list" into the "loop_array" array,
2313 * terminated by -1, construct a linked list of the corresponding
2314 * entries and put the result in *res.
2315 * The value returned is the number of CloogLoops in the (linked) list
2317 static int extract_component(CloogLoop
**loop_array
, int *list
, CloogLoop
**res
)
2321 sort_component(list
);
2322 while (list
[i
] != -1) {
2323 *res
= loop_array
[list
[i
]];
2324 res
= &(*res
)->next
;
2334 * Call cloog_loop_generate_scalar or cloog_loop_generate_general
2335 * on each of the strongly connected components in the list of CloogLoops
2336 * pointed to by "loop".
2338 * We use Tarjan's algorithm to find the strongly connected components.
2339 * Note that this algorithm also topologically sorts the components.
2341 * The components are treated separately to avoid spurious separations.
2342 * The concatentation of the results may contain successive loops
2343 * with the same bounds, so we try to combine such loops.
2345 CloogLoop
*cloog_loop_generate_components(CloogLoop
*loop
,
2346 int level
, int scalar
, int *scaldims
, int nb_scattdims
,
2347 CloogOptions
*options
)
2351 CloogLoop
*res
, **res_next
;
2352 CloogLoop
**loop_array
;
2353 struct cloog_loop_sort
*s
;
2355 if (level
== 0 || !loop
->next
)
2356 return cloog_loop_generate_general(loop
, level
, scalar
,
2357 scaldims
, nb_scattdims
, options
);
2359 nb_loops
= cloog_loop_count(loop
);
2361 loop_array
= (CloogLoop
**)malloc(nb_loops
* sizeof(CloogLoop
*));
2364 for (i
= 0, tmp
= loop
; i
< nb_loops
; i
++, tmp
= tmp
->next
)
2365 loop_array
[i
] = tmp
;
2367 s
= cloog_loop_sort_alloc(nb_loops
);
2368 for (i
= nb_loops
- 1; i
>= 0; --i
) {
2369 if (s
->node
[i
].index
>= 0)
2371 cloog_loop_components_tarjan(s
, loop_array
, i
, level
, scalar
, scaldims
,
2372 nb_scattdims
, &inner_loop_follows
);
2379 int n
= extract_component(loop_array
, &s
->order
[i
], &tmp
);
2382 *res_next
= cloog_loop_generate_general(tmp
, level
, scalar
,
2383 scaldims
, nb_scattdims
, options
);
2385 res_next
= &(*res_next
)->next
;
2388 cloog_loop_sort_free(s
);
2392 res
= cloog_loop_combine(res
);
2398 /* For each loop in the list "loop", decompose the list of
2399 * inner loops into strongly connected components and put
2400 * the components into separate loops at the top level.
2402 CloogLoop
*cloog_loop_decompose_inner(CloogLoop
*loop
,
2403 int level
, int scalar
, int *scaldims
, int nb_scattdims
)
2406 CloogLoop
**loop_array
;
2407 int i
, n_loops
, max_loops
= 0;
2408 struct cloog_loop_sort
*s
;
2410 for (l
= loop
; l
; l
= l
->next
) {
2411 n_loops
= cloog_loop_count(l
->inner
);
2412 if (max_loops
< n_loops
)
2413 max_loops
= n_loops
;
2419 loop_array
= (CloogLoop
**)malloc(max_loops
* sizeof(CloogLoop
*));
2422 for (l
= loop
; l
; l
= l
->next
) {
2425 for (i
= 0, tmp
= l
->inner
; tmp
; i
++, tmp
= tmp
->next
)
2426 loop_array
[i
] = tmp
;
2431 s
= cloog_loop_sort_alloc(n_loops
);
2432 for (i
= n_loops
- 1; i
>= 0; --i
) {
2433 if (s
->node
[i
].index
>= 0)
2435 cloog_loop_components_tarjan(s
, loop_array
, i
, level
, scalar
,
2436 scaldims
, nb_scattdims
, &cloog_loop_follows
);
2439 n
= extract_component(loop_array
, s
->order
, &l
->inner
);
2445 n
= extract_component(loop_array
, &s
->order
[i
], &inner
);
2448 tmp
= cloog_loop_alloc(l
->state
, cloog_domain_copy(l
->domain
),
2449 l
->otl
, l
->stride
, l
->block
, inner
, l
->next
);
2454 cloog_loop_sort_free(s
);
2463 CloogLoop
*cloog_loop_generate_restricted(CloogLoop
*loop
,
2464 int level
, int scalar
, int *scaldims
, int nb_scattdims
,
2465 CloogOptions
*options
)
2467 /* To save both time and memory, we switch here depending on whether the
2468 * current dimension is scalar (simplified processing) or not (general
2471 if (level_is_constant(level
, scalar
, scaldims
, nb_scattdims
))
2472 return cloog_loop_generate_scalar(loop
, level
, scalar
,
2473 scaldims
, nb_scattdims
, options
);
2475 * 2. Compute the projection of each polyhedron onto the outermost
2476 * loop variable and the parameters.
2478 loop
= cloog_loop_project_all(loop
, level
);
2480 return cloog_loop_generate_components(loop
, level
, scalar
, scaldims
,
2481 nb_scattdims
, options
);
2485 CloogLoop
*cloog_loop_generate_restricted_or_stop(CloogLoop
*loop
,
2486 CloogDomain
*context
,
2487 int level
, int scalar
, int *scaldims
, int nb_scattdims
,
2488 CloogOptions
*options
)
2490 /* If the user asked to stop code generation at this level, let's stop. */
2491 if ((options
->stop
>= 0) && (level
+scalar
>= options
->stop
+1))
2492 return cloog_loop_stop(loop
,context
) ;
2494 return cloog_loop_generate_restricted(loop
, level
, scalar
, scaldims
,
2495 nb_scattdims
, options
);
2500 * cloog_loop_generate function:
2501 * Adaptation from LoopGen 0.4 by F. Quillere. This function implements the
2502 * Quillere algorithm for polyhedron scanning from step 1 to 2.
2503 * (see the Quillere paper).
2504 * - loop is the loop for which we have to generate a scanning code,
2505 * - context is the context of the current loop (constraints on parameter and/or
2506 * on outer loop counters),
2507 * - level is the current non-scalar dimension,
2508 * - scalar is the current scalar dimension,
2509 * - scaldims is the boolean array saying whether a dimension is scalar or not,
2510 * - nb_scattdims is the size of the scaldims array,
2511 * - options are the general code generation options.
2513 * - October 26th 2001: first version.
2514 * - July 3rd->11th 2003: memory leaks hunt and correction.
2515 * - June 15th 2005: a memory leak fixed (loop was not entirely freed when
2516 * the result of cloog_loop_restrict was NULL).
2517 * - June 22nd 2005: Adaptation for GMP.
2518 * - September 2nd 2005: The function have been cutted out in two pieces:
2519 * cloog_loop_generate and this one, in order to handle
2520 * the scalar dimension case more efficiently with
2521 * cloog_loop_generate_scalar.
2522 * - November 15th 2005: (debug) Condition for stop option no more take care of
2523 * further scalar dimensions.
2525 CloogLoop
*cloog_loop_generate(CloogLoop
*loop
, CloogDomain
*context
,
2526 int level
, int scalar
, int *scaldims
, int nb_scattdims
,
2527 CloogOptions
*options
)
2529 /* 1. Replace each polyhedron by its intersection with the context.
2531 loop
= cloog_loop_restrict_all(loop
, context
);
2535 return cloog_loop_generate_restricted_or_stop(loop
, context
,
2536 level
, scalar
, scaldims
, nb_scattdims
, options
);
2541 * Internal function for simplifying a single loop in a list of loops.
2542 * See cloog_loop_simplify.
2544 static CloogLoop
*loop_simplify(CloogLoop
*loop
, CloogDomain
*context
,
2545 int level
, int nb_scattdims
, CloogOptions
*options
)
2548 CloogBlock
* new_block
;
2549 CloogLoop
*simplified
, *inner
;
2550 CloogDomain
* domain
, * simp
, * inter
, * extended_context
;
2552 domain
= loop
->domain
;
2554 domain_dim
= cloog_domain_dimension(domain
);
2555 extended_context
= cloog_domain_extend(context
, domain_dim
);
2556 inter
= cloog_domain_intersection(domain
,extended_context
) ;
2557 simp
= cloog_domain_simplify(domain
, extended_context
);
2558 cloog_domain_free(extended_context
) ;
2560 /* If the constraint system is never true, go to the next one. */
2561 if (cloog_domain_never_integral(simp
)) {
2562 cloog_loop_free(loop
->inner
);
2563 cloog_domain_free(inter
);
2564 cloog_domain_free(simp
);
2568 inner
= cloog_loop_simplify(loop
->inner
, inter
, level
+1, nb_scattdims
,
2571 if ((inner
== NULL
) && (loop
->block
== NULL
)) {
2572 cloog_domain_free(inter
);
2573 cloog_domain_free(simp
);
2577 new_block
= cloog_block_copy(loop
->block
) ;
2579 simplified
= cloog_loop_alloc(loop
->state
, simp
, loop
->otl
, loop
->stride
,
2580 new_block
, inner
, NULL
);
2582 /* Only save the domains, if it involves only scattering dimensions. */
2583 if (options
->save_domains
) {
2584 if (domain_dim
> nb_scattdims
) {
2586 inter
= cloog_domain_project(t
= inter
, nb_scattdims
);
2587 cloog_domain_free(t
);
2589 inter
= cloog_domain_add_stride_constraint(inter
, loop
->stride
);
2590 simplified
->unsimplified
= inter
;
2592 cloog_domain_free(inter
);
2594 return(simplified
) ;
2599 * cloog_loop_simplify function:
2600 * This function implements the part 6. of the Quillere algorithm, it
2601 * recursively simplifies each loop in the context of the preceding loop domain.
2602 * It returns a pointer to the simplified loop list.
2603 * The cloog_domain_simplify (DomainSimplify) behaviour is really bad with
2604 * polyhedra union and some really awful sidesteppings were written, I plan
2606 * - October 31th 2001: first version.
2607 * - July 3rd->11th 2003: memory leaks hunt and correction.
2608 * - April 16th 2005: a memory leak fixed (extended_context was not freed).
2609 * - June 15th 2005: a memory leak fixed (loop was not conveniently freed
2610 * when the constraint system is never true).
2611 * - October 27th 2005: - this function called before cloog_loop_fast_simplify
2612 * is now the official cloog_loop_simplify function in
2613 * replacement of a slower and more complex one (after
2614 * deep changes in the pretty printer).
2615 * - we use cloog_loop_disjoint to fix the problem when
2616 * simplifying gives a union of polyhedra (before, it
2617 * was under the responsibility of the pretty printer).
2619 CloogLoop
*cloog_loop_simplify(CloogLoop
*loop
, CloogDomain
*context
, int level
,
2620 int nb_scattdims
, CloogOptions
*options
)
2623 CloogLoop
*res
= NULL
;
2624 CloogLoop
**next
= &res
;
2627 for (now
= loop
; now
; now
= now
->next
)
2628 if (!cloog_domain_isconvex(now
->domain
)) {
2629 now
->domain
= cloog_domain_simplify_union(now
->domain
);
2630 if (!cloog_domain_isconvex(now
->domain
))
2634 /* If the input of CLooG contains any union domains, then they
2635 * may not have been split yet at this point. Do so now as the
2636 * clast construction assumes there are no union domains.
2639 loop
= cloog_loop_disjoint(loop
);
2641 for (now
= loop
; now
; now
= now
->next
) {
2642 *next
= loop_simplify(now
, context
, level
, nb_scattdims
, options
);
2644 now
->inner
= NULL
; /* For loop integrity. */
2645 cloog_domain_free(now
->domain
);
2649 next
= &(*next
)->next
;
2651 cloog_loop_free(loop
);
2658 * cloog_loop_scatter function:
2659 * This function add the scattering (scheduling) informations in a loop.
2661 void cloog_loop_scatter(CloogLoop
* loop
, CloogScattering
*scatt
)
2663 loop
->domain
= cloog_domain_scatter(loop
->domain
, scatt
);