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 is free software; you can redistribute it and/or modify it under the *
18 * terms of the GNU General Public License as published by the Free Software *
19 * Foundation; either version 2 of the License, or (at your option) any later *
22 * This software is distributed in the hope that it will be useful, but *
23 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
24 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
27 * You should have received a copy of the GNU General Public License along *
28 * with software; if not, write to the Free Software Foundation, Inc., *
29 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
31 * CLooG, the Chunky Loop Generator *
32 * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr *
34 ******************************************************************************/
35 /* CAUTION: the english used for comments is probably the worst you ever read,
36 * please feel free to correct and improve it !
41 # include "../include/cloog/cloog.h"
44 /******************************************************************************
45 * Memory leaks hunting *
46 ******************************************************************************/
50 * These functions and global variables are devoted to memory leaks hunting: we
51 * want to know at each moment how many CloogLoop structures had been allocated
52 * (cloog_loop_allocated) and how many had been freed (cloog_loop_freed).
53 * Each time a CloogLoog structure is allocated, a call to the function
54 * cloog_loop_leak_up() must be carried out, and respectively
55 * cloog_loop_leak_down() when a CloogLoop structure is freed. The special
56 * variable cloog_loop_max gives the maximal number of CloogLoop structures
57 * simultaneously alive (i.e. allocated and non-freed) in memory.
58 * - July 3rd->11th 2003: first version (memory leaks hunt and correction).
62 extern int cloog_value_allocated
;
63 extern int cloog_value_freed
;
64 extern int cloog_value_max
;
67 int cloog_loop_allocated
= 0 ;
68 int cloog_loop_freed
= 0 ;
69 int cloog_loop_max
= 0 ;
72 static void cloog_loop_leak_up()
73 { cloog_loop_allocated
++ ;
74 if ((cloog_loop_allocated
-cloog_loop_freed
) > cloog_loop_max
)
75 cloog_loop_max
= cloog_loop_allocated
- cloog_loop_freed
;
79 static void cloog_loop_leak_down()
80 { cloog_loop_freed
++ ;
84 /******************************************************************************
85 * Structure display function *
86 ******************************************************************************/
90 * cloog_loop_print_structure function:
91 * Displays a loop structure in a way that trends to be understandable without
92 * falling in a deep depression or, for the lucky ones, getting a headache...
93 * Written by Olivier Chorier, Luc Marchaud, Pierre Martin and Romain Tartiere.
94 * - April 24th 2005: Initial version.
95 * - May 21rd 2005: - New parameter `F' for destination file (ie stdout),
97 * - May 26th 2005: Memory leak hunt.
98 * - June 2nd 2005: (Ced) Integration and minor fixes.
99 * -June 22nd 2005: (Ced) Adaptation for GMP.
101 void cloog_loop_print_structure(FILE * file
, CloogLoop
* loop
, int level
)
102 { int i
, j
, first
=1 ;
105 { /* Go to the right level. */
106 for (i
=0; i
<level
; i
++)
107 fprintf(file
,"|\t") ;
109 fprintf(file
,"+-- CloogLoop\n") ;
115 { /* Go to the right level. */
116 for (i
=0; i
<level
; i
++)
117 fprintf(file
,"|\t") ;
119 fprintf(file
,"| CloogLoop\n") ;
125 for(j
=0; j
<=level
+1; j
++)
126 fprintf(file
,"|\t") ;
129 /* Print the domain. */
130 cloog_domain_print_structure(file
,cloog_loop_domain (loop
),level
+1) ;
132 /* Print the stride. */
133 for(j
=0; j
<=level
; j
++)
134 fprintf(file
,"|\t") ;
135 fprintf(file
, "Stride: ") ;
136 value_print(file
,VALUE_FMT
,cloog_loop_stride (loop
)) ;
137 fprintf(file
, "\n") ;
140 for(j
=0; j
<=level
+1; j
++)
141 fprintf(file
,"|\t") ;
144 /* Print the block. */
145 cloog_block_print_structure(file
,cloog_loop_block (loop
),level
+1) ;
148 for (i
=0; i
<=level
+1; i
++)
149 fprintf(file
,"|\t") ;
152 /* Print inner if any. */
153 if (cloog_loop_inner (loop
))
154 cloog_loop_print_structure (file
,cloog_loop_inner (loop
), level
+ 1);
156 /* And let's go for the next one. */
157 loop
= cloog_loop_next (loop
) ;
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
)
207 { cloog_loop_leak_down() ;
209 next
= cloog_loop_next (loop
) ;
210 cloog_domain_free(cloog_loop_domain (loop
)) ;
211 cloog_block_free(cloog_loop_block (loop
)) ;
212 if (cloog_loop_inner (loop
))
213 cloog_loop_free (cloog_loop_inner (loop
));
215 cloog_loop_clear_stride (loop
);
223 * cloog_loop_free_parts function:
224 * This function frees the allocated memory for some parts of a CloogLoop
225 * structure (loop), each other argument is a boolean having to be set to 1 if
226 * we want to free the corresponding part, 0 otherwise. This function applies
227 * the same freeing policy to its inner ans next loops recursively.
228 * - July 3rd 2003: first version.
229 * - June 22nd 2005: Adaptation for GMP.
231 void cloog_loop_free_parts(loop
, domain
, block
, inner
, next
)
233 int domain
, block
, inner
, next
;
234 { CloogLoop
* follow
;
237 { cloog_loop_leak_down() ;
238 follow
= cloog_loop_next (loop
) ;
241 cloog_domain_free(cloog_loop_domain (loop
)) ;
244 cloog_block_free(cloog_loop_block (loop
)) ;
246 if (inner
&& cloog_loop_inner (loop
))
247 cloog_loop_free_parts (cloog_loop_inner (loop
), domain
, block
, inner
, 1);
249 cloog_loop_clear_stride (loop
);
259 /******************************************************************************
260 * Reading functions *
261 ******************************************************************************/
265 * cloog_loop_read function:
266 * This function reads loop data into a file (foo, possibly stdin) and
267 * returns a pointer to a CloogLoop structure containing the read information.
268 * This function can be used only for input file reading, when one loop is
269 * associated with one statement.
270 * - number is the statement block number carried by the loop (-1 if none).
271 * - nb_parameters is the number of parameters.
273 * - September 9th 2002: first version.
274 * - April 16th 2005: adaptation to new CloogStatement struct (with number).
275 * - June 11th 2005: adaptation to new CloogBlock structure.
276 * - June 22nd 2005: Adaptation for GMP.
278 CloogLoop
* cloog_loop_read(FILE * foo
, int number
, int nb_parameters
)
279 { int nb_iterators
, op1
, op2
, op3
;
282 CloogStatement
* statement
;
284 cloog_loop_leak_up() ;
286 /* Memory allocation and information reading for the first domain: */
287 loop
= (CloogLoop
*)malloc(sizeof(CloogLoop
)) ;
289 { fprintf(stderr
, "Memory Overflow.\n") ;
293 cloog_loop_set_domain (loop
, cloog_domain_union_read (foo
));
294 if (cloog_loop_domain (loop
))
295 nb_iterators
= cloog_domain_dim (cloog_loop_domain (loop
)) - nb_parameters
;
298 /* stride is initialized to 1. */
299 cloog_loop_init_stride (loop
);
300 cloog_loop_set_si_stride (loop
, 1);
301 /* included statement block. */
302 statement
= cloog_statement_alloc(number
+1);
303 cloog_loop_set_block (loop
, cloog_block_alloc (statement
, NULL
, 0, NULL
, nb_iterators
));
304 cloog_loop_set_usr (loop
, NULL
);
305 /* inner is NULL at beginning. */
306 cloog_loop_set_inner (loop
, NULL
);
308 cloog_loop_set_next (loop
, NULL
);
310 /* To read that stupid "0 0 0" line. */
311 while (fgets(s
,MAX_STRING
,foo
) == 0) ;
312 while ((*s
=='#' || *s
=='\n') || (sscanf(s
," %d %d %d",&op1
,&op2
,&op3
)<3))
313 fgets(s
,MAX_STRING
,foo
) ;
319 /******************************************************************************
320 * Processing functions *
321 ******************************************************************************/
325 * cloog_loop_malloc function:
326 * This function allocates the memory space for a CloogLoop structure and
327 * sets its fields with default values. Then it returns a pointer to the
329 * - November 21th 2005: first version.
331 CloogLoop
* cloog_loop_malloc()
334 /* Memory allocation for the CloogLoop structure. */
335 loop
= (CloogLoop
*)malloc(sizeof(CloogLoop
)) ;
337 { fprintf(stderr
, "[CLooG]ERROR: memory overflow.\n") ;
340 cloog_loop_leak_up() ;
343 /* We set the various fields with default values. */
344 cloog_loop_set_domain (loop
, NULL
);
345 cloog_loop_set_block (loop
, NULL
);
346 cloog_loop_set_usr (loop
, NULL
);
347 cloog_loop_set_inner (loop
, NULL
);
348 cloog_loop_set_next (loop
, NULL
);
349 cloog_loop_init_stride (loop
);
350 cloog_loop_set_si_stride (loop
, 1);
357 * cloog_loop_alloc function:
358 * This function allocates the memory space for a CloogLoop structure and
359 * sets its fields with those given as input. Then it returns a pointer to the
361 * - October 27th 2001: first version.
362 * - June 22nd 2005: Adaptation for GMP.
363 * - November 21th 2005: use of cloog_loop_malloc.
365 CloogLoop
* cloog_loop_alloc(domain
, stride
, block
, inner
, next
)
366 CloogDomain
* domain
;
369 CloogLoop
* inner
, * next
;
372 loop
= cloog_loop_malloc() ;
374 cloog_loop_set_domain (loop
, domain
);
375 cloog_loop_set_block (loop
, block
);
376 cloog_loop_set_inner (loop
, inner
);
377 cloog_loop_set_next (loop
, next
);
378 cloog_loop_set_stride (loop
, stride
);
385 * cloog_loop_add function:
386 * This function adds a CloogLoop structure (loop) at a given place (now) of a
387 * NULL terminated list of CloogLoop structures. The beginning of this list
388 * is (start). This function updates (now) to (loop), and updates (start) if the
389 * added element is the first one -that is when (start) is NULL-.
390 * - October 28th 2001: first version.
392 void cloog_loop_add(CloogLoop
** start
, CloogLoop
** now
, CloogLoop
* loop
)
401 cloog_loop_set_next (*now
, loop
);
402 *now
= cloog_loop_next (*now
);
408 * cloog_loop_add function:
409 * This function adds a CloogLoop structure (loop) at a given place (now) of a
410 * NULL terminated list of CloogLoop structures. The beginning of this list
411 * is (start). This function updates (now) to the end of the loop list (loop),
412 * and updates (start) if the added element is the first one -that is when
414 * - September 9th 2005: first version.
416 void cloog_loop_add_list(CloogLoop
** start
, CloogLoop
** now
, CloogLoop
* loop
)
418 cloog_loop_add (start
, now
, loop
);
420 while (cloog_loop_next (*now
))
421 *now
= cloog_loop_next (*now
);
426 * cloog_loop_copy function:
427 * This function returns a copy of the CloogLoop structure given as input. In
428 * fact, there is just new allocations for the CloogLoop structures, but their
429 * contents are the same.
430 * - October 28th 2001: first version.
431 * - July 3rd->11th 2003: memory leaks hunt and correction.
433 CloogLoop
* cloog_loop_copy(CloogLoop
* source
)
436 CloogDomain
* domain
;
441 domain
= cloog_domain_copy (cloog_loop_domain (source
));
442 block
= cloog_block_copy (cloog_loop_block (source
));
443 loop
= cloog_loop_alloc(domain
,cloog_loop_stride (source
),block
,NULL
,NULL
) ;
444 cloog_loop_set_usr (loop
, cloog_loop_usr (source
));
445 cloog_loop_set_inner (loop
, cloog_loop_copy (cloog_loop_inner (source
)));
446 cloog_loop_set_next (loop
, cloog_loop_copy (cloog_loop_next (source
)));
453 * cloog_loop_add_disjoint function:
454 * This function adds some CloogLoop structures at a given place (now) of a
455 * NULL terminated list of CloogLoop structures. The beginning of this list
456 * is (start). (loop) can be an union of polyhedra, this function separates the
457 * union into a list of *disjoint* polyhedra then adds the list. This function
458 * updates (now) to the end of the list and updates (start) if first added
459 * element is the first of the principal list -that is when (start) is NULL-.
460 * (loop) can be freed by this function, basically when its domain is actually
461 * a union of polyhedra, but don't worry, all the useful data are now stored
462 * inside the list (start). We do not use PolyLib's Domain_Disjoint function,
463 * since the number of union components is often higher (thus code size too).
464 * - October 28th 2001: first version.
465 * - November 14th 2001: bug correction (this one was hard to find !).
466 * - July 3rd->11th 2003: memory leaks hunt and correction.
467 * - June 22nd 2005: Adaptation for GMP.
468 * - October 27th 2005: (debug) included blocks were not copied for new loops.
470 void cloog_loop_add_disjoint(start
, now
, loop
)
471 CloogLoop
** start
, ** now
, * loop
;
473 CloogLoop
* sep
, * inner
;
474 CloogDomain
* domain
, * convex
, * seen
, * seen_before
, * temp
, * rest
;
478 value_set_si(one
,1) ;
480 if (cloog_domain_isconvex (cloog_loop_domain (loop
)))
481 cloog_loop_add(start
,now
,loop
) ;
483 { /* Seems useless but may simplify the union expression (PolyLib pb). */
484 convex
= cloog_domain_convex(cloog_loop_domain (loop
)) ;
485 temp
= cloog_domain_difference(convex
,cloog_loop_domain (loop
)) ;
486 cloog_domain_free(cloog_loop_domain (loop
)) ;
487 cloog_loop_set_domain (loop
, NULL
);
488 domain
= cloog_domain_difference(convex
,temp
) ;
489 cloog_domain_free(convex
) ;
490 cloog_domain_free(temp
) ;
492 /* We separate the first element of the rest of the union. */
493 rest
= cloog_domain_cut_first(domain
) ;
495 /* This first element is the first of the list of disjoint polyhedra. */
496 sep
= cloog_loop_alloc (domain
, one
, cloog_loop_block (loop
),
497 cloog_loop_inner (loop
), NULL
);
498 cloog_loop_add(start
,now
,sep
) ;
500 /* If there are other elements, add a loop for each of them. */
502 { /* domain is used by the first element, and we will free 'seen', so... */
503 seen
= cloog_domain_copy(domain
) ;
505 while ((domain
= rest
) != NULL
)
506 { rest
= cloog_domain_cut_first(domain
) ;
507 temp
= cloog_domain_difference(domain
,seen
) ;
509 /* Each new loop will have its own life, for instance we can free its
510 * inner loop and included block. Then each one must have its own copy
511 * of both 'inner' and 'block'.
513 inner
= cloog_loop_copy (cloog_loop_inner (loop
)) ;
514 block
= cloog_block_copy (cloog_loop_block (loop
)) ;
516 sep
= cloog_loop_alloc(temp
,one
,block
,inner
,NULL
) ;
517 /* temp can be an union too. If so: recursion. */
518 if (cloog_domain_isconvex(temp
))
519 cloog_loop_add(start
,now
,sep
) ;
521 cloog_loop_add_disjoint(start
,now
,sep
) ;
525 seen
= cloog_domain_union(seen_before
,domain
) ;
527 cloog_domain_free(seen_before
) ;
528 cloog_domain_free(domain
) ;
531 cloog_loop_free_parts(loop
,0,0,0,0) ;
538 * cloog_loop_disjoint function:
539 * This function returns a list of loops such that each loop with non-convex
540 * domain in the input list (loop) is separated into several loops where the
541 * domains are the components of the union of *disjoint* polyhedra equivalent
542 * to the original non-convex domain. See cloog_loop_add_disjoint comments
544 * - September 16th 2005: first version.
546 CloogLoop
* cloog_loop_disjoint(CloogLoop
* loop
)
547 { CloogLoop
*res
=NULL
, * now
=NULL
, * next
;
549 /* Because this is often the case, don't waste time ! */
550 if ((loop
!= NULL
) && cloog_domain_isconvex(cloog_loop_domain (loop
)))
555 next
= cloog_loop_next (loop
);
556 cloog_loop_set_next (loop
, NULL
);
557 cloog_loop_add_disjoint(&res
,&now
,loop
) ;
566 * cloog_loop_restrict function:
567 * This function returns the (loop) in the context of (context): it makes the
568 * intersection between the (loop) domain and the (context), then it returns
569 * a pointer to a new loop, with this intersection as domain.
570 * - nb_par is the number of parameters.
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(loop
, context
, nb_par
)
578 CloogDomain
* context
;
580 { int new_dimension
;
582 CloogDomain
* domain
, * extended_context
, * new_domain
;
583 CloogLoop
* new_loop
;
585 domain
= cloog_loop_domain (loop
) ;
586 if (cloog_domain_dim(domain
) > cloog_domain_dim(context
))
587 { new_dimension
= cloog_domain_dim(domain
) - nb_par
;
588 extended_context
= cloog_domain_extend(context
,new_dimension
,nb_par
) ;
589 new_domain
= cloog_domain_intersection(extended_context
,cloog_loop_domain (loop
)) ;
590 cloog_domain_free(extended_context
) ;
593 new_domain
= cloog_domain_intersection(context
,cloog_loop_domain (loop
)) ;
595 if (cloog_domain_isempty(new_domain
))
596 { cloog_domain_free(new_domain
) ;
600 { value_init_c(one
) ;
601 value_set_si(one
,1) ;
602 new_loop
= cloog_loop_alloc (new_domain
, one
, cloog_loop_block (loop
),
603 cloog_loop_inner (loop
), NULL
);
611 * cloog_loop_project function:
612 * This function returns the projection of (loop) on the (level) first
613 * dimensions (outer loops). It makes the projection of the (loop) domain,
614 * then it returns a pointer to a new loop, with this projection as domain.
615 * - nb_par is the number of parameters.
617 * - October 27th 2001: first version.
618 * - July 3rd->11th 2003: memory leaks hunt and correction.
619 * - June 22nd 2005: Adaptation for GMP.
621 CloogLoop
* cloog_loop_project(CloogLoop
* loop
, int level
, int nb_par
)
623 CloogDomain
* new_domain
;
624 CloogLoop
* new_loop
, * copy
;
627 value_set_si(one
,1) ;
629 copy
= cloog_loop_alloc(cloog_loop_domain (loop
),cloog_loop_stride (loop
),cloog_loop_block (loop
),
630 cloog_loop_inner (loop
),NULL
) ;
632 if ((cloog_domain_dim(cloog_loop_domain (loop
))-nb_par
) == level
)
633 new_domain
= cloog_domain_copy(cloog_loop_domain (loop
)) ;
635 new_domain
= cloog_domain_project(cloog_loop_domain (loop
),level
,nb_par
) ;
637 new_loop
= cloog_loop_alloc(new_domain
,one
,NULL
,copy
,NULL
) ;
645 * cloog_loop_concat function:
646 * This function returns a pointer to the concatenation of the
647 * CloogLoop lists given as input.
648 * - October 28th 2001: first version.
650 CloogLoop
* cloog_loop_concat(CloogLoop
* a
, CloogLoop
* b
)
651 { CloogLoop
* loop
, * temp
;
657 while (cloog_loop_next (temp
))
658 temp
= cloog_loop_next (temp
);
660 cloog_loop_set_next (temp
, b
);
670 * cloog_loop_separate function:
671 * This function implements the Quillere algorithm for separation of multiple
672 * loops: for a given set of polyhedra (loop), it computes a set of disjoint
673 * polyhedra such that the unions of these sets are equal, and returns this set.
674 * - October 28th 2001: first version.
675 * - November 14th 2001: elimination of some unused blocks.
676 * - August 13th 2002: (debug) in the case of union of polyhedra for one
677 * loop, redundant constraints are fired.
678 * - July 3rd->11th 2003: memory leaks hunt and correction.
679 * - June 22nd 2005: Adaptation for GMP.
680 * - October 16th 2005: Removal of the non-shared constraint elimination when
681 * there is only one loop in the list (seems to work
682 * without now, DomainSimplify may have been improved).
683 * The problem was visible with test/iftest2.cloog.
685 CloogLoop
* cloog_loop_separate(CloogLoop
* loop
)
686 { int first
, lazy_equal
=0, lazy_disjoint
=0 ;
688 CloogLoop
* new_loop
, * new_inner
, * res
, * now
, * temp
, * Q
,
689 * inner
, * old
/*, * previous, * next*/ ;
690 CloogDomain
* UQ
, * old_UQ
, * domain
;
695 if (cloog_loop_next (loop
) == NULL
)
696 return cloog_loop_disjoint (loop
);
699 value_set_si(one
,1) ;
701 UQ
= cloog_domain_copy(cloog_loop_domain (loop
)) ;
702 domain
= cloog_domain_copy(cloog_loop_domain (loop
)) ;
703 res
= cloog_loop_alloc(domain
,one
,cloog_loop_block (loop
),cloog_loop_inner (loop
),NULL
) ;
706 while ((loop
= cloog_loop_next (loop
)))
711 /* For all Q, add Q-loop associated with the blocks of Q alone,
712 * and Q inter loop associated with the blocks of Q and loop.
716 { if (cloog_loop_block (Q
) == NULL
)
717 { /* Add (Q inter loop). */
718 if((lazy_disjoint
=cloog_domain_lazy_disjoint(cloog_loop_domain (Q
),cloog_loop_domain (loop
))))
721 { if ((lazy_equal
= cloog_domain_lazy_equal(cloog_loop_domain (Q
),cloog_loop_domain (loop
))))
722 domain
= cloog_domain_copy(cloog_loop_domain (Q
)) ;
724 domain
= cloog_domain_intersection(cloog_loop_domain (Q
),cloog_loop_domain (loop
)) ;
726 if (!cloog_domain_isempty(domain
))
727 { new_inner
= cloog_loop_concat(cloog_loop_copy(cloog_loop_inner (Q
)),
728 cloog_loop_copy(cloog_loop_inner (loop
))) ;
729 new_loop
= cloog_loop_alloc(domain
,one
,NULL
,new_inner
,NULL
) ;
730 cloog_loop_add_disjoint(&temp
,&now
,new_loop
) ;
733 cloog_domain_free(domain
) ;
736 /* Add (Q - loop). */
738 domain
= cloog_domain_copy(cloog_loop_domain (Q
)) ;
741 domain
= cloog_domain_empty(cloog_domain_dim(cloog_loop_domain (Q
))) ;
743 domain
= cloog_domain_difference(cloog_loop_domain (Q
),cloog_loop_domain (loop
)) ;
746 if (!cloog_domain_isempty(domain
))
747 { new_loop
= cloog_loop_alloc(domain
,one
,NULL
,cloog_loop_inner (Q
),NULL
) ;
748 cloog_loop_add_disjoint(&temp
,&now
,new_loop
) ;
751 { cloog_domain_free(domain
) ;
752 /* If cloog_loop_inner (Q) is no more useful, we can free it. */
753 inner
= cloog_loop_inner (Q
) ;
754 cloog_loop_set_inner (Q
, NULL
);
755 if (first
) /* For the first Q, inner is also cloog_loop_inner (old). */
756 cloog_loop_set_inner (old
, NULL
);
757 cloog_loop_free(inner
) ;
760 Q
= cloog_loop_next (Q
) ;
763 /* Add loop-UQ associated with the blocks of loop alone.*/
764 if (cloog_domain_lazy_disjoint(cloog_loop_domain (loop
),UQ
))
765 domain
= cloog_domain_copy(cloog_loop_domain (loop
)) ;
767 { if (cloog_domain_lazy_equal(cloog_loop_domain (loop
),UQ
))
768 domain
= cloog_domain_empty(cloog_domain_dim(UQ
)) ;
770 domain
= cloog_domain_difference(cloog_loop_domain (loop
),UQ
) ;
773 if (!cloog_domain_isempty(domain
))
774 { new_loop
= cloog_loop_alloc(domain
,one
,NULL
,cloog_loop_inner (loop
),NULL
) ;
775 cloog_loop_add_disjoint(&temp
,&now
,new_loop
) ;
778 { cloog_domain_free(domain
) ;
779 /* If cloog_loop_inner (loop) is no more useful, we can free it. */
780 cloog_loop_free(cloog_loop_inner (loop
)) ;
783 cloog_loop_set_inner (loop
, NULL
);
786 if (cloog_loop_next (loop
))
787 UQ
= cloog_domain_union(UQ
,cloog_loop_domain (loop
)) ;
789 cloog_domain_free(old_UQ
) ;
790 cloog_loop_free_parts(res
,1,0,0,1) ;
795 cloog_loop_free_parts(old
,1,0,0,1) ;
803 * cloog_loop_merge_list
804 * Merge two lists of CloogLoops. The new list contains the
805 * elements of the two lists in the same order, but they may
807 * In particular, if the elements of a and b are ordered
808 * according to the inner loops of the order list, then so are the elements
811 static CloogLoop
*cloog_loop_merge_inner_list(CloogLoop
*a
, CloogLoop
*b
,
814 CloogLoop
*loop
, **next
;
817 for ( ; order
&& (a
||b
); order
= cloog_loop_next (order
)) {
818 if (a
&& cloog_loop_block (cloog_loop_inner (order
)) == cloog_loop_block (a
)) {
820 a
= cloog_loop_next (a
);
821 next
= cloog_loop_next_addr (*next
);
824 if (b
&& cloog_loop_block (cloog_loop_inner (order
)) == cloog_loop_block (b
)) {
826 b
= cloog_loop_next (b
);
827 next
= cloog_loop_next_addr (*next
);
834 * cloog_loop_merge function:
835 * This function is the 'soft' version of loop_separate if we are looking for
836 * a code much simpler (and less efficicient). Here we merge loops if they have
837 * common parts in the iteration space (if the intersection of their domains is
838 * not empty), and let them isolated otherwise. This function returns the new
840 * - October 29th 2001: first version.
841 * - July 3rd->11th 2003: memory leaks hunt and correction.
842 * - June 22nd 2005: Adaptation for GMP.
844 CloogLoop
* cloog_loop_merge(CloogLoop
* loop
, int nb_par
, CloogOptions
* options
)
846 CloogLoop
* res
, * merge
, * now
, * Q
, * P
, * new_inner
, * next
, * old
;
847 CloogDomain
* new_domain
, * temp
;
849 if ((loop
== NULL
) || (cloog_loop_next (loop
) == NULL
))
853 value_set_si(one
,1) ;
855 /* First loop is added to the target list. */
856 res
= cloog_loop_alloc (cloog_loop_domain (loop
), one
,
857 cloog_loop_block (loop
), cloog_loop_inner (loop
), NULL
);
859 /* Now the domain is in 'res' and it will be freed. */
860 cloog_loop_set_domain (loop
, NULL
);
862 /* And one by one, we see if we have to merge or to add the other loops. */
863 while ((loop
= cloog_loop_next (loop
)))
866 P
= cloog_loop_alloc (cloog_loop_domain (loop
), one
,
867 cloog_loop_block (loop
), cloog_loop_inner (loop
), NULL
) ;
869 /* Now the domain is in 'P' and it will be freed. */
870 cloog_loop_set_domain (loop
, NULL
);
872 /* For each loop in the target list, if the intersection with the new loop
873 * is empty, we can add the new loop directly, otherwise, we can merge then
878 temp
= cloog_domain_intersection(cloog_loop_domain (Q
),cloog_loop_domain (P
)) ;
879 next
= cloog_loop_next (Q
) ;
880 if (cloog_domain_isempty(temp
))
881 { cloog_domain_free(temp
) ;
882 cloog_loop_add_disjoint(&merge
,&now
,Q
) ;
885 { cloog_domain_free(temp
) ;
886 new_inner
= cloog_loop_merge_inner_list(cloog_loop_inner (Q
), cloog_loop_inner (P
), old
);
887 temp
= cloog_domain_union(cloog_loop_domain (P
),cloog_loop_domain (Q
)) ;
889 new_domain
= cloog_domain_simple_convex(temp
, nb_par
);
891 new_domain
= cloog_domain_convex(temp
);
892 cloog_domain_free(temp
) ;
893 /* Q and P are no more used (but their content yes !).*/
894 cloog_loop_free_parts(P
,1,0,0,0) ;
895 cloog_loop_free_parts(Q
,1,0,0,0) ;
896 P
= cloog_loop_alloc(new_domain
,one
,NULL
,new_inner
,NULL
) ;
901 /* If there was merging, add it, otherwise add the loop lonely.
902 * DEBUG : ici pas besoin de s'assurer que cloog_loop_next (P) est NULL (possible que
903 * non si pas de fusion) car le dernier loop etudie a cloog_loop_next (loop) = NULL.
905 cloog_loop_add_disjoint(&merge
,&now
,P
) ;
908 cloog_loop_free_parts(old
,0,0,0,1) ;
916 * cloog_loop_sort function:
917 * Adaptation from LoopGen 0.4 by F. Quillere. This function sorts a list of
918 * parameterized disjoint polyhedra, in order to not have lexicographic order
919 * violation (see Quillere paper).
920 * - September 16th 2005: inclusion of cloog_loop_number (October 29th 2001).
922 CloogLoop
* cloog_loop_sort(CloogLoop
* loop
, int level
, int nb_par
)
923 { CloogLoop
* res
, * now
, * temp
, ** loop_array
;
924 CloogDomain
** pols
;
925 int i
, nb_loops
=0, * permut
;
927 /* We will need to know how many loops are in the list. */
932 temp
= cloog_loop_next (temp
) ;
935 /* If there is only one loop, it's the end. */
939 /* We have to allocate memory for some useful components:
940 * - loop_array: the loop array,
941 * - pols: the array of domains to sort,
942 * - permut: will give us a possible sort (maybe not the only one).
944 loop_array
= (CloogLoop
**)malloc(nb_loops
*sizeof(CloogLoop
*)) ;
945 pols
= (CloogDomain
**) malloc (nb_loops
* sizeof (CloogDomain
*)) ;
946 permut
= (int *)malloc(nb_loops
*sizeof(int)) ;
948 /* We fill up the loop and domain arrays. */
949 for (i
=0;i
<nb_loops
;i
++,loop
=cloog_loop_next (loop
))
951 loop_array
[i
] = loop
;
952 pols
[i
] = cloog_loop_domain (loop_array
[i
]) ;
955 /* cloog_domain_sort will fill up permut. */
956 cloog_domain_sort(pols
,nb_loops
,level
,nb_par
,permut
) ;
958 /* With permut and loop_array we build the sorted list. */
960 for (i
=0;i
<nb_loops
;i
++)
961 { /* To avoid pointer looping... loop_add will rebuild the list. */
962 cloog_loop_set_next (loop_array
[permut
[i
]-1], NULL
);
963 cloog_loop_add(&res
,&now
,loop_array
[permut
[i
]-1]) ;
975 * cloog_loop_nest function:
976 * This function changes the loop list in such a way that we have no more than
977 * one dimension added by level. It returns an equivalent loop list with
979 * - October 29th 2001: first version.
980 * - July 3rd->11th 2003: memory leaks hunt and correction.
981 * - June 22nd 2005: Adaptation for GMP.
982 * - November 21th 2005: (debug) now OK when cloog_loop_restrict returns NULL.
984 CloogLoop
* cloog_loop_nest(loop
, context
, level
, nb_par
)
986 CloogDomain
* context
;
990 CloogLoop
* p
, * temp
, * res
, * now
, * next
;
991 CloogDomain
* new_domain
;
994 value_set_si(one
,1) ;
997 /* Each domain is changed by its intersection with the context. */
999 { p
= cloog_loop_restrict(loop
,context
,nb_par
) ;
1000 next
= cloog_loop_next (loop
) ;
1003 { cloog_loop_free_parts(loop
,1,0,0,0) ;
1005 temp
= cloog_loop_alloc(cloog_loop_domain (p
),one
,cloog_loop_block (p
),cloog_loop_inner (p
),NULL
) ;
1007 /* If the intersection dimension is too big, we make projections smaller
1008 * and smaller, and each projection includes the preceding projection
1009 * (thus, in the target list, dimensions are added one by one).
1011 if ((cloog_domain_dim(cloog_loop_domain (p
))-nb_par
) > level
)
1012 for (l
=cloog_domain_dim(cloog_loop_domain (p
))-nb_par
-1;l
>=level
;l
--)
1013 { new_domain
= cloog_domain_project(cloog_loop_domain (p
),l
,nb_par
) ;
1014 temp
= cloog_loop_alloc(new_domain
,one
,NULL
,temp
,NULL
) ;
1017 /* p is no more useful (but its content yes !). */
1018 cloog_loop_free_parts(p
,0,0,0,0) ;
1020 cloog_loop_add(&res
,&now
,temp
) ;
1023 cloog_loop_free_parts(loop
,1,1,1,0) ;
1027 value_clear_c(one
) ;
1034 * cloog_loop_stride_1 function:
1035 * This function will find the stride of a loop for the iterator at the column
1036 * number 'level' in the constraint matrix. It will update the lower bound of
1037 * the iterator accordingly. Basically, the function will try to find in the
1038 * inner loops a common condition on this iterator for the inner loop iterators
1039 * to be integral. For instance, let us consider a loop with the iterator i,
1040 * the iteration domain -4<=i<=n, and its two inner loops with the iterator j.
1041 * The first inner loop has the constraint 3j=i, and the second one has the
1042 * constraint 6j=i. Then the common constraint on i for j to be integral is
1043 * i%3=0, the stride for i is 3. Lastly, we have to find the new lower bound
1044 * for i: the first value satisfying the common constraint: -3. At the end, the
1045 * iteration domain for i is -3<=i<=n and the stride for i is 3.
1046 * - loop is the loop including the iteration domain of the considered iterator,
1047 * - level is the column number of the iterator in the matrix of contraints.
1049 * - June 29th 2003: first version (work in progress since June 26th 2003).
1050 * - July 14th 2003: simpler version.
1051 * - June 22nd 2005: Adaptation for GMP (from S. Verdoolaege's 0.12.1 version).
1053 static void cloog_loop_stride_1 (CloogLoop
* loop
, int level
, int nb_par
)
1054 { int first_search
;
1055 Value stride
, ref_offset
, offset
, potential
, lower
;
1058 value_init_c(stride
) ;
1059 value_init_c(ref_offset
) ;
1060 value_init_c(offset
) ;
1061 value_init_c(potential
) ;
1062 value_init_c(lower
) ;
1064 value_set_si(ref_offset
,0) ;
1065 value_set_si(offset
,0) ;
1066 value_set_si(lower
,0) ;
1068 /* Default stride. */
1069 value_set_si(stride
,1) ;
1071 inner
= cloog_loop_inner (loop
) ;
1073 if (cloog_domain_integral_lowerbound(cloog_loop_domain (loop
),level
,&lower
))
1074 while (inner
!= NULL
)
1075 { /* If the minimun stride has not been found yet, find the stride. */
1076 if ((first_search
) || (value_notone_p(stride
)))
1077 { cloog_domain_stride(cloog_loop_domain (inner
),level
,nb_par
,&potential
,&offset
) ;
1078 if (value_notone_p(potential
) && (!first_search
))
1079 { /* Offsets must be the same for common stride. */
1080 Gcd(potential
,stride
,&stride
) ;
1081 value_modulus(offset
, offset
, stride
);
1082 value_modulus(ref_offset
, ref_offset
, stride
);
1083 if (value_ne(offset
,ref_offset
))
1084 value_set_si(stride
, 1);
1087 { value_assign(stride
,potential
) ;
1088 value_assign(ref_offset
,offset
) ;
1094 inner
= cloog_loop_next (inner
) ;
1097 /* Update the values if necessary. */
1098 if (value_notone_p(stride
))
1099 { /* Update the stride value. */
1100 cloog_loop_set_stride (loop
, stride
);
1101 /* The new lower bound l' is such that
1102 * (l' + offset) % s = 0 and l <= l' <= l+(s-1)
1103 * Let l' = k s - offset, then
1104 * k s - offset <= l + (s-1) <= k s - offset + (s-1)
1105 * Or l' = floor((l+offset+(s-1))/s) * s - offset
1106 * = (floor((l+offset-1)/s) + 1) * s - offset
1108 value_addto(lower
, lower
, offset
);
1109 value_decrement(lower
, lower
);
1110 value_pdivision(lower
, lower
, stride
);
1111 value_increment(lower
, lower
);
1112 value_multiply(lower
, lower
, stride
);
1113 value_subtract(lower
, lower
, offset
);
1114 cloog_domain_lowerbound_update(cloog_loop_domain (loop
),level
,lower
) ;
1117 value_clear_c(stride
) ;
1118 value_clear_c(ref_offset
) ;
1119 value_clear_c(offset
) ;
1120 value_clear_c(potential
) ;
1121 value_clear_c(lower
) ;
1126 * cloog_loop_stop function:
1127 * This function implements the 'stop' option : each domain of each loop
1128 * in the list 'loop' is replaced by 'context'. 'context' should be the
1129 * domain of the outer loop. By using this method, there are no more dimensions
1130 * to scan and the simplification step will automaticaly remove the domains
1131 * since they are the same as the corresponding contexts. The effect of this
1132 * function is to stop the code generation at the level this function is called,
1133 * the resulting code do not consider the next dimensions.
1134 * - January 11th 2005: first version.
1136 CloogLoop
* cloog_loop_stop(CloogLoop
* loop
, CloogDomain
* context
)
1141 cloog_domain_free(cloog_loop_domain (loop
)) ;
1142 cloog_loop_set_domain (loop
, cloog_domain_copy (context
));
1143 cloog_loop_set_next (loop
, cloog_loop_stop (cloog_loop_next (loop
), context
)) ;
1151 * cloog_loop_scalar_gt function:
1152 * This function returns 1 if loop 'l1' is greater than loop 'l2' for the
1153 * scalar dimension vector that begins at dimension 'scalar', 0 otherwise. What
1154 * we want to know is whether a loop is scheduled before another one or not.
1155 * This function solves the problem when the considered dimension for scheduling
1156 * is a scalar dimension. Since there may be a succession of scalar dimensions,
1157 * this function will reason about the vector of scalar dimension that begins
1158 * at dimension 'level+scalar' and finish to the first non-scalar dimension.
1159 * \param l1 Loop to be compared with l2.
1160 * \param l2 Loop to be compared with l1.
1161 * \param level Current non-scalar dimension.
1162 * \param scaldims Boolean array saying whether a dimension is scalar or not.
1163 * \param nb_scattdims Size of the scaldims array.
1164 * \param scalar Current scalar dimension.
1165 * \return 1 if (l1 > l2), 0 otherwise.
1167 * - September 9th 2005: first version.
1168 * - October 15nd 2007: now "greater than" instead of "greater or equal".
1170 int cloog_loop_scalar_gt(l1
, l2
, level
, scaldims
, nb_scattdims
, scalar
)
1171 CloogLoop
* l1
, * l2
;
1172 int level
, * scaldims
, nb_scattdims
, scalar
;
1174 while ((scalar
< cloog_block_nb_scaldims (cloog_loop_block (cloog_loop_inner (l1
))))
1175 && scaldims
[level
+scalar
-1])
1177 if (value_gt (cloog_block_scaldims_elt (cloog_loop_block (cloog_loop_inner (l1
)), scalar
),
1178 cloog_block_scaldims_elt (cloog_loop_block (cloog_loop_inner (l2
)), scalar
)))
1188 * cloog_loop_scalar_eq function:
1189 * This function returns 1 if loop 'l1' is equal to loop 'l2' for the scalar
1190 * dimension vector that begins at dimension 'scalar', 0 otherwise. What we want
1191 * to know is whether two loops are scheduled for the same time or not.
1192 * This function solves the problem when the considered dimension for scheduling
1193 * is a scalar dimension. Since there may be a succession of scalar dimensions,
1194 * this function will reason about the vector of scalar dimension that begins
1195 * at dimension 'level+scalar' and finish to the first non-scalar dimension.
1196 * - l1 and l2 are the loops to compare,
1197 * - level is the current non-scalar dimension,
1198 * - scaldims is the boolean array saying whether a dimension is scalar or not,
1199 * - nb_scattdims is the size of the scaldims array,
1200 * - scalar is the current scalar dimension.
1202 * - September 9th 2005 : first version.
1204 int cloog_loop_scalar_eq(l1
, l2
, level
, scaldims
, nb_scattdims
, scalar
)
1205 CloogLoop
* l1
, * l2
;
1206 int level
, * scaldims
, nb_scattdims
, scalar
;
1208 while ((scalar
< cloog_block_nb_scaldims (cloog_loop_block (cloog_loop_inner (l1
))))
1209 && scaldims
[level
+scalar
-1])
1211 if (value_eq (cloog_block_scaldims_elt (cloog_loop_block (cloog_loop_inner (l1
)), scalar
),
1212 cloog_block_scaldims_elt (cloog_loop_block (cloog_loop_inner (l2
)), scalar
)))
1222 * cloog_loop_scalar_sort function:
1223 * This function sorts a linked list of loops (loop) with respect to the
1224 * scalar dimension vector that begins at dimension 'scalar'. Since there may
1225 * be a succession of scalar dimensions, this function will reason about the
1226 * vector of scalar dimension that begins at dimension 'level+scalar' and
1227 * finish to the first non-scalar dimension.
1228 * \param loop Loop list to sort.
1229 * \param level Current non-scalar dimension.
1230 * \param scaldims Boolean array saying whether a dimension is scalar or not.
1231 * \param nb_scattdims Size of the scaldims array.
1232 * \param scalar Current scalar dimension.
1233 * \return A pointer to the sorted list.
1235 * - July 2nd 2005: first developments.
1236 * - September 2nd 2005: first version.
1237 * - October 15nd 2007: complete rewrite to remove bugs, now a bubble sort.
1239 CloogLoop
* cloog_loop_scalar_sort(loop
, level
, scaldims
, nb_scattdims
, scalar
)
1241 int level
, * scaldims
, nb_scattdims
, scalar
;
1243 CloogLoop
**current
;
1247 for (current
= &loop
; cloog_loop_next (*current
); current
= cloog_loop_next_addr (*current
)) {
1248 CloogLoop
*next
= cloog_loop_next (*current
);
1249 if (cloog_loop_scalar_gt(*current
,next
,level
,scaldims
,nb_scattdims
,scalar
)) {
1251 cloog_loop_set_next (*current
, cloog_loop_next (next
));
1252 cloog_loop_set_next (next
, *current
);
1263 * cloog_loop_generate_backtrack function:
1264 * adaptation from LoopGen 0.4 by F. Quillere. This function implements the
1265 * backtrack of the Quillere et al. algorithm (see the Quillere paper).
1266 * It eliminates unused iterations of the current level for the new one. See the
1267 * example called linearity-1-1 example with and without this part for an idea.
1268 * - October 26th 2001: first version in cloog_loop_generate_general.
1269 * - July 31th 2002: (debug) no more parasite loops (REALLY hard !).
1270 * - October 30th 2005: extraction from cloog_loop_generate_general.
1272 CloogLoop
* cloog_loop_generate_backtrack(loop
, context
, level
, nb_par
, options
)
1274 CloogDomain
* context
;
1276 CloogOptions
* options
;
1278 CloogDomain
* domain
;
1279 CloogLoop
* now
, * now2
, * next
, * next2
, * end
, * temp
, * l
, * inner
,
1283 value_set_si(one
,1) ;
1288 while (temp
!= NULL
)
1290 inner
= cloog_loop_inner (temp
) ;
1292 while (inner
!= NULL
)
1294 next
= cloog_loop_next (inner
) ;
1295 /* This 'if' and its first part is the debug of july 31th 2002. */
1296 if (cloog_loop_block (inner
))
1298 end
= cloog_loop_alloc (cloog_loop_domain (inner
), one
,
1299 cloog_loop_block (inner
), NULL
, NULL
);
1300 domain
= cloog_domain_copy(cloog_loop_domain (temp
)) ;
1301 new_loop
= cloog_loop_alloc(domain
,one
,NULL
,end
,NULL
) ;
1304 new_loop
= cloog_loop_project(inner
,level
,nb_par
) ;
1306 cloog_loop_free_parts(inner
,0,0,0,0) ;
1307 cloog_loop_add(&l
,&now2
,new_loop
) ;
1311 cloog_loop_set_inner (temp
, NULL
);
1314 { l
= cloog_loop_separate(l
) ;
1315 l
= cloog_loop_sort(l
,level
,nb_par
) ;
1318 cloog_loop_set_stride (l
, cloog_loop_stride (temp
));
1319 cloog_loop_add(&loop
,&now
,l
) ;
1320 l
= cloog_loop_next (l
) ;
1323 next2
= cloog_loop_next (temp
) ;
1324 cloog_loop_free_parts(temp
,1,0,0,0) ;
1328 value_clear_c(one
) ;
1335 * cloog_loop_generate_general function:
1336 * Adaptation from LoopGen 0.4 by F. Quillere. This function implements the
1337 * Quillere algorithm for polyhedron scanning from step 3 to 5.
1338 * (see the Quillere paper).
1339 * - loop is the loop for which we have to generate a scanning code,
1340 * - context is the context of the current loop (constraints on parameter and/or
1341 * on outer loop counters),
1342 * - level is the current non-scalar dimension,
1343 * - scalar is the current scalar dimension,
1344 * - scaldims is the boolean array saying whether a dimension is scalar or not,
1345 * - nb_scattdims is the size of the scaldims array,
1346 * - nb_par is the number of parameters,
1347 * - options are the general code generation options.
1349 * - October 26th 2001: first version.
1350 * - July 3rd->11th 2003: memory leaks hunt and correction.
1351 * - June 22nd 2005: Adaptation for GMP.
1352 * - September 2nd 2005: The function have been cutted out in two pieces:
1353 * cloog_loop_generate and this one, in order to handle
1354 * the scalar dimension case more efficiently with
1355 * cloog_loop_generate_scalar.
1356 * - November 15th 2005: (debug) the result of the cloog_loop_generate call may
1357 * be a list of polyhedra (especially if stop option is
1358 * used): cloog_loop_add_list instead of cloog_loop_add.
1360 CloogLoop
* cloog_loop_generate_general(loop
, context
, level
, scalar
,
1361 scaldims
, nb_scattdims
, nb_par
, options
)
1363 CloogDomain
* context
;
1364 int level
, scalar
, * scaldims
, nb_scattdims
, nb_par
;
1365 CloogOptions
* options
;
1367 CloogLoop
* res
, * now
, * temp
, * l
, * new_loop
, * inner
, * now2
, * end
,
1369 CloogDomain
* domain
;
1371 /* 3. Separate all projections into disjoint polyhedra. */
1372 res
= ((options
->f
> level
+scalar
) || (options
->f
< 0)) ?
1373 cloog_loop_merge(loop
, nb_par
, options
) : cloog_loop_separate(loop
);
1375 /* 3b. -correction- sort the loops to determine their textual order. */
1376 res
= cloog_loop_sort(res
,level
,nb_par
) ;
1379 value_set_si(one
,1) ;
1381 /* 4. Recurse for each loop with the current domain as context. */
1384 if ((level
+scalar
< options
->l
) || (options
->l
< 0))
1386 { if (options
->strides
)
1387 cloog_loop_stride_1 (temp
,level
,nb_par
) ;
1388 inner
= cloog_loop_inner (temp
) ;
1389 domain
= cloog_loop_domain (temp
) ;
1391 while (inner
!= NULL
)
1392 { /* 4b. -ced- recurse for each sub-list of non terminal loops. */
1393 if (cloog_domain_dim(cloog_loop_domain (inner
)) > (level
+ nb_par
))
1395 while ((cloog_loop_next (end
)) &&
1396 (cloog_domain_dim (cloog_loop_domain (cloog_loop_next (end
))) > (level
+ nb_par
)))
1397 end
= cloog_loop_next (end
) ;
1399 next
= cloog_loop_next (end
) ;
1400 cloog_loop_set_next (end
, NULL
);
1402 l
= cloog_loop_generate(inner
,domain
,level
+1,scalar
,
1403 scaldims
,nb_scattdims
,nb_par
,options
) ;
1406 cloog_loop_add_list(&into
,&now
,l
) ;
1411 { cloog_loop_add(&into
,&now
,inner
) ;
1412 inner
= cloog_loop_next (inner
) ;
1415 next
= cloog_loop_next (temp
) ;
1416 cloog_loop_set_next (temp
, NULL
);
1417 cloog_loop_set_inner (temp
, into
);
1418 cloog_loop_add(&res
,&now2
,temp
) ;
1422 while (temp
!= NULL
)
1423 { next
= cloog_loop_next (temp
) ;
1424 l
= cloog_loop_nest(cloog_loop_inner (temp
),cloog_loop_domain (temp
),level
+1,nb_par
) ;
1425 new_loop
= cloog_loop_alloc(cloog_loop_domain (temp
),one
,NULL
,l
,NULL
) ;
1426 cloog_loop_set_inner (temp
, NULL
);
1427 cloog_loop_set_next (temp
, NULL
);
1428 cloog_loop_free_parts(temp
,0,0,0,0) ;
1429 cloog_loop_add(&res
,&now
,new_loop
) ;
1433 /* 5. eliminate unused iterations of the current level for the new one. See
1434 * the example called linearity-1-1 example with and without this part
1437 if ((!options
->nobacktrack
) &&
1438 ((level
+scalar
< options
->l
) || (options
->l
< 0)) &&
1439 ((options
->f
<= level
+scalar
) && !(options
->f
< 0)))
1440 res
= cloog_loop_generate_backtrack(res
,context
,level
,nb_par
,options
) ;
1442 /* Pray for my new paper to be accepted somewhere since the following stuff
1443 * is really amazing :-) !
1444 * Far long later: The paper has been accepted to PACT 2004 :-))). But there
1445 * are still some bugs and I have no time to fix them. Thus now you have to
1446 * pray for me to get an academic position for that really amazing stuff :-) !
1447 * Later again: OK, I get my academic position, but still I have not enough
1448 * time to fix and clean this part... Pray again :-) !!!
1450 /* res = cloog_loop_unisolate(res,context,level,nb_par) ;*/
1452 value_clear_c(one
) ;
1458 * cloog_loop_generate_scalar function:
1459 * This function applies the simplified code generation scheme in the trivial
1460 * case of scalar dimensions. When dealing with scalar dimensions, there is
1461 * no need of costly polyhedral operations for separation or sorting: sorting
1462 * is a question of comparing scalar vectors and separation amounts to consider
1463 * only loops with the same scalar vector for the next step of the code
1464 * generation process. This function achieves the separation/sorting process
1465 * for the vector of scalar dimension that begins at dimension 'level+scalar'
1466 * and finish to the first non-scalar dimension.
1467 * - loop is the loop for which we have to generate a scanning code,
1468 * - context is the context of the current loop (constraints on parameter and/or
1469 * on outer loop counters),
1470 * - level is the current non-scalar dimension,
1471 * - scalar is the current scalar dimension,
1472 * - scaldims is the boolean array saying whether a dimension is scalar or not,
1473 * - nb_scattdims is the size of the scaldims array,
1474 * - nb_par is the number of parameters,
1475 * - options are the general code generation options.
1477 * - September 2nd 2005: First version.
1479 CloogLoop
* cloog_loop_generate_scalar(loop
, context
, level
, scalar
,
1480 scaldims
, nb_scattdims
, nb_par
, options
)
1482 CloogDomain
* context
;
1483 int level
, scalar
, * scaldims
, nb_scattdims
, nb_par
;
1484 CloogOptions
* options
;
1485 { CloogLoop
* res
, * now
, * temp
, * l
, * end
, * next
, * ref
;
1487 /* We sort the loop list with respect to the current scalar vector. */
1488 res
= cloog_loop_scalar_sort(loop
,level
,scaldims
,nb_scattdims
,scalar
) ;
1492 while (temp
!= NULL
)
1493 { /* Then we will appy the general code generation process to each sub-list
1494 * of loops with the same scalar vector.
1499 while ((cloog_loop_next (end
)) &&
1500 cloog_loop_scalar_eq(ref
,cloog_loop_next (end
),level
,scaldims
,nb_scattdims
,scalar
))
1501 end
= cloog_loop_next (end
) ;
1503 next
= cloog_loop_next (end
) ;
1504 cloog_loop_set_next (end
, NULL
);
1506 /* For the next dimension, scalar value is updated by adding the scalar
1507 * vector size, which is stored at scaldims[level+scalar-1].
1509 l
= cloog_loop_generate_general(temp
,context
,level
,
1510 scalar
+scaldims
[level
+scalar
-1],
1511 scaldims
,nb_scattdims
,nb_par
,options
) ;
1514 cloog_loop_add_list(&res
,&now
,l
) ;
1524 * cloog_loop_generate function:
1525 * Adaptation from LoopGen 0.4 by F. Quillere. This function implements the
1526 * Quillere algorithm for polyhedron scanning from step 1 to 2.
1527 * (see the Quillere paper).
1528 * - loop is the loop for which we have to generate a scanning code,
1529 * - context is the context of the current loop (constraints on parameter and/or
1530 * on outer loop counters),
1531 * - level is the current non-scalar dimension,
1532 * - scalar is the current scalar dimension,
1533 * - scaldims is the boolean array saying whether a dimension is scalar or not,
1534 * - nb_scattdims is the size of the scaldims array,
1535 * - nb_par is the number of parameters,
1536 * - options are the general code generation options.
1538 * - October 26th 2001: first version.
1539 * - July 3rd->11th 2003: memory leaks hunt and correction.
1540 * - June 15th 2005: a memory leak fixed (loop was not entirely freed when
1541 * the result of cloog_loop_restrict was NULL).
1542 * - June 22nd 2005: Adaptation for GMP.
1543 * - September 2nd 2005: The function have been cutted out in two pieces:
1544 * cloog_loop_generate and this one, in order to handle
1545 * the scalar dimension case more efficiently with
1546 * cloog_loop_generate_scalar.
1547 * - November 15th 2005: (debug) Condition for stop option no more take care of
1548 * further scalar dimensions.
1550 CloogLoop
* cloog_loop_generate(loop
, context
, level
, scalar
,
1551 scaldims
, nb_scattdims
, nb_par
, options
)
1553 CloogDomain
* context
;
1554 int level
, scalar
, * scaldims
, nb_scattdims
, nb_par
;
1555 CloogOptions
* options
;
1556 { CloogLoop
* res
, * now
, * temp
, * next
, * old
;
1558 /* If the user asked to stop code generation at this level, let's stop. */
1559 if ((options
->stop
>= 0) && (level
+scalar
>= options
->stop
+1))
1560 return cloog_loop_stop(loop
,context
) ;
1564 /* 1. Replace each polyhedron by its intersection with the context.
1565 * 2. Compute the projection of each polyhedron onto the outermost
1566 * loop variable and the parameters.
1568 while (loop
!= NULL
)
1570 next
= cloog_loop_next (loop
) ;
1571 temp
= cloog_loop_restrict(loop
,context
,nb_par
) ;
1575 temp
= cloog_loop_project(temp
,level
,nb_par
) ;
1576 cloog_loop_free_parts(old
,0,0,0,0) ;
1577 cloog_loop_add(&res
,&now
,temp
) ;
1578 cloog_loop_free_parts(loop
,1,0,0,0) ;
1582 cloog_loop_set_next (loop
, NULL
);
1583 cloog_loop_free(loop
) ;
1591 /* To save both time and memory, we switch here depending on whether the
1592 * current dimension is scalar (simplified processing) or not (general
1595 if ((level
+scalar
<= nb_scattdims
) && (scaldims
[level
+scalar
-1]))
1596 res
= cloog_loop_generate_scalar(res
,context
,level
,scalar
,
1597 scaldims
,nb_scattdims
,nb_par
,options
) ;
1599 res
= cloog_loop_generate_general(res
,context
,level
,scalar
,
1600 scaldims
,nb_scattdims
,nb_par
,options
) ;
1607 * cloog_loop_simplify function:
1608 * This function implements the part 6. of the Quillere algorithm, it
1609 * recursively simplifies each loop in the context of the preceding loop domain.
1610 * It returns a pointer to the simplified loop list.
1611 * The cloog_domain_simplify (DomainSimplify) behaviour is really bad with
1612 * polyhedra union and some really awful sidesteppings were written, I plan
1614 * - October 31th 2001: first version.
1615 * - July 3rd->11th 2003: memory leaks hunt and correction.
1616 * - April 16th 2005: a memory leak fixed (extended_context was not freed).
1617 * - June 15th 2005: a memory leak fixed (loop was not conveniently freed
1618 * when the constraint system is never true).
1619 * - October 27th 2005: - this function called before cloog_loop_fast_simplify
1620 * is now the official cloog_loop_simplify function in
1621 * replacement of a slower and more complex one (after
1622 * deep changes in the pretty printer).
1623 * - we use cloog_loop_disjoint to fix the problem when
1624 * simplifying gives a union of polyhedra (before, it
1625 * was under the responsibility of the pretty printer).
1627 CloogLoop
* cloog_loop_simplify(loop
, context
, level
, nb_par
)
1629 CloogDomain
* context
;
1632 CloogBlock
* new_block
;
1633 CloogLoop
* simplified
, * inner
, * next
;
1634 CloogDomain
* domain
, * simp
, * inter
, * extended_context
;
1639 domain
= cloog_loop_domain (loop
) ;
1641 next
= cloog_loop_simplify(cloog_loop_next (loop
),context
,level
,nb_par
) ;
1643 domain_dim
= cloog_domain_dim(domain
) - nb_par
;
1644 extended_context
=cloog_domain_extend(context
,domain_dim
,nb_par
);
1645 inter
= cloog_domain_intersection(domain
,extended_context
) ;
1646 simp
= cloog_domain_simplify(inter
,extended_context
) ;
1647 cloog_domain_free(extended_context
) ;
1649 /* If the constraint system is never true, go to the next one. */
1650 if (cloog_domain_never_integral(simp
)) {
1651 cloog_loop_set_next (loop
, NULL
);
1652 cloog_loop_free(loop
);
1653 cloog_domain_free(inter
);
1654 cloog_domain_free(simp
);
1658 inner
= cloog_loop_simplify(cloog_loop_inner (loop
),inter
,level
+1,nb_par
) ;
1659 cloog_domain_free(inter
) ;
1661 if ((inner
== NULL
) && (cloog_loop_block (loop
) == NULL
))
1662 { cloog_loop_set_inner (loop
, NULL
); /* For loop integrity. */
1663 cloog_loop_set_next (loop
, NULL
); /* For loop integrity. */
1664 cloog_loop_free_parts(loop
,1,1,1,0) ;
1665 cloog_domain_free(simp
);
1669 new_block
= cloog_block_copy (cloog_loop_block (loop
));
1671 simplified
= cloog_loop_alloc (simp
, cloog_loop_stride (loop
), new_block
, inner
, next
);
1673 /* Examples like test/iftest2.cloog give unions of polyhedra after
1674 * simplifying, thus we we have to disjoint them. Another good reason to
1675 * put the simplifying step in the Quillere backtrack.
1677 simplified
= cloog_loop_disjoint(simplified
) ;
1679 cloog_loop_set_inner (loop
, NULL
); /* For loop integrity. */
1680 cloog_loop_set_next (loop
, NULL
); /* For loop integrity. */
1681 cloog_loop_free_parts(loop
,1,1,0,0) ;
1683 return(simplified
) ;
1688 * cloog_loop_scatter function:
1689 * This function add the scattering (scheduling) informations in a loop.
1690 * - November 4th 2001: first version.
1692 void cloog_loop_scatter(CloogLoop
* loop
, CloogDomain
* scatt
)
1694 CloogDomain
* domain
, * ext
, * newdom
, * newpart
, * temp
;
1696 domain
= cloog_loop_domain (loop
) ;
1698 scatt_dim
= cloog_domain_dim(scatt
) - cloog_domain_dim(domain
) ;
1700 /* For each polyhedron of domain (it can be an union of polyhedra). */
1701 while (domain
!= NULL
)
1702 { /* Extend the domain by adding the scattering dimensions as the new
1703 * first domain dimensions.
1705 ext
= cloog_domain_extend(domain
,scatt_dim
,cloog_domain_dim(domain
)) ;
1706 /* Then add the scattering constraints. */
1707 newpart
= cloog_domain_addconstraints(scatt
,ext
) ;
1708 cloog_domain_free(ext
) ;
1712 newdom
= cloog_domain_union(newdom
,newpart
) ;
1713 cloog_domain_free(temp
) ;
1714 cloog_domain_free(newpart
) ;
1719 /* We don't want to free the rest of the list. */
1721 domain
= cloog_domain_cut_first(temp
) ;
1722 cloog_domain_free(temp
) ;
1725 cloog_loop_set_domain (loop
, newdom
);