dump ScatteringList in cloog_program_dump_cloog
[cloog/uuh.git] / source / program.c
blobdc289ece968d1f1d6190677c68a01f949893de3d
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 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 !
41 # include <sys/types.h>
42 # include <sys/time.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"
50 #ifdef CLOOG_RUSAGE
51 # include <sys/resource.h>
52 #endif
55 /******************************************************************************
56 * Structure display function *
57 ******************************************************************************/
60 /**
61 * cloog_program_print function:
62 * this function is a human-friendly way to display the CloogProgram data
63 * structure, it shows all the different fields and includes an indentation
64 * level (level) in order to work with others print_structure functions.
65 * - July 1st 2005: first version based on the old cloog_program_print function.
67 void cloog_program_print_structure(file, program, level)
68 FILE * file ;
69 CloogProgram * program ;
70 int level ;
71 { int i, j ;
73 /* Go to the right level. */
74 for (i=0; i<level; i++)
75 fprintf(file,"|\t") ;
77 fprintf(file,"+-- CloogProgram\n") ;
79 /* A blank line. */
80 for (i=0; i<=level+1; i++)
81 fprintf(file,"|\t") ;
82 fprintf(file,"\n") ;
84 /* Print the language. */
85 for (i=0; i<=level; i++)
86 fprintf(file,"|\t") ;
87 fprintf(file, "Language: %c\n",program->language) ;
89 /* A blank line. */
90 for (i=0; i<=level+1; i++)
91 fprintf(file,"|\t") ;
92 fprintf(file,"\n") ;
94 /* Print the scattering dimension number. */
95 for (i=0; i<=level; i++)
96 fprintf(file,"|\t") ;
97 fprintf(file,"Scattering dimension number: %d\n",program->nb_scattdims) ;
99 /* A blank line. */
100 for (i=0; i<=level+1; i++)
101 fprintf(file,"|\t") ;
102 fprintf(file,"\n") ;
104 /* Print the scalar scattering dimension informations. */
105 for (i=0; i<=level; i++)
106 fprintf(file,"|\t") ;
107 if (program->scaldims != NULL)
108 { fprintf(file,"Scalar dimensions:") ;
109 for (i=0;i<program->nb_scattdims;i++)
110 fprintf(file," %d:%d ",i,program->scaldims[i]) ;
111 fprintf(file,"\n") ;
113 else
114 fprintf(file,"No scalar scattering dimensions\n") ;
116 /* A blank line. */
117 for (i=0; i<=level+1; i++)
118 fprintf(file,"|\t") ;
119 fprintf(file,"\n") ;
121 /* Print the parameter and the iterator names. */
122 cloog_names_print_structure(file,program->names,level+1) ;
124 /* A blank line. */
125 for (i=0; i<=level+1; i++)
126 fprintf(file,"|\t") ;
127 fprintf(file,"\n") ;
129 /* Print the context. */
130 cloog_domain_print_structure(file, program->context, level+1, "Context");
132 /* Print the loop. */
133 cloog_loop_print_structure(file,program->loop,level+1) ;
135 /* One more time something that is here only for a better look. */
136 for (j=0; j<2; j++)
137 { for (i=0; i<=level; i++)
138 fprintf(file,"|\t") ;
140 fprintf(file,"\n") ;
146 * cloog_program_dump_cloog function:
147 * This function dumps a CloogProgram structure supposed to be completely
148 * filled in a CLooG input file (foo possibly stdout) such as CLooG can
149 * rebuild almost exactly the data structure from the input file.
151 * If the scattering is already applied, the scattering parameter is supposed to
152 * be NULL. In this case the number of scattering functions is lost, since they
153 * are included inside the iteration domains. This can only lead to a less
154 * beautiful pretty printing.
156 * In case the scattering is not yet applied it can be passed to this function
157 * and will be included in the CLooG input file dump.
159 void cloog_program_dump_cloog(FILE * foo, CloogProgram * program,
160 CloogScatteringList *scattering)
162 int i;
163 CloogLoop * loop ;
164 CloogScatteringList *tmp_scatt;
166 fprintf(foo,
167 "# CLooG -> CLooG\n"
168 "# This is an automatic dump of a CLooG input file from a CloogProgram data\n"
169 "# structure. WARNING: it is highly dangerous and MAY be correct ONLY if\n"
170 "# - it has been dumped before loop generation.\n"
171 "# - option -noscalars is used (it removes scalar dimensions otherwise)\n"
172 "# - option -l is at least the original scattering dimension number\n"
173 "# ASK THE AUTHOR IF YOU *NEED* SOMETHING MORE ROBUST\n") ;
175 /* Language. */
176 if (program->language == 'c')
177 fprintf(foo,"# Language: C\n") ;
178 else
179 fprintf(foo,"# Language: FORTRAN\n") ;
180 fprintf(foo,"%c\n\n",program->language) ;
182 /* Context. */
183 fprintf(foo, "# Context (%d parameter(s)):\n", program->names->nb_parameters);
184 cloog_domain_print_constraints(foo, program->context, 0);
185 fprintf(foo,"1 # Parameter name(s)\n") ;
186 for (i=0;i<program->names->nb_parameters;i++)
187 fprintf(foo,"%s ",program->names->parameters[i]) ;
189 /* Statement number. */
190 i = 0 ;
191 loop = program->loop ;
192 while (loop != NULL)
193 { i++ ;
194 loop = loop->next ;
196 fprintf(foo,"\n\n# Statement number:\n%d\n\n",i) ;
198 /* Iteration domains. */
199 i = 1 ;
200 loop = program->loop ;
201 while (loop != NULL)
202 { /* Name of the domain. */
203 fprintf(foo,"# Iteration domain of statement %d.\n",i) ;
205 cloog_domain_print_constraints(foo, loop->domain, 1);
206 fprintf(foo,"0 0 0 # For future options.\n\n") ;
208 i++ ;
209 loop = loop->next ;
211 fprintf(foo,"\n1 # Iterator name(s)\n") ;
213 /* Scattering already applied? In this case print the scattering names as
214 * additional iterator names. */
215 if (!scattering)
216 for (i = 0; i < program->names->nb_scattering; i++)
217 fprintf(foo, "%s ", program->names->scattering[i]);
218 for (i=0;i<program->names->nb_iterators;i++)
219 fprintf(foo,"%s ",program->names->iterators[i]);
220 fprintf(foo,"\n\n") ;
222 /* Exit, if scattering is already applied. */
223 if (!scattering) {
224 fprintf(foo, "# No scattering functions.\n0\n\n");
225 return;
228 /* Scattering relations. */
229 fprintf(foo, "# --------------------- SCATTERING --------------------\n");
231 i = 0;
232 for (tmp_scatt = scattering; tmp_scatt; tmp_scatt = tmp_scatt->next)
233 i++;
235 fprintf(foo, "%d # Scattering functions", i);
237 for (tmp_scatt = scattering; tmp_scatt; tmp_scatt = tmp_scatt->next)
238 cloog_scattering_print_constraints(foo, tmp_scatt->scatt, 1);
240 fprintf(foo, "\n1 # Scattering dimension name(s)\n");
242 for (i = 0; i < program->names->nb_scattering; i++)
243 fprintf(foo, "%s ", program->names->scattering[i]);
248 * cloog_program_print function:
249 * This function prints the content of a CloogProgram structure (program) into a
250 * file (file, possibly stdout).
251 * - July 1st 2005: Now this very old function (probably as old as CLooG) is
252 * only a frontend to cloog_program_print_structure, with a
253 * quite better human-readable representation.
255 void cloog_program_print(FILE * file, CloogProgram * program)
256 { cloog_program_print_structure(file,program,0) ;
260 static void print_comment(FILE *file, CloogOptions *options,
261 const char *fmt, ...)
263 va_list args;
265 va_start(args, fmt);
266 if (options->language == LANGUAGE_FORTRAN) {
267 fprintf(file, "! ");
268 vfprintf(file, fmt, args);
269 fprintf(file, "\n");
270 } else {
271 fprintf(file, "/* ");
272 vfprintf(file, fmt, args);
273 fprintf(file, " */\n");
277 static void print_macros(FILE *file)
279 fprintf(file, "/* Useful macros. */\n") ;
280 fprintf(file,
281 "#define floord(n,d) (((n)<0) ? -((-(n)+(d)-1)/(d)) : (n)/(d))\n");
282 fprintf(file,
283 "#define ceild(n,d) (((n)<0) ? -((-(n))/(d)) : ((n)+(d)-1)/(d))\n");
284 fprintf(file, "#define max(x,y) ((x) > (y) ? (x) : (y))\n") ;
285 fprintf(file, "#define min(x,y) ((x) < (y) ? (x) : (y))\n\n") ;
288 static void print_declarations(FILE *file, int n, char **names)
290 int i;
292 fprintf(file, " int %s", names[0]);
293 for (i = 1; i < n; i++)
294 fprintf(file, ", %s", names[i]);
296 fprintf(file, ";\n");
299 static void print_iterator_declarations(FILE *file, CloogProgram *program,
300 CloogOptions *options)
302 CloogNames *names = program->names;
304 if (names->nb_scattering) {
305 fprintf(file, " /* Scattering iterators. */\n");
306 print_declarations(file, names->nb_scattering, names->scattering);
308 if (names->nb_iterators) {
309 fprintf(file, " /* Original iterators. */\n");
310 print_declarations(file, names->nb_iterators, names->iterators);
314 static void print_callable_preamble(FILE *file, CloogProgram *program,
315 CloogOptions *options)
317 int j;
318 CloogBlockList *blocklist;
319 CloogBlock *block;
320 CloogStatement *statement;
322 fprintf(file, "extern void hash(int);\n\n");
324 print_macros(file);
326 for (blocklist = program->blocklist; blocklist; blocklist = blocklist->next) {
327 block = blocklist->block;
328 for (statement = block->statement; statement; statement = statement->next) {
329 fprintf(file, "#define S%d(", statement->number);
330 if (block->depth > 0) {
331 fprintf(file, "%s", program->names->iterators[0]);
332 for(j = 1; j < block->depth; j++)
333 fprintf(file, ",%s", program->names->iterators[j]);
335 fprintf(file,") { hash(%d);", statement->number);
336 for(j = 0; j < block->depth; j++)
337 fprintf(file, " hash(%s);", program->names->iterators[j]);
338 fprintf(file, " }\n");
341 fprintf(file, "\nvoid test(");
342 if (program->names->nb_parameters > 0) {
343 fprintf(file, "int %s", program->names->parameters[0]);
344 for(j = 1; j < program->names->nb_parameters; j++)
345 fprintf(file, ", int %s", program->names->parameters[j]);
347 fprintf(file, ")\n{\n");
348 print_iterator_declarations(file, program, options);
351 static void print_callable_postamble(FILE *file, CloogProgram *program)
353 fprintf(file, "}\n");
357 * cloog_program_pprint function:
358 * This function prints the content of a CloogProgram structure (program) into a
359 * file (file, possibly stdout), in a C-like language.
360 * - June 22nd 2005: Adaptation for GMP.
362 void cloog_program_pprint(file, program, options)
363 FILE * file ;
364 CloogProgram * program ;
365 CloogOptions * options ;
366 { int i, j, nb_scattering, indentation=0 ;
367 CloogStatement * statement ;
368 CloogBlockList * blocklist ;
369 CloogBlock * block ;
370 struct clast_stmt *root;
372 if (program->language == 'f')
373 options->language = LANGUAGE_FORTRAN ;
374 else
375 options->language = LANGUAGE_C ;
377 #ifdef CLOOG_RUSAGE
378 print_comment(file, options, "Generated from %s by %s in %.2fs.",
379 options->name, cloog_version(), options->time);
380 #else
381 print_comment(file, options, "Generated from %s by %s.",
382 options->name, cloog_version());
383 #endif
384 #ifdef CLOOG_MEMORY
385 print_comment(file, options, "CLooG asked for %d KBytes.", options->memory);
386 cloog_msg(CLOOG_INFO, "%.2fs and %dKB used for code generation.\n",
387 options->time,options->memory);
388 #endif
390 /* If the option "compilable" is set, we provide the whole stuff to generate
391 * a compilable code. This code just do nothing, but now the user can edit
392 * the source and set the statement macros and parameters values.
394 nb_scattering = program->nb_scattdims ;
395 if (options->compilable && (program->language == 'c'))
396 { /* The headers. */
397 fprintf(file,"/* DON'T FORGET TO USE -lm OPTION TO COMPILE. */\n\n") ;
398 fprintf(file,"/* Useful headers. */\n") ;
399 fprintf(file,"#include <stdio.h>\n") ;
400 fprintf(file,"#include <stdlib.h>\n") ;
401 fprintf(file,"#include <math.h>\n\n") ;
403 /* The value of parameters. */
404 fprintf(file,"/* Parameter value. */\n") ;
405 for (i = 1; i <= program->names->nb_parameters; i++)
406 fprintf(file, "#define PARVAL%d %d\n", i, options->compilable);
408 /* The macros. */
409 print_macros(file);
411 /* The statement macros. */
412 fprintf(file,"/* Statement macros (please set). */\n") ;
413 blocklist = program->blocklist ;
414 while (blocklist != NULL)
415 { block = blocklist->block ;
416 statement = block->statement ;
417 while (statement != NULL)
418 { fprintf(file,"#define S%d(",statement->number) ;
419 if (block->depth > 0)
420 { fprintf(file,"%s",program->names->iterators[0]) ;
421 for(j=1;j<block->depth;j++)
422 fprintf(file,",%s",program->names->iterators[j]) ;
424 fprintf(file,") {total++;") ;
425 if (block->depth > 0) {
426 fprintf(file, " printf(\"S%d %%d", statement->number);
427 for(j=1;j<block->depth;j++)
428 fprintf(file, " %%d");
430 fprintf(file,"\\n\",%s",program->names->iterators[0]) ;
431 for(j=1;j<block->depth;j++)
432 fprintf(file,",%s",program->names->iterators[j]) ;
433 fprintf(file,");") ;
435 fprintf(file,"}\n") ;
437 statement = statement->next ;
439 blocklist = blocklist->next ;
442 /* The iterator and parameter declaration. */
443 fprintf(file,"\nint main() {\n") ;
444 print_iterator_declarations(file, program, options);
445 if (program->names->nb_parameters > 0)
446 { fprintf(file," /* Parameters. */\n") ;
447 fprintf(file, " int %s=PARVAL1",program->names->parameters[0]);
448 for(i=2;i<=program->names->nb_parameters;i++)
449 fprintf(file, ", %s=PARVAL%d", program->names->parameters[i-1], i);
451 fprintf(file,";\n");
453 fprintf(file," int total=0;\n");
454 fprintf(file,"\n") ;
456 /* And we adapt the identation. */
457 indentation += 2 ;
458 } else if (options->callable && program->language == 'c') {
459 print_callable_preamble(file, program, options);
460 indentation += 2;
463 root = cloog_clast_create(program, options);
464 clast_pprint(file, root, indentation, options);
465 cloog_clast_free(root);
467 /* The end of the compilable code in case of 'compilable' option. */
468 if (options->compilable && (program->language == 'c'))
470 fprintf(file, "\n printf(\"Number of integral points: %%d.\\n\",total);");
471 fprintf(file, "\n return 0;\n}\n");
472 } else if (options->callable && program->language == 'c')
473 print_callable_postamble(file, program);
477 /******************************************************************************
478 * Memory deallocation function *
479 ******************************************************************************/
483 * cloog_program_free function:
484 * This function frees the allocated memory for a CloogProgram structure.
486 void cloog_program_free(CloogProgram * program)
487 { cloog_names_free(program->names) ;
488 cloog_loop_free(program->loop) ;
489 cloog_domain_free(program->context) ;
490 cloog_block_list_free(program->blocklist) ;
491 if (program->scaldims != NULL)
492 free(program->scaldims) ;
494 free(program) ;
498 /******************************************************************************
499 * Reading function *
500 ******************************************************************************/
504 * cloog_scattering_list_read
505 * Read in a list of scattering functions for the nb_statements
506 * domains in loop.
508 static CloogScatteringList *cloog_scattering_list_read(FILE * foo,
509 CloogLoop *loop, int nb_statements, int nb_parameters)
511 int nb_scat = 0;
512 char s[MAX_STRING];
513 CloogScatteringList *list = NULL, **next = &list;
515 /* We read first the number of scattering functions in the list. */
516 do {
517 if (!fgets(s, MAX_STRING, foo))
518 break;
519 } while ((*s=='#' || *s=='\n') || (sscanf(s, " %d", &nb_scat) < 1));
521 if (nb_scat == 0)
522 return NULL;
524 if (nb_scat > nb_statements)
525 cloog_die("too many scattering functions.\n");
527 while (nb_scat--) {
528 *next = (CloogScatteringList *)malloc(sizeof(CloogScatteringList));
529 (*next)->scatt = cloog_domain_read_scattering(loop->domain, foo);
530 (*next)->next = NULL;
532 next = &(*next)->next;
533 loop = loop->next;
535 return list;
539 static void cloog_program_construct_block_list(CloogProgram *p)
541 CloogLoop *loop;
542 CloogBlockList **next = &p->blocklist;
544 for (loop = p->loop; loop; loop = loop->next) {
545 *next = cloog_block_list_alloc(loop->block);
546 next = &(*next)->next;
552 * cloog_program_read function:
553 * This function read the informations to put in a CloogProgram structure from
554 * a file (file, possibly stdin). It returns a pointer to a CloogProgram
555 * structure containing the read informations.
556 * - October 25th 2001: first version.
557 * - September 9th 2002: - the big reading function is now split in several
558 * functions (one per read data structure).
559 * - adaptation to the new file format with naming.
561 CloogProgram * cloog_program_read(FILE * file, CloogOptions * options)
563 int i, nb_statements;
564 char s[MAX_STRING], language, prefix[2]={'c','\0'};
565 CloogLoop * current, * next ;
566 CloogScatteringList * scatteringl;
567 CloogNames *n;
568 CloogProgram * p ;
570 /* Memory allocation for the CloogProgram structure. */
571 p = cloog_program_malloc() ;
573 /* First of all, we read the language to use. */
574 while (fgets(s,MAX_STRING,file) == 0) ;
575 while ((*s=='#'||*s=='\n') || (sscanf(s," %c",&language)<1))
576 fgets(s,MAX_STRING,file) ;
577 p->language = language ;
579 p->names = n = cloog_names_alloc();
581 /* We then read the context data. */
582 p->context = cloog_domain_read_context(options->state, file);
583 n->nb_parameters = cloog_domain_parameter_dimension(p->context);
585 /* First part of the CloogNames structure: reading of the parameter names. */
586 n->parameters = cloog_names_read_strings(file, n->nb_parameters,
587 NULL, FIRST_PARAMETER);
589 /* We read the statement number. */
590 while (fgets(s,MAX_STRING,file) == 0) ;
591 while ((*s=='#'||*s=='\n') || (sscanf(s," %d",&nb_statements)<1))
592 fgets(s,MAX_STRING,file) ;
594 /* Statements and domains reading for each statement. */
595 if (nb_statements > 0)
596 { /* Reading of the first domain. */
597 p->loop = cloog_loop_read(options->state, file, 0, n->nb_parameters);
599 if (p->loop->domain != NULL)
600 n->nb_iterators = cloog_domain_dimension(p->loop->domain);
601 else
602 n->nb_iterators = 0;
604 /* And the same for each next domain. */
605 current = p->loop ;
606 for (i=2;i<=nb_statements;i++) {
607 next = cloog_loop_read(options->state, file, i-1, n->nb_parameters);
608 if (next->domain != NULL &&
609 cloog_domain_dimension(next->domain) > n->nb_iterators)
610 n->nb_iterators = cloog_domain_dimension(next->domain);
612 current->next = next ;
613 current = current->next ;
616 /* Reading of the iterator names. */
617 n->iterators = cloog_names_read_strings(file, n->nb_iterators,
618 NULL, FIRST_ITERATOR);
620 /* Reading and putting the scattering data in program structure. */
621 scatteringl = cloog_scattering_list_read(file, p->loop, nb_statements,
622 n->nb_parameters);
624 if (scatteringl != NULL)
625 { if (cloog_scattering_list_lazy_same(scatteringl))
626 cloog_msg(options, CLOOG_WARNING,
627 "some scattering functions are similar.\n");
629 p->nb_scattdims = cloog_scattering_dimension(scatteringl->scatt,
630 p->loop->domain);
631 n->nb_scattering = p->nb_scattdims;
632 n->scattering = cloog_names_read_strings(file, p->nb_scattdims, prefix, -1);
634 /* The boolean array for scalar dimensions is created and set to 0. */
635 p->scaldims = (int *)malloc(p->nb_scattdims*(sizeof(int))) ;
636 if (p->scaldims == NULL)
637 cloog_die("memory overflow.\n");
638 for (i=0;i<p->nb_scattdims;i++)
639 p->scaldims[i] = 0 ;
641 /* We try to find blocks in the input problem to reduce complexity. */
642 if (!options->noblocks)
643 cloog_program_block(p, scatteringl, options);
644 if (!options->noscalars)
645 cloog_program_extract_scalars(p, scatteringl, options);
647 cloog_program_scatter(p, scatteringl, options);
648 cloog_scattering_list_free(scatteringl);
650 if (!options->noblocks)
651 p->loop = cloog_loop_block(p->loop, p->scaldims, p->nb_scattdims);
653 else
654 { p->nb_scattdims = 0 ;
655 p->scaldims = NULL ;
658 cloog_names_scalarize(p->names,p->nb_scattdims,p->scaldims) ;
660 cloog_program_construct_block_list(p);
662 else
663 { p->loop = NULL ;
664 p->blocklist = NULL ;
665 p->scaldims = NULL ;
668 return(p) ;
672 /******************************************************************************
673 * Processing functions *
674 ******************************************************************************/
678 * cloog_program_malloc function:
679 * This function allocates the memory space for a CloogProgram structure and
680 * sets its fields with default values. Then it returns a pointer to the
681 * allocated space.
682 * - November 21th 2005: first version.
684 CloogProgram * cloog_program_malloc()
685 { CloogProgram * program ;
687 /* Memory allocation for the CloogProgram structure. */
688 program = (CloogProgram *)malloc(sizeof(CloogProgram)) ;
689 if (program == NULL)
690 cloog_die("memory overflow.\n");
692 /* We set the various fields with default values. */
693 program->language = 'c' ;
694 program->nb_scattdims = 0 ;
695 program->context = NULL ;
696 program->loop = NULL ;
697 program->names = NULL ;
698 program->blocklist = NULL ;
699 program->scaldims = NULL ;
700 program->usr = NULL;
702 return program ;
707 * cloog_program_generate function:
708 * This function calls the Quillere algorithm for loop scanning. (see the
709 * Quillere paper) and calls the loop simplification function.
710 * - depth is the loop depth we want to optimize (guard free as possible),
711 * the first loop depth is 1 and anegative value is the infinity depth.
712 * - sep_level is the level number where we want to start loop separation.
714 * - October 26th 2001: first version.
715 * - April 19th 2005: some basic fixes and memory usage feature.
716 * - April 29th 2005: (bug fix, bug found by DaeGon Kim) see case 2 below.
718 CloogProgram * cloog_program_generate(program, options)
719 CloogProgram * program ;
720 CloogOptions * options ;
722 #ifdef CLOOG_RUSAGE
723 float time;
724 struct rusage start, end ;
725 #endif
726 CloogLoop * loop ;
727 #ifdef CLOOG_MEMORY
728 char status_path[MAX_STRING_VAL] ;
729 FILE * status ;
731 /* We initialize the memory need to 0. */
732 options->memory = 0 ;
733 #endif
735 if (options->override)
737 cloog_msg(options, CLOOG_WARNING,
738 "you are using -override option, be aware that the "
739 "generated\n code may be incorrect.\n") ;
741 else
742 { /* Playing with options may be dangerous, here are two possible issues :
743 * 1. Using -l option less than scattering dimension number may lead to
744 * an illegal target code (since the scattering is not respected), if
745 * it is the case, we set -l depth to the first acceptable value.
747 if ((program->nb_scattdims > options->l) && (options->l >= 0))
749 cloog_msg(options, CLOOG_WARNING,
750 "-l depth is less than the scattering dimension number "
751 "(the \n generated code may be incorrect), it has been "
752 "automaticaly set\n to this value (use option -override "
753 "to override).\n") ;
754 options->l = program->nb_scattdims ;
757 /* 2. Using -f option greater than one while -l depth is greater than the
758 * scattering dimension number may lead to iteration duplication (try
759 * test/daegon_lu_osp.cloog with '-f 3' to test) because of the step 4b
760 * of the cloog_loop_generate function, if it is the case, we set -l to
761 * the first acceptable value.
763 if (((options->f > 1) || (options->f < 0)) &&
764 ((options->l > program->nb_scattdims) || (options->l < 0)))
766 cloog_msg(options, CLOOG_WARNING,
767 "-f depth is more than one, -l depth has been "
768 "automaticaly set\n to the scattering dimension number "
769 "(target code may have\n duplicated iterations), -l depth "
770 "has been automaticaly set to\n this value (use option "
771 "-override to override).\n") ;
772 options->l = program->nb_scattdims ;
776 #ifdef CLOOG_RUSAGE
777 getrusage(RUSAGE_SELF, &start) ;
778 #endif
779 if (program->loop != NULL)
780 { loop = program->loop ;
782 /* Here we go ! */
783 loop = cloog_loop_generate(loop, program->context, 0, 0,
784 program->scaldims,
785 program->nb_scattdims,
786 options);
788 #ifdef CLOOG_MEMORY
789 /* We read into the status file of the process how many memory it uses. */
790 sprintf(status_path,"/proc/%d/status",getpid()) ;
791 status = fopen(status_path, "r") ;
792 while (fscanf(status,"%s",status_path) && strcmp(status_path,"VmData:")!=0);
793 fscanf(status,"%d",&(options->memory)) ;
794 fclose(status) ;
795 #endif
797 if ((!options->nosimplify) && (program->loop != NULL))
798 loop = cloog_loop_simplify(loop, program->context, 1);
800 program->loop = loop ;
803 #ifdef CLOOG_RUSAGE
804 getrusage(RUSAGE_SELF, &end) ;
805 /* We calculate the time spent in code generation. */
806 time = (end.ru_utime.tv_usec - start.ru_utime.tv_usec)/(float)(MEGA) ;
807 time += (float)(end.ru_utime.tv_sec - start.ru_utime.tv_sec) ;
808 options->time = time ;
809 #endif
811 return program ;
816 * cloog_program_block function:
817 * this function gives a last chance to the lazy user to consider statement
818 * blocks instead of some statement lists where the whole list may be
819 * considered as a single statement from a code generation point of view.
820 * For instance two statements with the same iteration domain and the same
821 * scattering functions may be considered as a block. This function is lazy
822 * and can only find very simple forms of trivial blocks (see
823 * cloog_domain_lazy_block function for more details). The useless loops and
824 * scattering functions are removed and freed while the statement list of
825 * according blocks are filled.
826 * - program is the whole program structure (befaore applying scattering),
827 * - scattering is the list of scattering functions.
829 * - April 30th 2005: first attempt.
830 * - June 10-11th 2005: first working version.
832 void cloog_program_block(CloogProgram *program,
833 CloogScatteringList *scattering, CloogOptions *options)
834 { int blocked_reference=0, blocked=0, nb_blocked=0 ;
835 CloogLoop * reference, * start, * loop ;
836 CloogScatteringList * scatt_reference, * scatt_loop, * scatt_start;
838 if ((program->loop == NULL) || (program->loop->next == NULL))
839 return ;
841 /* The process will use three variables for the linked list :
842 * - 'start' is the starting point of a new block,
843 * - 'reference' is the node of the block used for the block checking,
844 * - 'loop' is the candidate to be inserted inside the block.
845 * At the beginning of the process, the linked lists are as follow:
846 * O------>O------>O------>O------>NULL
847 * | |
848 * start loop
849 * reference
852 reference = program->loop ;
853 start = program->loop ;
854 loop = reference->next ;
855 scatt_reference = scattering ;
856 scatt_start = scattering ;
857 scatt_loop = scattering->next ;
859 while (loop != NULL)
860 { if (cloog_domain_lazy_equal(reference->domain,loop->domain) &&
861 cloog_scattering_lazy_block(scatt_reference->scatt, scatt_loop->scatt,
862 scattering,program->nb_scattdims))
863 { /* If we find a block we update the links:
864 * +---------------+
865 * | v
866 * O O------>O------>O------>NULL
867 * | |
868 * start loop
869 * reference
871 blocked = 1 ;
872 nb_blocked ++ ;
873 cloog_block_merge(start->block,loop->block); /* merge frees loop->block */
874 loop->block = NULL ;
875 start->next = loop->next ;
876 scatt_start->next = scatt_loop->next ;
878 else
879 { /* If we didn't find a block, the next start of a block is updated:
880 * O------>O------>O------>O------>NULL
881 * | |
882 * reference start
883 * loop
885 blocked= 0 ;
886 start = loop ;
887 scatt_start = scatt_loop ;
890 /* If the reference node has been included into a block, we can free it. */
891 if (blocked_reference)
892 { reference->next = NULL ;
893 cloog_loop_free(reference) ;
894 cloog_scattering_free(scatt_reference->scatt);
895 free(scatt_reference) ;
898 /* The reference and the loop are now updated for the next try, the
899 * starting position depends on the previous step.
900 * O ? O------>O------>O------>NULL
901 * | |
902 * reference loop
904 reference = loop ;
905 loop = loop->next ;
906 scatt_reference = scatt_loop ;
907 scatt_loop = scatt_loop->next ;
909 /* We mark the new reference as being blocked or not, if will be freed
910 * during the next while loop execution.
912 if (blocked)
913 blocked_reference = 1 ;
914 else
915 blocked_reference = 0 ;
918 /* We free the last blocked reference if any (since in the while loop it was
919 * freed during the next loop execution, it was not possible to free the
920 * last one inside).
922 if (blocked_reference)
923 { reference->next = NULL ;
924 cloog_loop_free(reference) ;
925 cloog_scattering_free(scatt_reference->scatt);
926 free(scatt_reference) ;
929 if (nb_blocked != 0)
930 cloog_msg(options, CLOOG_INFO, "%d domains have been blocked.\n", nb_blocked);
935 * cloog_program_extract_scalars function:
936 * this functions finds and removes the dimensions of the scattering functions
937 * when they are scalar (i.e. of the shape "dim + scalar = 0") for all
938 * scattering functions. The reason is that the processing of such dimensions
939 * is trivial and do not need neither a row and a column in the matrix
940 * representation of the domain (this will save memory) neither the full
941 * Quillere processing (this will save time). The scalar dimensions data are
942 * dispatched in the CloogProgram structure (the boolean vector scaldims will
943 * say which original dimensions are scalar or not) and to the CloogBlock
944 * structures (each one has a scaldims vector that contains the scalar values).
945 * - June 14th 2005: first developments.
946 * - June 30th 2005: first version.
948 void cloog_program_extract_scalars(CloogProgram *program,
949 CloogScatteringList *scattering, CloogOptions *options)
950 { int i, j, scalar, current, nb_scaldims=0 ;
951 CloogScatteringList *start;
952 CloogScattering *old;
953 CloogLoop *loop;
954 CloogBlock * block ;
956 start = scattering ;
958 for (i=0;i<program->nb_scattdims;i++)
959 { scalar = 1 ;
960 scattering = start ;
961 while (scattering != NULL)
962 { if (!cloog_scattering_lazy_isscalar(scattering->scatt, i, NULL))
963 { scalar = 0 ;
964 break ;
966 scattering = scattering->next ;
969 if (scalar)
970 { nb_scaldims ++ ;
971 program->scaldims[i] = 1 ;
975 /* If there are no scalar dimensions, we can continue directly. */
976 if (!nb_scaldims)
977 return ;
979 /* Otherwise, in each block, we have to put the number of scalar dimensions,
980 * and to allocate the memory for the scalar values.
982 for (loop = program->loop; loop; loop = loop->next) {
983 block = loop->block;
984 block->nb_scaldims = nb_scaldims ;
985 block->scaldims = (cloog_int_t *)malloc(nb_scaldims*sizeof(cloog_int_t));
986 for (i=0;i<nb_scaldims;i++)
987 cloog_int_init(block->scaldims[i]);
990 /* Then we have to fill these scalar values, so we can erase those dimensions
991 * from the scattering functions. It's easier to begin with the last one,
992 * since there would be an offset otherwise (if we remove the i^th dimension,
993 * then the next one is not the (i+1)^th but still the i^th...).
995 current = nb_scaldims - 1 ;
996 for (i=program->nb_scattdims-1;i>=0;i--)
997 if (program->scaldims[i])
999 scattering = start ;
1000 for (loop = program->loop; loop; loop = loop->next) {
1001 block = loop->block;
1002 if (!cloog_scattering_lazy_isscalar(scattering->scatt, i,
1003 &block->scaldims[current])) {
1004 /* We should have found a scalar value: if not, there is an error. */
1005 cloog_die("dimension %d is not scalar as expected.\n", i);
1007 scattering = scattering->next ;
1010 scattering = start ;
1011 while (scattering != NULL) {
1012 old = scattering->scatt;
1013 scattering->scatt = cloog_scattering_erase_dimension(old, i);
1014 cloog_scattering_free(old);
1015 scattering = scattering->next ;
1017 current-- ;
1020 /* We postprocess the scaldims array in such a way that each entry is how
1021 * many scalar dimensions follows + 1 (the current one). This will make
1022 * some other processing easier (e.g. knowledge of some offsets).
1024 for (i=0;i<program->nb_scattdims-1;i++)
1025 { if (program->scaldims[i])
1026 { j = i + 1 ;
1027 while ((j < program->nb_scattdims) && program->scaldims[j])
1028 { program->scaldims[i] ++ ;
1029 j ++ ;
1034 if (nb_scaldims != 0)
1035 cloog_msg(options, CLOOG_INFO, "%d dimensions (over %d) are scalar.\n",
1036 nb_scaldims,program->nb_scattdims) ;
1041 * cloog_program_scatter function:
1042 * This function adds the scattering (scheduling) informations in a program.
1043 * If names is NULL, this function create names itself such that the i^th
1044 * name is ci.
1045 * - November 6th 2001: first version.
1047 void cloog_program_scatter(CloogProgram *program,
1048 CloogScatteringList *scattering, CloogOptions *options)
1049 { int scattering_dim, scattering_dim2, not_enough_constraints=0 ;
1050 CloogLoop * loop ;
1052 if ((program != NULL) && (scattering != NULL))
1053 { loop = program->loop ;
1055 /* We compute the scattering dimension and check it is >=0. */
1056 scattering_dim = cloog_scattering_dimension(scattering->scatt, loop->domain);
1057 if (scattering_dim < 0)
1058 cloog_die("scattering has not enough dimensions.\n");
1059 if (!cloog_scattering_fully_specified(scattering->scatt, loop->domain))
1060 not_enough_constraints ++ ;
1062 /* The scattering dimension may have been modified by scalar extraction. */
1063 scattering_dim = cloog_scattering_dimension(scattering->scatt, loop->domain);
1065 /* Finally we scatter all loops. */
1066 cloog_loop_scatter(loop, scattering->scatt);
1067 loop = loop->next ;
1068 scattering = scattering->next ;
1070 while ((loop != NULL) && (scattering != NULL))
1071 { scattering_dim2 = cloog_scattering_dimension(scattering->scatt,
1072 loop->domain);
1073 if (scattering_dim2 != scattering_dim)
1074 cloog_die("scattering dimensions are not the same.\n") ;
1075 if (!cloog_scattering_fully_specified(scattering->scatt, loop->domain))
1076 not_enough_constraints ++ ;
1078 cloog_loop_scatter(loop, scattering->scatt);
1079 loop = loop->next ;
1080 scattering = scattering->next ;
1082 if ((loop != NULL) || (scattering != NULL))
1083 cloog_msg(options, CLOOG_WARNING,
1084 "there is not a scattering for each statement.\n");
1086 if (not_enough_constraints)
1087 cloog_msg(options, CLOOG_WARNING, "not enough constraints for "
1088 "%d scattering function(s).\n",not_enough_constraints) ;