clast: allow clast_term to represent multiple of any clast_expr
[cloog.git] / source / loop.c
blob1dee51718f530664d04a669c9b5d6be763f4001a
2 /**-------------------------------------------------------------------**
3 ** CLooG **
4 **-------------------------------------------------------------------**
5 ** loop.c **
6 **-------------------------------------------------------------------**
7 ** First version: october 26th 2001 **
8 **-------------------------------------------------------------------**/
11 /******************************************************************************
12 * CLooG : the Chunky Loop Generator (experimental) *
13 ******************************************************************************
14 * *
15 * Copyright (C) 2001-2005 Cedric Bastoul *
16 * *
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 *
20 * version. *
21 * *
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 *
25 * for more details. *
26 * *
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 *
30 * *
31 * CLooG, the Chunky Loop Generator *
32 * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr *
33 * *
34 ******************************************************************************/
35 /* CAUTION: the english used for comments is probably the worst you ever read,
36 * please feel free to correct and improve it !
39 # include <stdlib.h>
40 # include <stdio.h>
41 # include "../include/cloog/cloog.h"
44 /******************************************************************************
45 * Memory leaks hunting *
46 ******************************************************************************/
49 /**
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 int cloog_loop_allocated = 0 ;
63 int cloog_loop_freed = 0 ;
64 int cloog_loop_max = 0 ;
67 static void cloog_loop_leak_up()
68 { cloog_loop_allocated ++ ;
69 if ((cloog_loop_allocated-cloog_loop_freed) > cloog_loop_max)
70 cloog_loop_max = cloog_loop_allocated - cloog_loop_freed ;
74 static void cloog_loop_leak_down()
75 { cloog_loop_freed ++ ;
79 /******************************************************************************
80 * Structure display function *
81 ******************************************************************************/
84 /**
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),
91 * - Minor tweaks.
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)
97 { int i, j, first=1 ;
99 if (loop)
100 { /* Go to the right level. */
101 for (i=0; i<level; i++)
102 fprintf(file,"|\t") ;
104 fprintf(file,"+-- CloogLoop\n") ;
107 /* For each loop. */
108 while (loop)
109 { if (!first)
110 { /* Go to the right level. */
111 for (i=0; i<level; i++)
112 fprintf(file,"|\t") ;
114 fprintf(file,"| CloogLoop\n") ;
116 else
117 first = 0 ;
119 /* A blank line. */
120 for(j=0; j<=level+1; j++)
121 fprintf(file,"|\t") ;
122 fprintf(file,"\n") ;
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") ;
130 fprintf(file, "Stride: ") ;
131 cloog_int_print(file, loop->stride);
132 fprintf(file, "\n") ;
134 /* A blank line. */
135 for(j=0; j<=level+1; j++)
136 fprintf(file,"|\t") ;
137 fprintf(file,"\n") ;
139 /* Print the block. */
140 cloog_block_print_structure(file,loop->block,level+1) ;
142 /* A blank line. */
143 for (i=0; i<=level+1; i++)
144 fprintf(file,"|\t") ;
145 fprintf(file,"\n") ;
147 /* Print inner if any. */
148 if (loop->inner)
149 cloog_loop_print_structure(file,loop->inner,level+1) ;
151 /* And let's go for the next one. */
152 loop = loop->next ;
154 /* One more time something that is here only for a better look. */
155 if (!loop)
156 { /* Two blank lines if this is the end of the linked list. */
157 for (j=0; j<2; j++)
158 { for (i=0; i<=level; i++)
159 fprintf(file,"|\t") ;
161 fprintf(file,"\n") ;
164 else
165 { /* A special blank line if the is a next loop. */
166 for (i=0; i<=level; i++)
167 fprintf(file,"|\t") ;
168 fprintf(file,"V\n") ;
175 * cloog_loop_print function:
176 * This function prints the content of a CloogLoop structure (start) into a
177 * file (file, possibly stdout).
178 * - June 2nd 2005: Now this very old function (probably as old as CLooG) is
179 * only a frontend to cloog_loop_print_structure, with a quite
180 * better human-readable representation.
182 void cloog_loop_print(FILE * file, CloogLoop * loop)
183 { cloog_loop_print_structure(file,loop,0) ;
187 /******************************************************************************
188 * Memory deallocation function *
189 ******************************************************************************/
193 * cloog_loop_free function:
194 * This function frees the allocated memory for a CloogLoop structure (loop),
195 * and frees its inner loops and its next loops.
196 * - June 22nd 2005: Adaptation for GMP.
198 void cloog_loop_free(CloogLoop * loop)
199 { CloogLoop * next ;
201 while (loop != NULL)
202 { cloog_loop_leak_down() ;
204 next = loop->next ;
205 cloog_domain_free(loop->domain) ;
206 cloog_block_free(loop->block) ;
207 if (loop->inner != NULL)
208 cloog_loop_free(loop->inner) ;
210 cloog_int_clear(loop->stride);
211 free(loop) ;
212 loop = next ;
218 * cloog_loop_free_parts function:
219 * This function frees the allocated memory for some parts of a CloogLoop
220 * structure (loop), each other argument is a boolean having to be set to 1 if
221 * we want to free the corresponding part, 0 otherwise. This function applies
222 * the same freeing policy to its inner ans next loops recursively.
223 * - July 3rd 2003: first version.
224 * - June 22nd 2005: Adaptation for GMP.
226 void cloog_loop_free_parts(loop, domain, block, inner, next)
227 CloogLoop * loop ;
228 int domain, block, inner, next ;
229 { CloogLoop * follow ;
231 while (loop != NULL)
232 { cloog_loop_leak_down() ;
233 follow = loop->next ;
235 if (domain)
236 cloog_domain_free(loop->domain) ;
238 if (block)
239 cloog_block_free(loop->block) ;
241 if ((inner) && (loop->inner != NULL))
242 cloog_loop_free_parts(loop->inner,domain,block,inner,1) ;
244 cloog_int_clear(loop->stride);
245 free(loop) ;
246 if (next)
247 loop = follow ;
248 else
249 loop = NULL ;
254 /******************************************************************************
255 * Reading functions *
256 ******************************************************************************/
260 * cloog_loop_read function:
261 * This function reads loop data into a file (foo, possibly stdin) and
262 * returns a pointer to a CloogLoop structure containing the read information.
263 * This function can be used only for input file reading, when one loop is
264 * associated with one statement.
265 * - number is the statement block number carried by the loop (-1 if none).
266 * - nb_parameters is the number of parameters.
268 * - September 9th 2002: first version.
269 * - April 16th 2005: adaptation to new CloogStatement struct (with number).
270 * - June 11th 2005: adaptation to new CloogBlock structure.
271 * - June 22nd 2005: Adaptation for GMP.
273 CloogLoop * cloog_loop_read(FILE * foo, int number, int nb_parameters,
274 CloogOptions *options)
275 { int nb_iterators, op1, op2, op3 ;
276 char s[MAX_STRING] ;
277 CloogLoop * loop ;
278 CloogStatement * statement ;
280 cloog_loop_leak_up() ;
282 /* Memory allocation and information reading for the first domain: */
283 loop = (CloogLoop *)malloc(sizeof(CloogLoop)) ;
284 if (loop == NULL)
285 cloog_die("memory overflow.\n");
286 /* domain. */
287 loop->domain = cloog_domain_union_read(foo, nb_parameters, options);
288 if (loop->domain != NULL)
289 nb_iterators = cloog_domain_dimension(loop->domain) - nb_parameters ;
290 else
291 nb_iterators = 0 ;
292 /* stride is initialized to 1. */
293 cloog_int_init(loop->stride);
294 cloog_int_set_si(loop->stride, 1);
295 /* included statement block. */
296 statement = cloog_statement_alloc(number+1);
297 loop->block = cloog_block_alloc(statement, 0, NULL, nb_iterators);
298 loop->usr = NULL;
299 /* inner is NULL at beginning. */
300 loop->inner = NULL ;
301 /* next element. */
302 loop->next = NULL ;
304 /* To read that stupid "0 0 0" line. */
305 while (fgets(s,MAX_STRING,foo) == 0) ;
306 while ((*s=='#' || *s=='\n') || (sscanf(s," %d %d %d",&op1,&op2,&op3)<3))
307 fgets(s,MAX_STRING,foo) ;
309 return loop ;
313 /******************************************************************************
314 * Processing functions *
315 ******************************************************************************/
319 * cloog_loop_malloc function:
320 * This function allocates the memory space for a CloogLoop structure and
321 * sets its fields with default values. Then it returns a pointer to the
322 * allocated space.
323 * - November 21th 2005: first version.
325 CloogLoop * cloog_loop_malloc()
326 { CloogLoop * loop ;
328 /* Memory allocation for the CloogLoop structure. */
329 loop = (CloogLoop *)malloc(sizeof(CloogLoop)) ;
330 if (loop == NULL)
331 cloog_die("memory overflow.\n");
332 cloog_loop_leak_up() ;
335 /* We set the various fields with default values. */
336 loop->domain = NULL ;
337 loop->block = NULL ;
338 loop->usr = NULL;
339 loop->inner = NULL ;
340 loop->next = NULL ;
341 cloog_int_init(loop->stride);
342 cloog_int_set_si(loop->stride, 1);
344 return loop ;
349 * cloog_loop_alloc function:
350 * This function allocates the memory space for a CloogLoop structure and
351 * sets its fields with those given as input. Then it returns a pointer to the
352 * allocated space.
353 * - October 27th 2001: first version.
354 * - June 22nd 2005: Adaptation for GMP.
355 * - November 21th 2005: use of cloog_loop_malloc.
357 CloogLoop * cloog_loop_alloc(domain, stride, block, inner, next)
358 CloogDomain * domain ;
359 cloog_int_t stride;
360 CloogBlock * block ;
361 CloogLoop * inner, * next ;
362 { CloogLoop * loop ;
364 loop = cloog_loop_malloc() ;
366 loop->domain = domain ;
367 loop->block = block ;
368 loop->inner = inner ;
369 loop->next = next ;
370 cloog_int_set(loop->stride, stride);
372 return(loop) ;
377 * cloog_loop_add function:
378 * This function adds a CloogLoop structure (loop) at a given place (now) of a
379 * NULL terminated list of CloogLoop structures. The beginning of this list
380 * is (start). This function updates (now) to (loop), and updates (start) if the
381 * added element is the first one -that is when (start) is NULL-.
382 * - October 28th 2001: first version.
384 void cloog_loop_add(CloogLoop ** start, CloogLoop ** now, CloogLoop * loop)
385 { if (*start == NULL)
386 { *start = loop ;
387 *now = *start ;
389 else
390 { (*now)->next = loop ;
391 *now = (*now)->next ;
397 * cloog_loop_add function:
398 * This function adds a CloogLoop structure (loop) at a given place (now) of a
399 * NULL terminated list of CloogLoop structures. The beginning of this list
400 * is (start). This function updates (now) to the end of the loop list (loop),
401 * and updates (start) if the added element is the first one -that is when
402 * (start) is NULL-.
403 * - September 9th 2005: first version.
405 void cloog_loop_add_list(CloogLoop ** start, CloogLoop ** now, CloogLoop * loop)
406 { if (*start == NULL)
407 { *start = loop ;
408 *now = *start ;
410 else
411 { (*now)->next = loop ;
412 *now = (*now)->next ;
415 while ((*now)->next != NULL)
416 *now = (*now)->next ;
421 * cloog_loop_copy function:
422 * This function returns a copy of the CloogLoop structure given as input. In
423 * fact, there is just new allocations for the CloogLoop structures, but their
424 * contents are the same.
425 * - October 28th 2001: first version.
426 * - July 3rd->11th 2003: memory leaks hunt and correction.
428 CloogLoop * cloog_loop_copy(CloogLoop * source)
429 { CloogLoop * loop ;
430 CloogBlock * block ;
431 CloogDomain * domain ;
433 loop = NULL ;
434 if (source != NULL)
435 { domain = cloog_domain_copy(source->domain) ;
436 block = cloog_block_copy(source->block) ;
437 loop = cloog_loop_alloc(domain,source->stride,block,NULL,NULL) ;
438 loop->usr = source->usr;
439 loop->inner = cloog_loop_copy(source->inner) ;
440 loop->next = cloog_loop_copy(source->next) ;
442 return(loop) ;
447 * cloog_loop_add_disjoint function:
448 * This function adds some CloogLoop structures at a given place (now) of a
449 * NULL terminated list of CloogLoop structures. The beginning of this list
450 * is (start). (loop) can be an union of polyhedra, this function separates the
451 * union into a list of *disjoint* polyhedra then adds the list. This function
452 * updates (now) to the end of the list and updates (start) if first added
453 * element is the first of the principal list -that is when (start) is NULL-.
454 * (loop) can be freed by this function, basically when its domain is actually
455 * a union of polyhedra, but don't worry, all the useful data are now stored
456 * inside the list (start). We do not use PolyLib's Domain_Disjoint function,
457 * since the number of union components is often higher (thus code size too).
458 * - October 28th 2001: first version.
459 * - November 14th 2001: bug correction (this one was hard to find !).
460 * - July 3rd->11th 2003: memory leaks hunt and correction.
461 * - June 22nd 2005: Adaptation for GMP.
462 * - October 27th 2005: (debug) included blocks were not copied for new loops.
464 void cloog_loop_add_disjoint(start, now, loop)
465 CloogLoop ** start, ** now, * loop ;
467 cloog_int_t one;
468 CloogLoop * sep, * inner ;
469 CloogDomain * domain, * convex, * seen, * seen_before, * temp, * rest ;
470 CloogBlock * block ;
472 cloog_int_init(one);
473 cloog_int_set_si(one, 1);
475 if (cloog_domain_isconvex(loop->domain))
476 cloog_loop_add(start,now,loop) ;
477 else
478 { /* Seems useless but may simplify the union expression (PolyLib pb). */
479 convex = cloog_domain_convex(loop->domain) ;
480 temp = cloog_domain_difference(convex,loop->domain) ;
481 cloog_domain_free(loop->domain) ;
482 loop->domain = NULL ;
483 domain = cloog_domain_difference(convex,temp) ;
484 cloog_domain_free(convex) ;
485 cloog_domain_free(temp) ;
487 /* We separate the first element of the rest of the union. */
488 domain = cloog_domain_cut_first(domain, &rest);
490 /* This first element is the first of the list of disjoint polyhedra. */
491 sep = cloog_loop_alloc(domain,one,loop->block,loop->inner,NULL) ;
492 cloog_loop_add(start,now,sep) ;
494 seen = cloog_domain_copy(domain);
495 while (!cloog_domain_isempty(domain = rest)) {
496 temp = cloog_domain_cut_first(domain, &rest);
497 domain = cloog_domain_difference(temp, seen);
498 cloog_domain_free(temp);
500 if (cloog_domain_isempty(domain)) {
501 cloog_domain_free(domain);
502 continue;
505 /* Each new loop will have its own life, for instance we can free its
506 * inner loop and included block. Then each one must have its own copy
507 * of both 'inner' and 'block'.
509 inner = cloog_loop_copy(loop->inner) ;
510 block = cloog_block_copy(loop->block) ;
512 sep = cloog_loop_alloc(cloog_domain_copy(domain), one, block, inner, NULL);
513 /* domain can be an union too. If so: recursion. */
514 if (cloog_domain_isconvex(domain))
515 cloog_loop_add(start,now,sep) ;
516 else
517 cloog_loop_add_disjoint(start,now,sep) ;
519 if (cloog_domain_isempty(rest)) {
520 cloog_domain_free(domain);
521 break;
524 seen_before = seen;
525 seen = cloog_domain_union(seen_before, domain);
526 cloog_domain_free(domain);
527 cloog_domain_free(seen_before);
529 cloog_domain_free(rest);
530 cloog_domain_free(seen);
531 cloog_loop_free_parts(loop,0,0,0,0) ;
533 cloog_int_clear(one);
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
543 * for more details.
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(loop->domain))
551 return loop ;
553 while (loop != NULL)
554 { next = loop->next ;
555 loop->next = NULL ;
556 cloog_loop_add_disjoint(&res,&now,loop) ;
557 loop = next ;
560 return res ;
565 * cloog_loop_restrict function:
566 * This function returns the (loop) in the context of (context): it makes the
567 * intersection between the (loop) domain and the (context), then it returns
568 * a pointer to a new loop, with this intersection as domain.
569 * - nb_par is the number of parameters.
571 * - October 27th 2001: first version.
572 * - June 15th 2005: a memory leak fixed (domain was not freed when empty).
573 * - June 22nd 2005: Adaptation for GMP.
575 CloogLoop * cloog_loop_restrict(loop, context, nb_par)
576 CloogLoop * loop ;
577 CloogDomain * context ;
578 int nb_par ;
579 { int new_dimension ;
580 cloog_int_t one;
581 CloogDomain * domain, * extended_context, * new_domain ;
582 CloogLoop * new_loop ;
584 domain = loop->domain ;
585 if (cloog_domain_dimension(domain) > cloog_domain_dimension(context))
586 { new_dimension = cloog_domain_dimension(domain) - nb_par ;
587 extended_context = cloog_domain_extend(context,new_dimension,nb_par) ;
588 new_domain = cloog_domain_intersection(extended_context,loop->domain) ;
589 cloog_domain_free(extended_context) ;
591 else
592 new_domain = cloog_domain_intersection(context,loop->domain) ;
594 if (cloog_domain_isempty(new_domain))
595 { cloog_domain_free(new_domain) ;
596 return(NULL) ;
598 else {
599 cloog_int_init(one);
600 cloog_int_set_si(one, 1);
601 new_loop = cloog_loop_alloc(new_domain,one,loop->block,loop->inner,NULL) ;
602 cloog_int_clear(one);
603 return(new_loop) ;
609 * cloog_loop_project function:
610 * This function returns the projection of (loop) on the (level) first
611 * dimensions (outer loops). It makes the projection of the (loop) domain,
612 * then it returns a pointer to a new loop, with this projection as domain.
613 * - nb_par is the number of parameters.
615 * - October 27th 2001: first version.
616 * - July 3rd->11th 2003: memory leaks hunt and correction.
617 * - June 22nd 2005: Adaptation for GMP.
619 CloogLoop * cloog_loop_project(CloogLoop * loop, int level, int nb_par)
621 cloog_int_t one;
622 CloogDomain * new_domain ;
623 CloogLoop * new_loop, * copy ;
625 cloog_int_init(one);
626 cloog_int_set_si(one, 1);
628 copy = cloog_loop_alloc(loop->domain,loop->stride,loop->block,
629 loop->inner,NULL) ;
631 if ((cloog_domain_dimension(loop->domain)-nb_par) == level)
632 new_domain = cloog_domain_copy(loop->domain) ;
633 else
634 new_domain = cloog_domain_project(loop->domain,level,nb_par) ;
636 new_loop = cloog_loop_alloc(new_domain,one,NULL,copy,NULL) ;
637 cloog_int_clear(one);
639 return(new_loop) ;
644 * cloog_loop_concat function:
645 * This function returns a pointer to the concatenation of the
646 * CloogLoop lists given as input.
647 * - October 28th 2001: first version.
649 CloogLoop * cloog_loop_concat(CloogLoop * a, CloogLoop * b)
650 { CloogLoop * loop, * temp ;
652 loop = a ;
653 temp = loop ;
654 if (loop != NULL)
655 { while (temp->next != NULL)
656 temp = temp->next ;
657 temp->next = b ;
659 else
660 loop = b ;
662 return(loop) ;
667 * cloog_loop_combine:
668 * Combine consecutive loops with identical domains into
669 * a single loop with the concatenation of their inner loops
670 * as inner loop.
672 CloogLoop *cloog_loop_combine(CloogLoop *loop)
674 CloogLoop *first, *second;
676 for (first = loop; first; first = first->next) {
677 while (first->next) {
678 if (!cloog_domain_lazy_equal(first->domain, first->next->domain))
679 break;
680 second = first->next;
681 first->inner = cloog_loop_concat(first->inner, second->inner);
682 first->next = second->next;
683 cloog_loop_free_parts(second, 1, 0, 0, 0);
687 return loop;
691 * cloog_loop_separate function:
692 * This function implements the Quillere algorithm for separation of multiple
693 * loops: for a given set of polyhedra (loop), it computes a set of disjoint
694 * polyhedra such that the unions of these sets are equal, and returns this set.
695 * - October 28th 2001: first version.
696 * - November 14th 2001: elimination of some unused blocks.
697 * - August 13th 2002: (debug) in the case of union of polyhedra for one
698 * loop, redundant constraints are fired.
699 * - July 3rd->11th 2003: memory leaks hunt and correction.
700 * - June 22nd 2005: Adaptation for GMP.
701 * - October 16th 2005: Removal of the non-shared constraint elimination when
702 * there is only one loop in the list (seems to work
703 * without now, DomainSimplify may have been improved).
704 * The problem was visible with test/iftest2.cloog.
706 CloogLoop * cloog_loop_separate(CloogLoop * loop)
707 { int lazy_equal=0, disjoint = 0;
708 cloog_int_t one;
709 CloogLoop * new_loop, * new_inner, * res, * now, * temp, * Q,
710 * inner, * old /*, * previous, * next*/ ;
711 CloogDomain * UQ, * old_UQ, * domain ;
713 if (loop == NULL)
714 return NULL ;
716 loop = cloog_loop_combine(loop);
718 if (loop->next == NULL)
719 return cloog_loop_disjoint(loop) ;
721 cloog_int_init(one);
722 cloog_int_set_si(one, 1);
724 UQ = cloog_domain_copy(loop->domain) ;
725 domain = cloog_domain_copy(loop->domain) ;
726 res = cloog_loop_alloc(domain,one,loop->block,loop->inner,NULL) ;
728 old = loop ;
729 while((loop = loop->next) != NULL)
730 { temp = NULL ;
732 /* For all Q, add Q-loop associated with the blocks of Q alone,
733 * and Q inter loop associated with the blocks of Q and loop.
735 for (Q = res; Q; Q = Q->next) {
736 /* Add (Q inter loop). */
737 if ((disjoint = cloog_domain_lazy_disjoint(Q->domain,loop->domain)))
738 domain = NULL ;
739 else
740 { if ((lazy_equal = cloog_domain_lazy_equal(Q->domain,loop->domain)))
741 domain = cloog_domain_copy(Q->domain) ;
742 else
743 domain = cloog_domain_intersection(Q->domain,loop->domain) ;
745 if (!cloog_domain_isempty(domain))
746 { new_inner = cloog_loop_concat(cloog_loop_copy(Q->inner),
747 cloog_loop_copy(loop->inner)) ;
748 new_loop = cloog_loop_alloc(domain,one,NULL,new_inner,NULL) ;
749 cloog_loop_add_disjoint(&temp,&now,new_loop) ;
751 else {
752 disjoint = 1;
753 cloog_domain_free(domain);
757 /* Add (Q - loop). */
758 if (disjoint)
759 domain = cloog_domain_copy(Q->domain) ;
760 else
761 { if (lazy_equal)
762 domain = cloog_domain_empty(Q->domain);
763 else
764 domain = cloog_domain_difference(Q->domain,loop->domain) ;
767 if (!cloog_domain_isempty(domain))
768 { new_loop = cloog_loop_alloc(domain,one,NULL,Q->inner,NULL) ;
769 cloog_loop_add_disjoint(&temp,&now,new_loop) ;
771 else
772 { cloog_domain_free(domain) ;
773 /* If Q->inner is no more useful, we can free it. */
774 inner = Q->inner ;
775 Q->inner = NULL ;
776 cloog_loop_free(inner) ;
780 /* Add loop-UQ associated with the blocks of loop alone.*/
781 if (cloog_domain_lazy_disjoint(loop->domain,UQ))
782 domain = cloog_domain_copy(loop->domain) ;
783 else
784 { if (cloog_domain_lazy_equal(loop->domain,UQ))
785 domain = cloog_domain_empty(UQ);
786 else
787 domain = cloog_domain_difference(loop->domain,UQ) ;
790 if (!cloog_domain_isempty(domain))
791 { new_loop = cloog_loop_alloc(domain,one,NULL,loop->inner,NULL) ;
792 cloog_loop_add_disjoint(&temp,&now,new_loop) ;
794 else
795 { cloog_domain_free(domain) ;
796 /* If loop->inner is no more useful, we can free it. */
797 cloog_loop_free(loop->inner) ;
800 loop->inner = NULL ;
802 old_UQ = UQ ;
803 if (loop->next != NULL)
804 UQ = cloog_domain_union(UQ,loop->domain) ;
806 cloog_domain_free(old_UQ) ;
807 cloog_loop_free_parts(res,1,0,0,1) ;
809 res = temp ;
811 cloog_loop_free_parts(old,1,0,0,1) ;
812 cloog_int_clear(one);
814 return(res) ;
819 * cloog_loop_merge_list
820 * Merge two lists of CloogLoops. The new list contains the
821 * elements of the two lists in the same order, but they may
822 * be interleaved.
823 * In particular, if the elements of a and b are ordered
824 * according to the inner loops of the order list, then so are the elements
825 * in the new list.
827 static CloogLoop *cloog_loop_merge_inner_list(CloogLoop *a, CloogLoop *b,
828 CloogLoop *order)
830 CloogLoop *loop, **next;
831 next = &loop;
833 for ( ; order && (a||b); order = order->next) {
834 if (a && order->inner->block == a->block) {
835 *next = a;
836 a = a->next;
837 next = &(*next)->next;
838 continue;
840 if (b && order->inner->block == b->block) {
841 *next = b;
842 b = b->next;
843 next = &(*next)->next;
846 return loop;
850 * cloog_loop_merge function:
851 * This function is the 'soft' version of loop_separate if we are looking for
852 * a code much simpler (and less efficicient). Here we merge loops if they have
853 * common parts in the iteration space (if the intersection of their domains is
854 * not empty), and let them isolated otherwise. This function returns the new
855 * CloogLoop list.
856 * - October 29th 2001: first version.
857 * - July 3rd->11th 2003: memory leaks hunt and correction.
858 * - June 22nd 2005: Adaptation for GMP.
860 CloogLoop * cloog_loop_merge(CloogLoop * loop, int nb_par, CloogOptions * options)
862 cloog_int_t one;
863 CloogLoop * res, * merge, * now, * Q, * P, * new_inner, * next, * old ;
864 CloogDomain * new_domain, * temp ;
866 if (loop == NULL)
867 return loop ;
869 if (loop->next == NULL)
870 return cloog_loop_disjoint(loop);
872 cloog_int_init(one);
873 cloog_int_set_si(one, 1);
875 /* First loop is added to the target list. */
876 res = cloog_loop_alloc(loop->domain,one,loop->block,loop->inner,NULL) ;
877 old = loop ;
878 /* Now the domain is in 'res' and it will be freed. */
879 loop->domain = NULL ;
881 /* And one by one, we see if we have to merge or to add the other loops. */
882 while((loop = loop->next) != NULL)
883 { merge = NULL ;
884 P = cloog_loop_alloc(loop->domain,one,loop->block,loop->inner,NULL) ;
885 Q = res ;
886 /* Now the domain is in 'P' and it will be freed. */
887 loop->domain = NULL ;
889 /* For each loop in the target list, if the intersection with the new loop
890 * is empty, we can add the new loop directly, otherwise, we can merge then
891 * add the fusion.
893 while (Q != NULL)
894 { temp = cloog_domain_intersection(Q->domain,P->domain) ;
895 next = Q->next ;
896 if (cloog_domain_isempty(temp))
897 { cloog_domain_free(temp) ;
898 cloog_loop_add_disjoint(&merge,&now,Q) ;
900 else
901 { cloog_domain_free(temp) ;
902 new_inner = cloog_loop_merge_inner_list(Q->inner, P->inner, old);
903 temp = cloog_domain_union(P->domain,Q->domain) ;
904 if (options->sh)
905 new_domain = cloog_domain_simple_convex(temp, nb_par);
906 else
907 new_domain = cloog_domain_convex(temp);
908 cloog_domain_free(temp) ;
909 /* Q and P are no more used (but their content yes !).*/
910 cloog_loop_free_parts(P,1,0,0,0) ;
911 cloog_loop_free_parts(Q,1,0,0,0) ;
912 P = cloog_loop_alloc(new_domain,one,NULL,new_inner,NULL) ;
914 Q = next ;
917 /* If there was merging, add it, otherwise add the loop lonely.
918 * DEBUG : ici pas besoin de s'assurer que P->next est NULL (possible que
919 * non si pas de fusion) car le dernier loop etudie a loop->next = NULL.
921 cloog_loop_add_disjoint(&merge,&now,P) ;
922 res = merge ;
924 cloog_loop_free_parts(old,0,0,0,1) ;
925 cloog_int_clear(one);
927 return (res);
932 * cloog_loop_sort function:
933 * Adaptation from LoopGen 0.4 by F. Quillere. This function sorts a list of
934 * parameterized disjoint polyhedra, in order to not have lexicographic order
935 * violation (see Quillere paper).
936 * - September 16th 2005: inclusion of cloog_loop_number (October 29th 2001).
938 CloogLoop * cloog_loop_sort(CloogLoop * loop, int level, int nb_par)
939 { CloogLoop * res, * now, * temp, ** loop_array ;
940 CloogDomain **doms;
941 int i, nb_loops=0, * permut ;
943 /* There is no need to sort the parameter domains. */
944 if (!level)
945 return loop;
947 /* We will need to know how many loops are in the list. */
948 temp = loop ;
949 while (temp != NULL)
950 { nb_loops ++ ;
951 temp = temp->next ;
954 /* If there is only one loop, it's the end. */
955 if (nb_loops == 1)
956 return(loop) ;
958 /* We have to allocate memory for some useful components:
959 * - loop_array: the loop array,
960 * - doms: the array of domains to sort,
961 * - permut: will give us a possible sort (maybe not the only one).
963 loop_array = (CloogLoop **)malloc(nb_loops*sizeof(CloogLoop *)) ;
964 doms = (CloogDomain **)malloc(nb_loops*sizeof(CloogDomain *));
965 permut = (int *)malloc(nb_loops*sizeof(int)) ;
967 /* We fill up the loop and domain arrays. */
968 for (i=0;i<nb_loops;i++,loop=loop->next)
969 { loop_array[i] = loop ;
970 doms[i] = loop_array[i]->domain;
973 /* cloog_domain_sort will fill up permut. */
974 cloog_domain_sort(doms, nb_loops, level, nb_par, permut);
976 /* With permut and loop_array we build the sorted list. */
977 res = NULL ;
978 for (i=0;i<nb_loops;i++)
979 { /* To avoid pointer looping... loop_add will rebuild the list. */
980 loop_array[permut[i]-1]->next = NULL ;
981 cloog_loop_add(&res,&now,loop_array[permut[i]-1]) ;
984 free(permut) ;
985 free(doms);
986 free(loop_array) ;
988 return res;
993 * cloog_loop_nest function:
994 * This function changes the loop list in such a way that we have no more than
995 * one dimension added by level. It returns an equivalent loop list with
996 * this property.
997 * - October 29th 2001: first version.
998 * - July 3rd->11th 2003: memory leaks hunt and correction.
999 * - June 22nd 2005: Adaptation for GMP.
1000 * - November 21th 2005: (debug) now OK when cloog_loop_restrict returns NULL.
1002 CloogLoop * cloog_loop_nest(loop, context, level, nb_par)
1003 CloogLoop * loop ;
1004 CloogDomain * context ;
1005 int level, nb_par ;
1006 { int l ;
1007 cloog_int_t one;
1008 CloogLoop * p, * temp, * res, * now, * next ;
1009 CloogDomain * new_domain ;
1011 cloog_int_init(one);
1012 cloog_int_set_si(one, 1);
1014 res = NULL ;
1015 /* Each domain is changed by its intersection with the context. */
1016 while (loop != NULL)
1017 { p = cloog_loop_restrict(loop,context,nb_par) ;
1018 next = loop->next ;
1020 if (p != NULL)
1021 { cloog_loop_free_parts(loop,1,0,0,0) ;
1023 temp = cloog_loop_alloc(p->domain,one,p->block,p->inner,NULL) ;
1025 /* If the intersection dimension is too big, we make projections smaller
1026 * and smaller, and each projection includes the preceding projection
1027 * (thus, in the target list, dimensions are added one by one).
1029 if ((cloog_domain_dimension(p->domain)-nb_par) > level)
1030 for (l=cloog_domain_dimension(p->domain)-nb_par-1;l>=level;l--)
1031 { new_domain = cloog_domain_project(p->domain,l,nb_par) ;
1032 temp = cloog_loop_alloc(new_domain,one,NULL,temp,NULL) ;
1035 /* p is no more useful (but its content yes !). */
1036 cloog_loop_free_parts(p,0,0,0,0) ;
1038 cloog_loop_add(&res,&now,temp) ;
1040 else
1041 cloog_loop_free_parts(loop,1,1,1,0) ;
1043 loop = next ;
1045 cloog_int_clear(one);
1047 return(res) ;
1052 * cloog_loop_stride function:
1053 * This function will find the stride of a loop for the iterator at the column
1054 * number 'level' in the constraint matrix. It will update the lower bound of
1055 * the iterator accordingly. Basically, the function will try to find in the
1056 * inner loops a common condition on this iterator for the inner loop iterators
1057 * to be integral. For instance, let us consider a loop with the iterator i,
1058 * the iteration domain -4<=i<=n, and its two inner loops with the iterator j.
1059 * The first inner loop has the constraint 3j=i, and the second one has the
1060 * constraint 6j=i. Then the common constraint on i for j to be integral is
1061 * i%3=0, the stride for i is 3. Lastly, we have to find the new lower bound
1062 * for i: the first value satisfying the common constraint: -3. At the end, the
1063 * iteration domain for i is -3<=i<=n and the stride for i is 3.
1064 * - loop is the loop including the iteration domain of the considered iterator,
1065 * - level is the column number of the iterator in the matrix of contraints.
1067 * - June 29th 2003: first version (work in progress since June 26th 2003).
1068 * - July 14th 2003: simpler version.
1069 * - June 22nd 2005: Adaptation for GMP (from S. Verdoolaege's 0.12.1 version).
1071 void cloog_loop_stride(CloogLoop * loop, int level, int nb_par)
1072 { int first_search ;
1073 cloog_int_t stride, ref_offset, offset, potential, lower;
1074 CloogLoop * inner ;
1076 cloog_int_init(stride);
1077 cloog_int_init(ref_offset);
1078 cloog_int_init(offset);
1079 cloog_int_init(potential);
1080 cloog_int_init(lower);
1082 cloog_int_set_si(ref_offset, 0);
1083 cloog_int_set_si(offset, 0);
1084 cloog_int_set_si(lower, 0);
1086 /* Default stride. */
1087 cloog_int_set_si(stride, 1);
1088 first_search = 1 ;
1089 inner = loop->inner ;
1091 if (cloog_domain_integral_lowerbound(loop->domain,level,&lower))
1092 while (inner != NULL)
1093 { /* If the minimun stride has not been found yet, find the stride. */
1094 if ((first_search) || (!cloog_int_is_one(stride)))
1095 { cloog_domain_stride(inner->domain,level,nb_par,&potential,&offset) ;
1096 if (!cloog_int_is_one(potential) && (!first_search))
1097 { /* Offsets must be the same for common stride. */
1098 cloog_int_gcd(stride, potential, stride);
1099 cloog_int_fdiv_r(offset, offset, stride);
1100 cloog_int_fdiv_r(ref_offset, ref_offset, stride);
1101 if (cloog_int_ne(offset,ref_offset))
1102 cloog_int_set_si(stride, 1);
1104 else {
1105 cloog_int_set(stride, potential);
1106 cloog_int_set(ref_offset, offset);
1109 first_search = 0 ;
1112 inner = inner->next ;
1115 /* Update the values if necessary. */
1116 if (!cloog_int_is_one(stride))
1117 { /* Update the stride value. */
1118 cloog_int_set(loop->stride, stride);
1119 /* The new lower bound l' is such that
1120 * (l' + offset) % s = 0 and l <= l' <= l+(s-1)
1121 * Let l' = k s - offset, then
1122 * k s - offset <= l + (s-1) <= k s - offset + (s-1)
1123 * Or l' = floor((l+offset+(s-1))/s) * s - offset
1124 * = (floor((l+offset-1)/s) + 1) * s - offset
1126 cloog_int_add(lower, lower, offset);
1127 cloog_int_sub_ui(lower, lower, 1);
1128 cloog_int_fdiv_q(lower, lower, stride);
1129 cloog_int_add_ui(lower, lower, 1);
1130 cloog_int_mul(lower, lower, stride);
1131 cloog_int_sub(lower, lower, offset);
1132 loop->domain = cloog_domain_lowerbound_update(loop->domain, level, lower);
1135 cloog_int_clear(stride);
1136 cloog_int_clear(ref_offset);
1137 cloog_int_clear(offset);
1138 cloog_int_clear(potential);
1139 cloog_int_clear(lower);
1144 * cloog_loop_stop function:
1145 * This function implements the 'stop' option : each domain of each loop
1146 * in the list 'loop' is replaced by 'context'. 'context' should be the
1147 * domain of the outer loop. By using this method, there are no more dimensions
1148 * to scan and the simplification step will automaticaly remove the domains
1149 * since they are the same as the corresponding contexts. The effect of this
1150 * function is to stop the code generation at the level this function is called,
1151 * the resulting code do not consider the next dimensions.
1152 * - January 11th 2005: first version.
1154 CloogLoop * cloog_loop_stop(CloogLoop * loop, CloogDomain * context)
1155 { if (loop == NULL)
1156 return NULL ;
1157 else
1158 { cloog_domain_free(loop->domain) ;
1159 loop->domain = cloog_domain_copy(context) ;
1160 loop->next = cloog_loop_stop(loop->next, context) ;
1163 return loop ;
1168 * cloog_loop_scalar_gt function:
1169 * This function returns 1 if loop 'l1' is greater than loop 'l2' for the
1170 * scalar dimension vector that begins at dimension 'scalar', 0 otherwise. What
1171 * we want to know is whether a loop is scheduled before another one or not.
1172 * This function solves the problem when the considered dimension for scheduling
1173 * is a scalar dimension. Since there may be a succession of scalar dimensions,
1174 * this function will reason about the vector of scalar dimension that begins
1175 * at dimension 'level+scalar' and finish to the first non-scalar dimension.
1176 * \param l1 Loop to be compared with l2.
1177 * \param l2 Loop to be compared with l1.
1178 * \param level Current non-scalar dimension.
1179 * \param scaldims Boolean array saying whether a dimension is scalar or not.
1180 * \param nb_scattdims Size of the scaldims array.
1181 * \param scalar Current scalar dimension.
1182 * \return 1 if (l1 > l2), 0 otherwise.
1184 * - September 9th 2005: first version.
1185 * - October 15nd 2007: now "greater than" instead of "greater or equal".
1187 int cloog_loop_scalar_gt(l1, l2, level, scaldims, nb_scattdims, scalar)
1188 CloogLoop * l1, * l2 ;
1189 int level, * scaldims, nb_scattdims, scalar ;
1190 { while ((scalar < l1->inner->block->nb_scaldims) && scaldims[level+scalar-1])
1191 { if (cloog_int_gt(l1->inner->block->scaldims[scalar],
1192 l2->inner->block->scaldims[scalar]))
1193 scalar ++ ;
1194 else
1195 return 0 ;
1197 return 1 ;
1202 * cloog_loop_scalar_eq function:
1203 * This function returns 1 if loop 'l1' is equal to loop 'l2' for the scalar
1204 * dimension vector that begins at dimension 'scalar', 0 otherwise. What we want
1205 * to know is whether two loops are scheduled for the same time or not.
1206 * This function solves the problem when the considered dimension for scheduling
1207 * is a scalar dimension. Since there may be a succession of scalar dimensions,
1208 * this function will reason about the vector of scalar dimension that begins
1209 * at dimension 'level+scalar' and finish to the first non-scalar dimension.
1210 * - l1 and l2 are the loops to compare,
1211 * - level is the current non-scalar dimension,
1212 * - scaldims is the boolean array saying whether a dimension is scalar or not,
1213 * - nb_scattdims is the size of the scaldims array,
1214 * - scalar is the current scalar dimension.
1216 * - September 9th 2005 : first version.
1218 int cloog_loop_scalar_eq(l1, l2, level, scaldims, nb_scattdims, scalar)
1219 CloogLoop * l1, * l2 ;
1220 int level, * scaldims, nb_scattdims, scalar ;
1221 { while ((scalar < l1->inner->block->nb_scaldims) && scaldims[level+scalar-1])
1222 { if (cloog_int_eq(l1->inner->block->scaldims[scalar],
1223 l2->inner->block->scaldims[scalar]))
1224 scalar ++ ;
1225 else
1226 return 0 ;
1228 return 1 ;
1233 * cloog_loop_scalar_sort function:
1234 * This function sorts a linked list of loops (loop) with respect to the
1235 * scalar dimension vector that begins at dimension 'scalar'. Since there may
1236 * be a succession of scalar dimensions, this function will reason about the
1237 * vector of scalar dimension that begins at dimension 'level+scalar' and
1238 * finish to the first non-scalar dimension.
1239 * \param loop Loop list to sort.
1240 * \param level Current non-scalar dimension.
1241 * \param scaldims Boolean array saying whether a dimension is scalar or not.
1242 * \param nb_scattdims Size of the scaldims array.
1243 * \param scalar Current scalar dimension.
1244 * \return A pointer to the sorted list.
1246 * - July 2nd 2005: first developments.
1247 * - September 2nd 2005: first version.
1248 * - October 15nd 2007: complete rewrite to remove bugs, now a bubble sort.
1250 CloogLoop * cloog_loop_scalar_sort(loop, level, scaldims, nb_scattdims, scalar)
1251 CloogLoop * loop ;
1252 int level, * scaldims, nb_scattdims, scalar ;
1253 { int ok ;
1254 CloogLoop **current;
1256 do {
1257 ok = 1;
1258 for (current = &loop; (*current)->next; current = &(*current)->next) {
1259 CloogLoop *next = (*current)->next;
1260 if (cloog_loop_scalar_gt(*current,next,level,scaldims,nb_scattdims,scalar)) {
1261 ok = 0;
1262 (*current)->next = next->next;
1263 next->next = *current;
1264 *current = next;
1267 } while (!ok);
1269 return loop ;
1274 * cloog_loop_generate_backtrack function:
1275 * adaptation from LoopGen 0.4 by F. Quillere. This function implements the
1276 * backtrack of the Quillere et al. algorithm (see the Quillere paper).
1277 * It eliminates unused iterations of the current level for the new one. See the
1278 * example called linearity-1-1 example with and without this part for an idea.
1279 * - October 26th 2001: first version in cloog_loop_generate_general.
1280 * - July 31th 2002: (debug) no more parasite loops (REALLY hard !).
1281 * - October 30th 2005: extraction from cloog_loop_generate_general.
1283 CloogLoop * cloog_loop_generate_backtrack(loop, context, level, nb_par, options)
1284 CloogLoop * loop ;
1285 CloogDomain * context ;
1286 int level, nb_par ;
1287 CloogOptions * options ;
1289 cloog_int_t one;
1290 CloogDomain * domain ;
1291 CloogLoop * now, * now2, * next, * next2, * end, * temp, * l, * inner,
1292 * new_loop ;
1294 cloog_int_init(one);
1295 cloog_int_set_si(one, 1);
1297 temp = loop ;
1298 loop = NULL ;
1300 while (temp != NULL)
1301 { l = NULL ;
1302 inner = temp->inner ;
1304 while (inner != NULL)
1305 { next = inner->next ;
1306 /* This 'if' and its first part is the debug of july 31th 2002. */
1307 if (inner->block != NULL)
1308 { end = cloog_loop_alloc(inner->domain,one,inner->block,NULL,NULL) ;
1309 domain = cloog_domain_copy(temp->domain) ;
1310 new_loop = cloog_loop_alloc(domain,one,NULL,end,NULL) ;
1312 else
1313 new_loop = cloog_loop_project(inner,level,nb_par) ;
1315 cloog_loop_free_parts(inner,0,0,0,0) ;
1316 cloog_loop_add(&l,&now2,new_loop) ;
1317 inner = next ;
1320 temp->inner = NULL ;
1322 if (l != NULL)
1323 { l = cloog_loop_separate(l) ;
1324 l = cloog_loop_sort(l,level,nb_par) ;
1325 while (l != NULL) {
1326 cloog_int_set(l->stride, temp->stride);
1327 cloog_loop_add(&loop,&now,l) ;
1328 l = l->next ;
1331 next2 = temp->next ;
1332 cloog_loop_free_parts(temp,1,0,0,0) ;
1333 temp = next2 ;
1336 cloog_int_clear(one);
1338 return loop ;
1343 * cloog_loop_generate_general function:
1344 * Adaptation from LoopGen 0.4 by F. Quillere. This function implements the
1345 * Quillere algorithm for polyhedron scanning from step 3 to 5.
1346 * (see the Quillere paper).
1347 * - loop is the loop for which we have to generate a scanning code,
1348 * - context is the context of the current loop (constraints on parameter and/or
1349 * on outer loop counters),
1350 * - level is the current non-scalar dimension,
1351 * - scalar is the current scalar dimension,
1352 * - scaldims is the boolean array saying whether a dimension is scalar or not,
1353 * - nb_scattdims is the size of the scaldims array,
1354 * - nb_par is the number of parameters,
1355 * - options are the general code generation options.
1357 * - October 26th 2001: first version.
1358 * - July 3rd->11th 2003: memory leaks hunt and correction.
1359 * - June 22nd 2005: Adaptation for GMP.
1360 * - September 2nd 2005: The function have been cutted out in two pieces:
1361 * cloog_loop_generate and this one, in order to handle
1362 * the scalar dimension case more efficiently with
1363 * cloog_loop_generate_scalar.
1364 * - November 15th 2005: (debug) the result of the cloog_loop_generate call may
1365 * be a list of polyhedra (especially if stop option is
1366 * used): cloog_loop_add_list instead of cloog_loop_add.
1368 CloogLoop * cloog_loop_generate_general(loop, context, level, scalar,
1369 scaldims, nb_scattdims, nb_par, options)
1370 CloogLoop * loop ;
1371 CloogDomain * context ;
1372 int level, scalar, * scaldims, nb_scattdims, nb_par ;
1373 CloogOptions * options ;
1375 cloog_int_t one;
1376 CloogLoop * res, * now, * temp, * l, * new_loop, * inner, * now2, * end,
1377 * next, * into ;
1378 CloogDomain * domain ;
1380 /* 3. Separate all projections into disjoint polyhedra. */
1381 res = ((options->f > level+scalar) || (options->f < 0)) ?
1382 cloog_loop_merge(loop, nb_par, options) : cloog_loop_separate(loop);
1384 /* 3b. -correction- sort the loops to determine their textual order. */
1385 res = cloog_loop_sort(res,level,nb_par) ;
1387 cloog_int_init(one);
1388 cloog_int_set_si(one, 1);
1390 /* 4. Recurse for each loop with the current domain as context. */
1391 temp = res ;
1392 res = NULL ;
1393 if (!level || (level+scalar < options->l) || (options->l < 0))
1394 while(temp != NULL)
1395 { if (level && options->strides)
1396 cloog_loop_stride(temp,level,nb_par) ;
1397 inner = temp->inner ;
1398 domain = temp->domain ;
1399 into = NULL ;
1400 while (inner != NULL)
1401 { /* 4b. -ced- recurse for each sub-list of non terminal loops. */
1402 if (cloog_domain_dimension(inner->domain) > (level + nb_par))
1403 { end = inner ;
1404 while ((end->next != NULL) &&
1405 (cloog_domain_dimension(end->next->domain) > (level + nb_par)))
1406 end = end->next ;
1408 next = end->next ;
1409 end->next = NULL ;
1411 l = cloog_loop_generate(inner,domain,level+1,scalar,
1412 scaldims,nb_scattdims,nb_par,options) ;
1414 if (l != NULL)
1415 cloog_loop_add_list(&into,&now,l) ;
1417 inner = next ;
1419 else
1420 { cloog_loop_add(&into,&now,inner) ;
1421 inner = inner->next ;
1424 next = temp->next ;
1425 temp->next = NULL ;
1426 temp->inner = into ;
1427 cloog_loop_add(&res,&now2,temp) ;
1428 temp = next ;
1430 else
1431 while (temp != NULL)
1432 { next = temp->next ;
1433 l = cloog_loop_nest(temp->inner,temp->domain,level+1,nb_par) ;
1434 new_loop = cloog_loop_alloc(temp->domain,one,NULL,l,NULL) ;
1435 temp->inner = NULL ;
1436 temp->next = NULL ;
1437 cloog_loop_free_parts(temp,0,0,0,0) ;
1438 cloog_loop_add(&res,&now,new_loop) ;
1439 temp = next ;
1442 /* 5. eliminate unused iterations of the current level for the new one. See
1443 * the example called linearity-1-1 example with and without this part
1444 * for an idea.
1446 if ((!options->nobacktrack) && level &&
1447 ((level+scalar < options->l) || (options->l < 0)) &&
1448 ((options->f <= level+scalar) && !(options->f < 0)))
1449 res = cloog_loop_generate_backtrack(res,context,level,nb_par,options) ;
1451 /* Pray for my new paper to be accepted somewhere since the following stuff
1452 * is really amazing :-) !
1453 * Far long later: The paper has been accepted to PACT 2004 :-))). But there
1454 * are still some bugs and I have no time to fix them. Thus now you have to
1455 * pray for me to get an academic position for that really amazing stuff :-) !
1456 * Later again: OK, I get my academic position, but still I have not enough
1457 * time to fix and clean this part... Pray again :-) !!!
1459 /* res = cloog_loop_unisolate(res,context,level,nb_par) ;*/
1461 cloog_int_clear(one);
1462 return(res) ;
1467 * cloog_loop_generate_scalar function:
1468 * This function applies the simplified code generation scheme in the trivial
1469 * case of scalar dimensions. When dealing with scalar dimensions, there is
1470 * no need of costly polyhedral operations for separation or sorting: sorting
1471 * is a question of comparing scalar vectors and separation amounts to consider
1472 * only loops with the same scalar vector for the next step of the code
1473 * generation process. This function achieves the separation/sorting process
1474 * for the vector of scalar dimension that begins at dimension 'level+scalar'
1475 * and finish to the first non-scalar dimension.
1476 * - loop is the loop for which we have to generate a scanning code,
1477 * - context is the context of the current loop (constraints on parameter and/or
1478 * on outer loop counters),
1479 * - level is the current non-scalar dimension,
1480 * - scalar is the current scalar dimension,
1481 * - scaldims is the boolean array saying whether a dimension is scalar or not,
1482 * - nb_scattdims is the size of the scaldims array,
1483 * - nb_par is the number of parameters,
1484 * - options are the general code generation options.
1486 * - September 2nd 2005: First version.
1488 CloogLoop * cloog_loop_generate_scalar(loop, context, level, scalar,
1489 scaldims, nb_scattdims, nb_par, options)
1490 CloogLoop * loop ;
1491 CloogDomain * context ;
1492 int level, scalar, * scaldims, nb_scattdims, nb_par ;
1493 CloogOptions * options ;
1494 { CloogLoop * res, * now, * temp, * l, * end, * next, * ref ;
1496 /* We sort the loop list with respect to the current scalar vector. */
1497 res = cloog_loop_scalar_sort(loop,level,scaldims,nb_scattdims,scalar) ;
1499 temp = res ;
1500 res = NULL ;
1501 while (temp != NULL)
1502 { /* Then we will appy the general code generation process to each sub-list
1503 * of loops with the same scalar vector.
1505 end = temp ;
1506 ref = temp ;
1508 while((end->next != NULL) &&
1509 cloog_loop_scalar_eq(ref,end->next,level,scaldims,nb_scattdims,scalar))
1510 end = end->next ;
1512 next = end->next ;
1513 end->next = NULL ;
1515 /* For the next dimension, scalar value is updated by adding the scalar
1516 * vector size, which is stored at scaldims[level+scalar-1].
1518 l = cloog_loop_generate_general(temp,context,level,
1519 scalar+scaldims[level+scalar-1],
1520 scaldims,nb_scattdims,nb_par,options) ;
1522 if (l != NULL)
1523 cloog_loop_add_list(&res,&now,l) ;
1525 temp = next ;
1528 return res ;
1532 /* Compare loop with the next loop based on their constant dimensions.
1533 * The result is < 0, == 0 or > 0 depending on whether the constant
1534 * dimensions of loop are lexicographically smaller, equal or greater
1535 * than those of loop->next.
1536 * If loop is the last in the list, then it is assumed to be smaller
1537 * than the "next" one.
1539 static int cloog_loop_next_scal_cmp(CloogLoop *loop)
1541 int i;
1542 int nb_scaldims;
1544 if (!loop->next)
1545 return -1;
1547 nb_scaldims = loop->block->nb_scaldims;
1548 if (loop->next->block->nb_scaldims < nb_scaldims)
1549 nb_scaldims = loop->next->block->nb_scaldims;
1551 for (i = 0; i < nb_scaldims; ++i) {
1552 int cmp = cloog_int_cmp(loop->block->scaldims[i],
1553 loop->next->block->scaldims[i]);
1554 if (cmp)
1555 return cmp;
1557 return loop->block->nb_scaldims - loop->next->block->nb_scaldims;
1561 /* Check whether the globally constant dimensions of a and b
1562 * have the same value for all globally constant dimensions
1563 * that are situated before any (locally) non-constant dimension.
1565 static int cloog_loop_equal_prefix(CloogLoop *a, CloogLoop *b,
1566 int *scaldims, int nb_scattdims)
1568 int i;
1569 int cst = 0;
1570 int dim = 0;
1572 for (i = 0; i < nb_scattdims; ++i) {
1573 if (!scaldims[i]) {
1574 dim++;
1575 continue;
1577 if (!cloog_int_eq(a->block->scaldims[cst], b->block->scaldims[cst]))
1578 break;
1579 cst++;
1581 for (i = i + 1; i < nb_scattdims; ++i) {
1582 if (scaldims[i])
1583 continue;
1584 if (!cloog_domain_lazy_isconstant(a->domain, dim))
1585 return 0;
1586 /* No need to check that dim is also constant in b and that the
1587 * constant values are equal. That will happen during the check
1588 * whether the two domains are equal.
1590 dim++;
1592 return 1;
1596 /* Try to block adjacent loops in the loop list "loop".
1597 * We only attempt blocking if the constant dimensions of the loops
1598 * in the least are (not necessarily strictly) increasing.
1599 * Then we look for a sublist such that the first (begin) has constant
1600 * dimensions strictly larger than the previous loop in the complete
1601 * list and such that the loop (end) after the last loop in the sublist
1602 * has constant dimensions strictly larger than the last loop in the sublist.
1603 * Furthermore, all loops in the sublist should have the same domain
1604 * (with globally constant dimensions removed) and the difference
1605 * (if any) in constant dimensions may only occur after all the
1606 * (locally) constant dimensions.
1607 * If we find such a sublist, then the blocks of all but the first
1608 * are merged into the block of the first.
1610 * Note that this function can only be called before the global
1611 * blocklist has been created because it may otherwise modify and destroy
1612 * elements on that list.
1614 CloogLoop *cloog_loop_block(CloogLoop *loop, int *scaldims, int nb_scattdims)
1616 CloogLoop *begin, *end, *l;
1617 int begin_after_previous;
1618 int end_after_previous;
1620 if (!loop->next)
1621 return loop;
1622 for (begin = loop; begin; begin = begin->next) {
1623 if (!begin->block || !begin->block->scaldims)
1624 return loop;
1625 if (cloog_loop_next_scal_cmp(loop) > 0)
1626 return loop;
1629 begin_after_previous = 1;
1630 for (begin = loop; begin; begin = begin->next) {
1631 if (!begin_after_previous) {
1632 begin_after_previous = cloog_loop_next_scal_cmp(begin) < 0;
1633 continue;
1636 end_after_previous = cloog_loop_next_scal_cmp(begin) < 0;
1637 for (end = begin->next; end; end = end->next) {
1638 if (!cloog_loop_equal_prefix(begin, end, scaldims, nb_scattdims))
1639 break;
1640 if (!cloog_domain_lazy_equal(begin->domain, end->domain))
1641 break;
1642 end_after_previous = cloog_loop_next_scal_cmp(end) < 0;
1644 if (end != begin->next && end_after_previous) {
1645 for (l = begin->next; l != end; l = begin->next) {
1646 cloog_block_merge(begin->block, l->block);
1647 begin->next = l->next;
1648 cloog_loop_free_parts(l, 1, 0, 1, 0);
1652 begin_after_previous = cloog_loop_next_scal_cmp(begin) < 0;
1655 return loop;
1660 * cloog_loop_generate function:
1661 * Adaptation from LoopGen 0.4 by F. Quillere. This function implements the
1662 * Quillere algorithm for polyhedron scanning from step 1 to 2.
1663 * (see the Quillere paper).
1664 * - loop is the loop for which we have to generate a scanning code,
1665 * - context is the context of the current loop (constraints on parameter and/or
1666 * on outer loop counters),
1667 * - level is the current non-scalar dimension,
1668 * - scalar is the current scalar dimension,
1669 * - scaldims is the boolean array saying whether a dimension is scalar or not,
1670 * - nb_scattdims is the size of the scaldims array,
1671 * - nb_par is the number of parameters,
1672 * - options are the general code generation options.
1674 * - October 26th 2001: first version.
1675 * - July 3rd->11th 2003: memory leaks hunt and correction.
1676 * - June 15th 2005: a memory leak fixed (loop was not entirely freed when
1677 * the result of cloog_loop_restrict was NULL).
1678 * - June 22nd 2005: Adaptation for GMP.
1679 * - September 2nd 2005: The function have been cutted out in two pieces:
1680 * cloog_loop_generate and this one, in order to handle
1681 * the scalar dimension case more efficiently with
1682 * cloog_loop_generate_scalar.
1683 * - November 15th 2005: (debug) Condition for stop option no more take care of
1684 * further scalar dimensions.
1686 CloogLoop * cloog_loop_generate(loop, context, level, scalar,
1687 scaldims, nb_scattdims, nb_par, options)
1688 CloogLoop * loop ;
1689 CloogDomain * context ;
1690 int level, scalar, * scaldims, nb_scattdims, nb_par ;
1691 CloogOptions * options ;
1692 { CloogLoop * res, * now, * temp, * next, * old ;
1694 /* If the user asked to stop code generation at this level, let's stop. */
1695 if ((options->stop >= 0) && (level+scalar >= options->stop+1))
1696 return cloog_loop_stop(loop,context) ;
1698 res = NULL ;
1700 /* 1. Replace each polyhedron by its intersection with the context.
1701 * 2. Compute the projection of each polyhedron onto the outermost
1702 * loop variable and the parameters.
1704 while (loop != NULL)
1705 { next = loop->next ;
1706 temp = cloog_loop_restrict(loop,context,nb_par) ;
1708 if (temp != NULL)
1709 { old = temp ;
1710 temp = cloog_loop_project(temp,level,nb_par) ;
1711 cloog_loop_free_parts(old,0,0,0,0) ;
1712 cloog_loop_add(&res,&now,temp) ;
1713 cloog_loop_free_parts(loop,1,0,0,0) ;
1715 else
1716 { loop->next = NULL ;
1717 cloog_loop_free(loop) ;
1720 loop = next ;
1722 if (res == NULL)
1723 return NULL ;
1725 /* To save both time and memory, we switch here depending on whether the
1726 * current dimension is scalar (simplified processing) or not (general
1727 * processing).
1729 if (level && (level+scalar <= nb_scattdims) && (scaldims[level+scalar-1]))
1730 res = cloog_loop_generate_scalar(res,context,level,scalar,
1731 scaldims,nb_scattdims,nb_par,options) ;
1732 else
1733 res = cloog_loop_generate_general(res,context,level,scalar,
1734 scaldims,nb_scattdims,nb_par,options) ;
1736 return res ;
1741 * cloog_loop_simplify function:
1742 * This function implements the part 6. of the Quillere algorithm, it
1743 * recursively simplifies each loop in the context of the preceding loop domain.
1744 * It returns a pointer to the simplified loop list.
1745 * The cloog_domain_simplify (DomainSimplify) behaviour is really bad with
1746 * polyhedra union and some really awful sidesteppings were written, I plan
1747 * to solve that...
1748 * - October 31th 2001: first version.
1749 * - July 3rd->11th 2003: memory leaks hunt and correction.
1750 * - April 16th 2005: a memory leak fixed (extended_context was not freed).
1751 * - June 15th 2005: a memory leak fixed (loop was not conveniently freed
1752 * when the constraint system is never true).
1753 * - October 27th 2005: - this function called before cloog_loop_fast_simplify
1754 * is now the official cloog_loop_simplify function in
1755 * replacement of a slower and more complex one (after
1756 * deep changes in the pretty printer).
1757 * - we use cloog_loop_disjoint to fix the problem when
1758 * simplifying gives a union of polyhedra (before, it
1759 * was under the responsibility of the pretty printer).
1761 CloogLoop * cloog_loop_simplify(loop, context, level, nb_par)
1762 CloogLoop * loop ;
1763 CloogDomain * context ;
1764 int level, nb_par ;
1765 { int domain_dim ;
1766 CloogBlock * new_block ;
1767 CloogLoop * simplified, * inner, * next ;
1768 CloogDomain * domain, * simp, * inter, * extended_context ;
1770 if (loop == NULL)
1771 return(NULL) ;
1773 domain = loop->domain ;
1775 next = cloog_loop_simplify(loop->next,context,level,nb_par) ;
1777 domain_dim = cloog_domain_dimension(domain) - nb_par ;
1778 extended_context=cloog_domain_extend(context,domain_dim,nb_par);
1779 inter = cloog_domain_intersection(domain,extended_context) ;
1780 simp = cloog_domain_simplify(inter,extended_context) ;
1781 cloog_domain_free(extended_context) ;
1783 /* If the constraint system is never true, go to the next one. */
1784 if (cloog_domain_never_integral(simp)) {
1785 loop->next = NULL;
1786 cloog_loop_free(loop);
1787 cloog_domain_free(inter);
1788 cloog_domain_free(simp);
1789 return next;
1792 inner = cloog_loop_simplify(loop->inner,inter,level+1,nb_par) ;
1793 cloog_domain_free(inter) ;
1795 if ((inner == NULL) && (loop->block == NULL))
1796 { loop->inner = NULL ; /* For loop integrity. */
1797 loop->next = NULL ; /* For loop integrity. */
1798 cloog_loop_free_parts(loop,1,1,1,0) ;
1799 cloog_domain_free(simp);
1800 return(next) ;
1803 new_block = cloog_block_copy(loop->block) ;
1805 simplified = cloog_loop_alloc(simp,loop->stride,new_block,inner,next) ;
1807 /* Examples like test/iftest2.cloog give unions of polyhedra after
1808 * simplifying, thus we we have to disjoint them. Another good reason to
1809 * put the simplifying step in the Quillere backtrack.
1811 simplified = cloog_loop_disjoint(simplified) ;
1813 loop->inner = NULL ; /* For loop integrity. */
1814 loop->next = NULL ; /* For loop integrity. */
1815 cloog_loop_free_parts(loop,1,1,0,0) ;
1817 return(simplified) ;
1822 * cloog_loop_scatter function:
1823 * This function add the scattering (scheduling) informations in a loop.
1825 void cloog_loop_scatter(CloogLoop * loop, CloogScattering *scatt)
1827 loop->domain = cloog_domain_scatter(loop->domain, scatt);