never use ->scaldims
[cloog-ppl.git] / source / program.c
blobbbcf08f397d51a08c4d845e879638120adbd3143
2 /**-------------------------------------------------------------------**
3 ** CLooG **
4 **-------------------------------------------------------------------**
5 ** program.c **
6 **-------------------------------------------------------------------**
7 ** First version: october 25th 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 !
40 # include <sys/types.h>
41 # include <sys/time.h>
42 # include <sys/resource.h>
43 #include <stdarg.h>
44 # include <stdlib.h>
45 # include <stdio.h>
46 # include <string.h>
47 # include <ctype.h>
48 # include <unistd.h>
49 # include "../include/cloog/cloog.h"
52 /******************************************************************************
53 * Memory leaks hunting *
54 ******************************************************************************/
57 /**
58 * These global variables are devoted to memory leaks hunting: we
59 * want to know at each moment how many Value variables have been allocated
60 * since in GMP mode they have to be freed (see domain.c for the declaration).
61 * - July 3rd->11th 2003: first version (memory leaks hunt and correction).
64 extern int cloog_value_allocated ;
65 extern int cloog_value_freed ;
66 extern int cloog_value_max ;
69 /******************************************************************************
70 * Structure display function *
71 ******************************************************************************/
74 /**
75 * cloog_program_print function:
76 * this function is a human-friendly way to display the CloogProgram data
77 * structure, it shows all the different fields and includes an indentation
78 * level (level) in order to work with others print_structure functions.
79 * - July 1st 2005: first version based on the old cloog_program_print function.
81 void cloog_program_print_structure(file, program, level)
82 FILE * file ;
83 CloogProgram * program ;
84 int level ;
85 { int i, j ;
87 /* Go to the right level. */
88 for (i=0; i<level; i++)
89 fprintf(file,"|\t") ;
91 fprintf(file,"+-- CloogProgram\n") ;
93 /* A blank line. */
94 for (i=0; i<=level+1; i++)
95 fprintf(file,"|\t") ;
96 fprintf(file,"\n") ;
98 /* Print the language. */
99 for (i=0; i<=level; i++)
100 fprintf(file,"|\t") ;
101 fprintf(file, "Language: %c\n",cloog_program_language (program)) ;
103 /* A blank line. */
104 for (i=0; i<=level+1; i++)
105 fprintf(file,"|\t") ;
106 fprintf(file,"\n") ;
108 /* Print the scattering dimension number. */
109 for (i=0; i<=level; i++)
110 fprintf(file,"|\t") ;
111 fprintf(file,"Scattering dimension number: %d\n",
112 cloog_program_nb_scattdims (program)) ;
114 /* A blank line. */
115 for (i=0; i<=level+1; i++)
116 fprintf(file,"|\t") ;
117 fprintf(file,"\n") ;
119 /* Print the scalar scattering dimension informations. */
120 for (i=0; i<=level; i++)
121 fprintf(file,"|\t") ;
122 if (cloog_program_scaldims (program))
124 fprintf (file,"Scalar dimensions:");
125 for (i = 0; i < cloog_program_nb_scattdims (program); i++)
126 fprintf (file," %d:%d ", i, cloog_program_scaldim (program, i));
127 fprintf (file,"\n");
129 else
130 fprintf (file, "No scalar scattering dimensions\n");
132 /* A blank line. */
133 for (i=0; i<=level+1; i++)
134 fprintf(file,"|\t") ;
135 fprintf(file,"\n") ;
137 /* Print the parameter and the iterator names. */
138 cloog_names_print_structure (file, cloog_program_names (program), level + 1);
140 /* A blank line. */
141 for (i=0; i<=level+1; i++)
142 fprintf(file,"|\t") ;
143 fprintf(file,"\n") ;
145 /* Print the context. */
146 cloog_domain_print_structure(file, cloog_program_context (program), level+1);
148 /* Print the loop. */
149 cloog_loop_print_structure (file,cloog_program_loop (program), level + 1);
151 /* One more time something that is here only for a better look. */
152 for (j=0; j<2; j++)
153 { for (i=0; i<=level; i++)
154 fprintf(file,"|\t") ;
156 fprintf(file,"\n") ;
162 * cloog_program_dump_cloog function:
163 * This function dumps a CloogProgram structure supposed to be completely
164 * filled in a CLooG input file (foo possibly stdout) such as CLooG can
165 * rebuild almost exactly the data structure from the input file (the number
166 * of scattering functions is lost since they are included inside the
167 * iteration domains, this can only lead to a less beautiful pretty printing).
168 * WARNING: this function do not respect CloogDomain as an object.
169 * - June 27th 2003: first version.
170 * - May 15th 2005: (debug) several patches by Kristof Beyls.
171 * - November 16th 2005: adaptation for CLooG 0.14.0 structures.
173 void cloog_program_dump_cloog(FILE * foo, CloogProgram * program)
174 { int i, j ;
175 Polyhedron * polyhedron ;
176 CloogLoop * loop ;
178 fprintf(foo,
179 "# CLooG -> CLooG\n"
180 "# This is an automatic dump of a CLooG input file from a CloogProgram data\n"
181 "# structure. WARNING: it is highly dangerous and MAY be correct ONLY if\n"
182 "# - it has been dumped before loop generation.\n"
183 "# - option -noscalars is used (it removes scalar dimensions otherwise)\n"
184 "# - option -l is at least the original scattering dimension number\n"
185 "# ASK THE AUTHOR IF YOU *NEED* SOMETHING MORE ROBUST\n") ;
187 /* Language. */
188 if (cloog_program_language (program) == 'c')
189 fprintf(foo,"# Language: C\n") ;
190 else
191 fprintf(foo,"# Language: FORTRAN\n") ;
192 fprintf(foo,"%c\n\n", cloog_program_language (program)) ;
194 /* Context. */
195 fprintf (foo,"# Context (%d parameter(s)):\n",
196 cloog_domain_dim (cloog_program_context (program)));
197 cloog_domain_print_structure (foo, cloog_program_context (program), 0);
198 fprintf(foo,"1 # Parameter name(s)\n") ;
199 for (i = 0; i < cloog_program_names (program)->nb_parameters; i++)
200 fprintf (foo, "%s ", cloog_program_names (program)->parameters[i]) ;
202 /* Statement number. */
203 i = 0 ;
204 loop = cloog_program_loop (program);
205 while (loop != NULL)
206 { i++ ;
207 loop = loop->next ;
209 fprintf(foo,"\n\n# Statement number:\n%d\n\n",i) ;
211 /* Iteration domains. */
212 i = 1 ;
213 loop = cloog_program_loop (program) ;
214 while (loop != NULL)
215 { /* Name of the domain. */
216 fprintf(foo,"# Iteration domain of statement %d.\n",i) ;
218 /* Number of polyhedron inside the union of disjoint polyhedra. */
219 j = 0 ;
220 polyhedron = cloog_domain_polyhedron(cloog_loop_domain (loop)) ;
221 while (polyhedron != NULL)
222 { j++ ;
223 polyhedron = polyhedron->next ;
225 fprintf(foo,"%d\n",j) ;
227 /* The polyhedra themselves. */
228 polyhedron = cloog_domain_polyhedron(cloog_loop_domain (loop)) ;
229 while (polyhedron != NULL) {
230 CloogMatrix * matrix ;
231 matrix = cloog_matrix_matrix(Polyhedron2Constraints(polyhedron));
232 cloog_matrix_print(foo,matrix) ;
233 cloog_matrix_free(matrix) ;
234 polyhedron = polyhedron->next ;
236 fprintf(foo,"0 0 0 # For future options.\n\n") ;
238 i++ ;
239 loop = loop->next ;
241 fprintf(foo,"\n1 # Iterator name(s)\n") ;
242 for (i = 0; i < cloog_program_names (program)->nb_scattering; i++)
243 fprintf (foo, "%s ", cloog_program_names (program)->scattering[i]);
244 for (i = 0; i < cloog_program_names (program)->nb_iterators; i++)
245 fprintf (foo, "%s ", cloog_program_names (program)->iterators[i]);
246 fprintf(foo,"\n\n") ;
248 /* Scattering functions (none since included inside domains). */
249 fprintf(foo,"# No scattering functions.\n0\n\n") ;
254 * cloog_program_print function:
255 * This function prints the content of a CloogProgram structure (program) into a
256 * file (file, possibly stdout).
257 * - July 1st 2005: Now this very old function (probably as old as CLooG) is
258 * only a frontend to cloog_program_print_structure, with a
259 * quite better human-readable representation.
261 void cloog_program_print(FILE * file, CloogProgram * program)
262 { cloog_program_print_structure(file,program,0) ;
266 static void print_comment(FILE *file, CloogOptions *options,
267 const char *fmt, ...)
269 va_list args;
271 va_start(args, fmt);
272 if (options->language == LANGUAGE_FORTRAN) {
273 fprintf(file, "! ");
274 vfprintf(file, fmt, args);
275 fprintf(file, "\n");
276 } else {
277 fprintf(file, "/* ");
278 vfprintf(file, fmt, args);
279 fprintf(file, " */\n");
284 * cloog_program_pprint function:
285 * This function prints the content of a CloogProgram structure (program) into a
286 * file (file, possibly stdout), in a C-like language.
287 * - June 22nd 2005: Adaptation for GMP.
289 void cloog_program_pprint(file, program, options)
290 FILE * file ;
291 CloogProgram * program ;
292 CloogOptions * options ;
293 { int i, j, nb_scattering, indentation=0 ;
294 CloogStatement * statement ;
295 CloogBlockList * blocklist ;
296 CloogBlock * block ;
297 struct clast_stmt *root;
299 if (cloog_program_language (program) == 'f')
300 options->language = LANGUAGE_FORTRAN ;
301 else
302 options->language = LANGUAGE_C ;
304 print_comment(file, options, "Generated from %s by %s in %.2fs.",
305 options->name, cloog_version(), options->time);
306 #ifdef CLOOG_MEMORY
307 print_comment(file, options, "CLooG asked for %d KBytes.", options->memory);
308 fprintf(stderr, "[CLooG]INFO: %.2fs and %dKB used for code generation.\n",
309 options->time,options->memory);
310 #endif
312 /* If the option "compilable" is set, we provide the whole stuff to generate
313 * a compilable code. This code just do nothing, but now the user can edit
314 * the source and set the statement macros and parameters values.
316 nb_scattering = cloog_program_nb_scattdims (program) ;
317 if (options->compilable && (cloog_program_language (program) == 'c'))
318 { /* The headers. */
319 fprintf(file,"/* DON'T FORGET TO USE -lm OPTION TO COMPILE. */\n\n") ;
320 fprintf(file,"/* Useful headers. */\n") ;
321 fprintf(file,"#include <stdio.h>\n") ;
322 fprintf(file,"#include <stdlib.h>\n") ;
323 fprintf(file,"#include <math.h>\n\n") ;
325 /* The value of parameters. */
326 fprintf(file,"/* Parameter value. */\n") ;
327 for (i = 1; i <= cloog_program_names (program)->nb_parameters; i++)
328 fprintf(file, "#define PARVAL%d %d\n", i, options->compilable);
330 /* The macros. */
331 fprintf(file,"/* Useful macros. */\n") ;
332 fprintf(file,"#define ceild(n,d) ceil(((double)(n))/((double)(d)))\n") ;
333 fprintf(file,"#define floord(n,d) floor(((double)(n))/((double)(d)))\n") ;
334 fprintf(file,"#define max(x,y) ((x) > (y)? (x) : (y)) \n") ;
335 fprintf(file,"#define min(x,y) ((x) < (y)? (x) : (y)) \n\n") ;
337 /* The statement macros. */
338 fprintf(file,"/* Statement macros (please set). */\n") ;
339 blocklist = cloog_program_blocklist (program) ;
340 while (blocklist != NULL)
341 { block = blocklist->block ;
342 statement = block->statement ;
343 while (statement != NULL)
344 { fprintf(file,"#define S%d(",statement->number) ;
345 if (block->depth > 0)
347 fprintf (file, "%s", cloog_program_names (program)->iterators[0]);
348 for(j=1;j<block->depth;j++)
349 fprintf (file, ",%s", cloog_program_names (program)->iterators[j]) ;
351 fprintf(file,") {total++;") ;
352 if (block->depth > 0)
353 { fprintf(file," printf(\"S%d \%%d",statement->number) ;
354 for(j=1;j<block->depth;j++)
355 fprintf(file," \%%d") ;
357 fprintf(file,"\\n\",%s", cloog_program_names (program)->iterators[0]) ;
358 for(j=1;j<block->depth;j++)
359 fprintf (file, ",%s", cloog_program_names (program)->iterators[j]) ;
360 fprintf(file,");") ;
362 fprintf(file,"}\n") ;
364 statement = statement->next ;
366 blocklist = blocklist->next ;
369 /* The iterator and parameter declaration. */
370 fprintf(file,"\nint main() {\n") ;
371 if ((cloog_program_names (program)->nb_scalars > 0) && (!options->csp))
372 { fprintf(file," /* Scalar dimension iterators. */\n") ;
373 fprintf (file," int %s", cloog_program_names (program)->scalars[0]);
374 for (i = 2; i <= cloog_program_names (program)->nb_scalars; i++)
375 fprintf (file, ", %s", cloog_program_names (program)->scalars[i-1]);
377 fprintf(file," ;\n") ;
379 if (cloog_program_names (program)->nb_scattering > 0)
380 { fprintf(file," /* Scattering iterators. */\n") ;
381 fprintf(file," int %s",cloog_program_names (program)->scattering[0]) ;
382 for(i=2;i<=cloog_program_names (program)->nb_scattering;i++)
383 fprintf(file,", %s",cloog_program_names (program)->scattering[i-1]) ;
385 fprintf(file," ;\n") ;
387 if (cloog_program_names (program)->nb_iterators > 0)
388 { fprintf(file," /* Original iterators. */\n") ;
389 fprintf(file," int %s",cloog_program_names (program)->iterators[0]) ;
390 for(i=2;i<=cloog_program_names (program)->nb_iterators;i++)
391 fprintf(file,", %s",cloog_program_names (program)->iterators[i-1]) ;
393 fprintf(file," ;\n") ;
395 if (cloog_program_names (program)->nb_parameters > 0)
396 { fprintf(file," /* Parameters. */\n") ;
397 fprintf(file, " int %s=PARVAL1",cloog_program_names (program)->parameters[0]);
398 for(i=2;i<=cloog_program_names (program)->nb_parameters;i++)
399 fprintf(file, ", %s=PARVAL%d", cloog_program_names (program)->parameters[i-1], i);
401 fprintf(file,";\n");
403 fprintf(file," int total=0;\n");
404 fprintf(file,"\n") ;
406 /* And we adapt the identation. */
407 indentation += 2 ;
410 root = cloog_clast_create(program, options);
411 pprint(file, root, indentation, options);
412 cloog_clast_free(root);
414 /* The end of the compilable code in case of 'compilable' option. */
415 if (options->compilable && (cloog_program_language (program) == 'c'))
416 { fprintf(file,"\n printf(\"Number of integral points: %%d.\\n\",total) ;") ;
417 fprintf(file,"\n return 0 ;\n}\n") ;
422 /******************************************************************************
423 * Memory deallocation function *
424 ******************************************************************************/
428 * cloog_program_free function:
429 * This function frees the allocated memory for a CloogProgram structure.
431 void cloog_program_free(CloogProgram * program)
432 { cloog_names_free(cloog_program_names (program)) ;
433 cloog_loop_free(cloog_program_loop (program)) ;
434 cloog_domain_free (cloog_program_context (program)) ;
435 cloog_block_list_free (cloog_program_blocklist (program)) ;
436 if (cloog_program_scaldims (program))
437 free (cloog_program_scaldims (program));
439 free(program) ;
443 /******************************************************************************
444 * Reading function *
445 ******************************************************************************/
449 * cloog_program_read function:
450 * This function read the informations to put in a CloogProgram structure from
451 * a file (file, possibly stdin). It returns a pointer to a CloogProgram
452 * structure containing the read informations.
453 * - October 25th 2001: first version.
454 * - September 9th 2002: - the big reading function is now split in several
455 * functions (one per read data structure).
456 * - adaptation to the new file format with naming.
458 CloogProgram * cloog_program_read(FILE * file, CloogOptions * options)
459 { int i, nb_statements, nb_parameters, nb_iterators, nb_scattering ;
460 char s[MAX_STRING], language, prefix[2]={'c','\0'},
461 ** scattering, ** iterators, ** parameters;
462 CloogLoop * current, * next ;
463 CloogBlockList * previous ;
464 CloogDomainList * scatteringl ;
465 CloogProgram * p ;
467 nb_scattering = 0 ;
468 scattering = NULL ;
470 /* Memory allocation for the CloogProgram structure. */
471 p = cloog_program_malloc() ;
473 /* First of all, we read the language to use. */
474 while (fgets(s,MAX_STRING,file) == 0) ;
475 while ((*s=='#'||*s=='\n') || (sscanf(s," %c",&language)<1))
476 fgets(s,MAX_STRING,file) ;
477 cloog_program_set_language (p, language);
479 /* We then read the context data. */
480 cloog_program_set_context (p, cloog_domain_read (file));
481 nb_parameters = cloog_domain_dim (cloog_program_context (p)) ;
483 /* First part of the CloogNames structure: reading of the parameter names. */
484 parameters=cloog_names_read_strings(file,nb_parameters,NULL,FIRST_PARAMETER) ;
486 /* We read the statement number. */
487 while (fgets(s,MAX_STRING,file) == 0) ;
488 while ((*s=='#'||*s=='\n') || (sscanf(s," %d",&nb_statements)<1))
489 fgets(s,MAX_STRING,file) ;
491 /* Statements and domains reading for each statement. */
492 if (nb_statements > 0)
493 { /* Reading of the first domain. */
494 cloog_program_set_loop (p, cloog_loop_read (file,0,nb_parameters));
495 cloog_program_set_blocklist (p, cloog_block_list_alloc (cloog_program_loop (p)->block));
496 previous = cloog_program_blocklist (p);
498 if (cloog_loop_domain (cloog_program_loop (p)) != NULL)
499 nb_iterators = cloog_domain_dim(cloog_loop_domain (cloog_program_loop (p))) - nb_parameters ;
500 else
501 nb_iterators = 0 ;
503 /* And the same for each next domain. */
504 current = cloog_program_loop (p) ;
505 for (i=2;i<=nb_statements;i++)
506 { next = cloog_loop_read(file,i-1,nb_parameters) ;
507 if (cloog_loop_domain (next) != NULL)
508 if (cloog_domain_dim(cloog_loop_domain (next)) - nb_parameters > nb_iterators)
509 nb_iterators = cloog_domain_dim (cloog_loop_domain (next)) - nb_parameters ;
511 previous->next = cloog_block_list_alloc(next->block) ;
512 previous = previous->next ;
514 current->next = next ;
515 current = current->next ;
518 /* Reading of the iterator names. */
519 iterators = cloog_names_read_strings(file,nb_iterators,NULL,FIRST_ITERATOR);
521 /* Reading and putting the scattering data in program structure. */
522 scatteringl = cloog_domain_list_read(file) ;
524 if (scatteringl != NULL)
526 if (cloog_domain_list_lazy_same(scatteringl))
527 fprintf(stderr, "[CLooG]WARNING: some scattering functions are "
528 "similar.\n") ;
530 cloog_program_set_nb_scattdims (p,
531 cloog_domain_dim (cloog_domain (scatteringl)) -
532 cloog_domain_dim (cloog_loop_domain (cloog_program_loop (p)))) ;
533 nb_scattering = cloog_program_nb_scattdims (p);
534 scattering = cloog_names_read_strings (file, cloog_program_nb_scattdims (p), prefix, -1);
536 /* The boolean array for scalar dimensions is created and set to 0. */
537 cloog_program_set_scaldims (p, (int *) malloc (cloog_program_nb_scattdims (p) * sizeof (int)));
538 if (cloog_program_scaldims (p) == NULL)
540 fprintf(stderr, "[CLooG]ERROR: memory overflow.\n") ;
541 exit(1) ;
543 for (i=0;i<cloog_program_nb_scattdims (p);i++)
544 cloog_program_set_scaldim (p, i, 0);
546 /* We try to find blocks in the input problem to reduce complexity. */
547 if (!options->noblocks)
548 cloog_program_block(p,scatteringl) ;
549 if (!options->noscalars)
550 cloog_program_extract_scalars(p,scatteringl) ;
552 cloog_program_scatter(p,scatteringl) ;
553 cloog_domain_list_free(scatteringl) ;
555 else
557 cloog_program_set_nb_scattdims (p, 0);
558 cloog_program_set_scaldims (p, NULL);
561 cloog_program_set_names
562 (p, cloog_names_alloc (0, nb_scattering, nb_iterators, nb_parameters,
563 NULL, scattering, iterators, parameters));
565 cloog_names_scalarize (cloog_program_names (p), cloog_program_nb_scattdims (p),
566 cloog_program_scaldims (p));
568 else
570 cloog_program_set_loop (p, NULL);
571 cloog_program_set_names (p, NULL);
572 cloog_program_set_blocklist (p, NULL);
573 cloog_program_set_scaldims (p, NULL);
576 return(p) ;
580 /******************************************************************************
581 * Processing functions *
582 ******************************************************************************/
586 * cloog_program_malloc function:
587 * This function allocates the memory space for a CloogProgram structure and
588 * sets its fields with default values. Then it returns a pointer to the
589 * allocated space.
590 * - November 21th 2005: first version.
592 CloogProgram * cloog_program_malloc()
593 { CloogProgram * program ;
595 /* Memory allocation for the CloogProgram structure. */
596 program = (CloogProgram *)malloc(sizeof(CloogProgram)) ;
597 if (program == NULL)
598 { fprintf(stderr, "[CLooG]ERROR: memory overflow.\n") ;
599 exit(1) ;
602 /* We set the various fields with default values. */
603 cloog_program_set_language (program, 'c');
604 cloog_program_set_nb_scattdims (program, 0);
605 cloog_program_set_context (program, NULL);
606 cloog_program_set_loop (program, NULL);
607 cloog_program_set_names (program, NULL);
608 cloog_program_set_blocklist (program, NULL);
609 cloog_program_set_scaldims (program, NULL);
610 program->usr = NULL;
612 return program ;
617 * cloog_program_generate function:
618 * This function calls the Quillere algorithm for loop scanning. (see the
619 * Quillere paper) and calls the loop simplification function.
620 * - depth is the loop depth we want to optimize (guard free as possible),
621 * the first loop depth is 1 and anegative value is the infinity depth.
622 * - sep_level is the level number where we want to start loop separation.
624 * - October 26th 2001: first version.
625 * - April 19th 2005: some basic fixes and memory usage feature.
626 * - April 29th 2005: (bug fix, bug found by DaeGon Kim) see case 2 below.
628 CloogProgram * cloog_program_generate(program, options)
629 CloogProgram * program ;
630 CloogOptions * options ;
631 { float time ;
632 struct rusage start, end ;
633 CloogLoop * loop ;
634 #ifdef CLOOG_MEMORY
635 char status_path[MAX_STRING_VAL] ;
636 FILE * status ;
638 /* We initialize the memory need to 0. */
639 options->memory = 0 ;
640 #endif
642 if (options->override)
643 { fprintf(stderr,
644 "[CLooG]WARNING: you are using -override option, be aware that the "
645 "generated\n code may be incorrect.\n") ;
647 else
648 { /* Playing with options may be dangerous, here are two possible issues :
649 * 1. Using -l option less than scattering dimension number may lead to
650 * an illegal target code (since the scattering is not respected), if
651 * it is the case, we set -l depth to the first acceptable value.
653 if ((cloog_program_nb_scattdims (program) > options->l) && (options->l >= 0))
654 { fprintf(stderr,
655 "[CLooG]WARNING: -l depth is less than the scattering dimension number "
656 "(the \n generated code may be incorrect), it has been "
657 "automaticaly set\n to this value (use option -override "
658 "to override).\n") ;
659 options->l = cloog_program_nb_scattdims (program);
662 /* 2. Using -f option greater than one while -l depth is greater than the
663 * scattering dimension number may lead to iteration duplication (try
664 * test/daegon_lu_osp.cloog with '-f 3' to test) because of the step 4b
665 * of the cloog_loop_generate function, if it is the case, we set -l to
666 * the first acceptable value.
668 if (((options->f > 1) || (options->f < 0)) &&
669 ((options->l > cloog_program_nb_scattdims (program)) || (options->l < 0)))
670 { fprintf(stderr,
671 "[CLooG]WARNING: -f depth is more than one, -l depth has been "
672 "automaticaly set\n to the scattering dimension number "
673 "(target code may have\n duplicated iterations), -l depth "
674 "has been automaticaly set to\n this value (use option "
675 "-override to override).\n") ;
676 options->l = cloog_program_nb_scattdims (program);
680 getrusage(RUSAGE_SELF, &start) ;
681 if (cloog_program_loop (program))
683 loop = cloog_program_loop (program) ;
685 /* Here we go ! */
686 loop = cloog_loop_generate(loop, cloog_program_context (program), 1, 0,
687 cloog_program_scaldims (program),
688 cloog_program_nb_scattdims (program),
689 cloog_domain_dim (cloog_program_context (program)),
690 options);
692 #ifdef CLOOG_MEMORY
693 /* We read into the status file of the process how many memory it uses. */
694 sprintf(status_path,"/proc/%d/status",getpid()) ;
695 status = fopen(status_path, "r") ;
696 while (fscanf(status,"%s",status_path) && strcmp(status_path,"VmData:")!=0);
697 fscanf(status,"%d",&(options->memory)) ;
698 fclose(status) ;
699 #endif
701 if ((!options->nosimplify) && cloog_program_loop (program))
702 loop = cloog_loop_simplify(loop, cloog_program_context (program), 1,
703 cloog_domain_dim (cloog_program_context (program))) ;
705 cloog_program_set_loop (program, loop);
708 getrusage(RUSAGE_SELF, &end) ;
709 /* We calculate the time spent in code generation. */
710 time = (end.ru_utime.tv_usec - start.ru_utime.tv_usec)/(float)(MEGA) ;
711 time += (float)(end.ru_utime.tv_sec - start.ru_utime.tv_sec) ;
712 options->time = time ;
714 return program ;
719 * cloog_program_block function:
720 * this function gives a last chance to the lazy user to consider statement
721 * blocks instead of some statement lists where the whole list may be
722 * considered as a single statement from a code generation point of view.
723 * For instance two statements with the same iteration domain and the same
724 * scattering functions may be considered as a block. This function is lazy
725 * and can only find very simple forms of trivial blocks (see
726 * cloog_domain_lazy_block function for more details). The useless loops and
727 * scattering functions are removed and freed while the statement list of
728 * according blocks are filled.
729 * - program is the whole program structure (befaore applying scattering),
730 * - scattering is the list of scattering functions.
732 * - April 30th 2005: first attempt.
733 * - June 10-11th 2005: first working version.
735 void cloog_program_block(CloogProgram * program, CloogDomainList * scattering)
736 { int blocked_reference=0, blocked=0, nb_blocked=0 ;
737 CloogLoop * reference, * start, * loop ;
738 CloogDomainList * scatt_reference, * scatt_loop, * scatt_start ;
739 CloogBlockList * previous ;
741 if ((cloog_program_loop (program) == NULL) || (cloog_program_loop (program)->next == NULL))
742 return ;
744 /* We will have to rebuild the block list. */
745 cloog_block_list_free (cloog_program_blocklist (program)) ;
746 cloog_program_set_blocklist (program, cloog_block_list_alloc (cloog_program_loop (program)->block));
747 previous = cloog_program_blocklist (program);
749 /* The process will use three variables for the linked list :
750 * - 'start' is the starting point of a new block,
751 * - 'reference' is the node of the block used for the block checking,
752 * - 'loop' is the candidate to be inserted inside the block.
753 * At the beginning of the process, the linked lists are as follow:
754 * O------>O------>O------>O------>NULL
755 * | |
756 * start loop
757 * reference
760 reference = cloog_program_loop (program) ;
761 start = cloog_program_loop (program) ;
762 loop = reference->next ;
763 scatt_reference = scattering ;
764 scatt_start = scattering ;
765 scatt_loop = scattering->next ;
767 while (loop != NULL)
769 if (cloog_domain_lazy_equal (cloog_loop_domain (reference),
770 cloog_loop_domain (loop)) &&
771 cloog_domain_lazy_block(cloog_domain (scatt_reference),
772 cloog_domain (scatt_loop),
773 scattering, cloog_program_nb_scattdims (program)))
774 { /* If we find a block we update the links:
775 * +---------------+
776 * | v
777 * O O------>O------>O------>NULL
778 * | |
779 * start loop
780 * reference
782 blocked = 1 ;
783 nb_blocked ++ ;
784 cloog_block_merge(start->block,loop->block); /* merge frees loop->block */
785 loop->block = NULL ;
786 start->next = loop->next ;
787 scatt_start->next = scatt_loop->next ;
789 else
790 { /* If we didn't find a block, the next start of a block is updated:
791 * O------>O------>O------>O------>NULL
792 * | |
793 * reference start
794 * loop
796 blocked= 0 ;
797 start = loop ;
798 scatt_start = scatt_loop ;
800 /* We update the block list. */
801 previous->next = cloog_block_list_alloc(start->block) ;
802 previous = previous->next ;
805 /* If the reference node has been included into a block, we can free it. */
806 if (blocked_reference)
807 { reference->next = NULL ;
808 cloog_loop_free (reference) ;
809 cloog_domain_free (cloog_domain (scatt_reference)) ;
810 free (scatt_reference) ;
813 /* The reference and the loop are now updated for the next try, the
814 * starting position depends on the previous step.
815 * O ? O------>O------>O------>NULL
816 * | |
817 * reference loop
819 reference = loop ;
820 loop = loop->next ;
821 scatt_reference = scatt_loop ;
822 scatt_loop = scatt_loop->next ;
824 /* We mark the new reference as being blocked or not, if will be freed
825 * during the next while loop execution.
827 if (blocked)
828 blocked_reference = 1 ;
829 else
830 blocked_reference = 0 ;
833 /* We free the last blocked reference if any (since in the while loop it was
834 * freed during the next loop execution, it was not possible to free the
835 * last one inside).
837 if (blocked_reference)
838 { reference->next = NULL ;
839 cloog_loop_free (reference) ;
840 cloog_domain_free (cloog_domain (scatt_reference)) ;
841 free (scatt_reference) ;
844 if (nb_blocked != 0)
845 fprintf(stderr, "[CLooG]INFO: %d domains have been blocked.\n",nb_blocked) ;
850 * cloog_program_extract_scalars function:
851 * this functions finds and removes the dimensions of the scattering functions
852 * when they are scalar (i.e. of the shape "dim + scalar = 0") for all
853 * scattering functions. The reason is that the processing of such dimensions
854 * is trivial and do not need neither a row and a column in the matrix
855 * representation of the domain (this will save memory) neither the full
856 * Quillere processing (this will save time). The scalar dimensions data are
857 * dispatched in the CloogProgram structure (the boolean vector scaldims will
858 * say which original dimensions are scalar or not) and to the CloogBlock
859 * structures (each one has a scaldims vector that contains the scalar values).
860 * - June 14th 2005: first developments.
861 * - June 30th 2005: first version.
863 void cloog_program_extract_scalars(program, scattering)
864 CloogProgram * program ;
865 CloogDomainList * scattering ;
866 { int i, j, scalar, current, nb_scaldims=0 ;
867 CloogDomainList * start ;
868 CloogDomain * old ;
869 CloogBlockList * blocklist ;
870 CloogBlock * block ;
872 start = scattering ;
874 for (i = 0; i < cloog_program_nb_scattdims (program); i++)
875 { scalar = 1 ;
876 scattering = start ;
877 while (scattering != NULL)
879 if (!cloog_domain_lazy_isscalar (cloog_domain (scattering),i))
881 scalar = 0 ;
882 break ;
884 scattering = scattering->next ;
887 if (scalar)
889 nb_scaldims ++ ;
890 cloog_program_set_scaldim (program, i, 1);
894 /* If there are no scalar dimensions, we can continue directly. */
895 if (!nb_scaldims)
896 return ;
898 /* Otherwise, in each block, we have to put the number of scalar dimensions,
899 * and to allocate the memory for the scalar values.
901 blocklist = cloog_program_blocklist (program);
902 while (blocklist != NULL)
903 { block = blocklist->block ;
904 block->nb_scaldims = nb_scaldims ;
905 block->scaldims = (Value *)malloc(nb_scaldims*sizeof(Value)) ;
906 for (i=0;i<nb_scaldims;i++)
907 value_init_c(block->scaldims[i]) ;
909 blocklist = blocklist->next ;
912 /* Then we have to fill these scalar values, so we can erase those dimensions
913 * from the scattering functions. It's easier to begin with the last one,
914 * since there would be an offset otherwise (if we remove the i^th dimension,
915 * then the next one is not the (i+1)^th but still the i^th...).
917 current = nb_scaldims - 1 ;
918 for (i = cloog_program_nb_scattdims (program) - 1; i >= 0; i--)
919 if (cloog_program_scaldim (program, i))
921 blocklist = cloog_program_blocklist (program);
922 scattering = start;
924 while (blocklist != NULL)
926 block = blocklist->block ;
927 cloog_domain_scalar (cloog_domain (scattering), i, &block->scaldims[current]) ;
928 blocklist = blocklist->next ;
929 scattering = scattering->next ;
932 scattering = start ;
933 while (scattering != NULL)
935 old = cloog_domain (scattering) ;
936 cloog_set_domain (scattering, cloog_domain_erase_dimension (old, i)) ;
937 cloog_domain_free (old) ;
938 scattering = scattering->next ;
940 current-- ;
943 /* We postprocess the scaldims array in such a way that each entry is how
944 * many scalar dimensions follows + 1 (the current one). This will make
945 * some other processing easier (e.g. knowledge of some offsets).
947 for (i = 0; i < cloog_program_nb_scattdims (program) - 1; i++)
949 if (cloog_program_scaldim (program, i))
951 j = i + 1 ;
952 while ((j < cloog_program_nb_scattdims (program))
953 && cloog_program_scaldim (program, j))
955 cloog_program_set_scaldim (program, i,
956 cloog_program_scaldim (program, i) + 1);
957 j ++ ;
962 if (nb_scaldims != 0)
963 fprintf(stderr, "[CLooG]INFO: %d dimensions (over %d) are scalar.\n",
964 nb_scaldims, cloog_program_nb_scattdims (program)) ;
969 * cloog_program_scatter function:
970 * This function adds the scattering (scheduling) informations in a program.
971 * If names is NULL, this function create names itself such that the i^th
972 * name is ci.
973 * - November 6th 2001: first version.
975 void cloog_program_scatter(program, scattering)
976 CloogProgram * program ;
977 CloogDomainList * scattering ;
978 { int scattering_dim, scattering_dim2, not_enough_constraints=0 ;
979 CloogLoop * loop ;
981 if ((program != NULL) && (scattering != NULL))
983 loop = cloog_program_loop (program) ;
985 /* We compute the scattering dimension and check it is >=0. */
986 scattering_dim =
987 cloog_domain_dim (cloog_domain (scattering)) -
988 cloog_domain_dim (cloog_loop_domain (loop)) ;
989 if (scattering_dim < 0)
990 { fprintf(stderr, "[CLooG]ERROR: scattering has not enough dimensions.\n") ;
991 exit(1) ;
993 if (scattering_dim >= cloog_domain_nbconstraints (cloog_domain (scattering)))
994 not_enough_constraints ++ ;
996 /* The scattering dimension may have been modified by scalar extraction. */
997 scattering_dim =
998 cloog_domain_dim (cloog_domain (scattering)) -
999 cloog_domain_dim (cloog_loop_domain (loop));
1001 /* Finally we scatter all loops. */
1002 cloog_loop_scatter(loop, cloog_domain (scattering)) ;
1003 loop = loop->next ;
1004 scattering = scattering->next ;
1006 while ((loop != NULL) && (scattering != NULL))
1008 scattering_dim2 =
1009 cloog_domain_dim (cloog_domain (scattering)) -
1010 cloog_domain_dim (cloog_loop_domain (loop)) ;
1011 if (scattering_dim2 != scattering_dim)
1012 { fprintf(stderr, "[CLooG]ERROR: "
1013 "scattering dimensions are not the same.\n") ;
1014 exit(1) ;
1016 if (scattering_dim2 >= cloog_domain_nbconstraints(cloog_domain (scattering)))
1017 not_enough_constraints ++ ;
1019 cloog_loop_scatter(loop,cloog_domain (scattering)) ;
1020 loop = loop->next ;
1021 scattering = scattering->next ;
1023 if ((loop != NULL) || (scattering != NULL))
1024 fprintf(stderr, "[CLooG]WARNING: "
1025 "there is not a scattering for each statement.\n");
1027 if (not_enough_constraints)
1028 fprintf(stderr, "[CLooG]WARNING: not enough constraints for "
1029 "%d scattering function(s).\n",not_enough_constraints) ;