cloog_loop_generate: restrict inner loop domains before recursing
[cloog/uuh.git] / source / loop.c
blob85c93a48603e06277fbaf317e78a33b0b4dd90ce
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 library is free software; you can redistribute it and/or *
18 * modify it under the terms of the GNU Lesser General Public *
19 * License as published by the Free Software Foundation; either *
20 * version 2.1 of the License, or (at your option) any later version. *
21 * *
22 * This library is distributed in the hope that it will be useful, *
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
25 * Lesser General Public License for more details. *
26 * *
27 * You should have received a copy of the GNU Lesser General Public *
28 * License along with this library; if not, write to the Free Software *
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
30 * Boston, MA 02110-1301 USA *
31 * *
32 * CLooG, the Chunky Loop Generator *
33 * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr *
34 * *
35 ******************************************************************************/
36 /* CAUTION: the english used for comments is probably the worst you ever read,
37 * please feel free to correct and improve it !
40 # include <stdlib.h>
41 # include <stdio.h>
42 # include "../include/cloog/cloog.h"
45 /******************************************************************************
46 * Memory leaks hunting *
47 ******************************************************************************/
50 /**
51 * These functions and global variables are devoted to memory leaks hunting: we
52 * want to know at each moment how many CloogLoop structures had been allocated
53 * (cloog_loop_allocated) and how many had been freed (cloog_loop_freed).
54 * Each time a CloogLoog structure is allocated, a call to the function
55 * cloog_loop_leak_up() must be carried out, and respectively
56 * cloog_loop_leak_down() when a CloogLoop structure is freed. The special
57 * variable cloog_loop_max gives the maximal number of CloogLoop structures
58 * simultaneously alive (i.e. allocated and non-freed) in memory.
59 * - July 3rd->11th 2003: first version (memory leaks hunt and correction).
63 static void cloog_loop_leak_up(CloogState *state)
65 state->loop_allocated++;
66 if ((state->loop_allocated - state->loop_freed) > state->loop_max)
67 state->loop_max = state->loop_allocated - state->loop_freed;
71 static void cloog_loop_leak_down(CloogState *state)
73 state->loop_freed++;
77 /******************************************************************************
78 * Structure display function *
79 ******************************************************************************/
82 /**
83 * cloog_loop_print_structure function:
84 * Displays a loop structure in a way that trends to be understandable without
85 * falling in a deep depression or, for the lucky ones, getting a headache...
86 * Written by Olivier Chorier, Luc Marchaud, Pierre Martin and Romain Tartiere.
87 * - April 24th 2005: Initial version.
88 * - May 21rd 2005: - New parameter `F' for destination file (ie stdout),
89 * - Minor tweaks.
90 * - May 26th 2005: Memory leak hunt.
91 * - June 2nd 2005: (Ced) Integration and minor fixes.
92 * -June 22nd 2005: (Ced) Adaptation for GMP.
94 void cloog_loop_print_structure(FILE * file, CloogLoop * loop, int level)
95 { int i, j, first=1 ;
97 if (loop)
98 { /* Go to the right level. */
99 for (i=0; i<level; i++)
100 fprintf(file,"|\t") ;
102 fprintf(file,"+-- CloogLoop\n") ;
105 /* For each loop. */
106 while (loop)
107 { if (!first)
108 { /* Go to the right level. */
109 for (i=0; i<level; i++)
110 fprintf(file,"|\t") ;
112 fprintf(file,"| CloogLoop\n") ;
114 else
115 first = 0 ;
117 /* A blank line. */
118 for(j=0; j<=level+1; j++)
119 fprintf(file,"|\t") ;
120 fprintf(file,"\n") ;
122 /* Print the domain. */
123 cloog_domain_print_structure(file, loop->domain, level+1, "CloogDomain");
125 /* Print the stride. */
126 for(j=0; j<=level; j++)
127 fprintf(file,"|\t") ;
128 fprintf(file, "Stride: ") ;
129 cloog_int_print(file, loop->stride);
130 fprintf(file, "\n") ;
131 fprintf(file, "Offset: ") ;
132 cloog_int_print(file, loop->offset);
133 fprintf(file, "\n") ;
135 /* A blank line. */
136 for(j=0; j<=level+1; j++)
137 fprintf(file,"|\t") ;
138 fprintf(file,"\n") ;
140 /* Print the block. */
141 cloog_block_print_structure(file,loop->block,level+1) ;
143 /* A blank line. */
144 for (i=0; i<=level+1; i++)
145 fprintf(file,"|\t") ;
146 fprintf(file,"\n") ;
148 /* Print inner if any. */
149 if (loop->inner)
150 cloog_loop_print_structure(file,loop->inner,level+1) ;
152 /* And let's go for the next one. */
153 loop = loop->next ;
155 /* One more time something that is here only for a better look. */
156 if (!loop)
157 { /* Two blank lines if this is the end of the linked list. */
158 for (j=0; j<2; j++)
159 { for (i=0; i<=level; i++)
160 fprintf(file,"|\t") ;
162 fprintf(file,"\n") ;
165 else
166 { /* A special blank line if the is a next loop. */
167 for (i=0; i<=level; i++)
168 fprintf(file,"|\t") ;
169 fprintf(file,"V\n") ;
176 * cloog_loop_print function:
177 * This function prints the content of a CloogLoop structure (start) into a
178 * file (file, possibly stdout).
179 * - June 2nd 2005: Now this very old function (probably as old as CLooG) is
180 * only a frontend to cloog_loop_print_structure, with a quite
181 * better human-readable representation.
183 void cloog_loop_print(FILE * file, CloogLoop * loop)
184 { cloog_loop_print_structure(file,loop,0) ;
188 /******************************************************************************
189 * Memory deallocation function *
190 ******************************************************************************/
194 * cloog_loop_free function:
195 * This function frees the allocated memory for a CloogLoop structure (loop),
196 * and frees its inner loops and its next loops.
197 * - June 22nd 2005: Adaptation for GMP.
199 void cloog_loop_free(CloogLoop * loop)
200 { CloogLoop * next ;
202 while (loop != NULL) {
203 cloog_loop_leak_down(loop->state);
205 next = loop->next ;
206 cloog_domain_free(loop->domain) ;
207 cloog_block_free(loop->block) ;
208 if (loop->inner != NULL)
209 cloog_loop_free(loop->inner) ;
211 cloog_int_clear(loop->stride);
212 cloog_int_clear(loop->offset);
213 free(loop) ;
214 loop = next ;
220 * cloog_loop_free_parts function:
221 * This function frees the allocated memory for some parts of a CloogLoop
222 * structure (loop), each other argument is a boolean having to be set to 1 if
223 * we want to free the corresponding part, 0 otherwise. This function applies
224 * the same freeing policy to its inner ans next loops recursively.
225 * - July 3rd 2003: first version.
226 * - June 22nd 2005: Adaptation for GMP.
228 void cloog_loop_free_parts(loop, domain, block, inner, next)
229 CloogLoop * loop ;
230 int domain, block, inner, next ;
231 { CloogLoop * follow ;
233 while (loop != NULL) {
234 cloog_loop_leak_down(loop->state);
235 follow = loop->next ;
237 if (domain)
238 cloog_domain_free(loop->domain) ;
240 if (block)
241 cloog_block_free(loop->block) ;
243 if ((inner) && (loop->inner != NULL))
244 cloog_loop_free_parts(loop->inner,domain,block,inner,1) ;
246 cloog_int_clear(loop->stride);
247 cloog_int_clear(loop->offset);
248 free(loop) ;
249 if (next)
250 loop = follow ;
251 else
252 loop = NULL ;
257 /******************************************************************************
258 * Reading functions *
259 ******************************************************************************/
263 * cloog_loop_read function:
264 * This function reads loop data into a file (foo, possibly stdin) and
265 * returns a pointer to a CloogLoop structure containing the read information.
266 * This function can be used only for input file reading, when one loop is
267 * associated with one statement.
268 * - number is the statement block number carried by the loop (-1 if none).
269 * - nb_parameters is the number of parameters.
271 * - September 9th 2002: first version.
272 * - April 16th 2005: adaptation to new CloogStatement struct (with number).
273 * - June 11th 2005: adaptation to new CloogBlock structure.
274 * - June 22nd 2005: Adaptation for GMP.
276 CloogLoop *cloog_loop_read(CloogState *state,
277 FILE * foo, int number, int nb_parameters)
278 { int nb_iterators, op1, op2, op3 ;
279 char s[MAX_STRING] ;
280 CloogLoop * loop ;
281 CloogStatement * statement ;
283 cloog_loop_leak_up(state);
285 /* Memory allocation and information reading for the first domain: */
286 loop = (CloogLoop *)malloc(sizeof(CloogLoop)) ;
287 if (loop == NULL)
288 cloog_die("memory overflow.\n");
289 /* domain. */
290 loop->state = state;
291 loop->domain = cloog_domain_union_read(state, foo, nb_parameters);
292 if (loop->domain != NULL)
293 nb_iterators = cloog_domain_dimension(loop->domain);
294 else
295 nb_iterators = 0 ;
296 /* stride is initialized to 1. */
297 cloog_int_init(loop->stride);
298 cloog_int_set_si(loop->stride, 1);
299 cloog_int_init(loop->offset);
300 cloog_int_set_si(loop->offset, 0);
301 /* included statement block. */
302 statement = cloog_statement_alloc(state, number + 1);
303 loop->block = cloog_block_alloc(statement, 0, NULL, nb_iterators);
304 loop->usr = NULL;
305 /* inner is NULL at beginning. */
306 loop->inner = NULL ;
307 /* next element. */
308 loop->next = 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) ;
315 return loop ;
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
328 * allocated space.
329 * - November 21th 2005: first version.
331 CloogLoop *cloog_loop_malloc(CloogState *state)
332 { CloogLoop * loop ;
334 /* Memory allocation for the CloogLoop structure. */
335 loop = (CloogLoop *)malloc(sizeof(CloogLoop)) ;
336 if (loop == NULL)
337 cloog_die("memory overflow.\n");
338 cloog_loop_leak_up(state);
341 /* We set the various fields with default values. */
342 loop->state = state;
343 loop->domain = NULL ;
344 loop->block = NULL ;
345 loop->usr = NULL;
346 loop->inner = NULL ;
347 loop->next = NULL ;
348 cloog_int_init(loop->stride);
349 cloog_int_set_si(loop->stride, 1);
350 cloog_int_init(loop->offset);
351 cloog_int_set_si(loop->offset, 0);
353 return loop ;
358 * cloog_loop_alloc function:
359 * This function allocates the memory space for a CloogLoop structure and
360 * sets its fields with those given as input. Then it returns a pointer to the
361 * allocated space.
362 * - October 27th 2001: first version.
363 * - June 22nd 2005: Adaptation for GMP.
364 * - November 21th 2005: use of cloog_loop_malloc.
366 CloogLoop *cloog_loop_alloc(CloogState *state,
367 CloogDomain *domain, cloog_int_t stride, cloog_int_t offset,
368 CloogBlock *block, CloogLoop *inner, CloogLoop *next)
369 { CloogLoop * loop ;
371 loop = cloog_loop_malloc(state);
373 loop->domain = domain ;
374 loop->block = block ;
375 loop->inner = inner ;
376 loop->next = next ;
377 cloog_int_set(loop->stride, stride);
378 cloog_int_set(loop->offset, offset);
380 return(loop) ;
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)
393 { if (*start == NULL)
394 { *start = loop ;
395 *now = *start ;
397 else
398 { (*now)->next = loop ;
399 *now = (*now)->next ;
405 * cloog_loop_add function:
406 * This function adds a CloogLoop structure (loop) at a given place (now) of a
407 * NULL terminated list of CloogLoop structures. The beginning of this list
408 * is (start). This function updates (now) to the end of the loop list (loop),
409 * and updates (start) if the added element is the first one -that is when
410 * (start) is NULL-.
411 * - September 9th 2005: first version.
413 void cloog_loop_add_list(CloogLoop ** start, CloogLoop ** now, CloogLoop * loop)
414 { if (*start == NULL)
415 { *start = loop ;
416 *now = *start ;
418 else
419 { (*now)->next = loop ;
420 *now = (*now)->next ;
423 while ((*now)->next != NULL)
424 *now = (*now)->next ;
429 * cloog_loop_copy function:
430 * This function returns a copy of the CloogLoop structure given as input. In
431 * fact, there is just new allocations for the CloogLoop structures, but their
432 * contents are the same.
433 * - October 28th 2001: first version.
434 * - July 3rd->11th 2003: memory leaks hunt and correction.
436 CloogLoop * cloog_loop_copy(CloogLoop * source)
437 { CloogLoop * loop ;
438 CloogBlock * block ;
439 CloogDomain * domain ;
441 loop = NULL ;
442 if (source != NULL)
443 { domain = cloog_domain_copy(source->domain) ;
444 block = cloog_block_copy(source->block) ;
445 loop = cloog_loop_alloc(source->state, domain, source->stride,
446 source->offset, block, NULL, NULL);
447 loop->usr = source->usr;
448 loop->inner = cloog_loop_copy(source->inner) ;
449 loop->next = cloog_loop_copy(source->next) ;
451 return(loop) ;
456 * cloog_loop_add_disjoint function:
457 * This function adds some CloogLoop structures at a given place (now) of a
458 * NULL terminated list of CloogLoop structures. The beginning of this list
459 * is (start). (loop) can be an union of polyhedra, this function separates the
460 * union into a list of *disjoint* polyhedra then adds the list. This function
461 * updates (now) to the end of the list and updates (start) if first added
462 * element is the first of the principal list -that is when (start) is NULL-.
463 * (loop) can be freed by this function, basically when its domain is actually
464 * a union of polyhedra, but don't worry, all the useful data are now stored
465 * inside the list (start). We do not use PolyLib's Domain_Disjoint function,
466 * since the number of union components is often higher (thus code size too).
467 * - October 28th 2001: first version.
468 * - November 14th 2001: bug correction (this one was hard to find !).
469 * - July 3rd->11th 2003: memory leaks hunt and correction.
470 * - June 22nd 2005: Adaptation for GMP.
471 * - October 27th 2005: (debug) included blocks were not copied for new loops.
473 void cloog_loop_add_disjoint(start, now, loop)
474 CloogLoop ** start, ** now, * loop ;
476 CloogLoop * sep, * inner ;
477 CloogDomain *domain, *seen, *temp, *rest;
478 CloogBlock * block ;
480 if (cloog_domain_isconvex(loop->domain))
481 cloog_loop_add(start,now,loop) ;
482 else {
483 domain = cloog_domain_simplify_union(loop->domain);
484 loop->domain = NULL ;
486 /* We separate the first element of the rest of the union. */
487 domain = cloog_domain_cut_first(domain, &rest);
489 /* This first element is the first of the list of disjoint polyhedra. */
490 sep = cloog_loop_alloc(loop->state, domain, loop->state->one,
491 loop->state->zero, 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(loop->state, cloog_domain_copy(domain),
513 loop->state->one, loop->state->zero,
514 block, inner, NULL);
515 /* domain can be an union too. If so: recursion. */
516 if (cloog_domain_isconvex(domain))
517 cloog_loop_add(start,now,sep) ;
518 else
519 cloog_loop_add_disjoint(start,now,sep) ;
521 if (cloog_domain_isempty(rest)) {
522 cloog_domain_free(domain);
523 break;
526 seen = cloog_domain_union(seen, domain);
528 cloog_domain_free(rest);
529 cloog_domain_free(seen);
530 cloog_loop_free_parts(loop,0,0,0,0) ;
536 * cloog_loop_disjoint function:
537 * This function returns a list of loops such that each loop with non-convex
538 * domain in the input list (loop) is separated into several loops where the
539 * domains are the components of the union of *disjoint* polyhedra equivalent
540 * to the original non-convex domain. See cloog_loop_add_disjoint comments
541 * for more details.
542 * - September 16th 2005: first version.
544 CloogLoop * cloog_loop_disjoint(CloogLoop * loop)
545 { CloogLoop *res=NULL, * now=NULL, * next ;
547 /* Because this is often the case, don't waste time ! */
548 if (loop && !loop->next && cloog_domain_isconvex(loop->domain))
549 return loop ;
551 while (loop != NULL)
552 { next = loop->next ;
553 loop->next = NULL ;
554 cloog_loop_add_disjoint(&res,&now,loop) ;
555 loop = next ;
558 return res ;
563 * cloog_loop_restrict function:
564 * This function returns the (loop) in the context of (context): it makes the
565 * intersection between the (loop) domain and the (context), then it returns
566 * a pointer to a new loop, with this intersection as domain.
568 * - October 27th 2001: first version.
569 * - June 15th 2005: a memory leak fixed (domain was not freed when empty).
570 * - June 22nd 2005: Adaptation for GMP.
572 CloogLoop *cloog_loop_restrict(CloogLoop *loop, CloogDomain *context)
573 { int new_dimension ;
574 CloogDomain * domain, * extended_context, * new_domain ;
575 CloogLoop * new_loop ;
577 domain = loop->domain ;
578 if (cloog_domain_dimension(domain) > cloog_domain_dimension(context))
580 new_dimension = cloog_domain_dimension(domain);
581 extended_context = cloog_domain_extend(context, new_dimension);
582 new_domain = cloog_domain_intersection(extended_context,loop->domain) ;
583 cloog_domain_free(extended_context) ;
585 else
586 new_domain = cloog_domain_intersection(context,loop->domain) ;
588 if (cloog_domain_isempty(new_domain))
589 { cloog_domain_free(new_domain) ;
590 return(NULL) ;
592 else {
593 new_loop = cloog_loop_alloc(loop->state, new_domain,
594 loop->state->one, loop->state->zero,
595 loop->block, loop->inner, NULL);
596 return(new_loop) ;
602 * Call cloog_loop_restrict on each loop in the list "loop" and return
603 * the concatenated result.
605 CloogLoop *cloog_loop_restrict_all(CloogLoop *loop, CloogDomain *context)
607 CloogLoop *next;
608 CloogLoop *res = NULL;
609 CloogLoop **res_next = &res;
611 for (; loop; loop = next) {
612 next = loop->next;
614 *res_next = cloog_loop_restrict(loop, context);
615 if (*res_next) {
616 res_next = &(*res_next)->next;
617 cloog_loop_free_parts(loop, 1, 0, 0, 0);
618 } else {
619 loop->next = NULL;
620 cloog_loop_free(loop);
624 return res;
627 CloogLoop *cloog_loop_restrict_inner(CloogLoop *loop)
629 CloogLoop *l;
631 for (l = loop; l; l = l->next)
632 l->inner = cloog_loop_restrict_all(l->inner, l->domain);
634 return loop;
638 * cloog_loop_project function:
639 * This function returns the projection of (loop) on the (level) first
640 * dimensions (outer loops). It makes the projection of the (loop) domain,
641 * then it returns a pointer to a new loop, with this projection as domain.
643 * - October 27th 2001: first version.
644 * - July 3rd->11th 2003: memory leaks hunt and correction.
645 * - June 22nd 2005: Adaptation for GMP.
647 CloogLoop * cloog_loop_project(CloogLoop * loop, int level)
649 CloogDomain * new_domain ;
650 CloogLoop * new_loop, * copy ;
652 copy = cloog_loop_alloc(loop->state, loop->domain, loop->stride, loop->offset,
653 loop->block, loop->inner, NULL);
655 if (cloog_domain_dimension(loop->domain) == level)
656 new_domain = cloog_domain_copy(loop->domain) ;
657 else
658 new_domain = cloog_domain_project(loop->domain, level);
660 new_loop = cloog_loop_alloc(loop->state, new_domain, loop->state->one,
661 loop->state->zero, NULL, copy, NULL);
663 return(new_loop) ;
668 * Call cloog_loop_project on each loop in the list "loop" and return
669 * the concatenated result.
671 CloogLoop *cloog_loop_project_all(CloogLoop *loop, int level)
673 CloogLoop *next;
674 CloogLoop *res = NULL;
675 CloogLoop **res_next = &res;
677 for (; loop; loop = next) {
678 next = loop->next;
680 *res_next = cloog_loop_project(loop, level);
681 res_next = &(*res_next)->next;
682 cloog_loop_free_parts(loop, 0, 0, 0, 0);
685 return res;
690 * cloog_loop_concat function:
691 * This function returns a pointer to the concatenation of the
692 * CloogLoop lists given as input.
693 * - October 28th 2001: first version.
695 CloogLoop * cloog_loop_concat(CloogLoop * a, CloogLoop * b)
696 { CloogLoop * loop, * temp ;
698 loop = a ;
699 temp = loop ;
700 if (loop != NULL)
701 { while (temp->next != NULL)
702 temp = temp->next ;
703 temp->next = b ;
705 else
706 loop = b ;
708 return(loop) ;
713 * cloog_loop_combine:
714 * Combine consecutive loops with identical domains into
715 * a single loop with the concatenation of their inner loops
716 * as inner loop.
718 CloogLoop *cloog_loop_combine(CloogLoop *loop)
720 CloogLoop *first, *second;
722 for (first = loop; first; first = first->next) {
723 while (first->next) {
724 if (!cloog_domain_lazy_equal(first->domain, first->next->domain))
725 break;
726 second = first->next;
727 first->inner = cloog_loop_concat(first->inner, second->inner);
728 first->next = second->next;
729 cloog_loop_free_parts(second, 1, 0, 0, 0);
733 return loop;
737 * cloog_loop_separate function:
738 * This function implements the Quillere algorithm for separation of multiple
739 * loops: for a given set of polyhedra (loop), it computes a set of disjoint
740 * polyhedra such that the unions of these sets are equal, and returns this set.
741 * - October 28th 2001: first version.
742 * - November 14th 2001: elimination of some unused blocks.
743 * - August 13th 2002: (debug) in the case of union of polyhedra for one
744 * loop, redundant constraints are fired.
745 * - July 3rd->11th 2003: memory leaks hunt and correction.
746 * - June 22nd 2005: Adaptation for GMP.
747 * - October 16th 2005: Removal of the non-shared constraint elimination when
748 * there is only one loop in the list (seems to work
749 * without now, DomainSimplify may have been improved).
750 * The problem was visible with test/iftest2.cloog.
752 CloogLoop * cloog_loop_separate(CloogLoop * loop)
753 { int lazy_equal=0, disjoint = 0;
754 CloogLoop * new_loop, * new_inner, * res, * now, * temp, * Q,
755 * inner, * old /*, * previous, * next*/ ;
756 CloogDomain *UQ, *domain;
758 if (loop == NULL)
759 return NULL ;
761 loop = cloog_loop_combine(loop);
763 if (loop->next == NULL)
764 return cloog_loop_disjoint(loop) ;
766 UQ = cloog_domain_copy(loop->domain) ;
767 domain = cloog_domain_copy(loop->domain) ;
768 res = cloog_loop_alloc(loop->state, domain, loop->state->one,
769 loop->state->zero, loop->block, loop->inner, NULL);
771 old = loop ;
772 while((loop = loop->next) != NULL)
773 { temp = NULL ;
775 /* For all Q, add Q-loop associated with the blocks of Q alone,
776 * and Q inter loop associated with the blocks of Q and loop.
778 for (Q = res; Q; Q = Q->next) {
779 /* Add (Q inter loop). */
780 if ((disjoint = cloog_domain_lazy_disjoint(Q->domain,loop->domain)))
781 domain = NULL ;
782 else
783 { if ((lazy_equal = cloog_domain_lazy_equal(Q->domain,loop->domain)))
784 domain = cloog_domain_copy(Q->domain) ;
785 else
786 domain = cloog_domain_intersection(Q->domain,loop->domain) ;
788 if (!cloog_domain_isempty(domain))
789 { new_inner = cloog_loop_concat(cloog_loop_copy(Q->inner),
790 cloog_loop_copy(loop->inner)) ;
791 new_loop = cloog_loop_alloc(loop->state, domain, loop->state->one,
792 loop->state->zero, NULL, new_inner, NULL);
793 cloog_loop_add_disjoint(&temp,&now,new_loop) ;
795 else {
796 disjoint = 1;
797 cloog_domain_free(domain);
801 /* Add (Q - loop). */
802 if (disjoint)
803 domain = cloog_domain_copy(Q->domain) ;
804 else
805 { if (lazy_equal)
806 domain = cloog_domain_empty(Q->domain);
807 else
808 domain = cloog_domain_difference(Q->domain,loop->domain) ;
811 if (!cloog_domain_isempty(domain)) {
812 new_loop = cloog_loop_alloc(loop->state, domain, loop->state->one,
813 loop->state->zero, NULL, Q->inner, NULL);
814 cloog_loop_add_disjoint(&temp,&now,new_loop) ;
816 else
817 { cloog_domain_free(domain) ;
818 /* If Q->inner is no more useful, we can free it. */
819 inner = Q->inner ;
820 Q->inner = NULL ;
821 cloog_loop_free(inner) ;
825 /* Add loop-UQ associated with the blocks of loop alone.*/
826 if (cloog_domain_lazy_disjoint(loop->domain,UQ))
827 domain = cloog_domain_copy(loop->domain) ;
828 else
829 { if (cloog_domain_lazy_equal(loop->domain,UQ))
830 domain = cloog_domain_empty(UQ);
831 else
832 domain = cloog_domain_difference(loop->domain,UQ) ;
835 if (!cloog_domain_isempty(domain)) {
836 new_loop = cloog_loop_alloc(loop->state, domain, loop->state->one,
837 loop->state->zero, NULL, loop->inner, NULL);
838 cloog_loop_add_disjoint(&temp,&now,new_loop) ;
840 else
841 { cloog_domain_free(domain) ;
842 /* If loop->inner is no more useful, we can free it. */
843 cloog_loop_free(loop->inner) ;
846 loop->inner = NULL ;
848 if (loop->next != NULL)
849 UQ = cloog_domain_union(UQ, cloog_domain_copy(loop->domain));
850 else
851 cloog_domain_free(UQ);
853 cloog_loop_free_parts(res,1,0,0,1) ;
855 res = temp ;
857 cloog_loop_free_parts(old,1,0,0,1) ;
859 return(res) ;
863 static CloogDomain *bounding_domain(CloogDomain *dom, CloogOptions *options)
865 if (options->sh)
866 return cloog_domain_simple_convex(dom);
867 else
868 return cloog_domain_convex(dom);
873 * cloog_loop_merge function:
874 * This function is the 'soft' version of loop_separate if we are looking for
875 * a code much simpler (and less efficicient). This function returns the new
876 * CloogLoop list.
877 * - October 29th 2001: first version.
878 * - July 3rd->11th 2003: memory leaks hunt and correction.
879 * - June 22nd 2005: Adaptation for GMP.
881 CloogLoop *cloog_loop_merge(CloogLoop *loop, int level, CloogOptions *options)
883 CloogLoop *res, *new_inner, *old;
884 CloogDomain *new_domain, *temp;
886 if (loop == NULL)
887 return loop;
889 if (loop->next == NULL)
890 return cloog_loop_disjoint(loop);
892 old = loop;
893 temp = loop->domain;
894 loop->domain = NULL;
895 new_inner = loop->inner;
897 for (loop = loop->next; loop; loop = loop->next) {
898 temp = cloog_domain_union(temp, loop->domain);
899 loop->domain = NULL;
900 new_inner = cloog_loop_concat(new_inner, loop->inner);
903 new_domain = bounding_domain(temp, options);
905 if (level > 0 && !cloog_domain_is_bounded(new_domain, level) &&
906 cloog_domain_is_bounded(temp, level)) {
907 CloogDomain *splitter, *t2;
909 cloog_domain_free(new_domain);
910 splitter = cloog_domain_bound_splitter(temp, level);
912 res = NULL;
913 while (!cloog_domain_isconvex(splitter)) {
914 CloogDomain *first, *rest;
915 first = cloog_domain_cut_first(splitter, &rest);
916 splitter = rest;
917 t2 = cloog_domain_intersection(first, temp);
918 cloog_domain_free(first);
920 new_domain = bounding_domain(t2, options);
921 cloog_domain_free(t2);
923 if (cloog_domain_isempty(new_domain)) {
924 cloog_domain_free(new_domain);
925 continue;
927 res = cloog_loop_alloc(old->state, new_domain, old->state->one,
928 old->state->zero, NULL,
929 cloog_loop_copy(new_inner), res);
932 t2 = cloog_domain_intersection(splitter, temp);
933 cloog_domain_free(splitter);
935 new_domain = bounding_domain(t2, options);
936 cloog_domain_free(t2);
938 if (cloog_domain_isempty(new_domain)) {
939 cloog_domain_free(new_domain);
940 cloog_loop_free(new_inner);
941 } else
942 res = cloog_loop_alloc(old->state, new_domain, old->state->one,
943 old->state->zero, NULL, new_inner, res);
944 } else {
945 res = cloog_loop_alloc(old->state, new_domain, old->state->one,
946 old->state->zero, NULL, new_inner, NULL);
948 cloog_domain_free(temp);
950 cloog_loop_free_parts(old, 0, 0, 0, 1);
952 return res;
956 static int cloog_loop_count(CloogLoop *loop)
958 int nb_loops;
960 for (nb_loops = 0; loop; loop = loop->next)
961 nb_loops++;
963 return nb_loops;
968 * cloog_loop_sort function:
969 * Adaptation from LoopGen 0.4 by F. Quillere. This function sorts a list of
970 * parameterized disjoint polyhedra, in order to not have lexicographic order
971 * violation (see Quillere paper).
972 * - September 16th 2005: inclusion of cloog_loop_number (October 29th 2001).
974 CloogLoop *cloog_loop_sort(CloogLoop *loop, int level)
976 CloogLoop *res, *now, **loop_array;
977 CloogDomain **doms;
978 int i, nb_loops=0, * permut ;
980 /* There is no need to sort the parameter domains. */
981 if (!level)
982 return loop;
984 /* We will need to know how many loops are in the list. */
985 nb_loops = cloog_loop_count(loop);
987 /* If there is only one loop, it's the end. */
988 if (nb_loops == 1)
989 return(loop) ;
991 /* We have to allocate memory for some useful components:
992 * - loop_array: the loop array,
993 * - doms: the array of domains to sort,
994 * - permut: will give us a possible sort (maybe not the only one).
996 loop_array = (CloogLoop **)malloc(nb_loops*sizeof(CloogLoop *)) ;
997 doms = (CloogDomain **)malloc(nb_loops*sizeof(CloogDomain *));
998 permut = (int *)malloc(nb_loops*sizeof(int)) ;
1000 /* We fill up the loop and domain arrays. */
1001 for (i=0;i<nb_loops;i++,loop=loop->next)
1002 { loop_array[i] = loop ;
1003 doms[i] = loop_array[i]->domain;
1006 /* cloog_domain_sort will fill up permut. */
1007 cloog_domain_sort(doms, nb_loops, level, permut);
1009 /* With permut and loop_array we build the sorted list. */
1010 res = NULL ;
1011 for (i=0;i<nb_loops;i++)
1012 { /* To avoid pointer looping... loop_add will rebuild the list. */
1013 loop_array[permut[i]-1]->next = NULL ;
1014 cloog_loop_add(&res,&now,loop_array[permut[i]-1]) ;
1017 free(permut) ;
1018 free(doms);
1019 free(loop_array) ;
1021 return res;
1026 * cloog_loop_nest function:
1027 * This function changes the loop list in such a way that we have no more than
1028 * one dimension added by level. It returns an equivalent loop list with
1029 * this property.
1030 * - October 29th 2001: first version.
1031 * - July 3rd->11th 2003: memory leaks hunt and correction.
1032 * - June 22nd 2005: Adaptation for GMP.
1033 * - November 21th 2005: (debug) now OK when cloog_loop_restrict returns NULL.
1035 CloogLoop *cloog_loop_nest(CloogLoop *loop, CloogDomain *context, int level)
1036 { int l ;
1037 CloogLoop * p, * temp, * res, * now, * next ;
1038 CloogDomain * new_domain ;
1040 loop = cloog_loop_disjoint(loop);
1042 res = NULL ;
1043 /* Each domain is changed by its intersection with the context. */
1044 while (loop != NULL)
1045 { p = cloog_loop_restrict(loop, context);
1046 next = loop->next ;
1048 if (p != NULL)
1049 { cloog_loop_free_parts(loop,1,0,0,0) ;
1051 temp = cloog_loop_alloc(p->state, p->domain, p->state->one,
1052 p->state->zero, p->block, p->inner, NULL);
1054 /* If the intersection dimension is too big, we make projections smaller
1055 * and smaller, and each projection includes the preceding projection
1056 * (thus, in the target list, dimensions are added one by one).
1058 if (cloog_domain_dimension(p->domain) >= level)
1059 for (l = cloog_domain_dimension(p->domain); l >= level; l--) {
1060 new_domain = cloog_domain_project(p->domain, l);
1061 temp = cloog_loop_alloc(p->state, new_domain, p->state->one,
1062 p->state->zero, NULL, temp, NULL);
1065 /* p is no more useful (but its content yes !). */
1066 cloog_loop_free_parts(p,0,0,0,0) ;
1068 cloog_loop_add(&res,&now,temp) ;
1070 else
1071 cloog_loop_free_parts(loop,1,1,1,0) ;
1073 loop = next ;
1076 return(res) ;
1081 * cloog_loop_stride function:
1082 * This function will find the stride of a loop for the iterator at the column
1083 * number 'level' in the constraint matrix. It will update the lower bound of
1084 * the iterator accordingly. Basically, the function will try to find in the
1085 * inner loops a common condition on this iterator for the inner loop iterators
1086 * to be integral. For instance, let us consider a loop with the iterator i,
1087 * the iteration domain -4<=i<=n, and its two inner loops with the iterator j.
1088 * The first inner loop has the constraint 3j=i, and the second one has the
1089 * constraint 6j=i. Then the common constraint on i for j to be integral is
1090 * i%3=0, the stride for i is 3. Lastly, we have to find the new lower bound
1091 * for i: the first value satisfying the common constraint: -3. At the end, the
1092 * iteration domain for i is -3<=i<=n and the stride for i is 3.
1093 * - loop is the loop including the iteration domain of the considered iterator,
1094 * - level is the column number of the iterator in the matrix of contraints.
1096 * - June 29th 2003: first version (work in progress since June 26th 2003).
1097 * - July 14th 2003: simpler version.
1098 * - June 22nd 2005: Adaptation for GMP (from S. Verdoolaege's 0.12.1 version).
1100 void cloog_loop_stride(CloogLoop * loop, int level)
1101 { int first_search ;
1102 cloog_int_t stride, ref_offset, offset, potential, lower;
1103 CloogLoop * inner ;
1105 cloog_int_init(stride);
1106 cloog_int_init(ref_offset);
1107 cloog_int_init(offset);
1108 cloog_int_init(potential);
1109 cloog_int_init(lower);
1111 cloog_int_set_si(ref_offset, 0);
1112 cloog_int_set_si(offset, 0);
1113 cloog_int_set_si(lower, 0);
1115 /* Default stride. */
1116 cloog_int_set_si(stride, 1);
1117 first_search = 1 ;
1118 inner = loop->inner ;
1120 if (cloog_domain_integral_lowerbound(loop->domain,level,&lower))
1121 while (inner != NULL)
1122 { /* If the minimun stride has not been found yet, find the stride. */
1123 if ((first_search) || (!cloog_int_is_one(stride)))
1125 cloog_domain_stride(inner->domain, level, &potential, &offset);
1126 if (!cloog_int_is_one(potential) && (!first_search))
1127 { /* Offsets must be the same for common stride. */
1128 cloog_int_gcd(stride, potential, stride);
1129 if (!cloog_int_is_zero(stride)) {
1130 cloog_int_fdiv_r(offset, offset, stride);
1131 cloog_int_fdiv_r(ref_offset, ref_offset, stride);
1133 if (cloog_int_ne(offset,ref_offset))
1134 cloog_int_set_si(stride, 1);
1136 else {
1137 cloog_int_set(stride, potential);
1138 cloog_int_set(ref_offset, offset);
1141 first_search = 0 ;
1144 inner = inner->next ;
1147 if (cloog_int_is_zero(stride))
1148 cloog_int_set_si(stride, 1);
1150 /* Update the values if necessary. */
1151 if (!cloog_int_is_one(stride))
1152 { /* Update the stride value. */
1153 cloog_int_set(loop->stride, stride);
1154 if (!cloog_int_is_zero(offset))
1155 cloog_int_sub(loop->offset, stride, offset);
1158 cloog_int_clear(stride);
1159 cloog_int_clear(ref_offset);
1160 cloog_int_clear(offset);
1161 cloog_int_clear(potential);
1162 cloog_int_clear(lower);
1167 * cloog_loop_stop function:
1168 * This function implements the 'stop' option : each domain of each loop
1169 * in the list 'loop' is replaced by 'context'. 'context' should be the
1170 * domain of the outer loop. By using this method, there are no more dimensions
1171 * to scan and the simplification step will automaticaly remove the domains
1172 * since they are the same as the corresponding contexts. The effect of this
1173 * function is to stop the code generation at the level this function is called,
1174 * the resulting code do not consider the next dimensions.
1175 * - January 11th 2005: first version.
1177 CloogLoop * cloog_loop_stop(CloogLoop * loop, CloogDomain * context)
1178 { if (loop == NULL)
1179 return NULL ;
1180 else
1181 { cloog_domain_free(loop->domain) ;
1182 loop->domain = cloog_domain_copy(context) ;
1183 loop->next = cloog_loop_stop(loop->next, context) ;
1186 return loop ;
1190 static int level_is_constant(int level, int scalar, int *scaldims, int nb_scattdims)
1192 return level && (level+scalar <= nb_scattdims) && (scaldims[level+scalar-1]);
1197 * Compare the constant dimensions of loops 'l1' and 'l2' starting at 'scalar'
1198 * and return -1 if the vector of constant dimensions of 'l1' is smaller
1199 * than that of 'l2', 0 if they are the same and +1 if that of 'l1' is
1200 * greater than that of 'l2'.
1201 * This function should be called on the innermost loop (the loop
1202 * containing a block).
1203 * \param l1 Loop to be compared with l2.
1204 * \param l2 Loop to be compared with l1.
1205 * \param level Current non-scalar dimension.
1206 * \param scaldims Boolean array saying whether a dimension is scalar or not.
1207 * \param nb_scattdims Size of the scaldims array.
1208 * \param scalar Current scalar dimension.
1209 * \return -1 if (l1 < l2), 0 if (l1 == l2) and +1 if (l1 > l2)
1211 int cloog_loop_constant_cmp(CloogLoop *l1, CloogLoop *l2, int level,
1212 int *scaldims, int nb_scattdims, int scalar)
1214 CloogBlock *b1, *b2;
1215 b1 = l1->block;
1216 b2 = l2->block;
1217 while (level_is_constant(level, scalar, scaldims, nb_scattdims)) {
1218 int cmp = cloog_int_cmp(b1->scaldims[scalar], b2->scaldims[scalar]);
1219 if (cmp)
1220 return cmp;
1221 scalar++;
1223 return 0;
1228 * cloog_loop_scalar_gt function:
1229 * This function returns 1 if loop 'l1' is greater than loop 'l2' for the
1230 * scalar dimension vector that begins at dimension 'scalar', 0 otherwise. What
1231 * we want to know is whether a loop is scheduled before another one or not.
1232 * This function solves the problem when the considered dimension for scheduling
1233 * is a scalar dimension. Since there may be a succession of scalar dimensions,
1234 * this function will reason about the vector of scalar dimension that begins
1235 * at dimension 'level+scalar' and finish to the first non-scalar dimension.
1236 * \param l1 Loop to be compared with l2.
1237 * \param l2 Loop to be compared with l1.
1238 * \param level Current non-scalar dimension.
1239 * \param scaldims Boolean array saying whether a dimension is scalar or not.
1240 * \param nb_scattdims Size of the scaldims array.
1241 * \param scalar Current scalar dimension.
1242 * \return 1 if (l1 > l2), 0 otherwise.
1244 * - September 9th 2005: first version.
1245 * - October 15nd 2007: now "greater than" instead of "greater or equal".
1247 int cloog_loop_scalar_gt(l1, l2, level, scaldims, nb_scattdims, scalar)
1248 CloogLoop * l1, * l2 ;
1249 int level, * scaldims, nb_scattdims, scalar ;
1251 return cloog_loop_constant_cmp(l1, l2, level, scaldims, nb_scattdims, scalar) > 0;
1256 * cloog_loop_scalar_eq function:
1257 * This function returns 1 if loop 'l1' is equal to loop 'l2' for the scalar
1258 * dimension vector that begins at dimension 'scalar', 0 otherwise. What we want
1259 * to know is whether two loops are scheduled for the same time or not.
1260 * This function solves the problem when the considered dimension for scheduling
1261 * is a scalar dimension. Since there may be a succession of scalar dimensions,
1262 * this function will reason about the vector of scalar dimension that begins
1263 * at dimension 'level+scalar' and finish to the first non-scalar dimension.
1264 * - l1 and l2 are the loops to compare,
1265 * - level is the current non-scalar dimension,
1266 * - scaldims is the boolean array saying whether a dimension is scalar or not,
1267 * - nb_scattdims is the size of the scaldims array,
1268 * - scalar is the current scalar dimension.
1270 * - September 9th 2005 : first version.
1272 int cloog_loop_scalar_eq(l1, l2, level, scaldims, nb_scattdims, scalar)
1273 CloogLoop * l1, * l2 ;
1274 int level, * scaldims, nb_scattdims, scalar ;
1276 return cloog_loop_constant_cmp(l1, l2, level, scaldims, nb_scattdims, scalar) == 0;
1281 * cloog_loop_scalar_sort function:
1282 * This function sorts a linked list of loops (loop) with respect to the
1283 * scalar dimension vector that begins at dimension 'scalar'. Since there may
1284 * be a succession of scalar dimensions, this function will reason about the
1285 * vector of scalar dimension that begins at dimension 'level+scalar' and
1286 * finish to the first non-scalar dimension.
1287 * \param loop Loop list to sort.
1288 * \param level Current non-scalar dimension.
1289 * \param scaldims Boolean array saying whether a dimension is scalar or not.
1290 * \param nb_scattdims Size of the scaldims array.
1291 * \param scalar Current scalar dimension.
1292 * \return A pointer to the sorted list.
1294 * - July 2nd 2005: first developments.
1295 * - September 2nd 2005: first version.
1296 * - October 15nd 2007: complete rewrite to remove bugs, now a bubble sort.
1298 CloogLoop * cloog_loop_scalar_sort(loop, level, scaldims, nb_scattdims, scalar)
1299 CloogLoop * loop ;
1300 int level, * scaldims, nb_scattdims, scalar ;
1301 { int ok ;
1302 CloogLoop **current;
1304 do {
1305 ok = 1;
1306 for (current = &loop; (*current)->next; current = &(*current)->next) {
1307 CloogLoop *next = (*current)->next;
1308 if (cloog_loop_scalar_gt(*current,next,level,scaldims,nb_scattdims,scalar)) {
1309 ok = 0;
1310 (*current)->next = next->next;
1311 next->next = *current;
1312 *current = next;
1315 } while (!ok);
1317 return loop ;
1322 * cloog_loop_generate_backtrack function:
1323 * adaptation from LoopGen 0.4 by F. Quillere. This function implements the
1324 * backtrack of the Quillere et al. algorithm (see the Quillere paper).
1325 * It eliminates unused iterations of the current level for the new one. See the
1326 * example called linearity-1-1 example with and without this part for an idea.
1327 * - October 26th 2001: first version in cloog_loop_generate_general.
1328 * - July 31th 2002: (debug) no more parasite loops (REALLY hard !).
1329 * - October 30th 2005: extraction from cloog_loop_generate_general.
1331 CloogLoop *cloog_loop_generate_backtrack(CloogLoop *loop,
1332 int level, CloogOptions *options)
1334 CloogDomain * domain ;
1335 CloogLoop * now, * now2, * next, * next2, * end, * temp, * l, * inner,
1336 * new_loop ;
1338 temp = loop ;
1339 loop = NULL ;
1341 while (temp != NULL)
1342 { l = NULL ;
1343 inner = temp->inner ;
1345 while (inner != NULL)
1346 { next = inner->next ;
1347 /* This 'if' and its first part is the debug of july 31th 2002. */
1348 if (inner->block != NULL) {
1349 end = cloog_loop_alloc(temp->state, inner->domain, temp->state->one,
1350 temp->state->zero, inner->block, NULL, NULL);
1351 domain = cloog_domain_copy(temp->domain) ;
1352 new_loop = cloog_loop_alloc(temp->state, domain, temp->state->one,
1353 temp->state->zero, NULL, end, NULL);
1355 else
1356 new_loop = cloog_loop_project(inner, level);
1358 cloog_loop_free_parts(inner,0,0,0,0) ;
1359 cloog_loop_add(&l,&now2,new_loop) ;
1360 inner = next ;
1363 temp->inner = NULL ;
1365 if (l != NULL)
1366 { l = cloog_loop_separate(l) ;
1367 l = cloog_loop_sort(l, level);
1368 while (l != NULL) {
1369 cloog_int_set(l->stride, temp->stride);
1370 cloog_int_set(l->offset, temp->offset);
1371 cloog_loop_add(&loop,&now,l) ;
1372 l = l->next ;
1375 next2 = temp->next ;
1376 cloog_loop_free_parts(temp,1,0,0,0) ;
1377 temp = next2 ;
1380 return loop ;
1385 * Return 1 if we need to continue recursing to the specified level.
1387 int cloog_loop_more(CloogLoop *loop, int level, int scalar, int nb_scattdims)
1389 return level + scalar <= nb_scattdims ||
1390 cloog_domain_dimension(loop->domain) >= level;
1393 CloogLoop *cloog_loop_generate_restricted_or_stop(CloogLoop *loop,
1394 CloogDomain *context,
1395 int level, int scalar, int *scaldims, int nb_scattdims,
1396 CloogOptions *options);
1399 * cloog_loop_generate_general function:
1400 * Adaptation from LoopGen 0.4 by F. Quillere. This function implements the
1401 * Quillere algorithm for polyhedron scanning from step 3 to 5.
1402 * (see the Quillere paper).
1403 * - loop is the loop for which we have to generate a scanning code,
1404 * - level is the current non-scalar dimension,
1405 * - scalar is the current scalar dimension,
1406 * - scaldims is the boolean array saying whether a dimension is scalar or not,
1407 * - nb_scattdims is the size of the scaldims array,
1408 * - options are the general code generation options.
1410 * - October 26th 2001: first version.
1411 * - July 3rd->11th 2003: memory leaks hunt and correction.
1412 * - June 22nd 2005: Adaptation for GMP.
1413 * - September 2nd 2005: The function have been cutted out in two pieces:
1414 * cloog_loop_generate and this one, in order to handle
1415 * the scalar dimension case more efficiently with
1416 * cloog_loop_generate_scalar.
1417 * - November 15th 2005: (debug) the result of the cloog_loop_generate call may
1418 * be a list of polyhedra (especially if stop option is
1419 * used): cloog_loop_add_list instead of cloog_loop_add.
1421 CloogLoop *cloog_loop_generate_general(CloogLoop *loop,
1422 int level, int scalar, int *scaldims, int nb_scattdims,
1423 CloogOptions *options)
1425 CloogLoop * res, * now, * temp, * l, * new_loop, * inner, * now2, * end,
1426 * next, * into ;
1427 CloogDomain * domain ;
1429 /* 3. Separate all projections into disjoint polyhedra. */
1430 res = ((options->f > level+scalar) || (options->f < 0)) ?
1431 cloog_loop_merge(loop, level, options) : cloog_loop_separate(loop);
1433 /* 3b. -correction- sort the loops to determine their textual order. */
1434 res = cloog_loop_sort(res, level);
1436 res = cloog_loop_restrict_inner(res);
1438 /* 4. Recurse for each loop with the current domain as context. */
1439 temp = res ;
1440 res = NULL ;
1441 if (!level || (level+scalar < options->l) || (options->l < 0))
1442 while(temp != NULL)
1443 { if (level && options->strides)
1444 cloog_loop_stride(temp, level);
1445 inner = temp->inner ;
1446 domain = temp->domain ;
1447 into = NULL ;
1448 while (inner != NULL)
1449 { /* 4b. -ced- recurse for each sub-list of non terminal loops. */
1450 if (cloog_loop_more(inner, level + 1, scalar, nb_scattdims)) {
1451 end = inner;
1452 while ((end->next != NULL) &&
1453 cloog_loop_more(end->next, level + 1, scalar, nb_scattdims))
1454 end = end->next ;
1456 next = end->next ;
1457 end->next = NULL ;
1459 l = cloog_loop_generate_restricted_or_stop(inner, domain,
1460 level + 1, scalar, scaldims, nb_scattdims, options);
1462 if (l != NULL)
1463 cloog_loop_add_list(&into,&now,l) ;
1465 inner = next ;
1467 else
1468 { cloog_loop_add(&into,&now,inner) ;
1469 inner = inner->next ;
1472 next = temp->next ;
1473 temp->next = NULL ;
1474 temp->inner = into ;
1475 cloog_loop_add(&res,&now2,temp) ;
1476 temp = next ;
1478 else
1479 while (temp != NULL)
1480 { next = temp->next ;
1481 l = cloog_loop_nest(temp->inner, temp->domain, level+1);
1482 new_loop = cloog_loop_alloc(temp->state, temp->domain, temp->state->one,
1483 temp->state->zero, NULL, l, NULL);
1484 temp->inner = NULL ;
1485 temp->next = NULL ;
1486 cloog_loop_free_parts(temp,0,0,0,0) ;
1487 cloog_loop_add(&res,&now,new_loop) ;
1488 temp = next ;
1491 /* 5. eliminate unused iterations of the current level for the new one. See
1492 * the example called linearity-1-1 example with and without this part
1493 * for an idea.
1495 if ((!options->nobacktrack) && level &&
1496 ((level+scalar < options->l) || (options->l < 0)) &&
1497 ((options->f <= level+scalar) && !(options->f < 0)))
1498 res = cloog_loop_generate_backtrack(res, level, options);
1500 /* Pray for my new paper to be accepted somewhere since the following stuff
1501 * is really amazing :-) !
1502 * Far long later: The paper has been accepted to PACT 2004 :-))). But there
1503 * are still some bugs and I have no time to fix them. Thus now you have to
1504 * pray for me to get an academic position for that really amazing stuff :-) !
1505 * Later again: OK, I get my academic position, but still I have not enough
1506 * time to fix and clean this part... Pray again :-) !!!
1508 /* res = cloog_loop_unisolate(res,level) ;*/
1510 return(res) ;
1514 CloogLoop *cloog_loop_generate_restricted(CloogLoop *loop,
1515 int level, int scalar, int *scaldims, int nb_scattdims,
1516 CloogOptions *options);
1520 * cloog_loop_generate_scalar function:
1521 * This function applies the simplified code generation scheme in the trivial
1522 * case of scalar dimensions. When dealing with scalar dimensions, there is
1523 * no need of costly polyhedral operations for separation or sorting: sorting
1524 * is a question of comparing scalar vectors and separation amounts to consider
1525 * only loops with the same scalar vector for the next step of the code
1526 * generation process. This function achieves the separation/sorting process
1527 * for the vector of scalar dimension that begins at dimension 'level+scalar'
1528 * and finish to the first non-scalar dimension.
1529 * - loop is the loop for which we have to generate a scanning code,
1530 * - level is the current non-scalar dimension,
1531 * - scalar is the current scalar dimension,
1532 * - scaldims is the boolean array saying whether a dimension is scalar or not,
1533 * - nb_scattdims is the size of the scaldims array,
1534 * - options are the general code generation options.
1536 * - September 2nd 2005: First version.
1538 CloogLoop *cloog_loop_generate_scalar(CloogLoop *loop,
1539 int level, int scalar, int *scaldims, int nb_scattdims,
1540 CloogOptions *options)
1541 { CloogLoop * res, * now, * temp, * l, * end, * next, * ref ;
1542 int scalar_new;
1544 /* We sort the loop list with respect to the current scalar vector. */
1545 res = cloog_loop_scalar_sort(loop,level,scaldims,nb_scattdims,scalar) ;
1547 scalar_new = scalar + scaldims[level + scalar - 1];
1549 temp = res ;
1550 res = NULL ;
1551 while (temp != NULL)
1552 { /* Then we will appy the general code generation process to each sub-list
1553 * of loops with the same scalar vector.
1555 end = temp ;
1556 ref = temp ;
1558 while((end->next != NULL) &&
1559 cloog_loop_more(end->next, level, scalar_new, nb_scattdims) &&
1560 cloog_loop_scalar_eq(ref,end->next,level,scaldims,nb_scattdims,scalar))
1561 end = end->next ;
1563 next = end->next ;
1564 end->next = NULL ;
1566 /* For the next dimension, scalar value is updated by adding the scalar
1567 * vector size, which is stored at scaldims[level+scalar-1].
1569 if (cloog_loop_more(temp, level, scalar_new, nb_scattdims)) {
1570 l = cloog_loop_generate_restricted(temp, level, scalar_new,
1571 scaldims, nb_scattdims, options);
1573 if (l != NULL)
1574 cloog_loop_add_list(&res, &now, l);
1575 } else
1576 cloog_loop_add(&res, &now, temp);
1578 temp = next ;
1581 return res ;
1585 /* Compare loop with the next loop based on their constant dimensions.
1586 * The result is < 0, == 0 or > 0 depending on whether the constant
1587 * dimensions of loop are lexicographically smaller, equal or greater
1588 * than those of loop->next.
1589 * If loop is the last in the list, then it is assumed to be smaller
1590 * than the "next" one.
1592 static int cloog_loop_next_scal_cmp(CloogLoop *loop)
1594 int i;
1595 int nb_scaldims;
1597 if (!loop->next)
1598 return -1;
1600 nb_scaldims = loop->block->nb_scaldims;
1601 if (loop->next->block->nb_scaldims < nb_scaldims)
1602 nb_scaldims = loop->next->block->nb_scaldims;
1604 for (i = 0; i < nb_scaldims; ++i) {
1605 int cmp = cloog_int_cmp(loop->block->scaldims[i],
1606 loop->next->block->scaldims[i]);
1607 if (cmp)
1608 return cmp;
1610 return loop->block->nb_scaldims - loop->next->block->nb_scaldims;
1614 /* Check whether the globally constant dimensions of a and b
1615 * have the same value for all globally constant dimensions
1616 * that are situated before any (locally) non-constant dimension.
1618 static int cloog_loop_equal_prefix(CloogLoop *a, CloogLoop *b,
1619 int *scaldims, int nb_scattdims)
1621 int i;
1622 int cst = 0;
1623 int dim = 0;
1625 for (i = 0; i < nb_scattdims; ++i) {
1626 if (!scaldims[i]) {
1627 dim++;
1628 continue;
1630 if (!cloog_int_eq(a->block->scaldims[cst], b->block->scaldims[cst]))
1631 break;
1632 cst++;
1634 for (i = i + 1; i < nb_scattdims; ++i) {
1635 if (scaldims[i])
1636 continue;
1637 if (!cloog_domain_lazy_isconstant(a->domain, dim))
1638 return 0;
1639 /* No need to check that dim is also constant in b and that the
1640 * constant values are equal. That will happen during the check
1641 * whether the two domains are equal.
1643 dim++;
1645 return 1;
1649 /* Try to block adjacent loops in the loop list "loop".
1650 * We only attempt blocking if the constant dimensions of the loops
1651 * in the least are (not necessarily strictly) increasing.
1652 * Then we look for a sublist such that the first (begin) has constant
1653 * dimensions strictly larger than the previous loop in the complete
1654 * list and such that the loop (end) after the last loop in the sublist
1655 * has constant dimensions strictly larger than the last loop in the sublist.
1656 * Furthermore, all loops in the sublist should have the same domain
1657 * (with globally constant dimensions removed) and the difference
1658 * (if any) in constant dimensions may only occur after all the
1659 * (locally) constant dimensions.
1660 * If we find such a sublist, then the blocks of all but the first
1661 * are merged into the block of the first.
1663 * Note that this function can only be called before the global
1664 * blocklist has been created because it may otherwise modify and destroy
1665 * elements on that list.
1667 CloogLoop *cloog_loop_block(CloogLoop *loop, int *scaldims, int nb_scattdims)
1669 CloogLoop *begin, *end, *l;
1670 int begin_after_previous;
1671 int end_after_previous;
1673 if (!loop->next)
1674 return loop;
1675 for (begin = loop; begin; begin = begin->next) {
1676 if (!begin->block || !begin->block->scaldims)
1677 return loop;
1678 if (cloog_loop_next_scal_cmp(loop) > 0)
1679 return loop;
1682 begin_after_previous = 1;
1683 for (begin = loop; begin; begin = begin->next) {
1684 if (!begin_after_previous) {
1685 begin_after_previous = cloog_loop_next_scal_cmp(begin) < 0;
1686 continue;
1689 end_after_previous = cloog_loop_next_scal_cmp(begin) < 0;
1690 for (end = begin->next; end; end = end->next) {
1691 if (!cloog_loop_equal_prefix(begin, end, scaldims, nb_scattdims))
1692 break;
1693 if (!cloog_domain_lazy_equal(begin->domain, end->domain))
1694 break;
1695 end_after_previous = cloog_loop_next_scal_cmp(end) < 0;
1697 if (end != begin->next && end_after_previous) {
1698 for (l = begin->next; l != end; l = begin->next) {
1699 cloog_block_merge(begin->block, l->block);
1700 begin->next = l->next;
1701 cloog_loop_free_parts(l, 1, 0, 1, 0);
1705 begin_after_previous = cloog_loop_next_scal_cmp(begin) < 0;
1708 return loop;
1713 * Check whether for any fixed iteration of the outer loops,
1714 * there is an iteration of loop1 that is lexicographically greater
1715 * than an iteration of loop2.
1716 * Return 1 if there exists (or may exist) such a pair.
1717 * Return 0 if all iterations of loop1 are lexicographically smaller
1718 * than the iterations of loop2.
1719 * If no iteration is lexicographically greater, but if there are
1720 * iterations that are equal to iterations of loop2, then return "def".
1721 * This is useful for ensuring that such statements are not reordered.
1722 * Some users, including the test_run target in test, expect
1723 * the statements at a given point to be run in the original order.
1724 * Passing the value "0" for "def" would allow such statements to be reordered
1725 * and would allow for the detection of more components.
1727 int cloog_loop_follows(CloogLoop *loop1, CloogLoop *loop2,
1728 int level, int scalar, int *scaldims, int nb_scattdims, int def)
1730 int dim1, dim2;
1732 dim1 = cloog_domain_dimension(loop1->domain);
1733 dim2 = cloog_domain_dimension(loop2->domain);
1734 while ((level <= dim1 && level <= dim2) ||
1735 level_is_constant(level, scalar, scaldims, nb_scattdims)) {
1736 if (level_is_constant(level, scalar, scaldims, nb_scattdims)) {
1737 int cmp = cloog_loop_constant_cmp(loop1, loop2, level, scaldims,
1738 nb_scattdims, scalar);
1739 if (cmp > 0)
1740 return 1;
1741 if (cmp < 0)
1742 return 0;
1743 scalar += scaldims[level + scalar - 1];
1744 } else {
1745 int follows = cloog_domain_follows(loop1->domain, loop2->domain,
1746 level);
1747 if (follows > 0)
1748 return 1;
1749 if (follows < 0)
1750 return 0;
1751 level++;
1755 return def;
1759 /* Structure for representing the nodes in the graph being traversed
1760 * using Tarjan's algorithm.
1761 * index represents the order in which nodes are visited.
1762 * min_index is the index of the root of a (sub)component.
1763 * on_stack indicates whether the node is currently on the stack.
1765 struct cloog_loop_sort_node {
1766 int index;
1767 int min_index;
1768 int on_stack;
1770 /* Structure for representing the graph being traversed
1771 * using Tarjan's algorithm.
1772 * len is the number of nodes
1773 * node is an array of nodes
1774 * stack contains the nodes on the path from the root to the current node
1775 * sp is the stack pointer
1776 * index is the index of the last node visited
1777 * order contains the elements of the components separated by -1
1778 * op represents the current position in order
1780 struct cloog_loop_sort {
1781 int len;
1782 struct cloog_loop_sort_node *node;
1783 int *stack;
1784 int sp;
1785 int index;
1786 int *order;
1787 int op;
1790 /* Allocate and initialize cloog_loop_sort structure.
1792 static struct cloog_loop_sort *cloog_loop_sort_alloc(int len)
1794 struct cloog_loop_sort *s;
1795 int i;
1797 s = (struct cloog_loop_sort *)malloc(sizeof(struct cloog_loop_sort));
1798 assert(s);
1799 s->len = len;
1800 s->node = (struct cloog_loop_sort_node *)
1801 malloc(len * sizeof(struct cloog_loop_sort_node));
1802 assert(s->node);
1803 for (i = 0; i < len; ++i)
1804 s->node[i].index = -1;
1805 s->stack = (int *)malloc(len * sizeof(int));
1806 assert(s->stack);
1807 s->order = (int *)malloc(2 * len * sizeof(int));
1808 assert(s->order);
1810 s->sp = 0;
1811 s->index = 0;
1812 s->op = 0;
1814 return s;
1817 /* Free cloog_loop_sort structure.
1819 static void cloog_loop_sort_free(struct cloog_loop_sort *s)
1821 free(s->node);
1822 free(s->stack);
1823 free(s->order);
1824 free(s);
1828 /* Check whether for any fixed iteration of the outer loops,
1829 * there is an iteration of loop1 that is lexicographically greater
1830 * than an iteration of loop2, where the iteration domains are
1831 * available in the inner loops of the arguments.
1833 * By using this functions to detect components, we ensure that
1834 * two CloogLoops appear in the same component if some iterations of
1835 * each loop should be executed before some iterations of the other loop.
1836 * Since we also want two CloogLoops that have exactly the same
1837 * iteration domain at the current level to be placed in the same component,
1838 * we first check if these domains are indeed the same.
1840 static int inner_loop_follows(CloogLoop *loop1, CloogLoop *loop2,
1841 int level, int scalar, int *scaldims, int nb_scattdims, int def)
1843 int f;
1845 f = cloog_domain_lazy_equal(loop1->domain, loop2->domain);
1846 if (!f)
1847 f = cloog_loop_follows(loop1->inner, loop2->inner,
1848 level, scalar, scaldims, nb_scattdims, def);
1850 return f;
1854 /* Perform Tarjan's algorithm for computing the strongly connected components
1855 * in the graph with the individual CloogLoops as vertices.
1856 * Two CloopLoops appear in the same component if they both (indirectly)
1857 * "follow" each other, where the following relation is determined
1858 * by the follows function.
1860 static void cloog_loop_components_tarjan(struct cloog_loop_sort *s,
1861 CloogLoop **loop_array, int i, int level, int scalar, int *scaldims,
1862 int nb_scattdims,
1863 int (*follows)(CloogLoop *loop1, CloogLoop *loop2,
1864 int level, int scalar, int *scaldims, int nb_scattdims, int def))
1866 int j;
1868 s->node[i].index = s->index;
1869 s->node[i].min_index = s->index;
1870 s->node[i].on_stack = 1;
1871 s->index++;
1872 s->stack[s->sp++] = i;
1874 for (j = s->len - 1; j >= 0; --j) {
1875 int f;
1877 if (j == i)
1878 continue;
1879 if (s->node[j].index >= 0 &&
1880 (!s->node[j].on_stack ||
1881 s->node[j].index > s->node[i].min_index))
1882 continue;
1884 f = follows(loop_array[i], loop_array[j],
1885 level, scalar, scaldims, nb_scattdims, i > j);
1886 if (!f)
1887 continue;
1889 if (s->node[j].index < 0) {
1890 cloog_loop_components_tarjan(s, loop_array, j, level, scalar,
1891 scaldims, nb_scattdims, follows);
1892 if (s->node[j].min_index < s->node[i].min_index)
1893 s->node[i].min_index = s->node[j].min_index;
1894 } else if (s->node[j].index < s->node[i].min_index)
1895 s->node[i].min_index = s->node[j].index;
1898 if (s->node[i].index != s->node[i].min_index)
1899 return;
1901 do {
1902 j = s->stack[--s->sp];
1903 s->node[j].on_stack = 0;
1904 s->order[s->op++] = j;
1905 } while (j != i);
1906 s->order[s->op++] = -1;
1910 static int qsort_index_cmp(const void *p1, const void *p2)
1912 return *(int *)p1 - *(int *)p2;
1915 /* Sort the elements of the component starting at list.
1916 * The list is terminated by a -1.
1918 static void sort_component(int *list)
1920 int len;
1922 for (len = 0; list[len] != -1; ++len)
1925 qsort(list, len, sizeof(int), qsort_index_cmp);
1928 /* Given an array of indices "list" into the "loop_array" array,
1929 * terminated by -1, construct a linked list of the corresponding
1930 * entries and put the result in *res.
1931 * The value returned is the number of CloogLoops in the (linked) list
1933 static int extract_component(CloogLoop **loop_array, int *list, CloogLoop **res)
1935 int i = 0;
1937 sort_component(list);
1938 while (list[i] != -1) {
1939 *res = loop_array[list[i]];
1940 res = &(*res)->next;
1941 ++i;
1943 *res = NULL;
1945 return i;
1950 * Call cloog_loop_generate_scalar or cloog_loop_generate_general
1951 * on each of the strongly connected components in the list of CloogLoops
1952 * pointed to by "loop".
1954 * We use Tarjan's algorithm to find the strongly connected components.
1955 * Note that this algorithm also topologically sorts the components.
1957 * The components are treated separately to avoid spurious separations.
1958 * The concatentation of the results may contain successive loops
1959 * with the same bounds, so we try to combine such loops.
1961 CloogLoop *cloog_loop_generate_components(CloogLoop *loop,
1962 int level, int scalar, int *scaldims, int nb_scattdims,
1963 CloogOptions *options)
1965 int i, nb_loops;
1966 CloogLoop *tmp;
1967 CloogLoop *res, **res_next;
1968 CloogLoop **loop_array;
1969 struct cloog_loop_sort *s;
1971 if (level == 0 || !loop->next)
1972 return cloog_loop_generate_general(loop, level, scalar,
1973 scaldims, nb_scattdims, options);
1975 nb_loops = cloog_loop_count(loop);
1977 loop_array = (CloogLoop **)malloc(nb_loops * sizeof(CloogLoop *));
1978 assert(loop_array);
1980 for (i = 0, tmp = loop; i < nb_loops; i++, tmp = tmp->next)
1981 loop_array[i] = tmp;
1983 s = cloog_loop_sort_alloc(nb_loops);
1984 for (i = nb_loops - 1; i >= 0; --i) {
1985 if (s->node[i].index >= 0)
1986 continue;
1987 cloog_loop_components_tarjan(s, loop_array, i, level, scalar, scaldims,
1988 nb_scattdims, &inner_loop_follows);
1991 i = 0;
1992 res = NULL;
1993 res_next = &res;
1994 while (nb_loops) {
1995 int n = extract_component(loop_array, &s->order[i], &tmp);
1996 i += n + 1;
1997 nb_loops -= n;
1998 *res_next = cloog_loop_generate_general(tmp, level, scalar,
1999 scaldims, nb_scattdims, options);
2000 while (*res_next)
2001 res_next = &(*res_next)->next;
2004 cloog_loop_sort_free(s);
2006 free(loop_array);
2008 res = cloog_loop_combine(res);
2010 return res;
2014 CloogLoop *cloog_loop_generate_restricted(CloogLoop *loop,
2015 int level, int scalar, int *scaldims, int nb_scattdims,
2016 CloogOptions *options)
2018 /* To save both time and memory, we switch here depending on whether the
2019 * current dimension is scalar (simplified processing) or not (general
2020 * processing).
2022 if (level_is_constant(level, scalar, scaldims, nb_scattdims))
2023 return cloog_loop_generate_scalar(loop, level, scalar,
2024 scaldims, nb_scattdims, options);
2026 * 2. Compute the projection of each polyhedron onto the outermost
2027 * loop variable and the parameters.
2029 loop = cloog_loop_project_all(loop, level);
2031 return cloog_loop_generate_components(loop, level, scalar, scaldims,
2032 nb_scattdims, options);
2036 CloogLoop *cloog_loop_generate_restricted_or_stop(CloogLoop *loop,
2037 CloogDomain *context,
2038 int level, int scalar, int *scaldims, int nb_scattdims,
2039 CloogOptions *options)
2041 /* If the user asked to stop code generation at this level, let's stop. */
2042 if ((options->stop >= 0) && (level+scalar >= options->stop+1))
2043 return cloog_loop_stop(loop,context) ;
2045 return cloog_loop_generate_restricted(loop, level, scalar, scaldims,
2046 nb_scattdims, options);
2051 * cloog_loop_generate function:
2052 * Adaptation from LoopGen 0.4 by F. Quillere. This function implements the
2053 * Quillere algorithm for polyhedron scanning from step 1 to 2.
2054 * (see the Quillere paper).
2055 * - loop is the loop for which we have to generate a scanning code,
2056 * - context is the context of the current loop (constraints on parameter and/or
2057 * on outer loop counters),
2058 * - level is the current non-scalar dimension,
2059 * - scalar is the current scalar dimension,
2060 * - scaldims is the boolean array saying whether a dimension is scalar or not,
2061 * - nb_scattdims is the size of the scaldims array,
2062 * - options are the general code generation options.
2064 * - October 26th 2001: first version.
2065 * - July 3rd->11th 2003: memory leaks hunt and correction.
2066 * - June 15th 2005: a memory leak fixed (loop was not entirely freed when
2067 * the result of cloog_loop_restrict was NULL).
2068 * - June 22nd 2005: Adaptation for GMP.
2069 * - September 2nd 2005: The function have been cutted out in two pieces:
2070 * cloog_loop_generate and this one, in order to handle
2071 * the scalar dimension case more efficiently with
2072 * cloog_loop_generate_scalar.
2073 * - November 15th 2005: (debug) Condition for stop option no more take care of
2074 * further scalar dimensions.
2076 CloogLoop *cloog_loop_generate(CloogLoop *loop, CloogDomain *context,
2077 int level, int scalar, int *scaldims, int nb_scattdims,
2078 CloogOptions *options)
2080 /* 1. Replace each polyhedron by its intersection with the context.
2082 loop = cloog_loop_restrict_all(loop, context);
2083 if (!loop)
2084 return NULL;
2086 return cloog_loop_generate_restricted_or_stop(loop, context,
2087 level, scalar, scaldims, nb_scattdims, options);
2092 * Internal function for simplifying a single loop in a list of loops.
2093 * See cloog_loop_simplify.
2095 static CloogLoop *loop_simplify(CloogLoop *loop, CloogDomain *context,
2096 int level)
2098 int domain_dim;
2099 CloogBlock * new_block ;
2100 CloogLoop *simplified, *inner;
2101 CloogDomain * domain, * simp, * inter, * extended_context ;
2103 if (!cloog_domain_isconvex(loop->domain))
2104 loop->domain = cloog_domain_simplify_union(loop->domain);
2106 domain = loop->domain ;
2108 domain_dim = cloog_domain_dimension(domain);
2109 extended_context = cloog_domain_extend(context, domain_dim);
2110 inter = cloog_domain_intersection(domain,extended_context) ;
2111 simp = cloog_domain_simplify(inter,extended_context) ;
2112 cloog_domain_free(extended_context) ;
2114 /* If the constraint system is never true, go to the next one. */
2115 if (cloog_domain_never_integral(simp)) {
2116 cloog_loop_free(loop->inner);
2117 cloog_domain_free(inter);
2118 cloog_domain_free(simp);
2119 return NULL;
2122 inner = cloog_loop_simplify(loop->inner, inter, level+1);
2123 cloog_domain_free(inter) ;
2125 if ((inner == NULL) && (loop->block == NULL)) {
2126 cloog_domain_free(simp);
2127 return NULL;
2130 new_block = cloog_block_copy(loop->block) ;
2132 simplified = cloog_loop_alloc(loop->state, simp, loop->stride, loop->offset,
2133 new_block, inner, NULL);
2135 return(simplified) ;
2140 * cloog_loop_simplify function:
2141 * This function implements the part 6. of the Quillere algorithm, it
2142 * recursively simplifies each loop in the context of the preceding loop domain.
2143 * It returns a pointer to the simplified loop list.
2144 * The cloog_domain_simplify (DomainSimplify) behaviour is really bad with
2145 * polyhedra union and some really awful sidesteppings were written, I plan
2146 * to solve that...
2147 * - October 31th 2001: first version.
2148 * - July 3rd->11th 2003: memory leaks hunt and correction.
2149 * - April 16th 2005: a memory leak fixed (extended_context was not freed).
2150 * - June 15th 2005: a memory leak fixed (loop was not conveniently freed
2151 * when the constraint system is never true).
2152 * - October 27th 2005: - this function called before cloog_loop_fast_simplify
2153 * is now the official cloog_loop_simplify function in
2154 * replacement of a slower and more complex one (after
2155 * deep changes in the pretty printer).
2156 * - we use cloog_loop_disjoint to fix the problem when
2157 * simplifying gives a union of polyhedra (before, it
2158 * was under the responsibility of the pretty printer).
2160 CloogLoop *cloog_loop_simplify(CloogLoop *loop, CloogDomain *context, int level)
2162 CloogLoop *now;
2163 CloogLoop *res = NULL;
2164 CloogLoop **next = &res;
2166 for (now = loop; now; now = now->next) {
2167 *next = loop_simplify(now, context, level);
2169 now->inner = NULL; /* For loop integrity. */
2170 cloog_domain_free(now->domain);
2171 now->domain = NULL;
2173 if (*next)
2174 next = &(*next)->next;
2176 cloog_loop_free(loop);
2178 /* Examples like test/iftest2.cloog give unions of polyhedra after
2179 * simplifying, thus we we have to disjoint them. Another good reason to
2180 * put the simplifying step in the Quillere backtrack.
2182 res = cloog_loop_disjoint(res);
2184 return res;
2189 * cloog_loop_scatter function:
2190 * This function add the scattering (scheduling) informations in a loop.
2192 void cloog_loop_scatter(CloogLoop * loop, CloogScattering *scatt)
2194 loop->domain = cloog_domain_scatter(loop->domain, scatt);