Add CLOOG_ prefix to LANGUAGE_* macros
[cloog/uuh.git] / source / program.c
blobb7895ff273f0c97d4a53e3adb5e73a72f3b9c40c
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
54 #define ALLOC(type) (type*)malloc(sizeof(type))
57 /******************************************************************************
58 * Structure display function *
59 ******************************************************************************/
62 /**
63 * cloog_program_print function:
64 * this function is a human-friendly way to display the CloogProgram data
65 * structure, it shows all the different fields and includes an indentation
66 * level (level) in order to work with others print_structure functions.
67 * - July 1st 2005: first version based on the old cloog_program_print function.
69 void cloog_program_print_structure(file, program, level)
70 FILE * file ;
71 CloogProgram * program ;
72 int level ;
73 { int i, j ;
75 /* Go to the right level. */
76 for (i=0; i<level; i++)
77 fprintf(file,"|\t") ;
79 fprintf(file,"+-- CloogProgram\n") ;
81 /* A blank line. */
82 for (i=0; i<=level+1; i++)
83 fprintf(file,"|\t") ;
84 fprintf(file,"\n") ;
86 /* Print the language. */
87 for (i=0; i<=level; i++)
88 fprintf(file,"|\t") ;
89 fprintf(file, "Language: %c\n",program->language) ;
91 /* A blank line. */
92 for (i=0; i<=level+1; i++)
93 fprintf(file,"|\t") ;
94 fprintf(file,"\n") ;
96 /* Print the scattering dimension number. */
97 for (i=0; i<=level; i++)
98 fprintf(file,"|\t") ;
99 fprintf(file,"Scattering dimension number: %d\n",program->nb_scattdims) ;
101 /* A blank line. */
102 for (i=0; i<=level+1; i++)
103 fprintf(file,"|\t") ;
104 fprintf(file,"\n") ;
106 /* Print the scalar scattering dimension informations. */
107 for (i=0; i<=level; i++)
108 fprintf(file,"|\t") ;
109 if (program->scaldims != NULL)
110 { fprintf(file,"Scalar dimensions:") ;
111 for (i=0;i<program->nb_scattdims;i++)
112 fprintf(file," %d:%d ",i,program->scaldims[i]) ;
113 fprintf(file,"\n") ;
115 else
116 fprintf(file,"No scalar scattering dimensions\n") ;
118 /* A blank line. */
119 for (i=0; i<=level+1; i++)
120 fprintf(file,"|\t") ;
121 fprintf(file,"\n") ;
123 /* Print the parameter and the iterator names. */
124 cloog_names_print_structure(file,program->names,level+1) ;
126 /* A blank line. */
127 for (i=0; i<=level+1; i++)
128 fprintf(file,"|\t") ;
129 fprintf(file,"\n") ;
131 /* Print the context. */
132 cloog_domain_print_structure(file, program->context, level+1, "Context");
134 /* Print the loop. */
135 cloog_loop_print_structure(file,program->loop,level+1) ;
137 /* One more time something that is here only for a better look. */
138 for (j=0; j<2; j++)
139 { for (i=0; i<=level; i++)
140 fprintf(file,"|\t") ;
142 fprintf(file,"\n") ;
148 * cloog_program_dump_cloog function:
149 * This function dumps a CloogProgram structure supposed to be completely
150 * filled in a CLooG input file (foo possibly stdout) such as CLooG can
151 * rebuild almost exactly the data structure from the input file.
153 * If the scattering is already applied, the scattering parameter is supposed to
154 * be NULL. In this case the number of scattering functions is lost, since they
155 * are included inside the iteration domains. This can only lead to a less
156 * beautiful pretty printing.
158 * In case the scattering is not yet applied it can be passed to this function
159 * and will be included in the CLooG input file dump.
161 void cloog_program_dump_cloog(FILE * foo, CloogProgram * program,
162 CloogScatteringList *scattering)
164 int i;
165 CloogLoop * loop ;
166 CloogScatteringList *tmp_scatt;
168 fprintf(foo,
169 "# CLooG -> CLooG\n"
170 "# This is an automatic dump of a CLooG input file from a CloogProgram data\n"
171 "# structure. WARNING: it is highly dangerous and MAY be correct ONLY if\n"
172 "# - it has been dumped before loop generation.\n"
173 "# - option -noscalars is used (it removes scalar dimensions otherwise)\n"
174 "# - option -l is at least the original scattering dimension number\n"
175 "# ASK THE AUTHOR IF YOU *NEED* SOMETHING MORE ROBUST\n") ;
177 /* Language. */
178 if (program->language == 'c')
179 fprintf(foo,"# Language: C\n") ;
180 else
181 fprintf(foo,"# Language: FORTRAN\n") ;
182 fprintf(foo,"%c\n\n",program->language) ;
184 /* Context. */
185 fprintf(foo, "# Context (%d parameter(s)):\n", program->names->nb_parameters);
186 cloog_domain_print_constraints(foo, program->context, 0);
187 fprintf(foo,"1 # Parameter name(s)\n") ;
188 for (i=0;i<program->names->nb_parameters;i++)
189 fprintf(foo,"%s ",program->names->parameters[i]) ;
191 /* Statement number. */
192 i = 0 ;
193 loop = program->loop ;
194 while (loop != NULL)
195 { i++ ;
196 loop = loop->next ;
198 fprintf(foo,"\n\n# Statement number:\n%d\n\n",i) ;
200 /* Iteration domains. */
201 i = 1 ;
202 loop = program->loop ;
203 while (loop != NULL)
204 { /* Name of the domain. */
205 fprintf(foo,"# Iteration domain of statement %d.\n",i) ;
207 cloog_domain_print_constraints(foo, loop->domain, 1);
208 fprintf(foo,"0 0 0 # For future options.\n\n") ;
210 i++ ;
211 loop = loop->next ;
213 fprintf(foo,"\n1 # Iterator name(s)\n") ;
215 /* Scattering already applied? In this case print the scattering names as
216 * additional iterator names. */
217 if (!scattering)
218 for (i = 0; i < program->names->nb_scattering; i++)
219 fprintf(foo, "%s ", program->names->scattering[i]);
220 for (i=0;i<program->names->nb_iterators;i++)
221 fprintf(foo,"%s ",program->names->iterators[i]);
222 fprintf(foo,"\n\n") ;
224 /* Exit, if scattering is already applied. */
225 if (!scattering) {
226 fprintf(foo, "# No scattering functions.\n0\n\n");
227 return;
230 /* Scattering relations. */
231 fprintf(foo, "# --------------------- SCATTERING --------------------\n");
233 i = 0;
234 for (tmp_scatt = scattering; tmp_scatt; tmp_scatt = tmp_scatt->next)
235 i++;
237 fprintf(foo, "%d # Scattering functions", i);
239 for (tmp_scatt = scattering; tmp_scatt; tmp_scatt = tmp_scatt->next)
240 cloog_scattering_print_constraints(foo, tmp_scatt->scatt);
242 fprintf(foo, "\n1 # Scattering dimension name(s)\n");
244 for (i = 0; i < program->names->nb_scattering; i++)
245 fprintf(foo, "%s ", program->names->scattering[i]);
250 * cloog_program_print function:
251 * This function prints the content of a CloogProgram structure (program) into a
252 * file (file, possibly stdout).
253 * - July 1st 2005: Now this very old function (probably as old as CLooG) is
254 * only a frontend to cloog_program_print_structure, with a
255 * quite better human-readable representation.
257 void cloog_program_print(FILE * file, CloogProgram * program)
258 { cloog_program_print_structure(file,program,0) ;
262 static void print_comment(FILE *file, CloogOptions *options,
263 const char *fmt, ...)
265 va_list args;
267 va_start(args, fmt);
268 if (options->language == CLOOG_LANGUAGE_FORTRAN) {
269 fprintf(file, "! ");
270 vfprintf(file, fmt, args);
271 fprintf(file, "\n");
272 } else {
273 fprintf(file, "/* ");
274 vfprintf(file, fmt, args);
275 fprintf(file, " */\n");
279 static void print_macros(FILE *file)
281 fprintf(file, "/* Useful macros. */\n") ;
282 fprintf(file,
283 "#define floord(n,d) (((n)<0) ? -((-(n)+(d)-1)/(d)) : (n)/(d))\n");
284 fprintf(file,
285 "#define ceild(n,d) (((n)<0) ? -((-(n))/(d)) : ((n)+(d)-1)/(d))\n");
286 fprintf(file, "#define max(x,y) ((x) > (y) ? (x) : (y))\n") ;
287 fprintf(file, "#define min(x,y) ((x) < (y) ? (x) : (y))\n\n") ;
290 static void print_declarations(FILE *file, int n, char **names)
292 int i;
294 fprintf(file, " int %s", names[0]);
295 for (i = 1; i < n; i++)
296 fprintf(file, ", %s", names[i]);
298 fprintf(file, ";\n");
301 static void print_iterator_declarations(FILE *file, CloogProgram *program,
302 CloogOptions *options)
304 CloogNames *names = program->names;
306 if (names->nb_scattering) {
307 fprintf(file, " /* Scattering iterators. */\n");
308 print_declarations(file, names->nb_scattering, names->scattering);
310 if (names->nb_iterators) {
311 fprintf(file, " /* Original iterators. */\n");
312 print_declarations(file, names->nb_iterators, names->iterators);
316 static void print_callable_preamble(FILE *file, CloogProgram *program,
317 CloogOptions *options)
319 int j;
320 CloogBlockList *blocklist;
321 CloogBlock *block;
322 CloogStatement *statement;
324 fprintf(file, "extern void hash(int);\n\n");
326 print_macros(file);
328 for (blocklist = program->blocklist; blocklist; blocklist = blocklist->next) {
329 block = blocklist->block;
330 for (statement = block->statement; statement; statement = statement->next) {
331 fprintf(file, "#define S%d(", statement->number);
332 if (block->depth > 0) {
333 fprintf(file, "%s", program->names->iterators[0]);
334 for(j = 1; j < block->depth; j++)
335 fprintf(file, ",%s", program->names->iterators[j]);
337 fprintf(file,") { hash(%d);", statement->number);
338 for(j = 0; j < block->depth; j++)
339 fprintf(file, " hash(%s);", program->names->iterators[j]);
340 fprintf(file, " }\n");
343 fprintf(file, "\nvoid test(");
344 if (program->names->nb_parameters > 0) {
345 fprintf(file, "int %s", program->names->parameters[0]);
346 for(j = 1; j < program->names->nb_parameters; j++)
347 fprintf(file, ", int %s", program->names->parameters[j]);
349 fprintf(file, ")\n{\n");
350 print_iterator_declarations(file, program, options);
353 static void print_callable_postamble(FILE *file, CloogProgram *program)
355 fprintf(file, "}\n");
359 * cloog_program_pprint function:
360 * This function prints the content of a CloogProgram structure (program) into a
361 * file (file, possibly stdout), in a C-like language.
362 * - June 22nd 2005: Adaptation for GMP.
364 void cloog_program_pprint(file, program, options)
365 FILE * file ;
366 CloogProgram * program ;
367 CloogOptions * options ;
368 { int i, j, nb_scattering, indentation=0 ;
369 CloogStatement * statement ;
370 CloogBlockList * blocklist ;
371 CloogBlock * block ;
372 struct clast_stmt *root;
374 if (program->language == 'f')
375 options->language = CLOOG_LANGUAGE_FORTRAN ;
376 else
377 options->language = CLOOG_LANGUAGE_C ;
379 #ifdef CLOOG_RUSAGE
380 print_comment(file, options, "Generated from %s by %s in %.2fs.",
381 options->name, cloog_version(), options->time);
382 #else
383 print_comment(file, options, "Generated from %s by %s.",
384 options->name, cloog_version());
385 #endif
386 #ifdef CLOOG_MEMORY
387 print_comment(file, options, "CLooG asked for %d KBytes.", options->memory);
388 cloog_msg(CLOOG_INFO, "%.2fs and %dKB used for code generation.\n",
389 options->time,options->memory);
390 #endif
392 /* If the option "compilable" is set, we provide the whole stuff to generate
393 * a compilable code. This code just do nothing, but now the user can edit
394 * the source and set the statement macros and parameters values.
396 nb_scattering = program->nb_scattdims ;
397 if (options->compilable && (program->language == 'c'))
398 { /* The headers. */
399 fprintf(file,"/* DON'T FORGET TO USE -lm OPTION TO COMPILE. */\n\n") ;
400 fprintf(file,"/* Useful headers. */\n") ;
401 fprintf(file,"#include <stdio.h>\n") ;
402 fprintf(file,"#include <stdlib.h>\n") ;
403 fprintf(file,"#include <math.h>\n\n") ;
405 /* The value of parameters. */
406 fprintf(file,"/* Parameter value. */\n") ;
407 for (i = 1; i <= program->names->nb_parameters; i++)
408 fprintf(file, "#define PARVAL%d %d\n", i, options->compilable);
410 /* The macros. */
411 print_macros(file);
413 /* The statement macros. */
414 fprintf(file,"/* Statement macros (please set). */\n") ;
415 blocklist = program->blocklist ;
416 while (blocklist != NULL)
417 { block = blocklist->block ;
418 statement = block->statement ;
419 while (statement != NULL)
420 { fprintf(file,"#define S%d(",statement->number) ;
421 if (block->depth > 0)
422 { fprintf(file,"%s",program->names->iterators[0]) ;
423 for(j=1;j<block->depth;j++)
424 fprintf(file,",%s",program->names->iterators[j]) ;
426 fprintf(file,") {total++;") ;
427 if (block->depth > 0) {
428 fprintf(file, " printf(\"S%d %%d", statement->number);
429 for(j=1;j<block->depth;j++)
430 fprintf(file, " %%d");
432 fprintf(file,"\\n\",%s",program->names->iterators[0]) ;
433 for(j=1;j<block->depth;j++)
434 fprintf(file,",%s",program->names->iterators[j]) ;
435 fprintf(file,");") ;
437 fprintf(file,"}\n") ;
439 statement = statement->next ;
441 blocklist = blocklist->next ;
444 /* The iterator and parameter declaration. */
445 fprintf(file,"\nint main() {\n") ;
446 print_iterator_declarations(file, program, options);
447 if (program->names->nb_parameters > 0)
448 { fprintf(file," /* Parameters. */\n") ;
449 fprintf(file, " int %s=PARVAL1",program->names->parameters[0]);
450 for(i=2;i<=program->names->nb_parameters;i++)
451 fprintf(file, ", %s=PARVAL%d", program->names->parameters[i-1], i);
453 fprintf(file,";\n");
455 fprintf(file," int total=0;\n");
456 fprintf(file,"\n") ;
458 /* And we adapt the identation. */
459 indentation += 2 ;
460 } else if (options->callable && program->language == 'c') {
461 print_callable_preamble(file, program, options);
462 indentation += 2;
465 root = cloog_clast_create(program, options);
466 clast_pprint(file, root, indentation, options);
467 cloog_clast_free(root);
469 /* The end of the compilable code in case of 'compilable' option. */
470 if (options->compilable && (program->language == 'c'))
472 fprintf(file, "\n printf(\"Number of integral points: %%d.\\n\",total);");
473 fprintf(file, "\n return 0;\n}\n");
474 } else if (options->callable && program->language == 'c')
475 print_callable_postamble(file, program);
479 /******************************************************************************
480 * Memory deallocation function *
481 ******************************************************************************/
485 * cloog_program_free function:
486 * This function frees the allocated memory for a CloogProgram structure.
488 void cloog_program_free(CloogProgram * program)
489 { cloog_names_free(program->names) ;
490 cloog_loop_free(program->loop) ;
491 cloog_domain_free(program->context) ;
492 cloog_block_list_free(program->blocklist) ;
493 if (program->scaldims != NULL)
494 free(program->scaldims) ;
496 free(program) ;
500 /******************************************************************************
501 * Reading function *
502 ******************************************************************************/
505 static void cloog_program_construct_block_list(CloogProgram *p)
507 CloogLoop *loop;
508 CloogBlockList **next = &p->blocklist;
510 for (loop = p->loop; loop; loop = loop->next) {
511 *next = cloog_block_list_alloc(loop->block);
512 next = &(*next)->next;
518 * Construct a CloogProgram structure from a given context and
519 * union domain representing the iteration domains and scattering functions.
521 CloogProgram *cloog_program_alloc(CloogDomain *context, CloogUnionDomain *ud,
522 CloogOptions *options)
524 int i;
525 char prefix[] = "c";
526 CloogScatteringList * scatteringl;
527 CloogNames *n;
528 CloogProgram * p ;
530 /* Memory allocation for the CloogProgram structure. */
531 p = cloog_program_malloc() ;
533 if (options->language == CLOOG_LANGUAGE_FORTRAN)
534 p->language = 'f';
535 else
536 p->language = 'c';
538 p->names = n = cloog_names_alloc();
540 /* We then read the context data. */
541 p->context = context;
542 n->nb_parameters = ud->n_name[CLOOG_PARAM];
544 /* First part of the CloogNames structure: the parameter names. */
545 if (ud->name[CLOOG_PARAM]) {
546 n->parameters = ud->name[CLOOG_PARAM];
547 ud->name[CLOOG_PARAM] = NULL;
548 } else
549 n->parameters = cloog_names_generate_items(n->nb_parameters, NULL,
550 FIRST_PARAMETER);
552 n->nb_iterators = ud->n_name[CLOOG_ITER];
553 if (ud->name[CLOOG_ITER]) {
554 n->iterators = ud->name[CLOOG_ITER];
555 ud->name[CLOOG_ITER] = NULL;
556 } else
557 n->iterators = cloog_names_generate_items(n->nb_iterators, NULL,
558 FIRST_ITERATOR);
560 if (ud->domain) {
561 CloogNamedDomainList *l;
562 CloogLoop **next = &p->loop;
563 CloogScatteringList **next_scat = &scatteringl;
565 scatteringl = NULL;
566 for (i = 0, l = ud->domain; l; ++i, l = l->next) {
567 *next = cloog_loop_from_domain(options->state, l->domain, i);
568 l->domain = NULL;
569 (*next)->block->statement->name = l->name;
570 (*next)->block->statement->usr = l->usr;
571 l->name = NULL;
573 if (l->scattering) {
574 *next_scat = ALLOC(CloogScatteringList);
575 (*next_scat)->scatt = l->scattering;
576 l->scattering = NULL;
577 (*next_scat)->next = NULL;
579 next_scat = &(*next_scat)->next;
582 next = &(*next)->next;
585 if (scatteringl != NULL) {
586 p->nb_scattdims = cloog_scattering_dimension(scatteringl->scatt,
587 p->loop->domain);
588 n->nb_scattering = p->nb_scattdims;
589 if (ud->name[CLOOG_SCAT]) {
590 n->scattering = ud->name[CLOOG_SCAT];
591 ud->name[CLOOG_SCAT] = NULL;
592 } else
593 n->scattering = cloog_names_generate_items(n->nb_scattering, prefix, -1);
595 /* The boolean array for scalar dimensions is created and set to 0. */
596 p->scaldims = (int *)malloc(p->nb_scattdims*(sizeof(int))) ;
597 if (p->scaldims == NULL)
598 cloog_die("memory overflow.\n");
599 for (i=0;i<p->nb_scattdims;i++)
600 p->scaldims[i] = 0 ;
602 /* We try to find blocks in the input problem to reduce complexity. */
603 if (!options->noblocks)
604 cloog_program_block(p, scatteringl, options);
605 if (!options->noscalars)
606 cloog_program_extract_scalars(p, scatteringl, options);
608 cloog_program_scatter(p, scatteringl, options);
609 cloog_scattering_list_free(scatteringl);
611 if (!options->noblocks)
612 p->loop = cloog_loop_block(p->loop, p->scaldims, p->nb_scattdims);
614 else
615 { p->nb_scattdims = 0 ;
616 p->scaldims = NULL ;
619 cloog_names_scalarize(p->names,p->nb_scattdims,p->scaldims) ;
621 cloog_program_construct_block_list(p);
623 else
624 { p->loop = NULL ;
625 p->blocklist = NULL ;
626 p->scaldims = NULL ;
629 cloog_union_domain_free(ud);
631 return(p) ;
636 * cloog_program_read function:
637 * This function read the informations to put in a CloogProgram structure from
638 * a file (file, possibly stdin). It returns a pointer to a CloogProgram
639 * structure containing the read informations.
640 * - October 25th 2001: first version.
641 * - September 9th 2002: - the big reading function is now split in several
642 * functions (one per read data structure).
643 * - adaptation to the new file format with naming.
645 CloogProgram *cloog_program_read(FILE *file, CloogOptions *options)
647 CloogInput *input;
648 CloogProgram *p;
650 input = cloog_input_read(file, options);
651 p = cloog_program_alloc(input->context, input->ud, options);
652 free(input);
654 return p;
658 /******************************************************************************
659 * Processing functions *
660 ******************************************************************************/
664 * cloog_program_malloc function:
665 * This function allocates the memory space for a CloogProgram structure and
666 * sets its fields with default values. Then it returns a pointer to the
667 * allocated space.
668 * - November 21th 2005: first version.
670 CloogProgram * cloog_program_malloc()
671 { CloogProgram * program ;
673 /* Memory allocation for the CloogProgram structure. */
674 program = (CloogProgram *)malloc(sizeof(CloogProgram)) ;
675 if (program == NULL)
676 cloog_die("memory overflow.\n");
678 /* We set the various fields with default values. */
679 program->language = 'c' ;
680 program->nb_scattdims = 0 ;
681 program->context = NULL ;
682 program->loop = NULL ;
683 program->names = NULL ;
684 program->blocklist = NULL ;
685 program->scaldims = NULL ;
686 program->usr = NULL;
688 return program ;
693 * cloog_program_generate function:
694 * This function calls the Quillere algorithm for loop scanning. (see the
695 * Quillere paper) and calls the loop simplification function.
696 * - depth is the loop depth we want to optimize (guard free as possible),
697 * the first loop depth is 1 and anegative value is the infinity depth.
698 * - sep_level is the level number where we want to start loop separation.
700 * - October 26th 2001: first version.
701 * - April 19th 2005: some basic fixes and memory usage feature.
702 * - April 29th 2005: (bug fix, bug found by DaeGon Kim) see case 2 below.
704 CloogProgram * cloog_program_generate(program, options)
705 CloogProgram * program ;
706 CloogOptions * options ;
708 #ifdef CLOOG_RUSAGE
709 float time;
710 struct rusage start, end ;
711 #endif
712 CloogLoop * loop ;
713 #ifdef CLOOG_MEMORY
714 char status_path[MAX_STRING_VAL] ;
715 FILE * status ;
717 /* We initialize the memory need to 0. */
718 options->memory = 0 ;
719 #endif
721 if (options->override)
723 cloog_msg(options, CLOOG_WARNING,
724 "you are using -override option, be aware that the "
725 "generated\n code may be incorrect.\n") ;
727 else
728 { /* Playing with options may be dangerous, here are two possible issues :
729 * 1. Using -l option less than scattering dimension number may lead to
730 * an illegal target code (since the scattering is not respected), if
731 * it is the case, we set -l depth to the first acceptable value.
733 if ((program->nb_scattdims > options->l) && (options->l >= 0))
735 cloog_msg(options, CLOOG_WARNING,
736 "-l depth is less than the scattering dimension number "
737 "(the \n generated code may be incorrect), it has been "
738 "automaticaly set\n to this value (use option -override "
739 "to override).\n") ;
740 options->l = program->nb_scattdims ;
743 /* 2. Using -f option greater than one while -l depth is greater than the
744 * scattering dimension number may lead to iteration duplication (try
745 * test/daegon_lu_osp.cloog with '-f 3' to test) because of the step 4b
746 * of the cloog_loop_generate function, if it is the case, we set -l to
747 * the first acceptable value.
749 if (((options->f > 1) || (options->f < 0)) &&
750 ((options->l > program->nb_scattdims) || (options->l < 0)))
752 cloog_msg(options, CLOOG_WARNING,
753 "-f depth is more than one, -l depth has been "
754 "automaticaly set\n to the scattering dimension number "
755 "(target code may have\n duplicated iterations), -l depth "
756 "has been automaticaly set to\n this value (use option "
757 "-override to override).\n") ;
758 options->l = program->nb_scattdims ;
762 #ifdef CLOOG_RUSAGE
763 getrusage(RUSAGE_SELF, &start) ;
764 #endif
765 if (program->loop != NULL)
766 { loop = program->loop ;
768 /* Here we go ! */
769 loop = cloog_loop_generate(loop, program->context, 0, 0,
770 program->scaldims,
771 program->nb_scattdims,
772 options);
774 #ifdef CLOOG_MEMORY
775 /* We read into the status file of the process how many memory it uses. */
776 sprintf(status_path,"/proc/%d/status",getpid()) ;
777 status = fopen(status_path, "r") ;
778 while (fscanf(status,"%s",status_path) && strcmp(status_path,"VmData:")!=0);
779 fscanf(status,"%d",&(options->memory)) ;
780 fclose(status) ;
781 #endif
783 if ((!options->nosimplify) && (program->loop != NULL))
784 loop = cloog_loop_simplify(loop, program->context, 0,
785 program->nb_scattdims, options);
787 program->loop = loop ;
790 #ifdef CLOOG_RUSAGE
791 getrusage(RUSAGE_SELF, &end) ;
792 /* We calculate the time spent in code generation. */
793 time = (end.ru_utime.tv_usec - start.ru_utime.tv_usec)/(float)(MEGA) ;
794 time += (float)(end.ru_utime.tv_sec - start.ru_utime.tv_sec) ;
795 options->time = time ;
796 #endif
798 return program ;
803 * cloog_program_block function:
804 * this function gives a last chance to the lazy user to consider statement
805 * blocks instead of some statement lists where the whole list may be
806 * considered as a single statement from a code generation point of view.
807 * For instance two statements with the same iteration domain and the same
808 * scattering functions may be considered as a block. This function is lazy
809 * and can only find very simple forms of trivial blocks (see
810 * cloog_domain_lazy_block function for more details). The useless loops and
811 * scattering functions are removed and freed while the statement list of
812 * according blocks are filled.
813 * - program is the whole program structure (befaore applying scattering),
814 * - scattering is the list of scattering functions.
816 * - April 30th 2005: first attempt.
817 * - June 10-11th 2005: first working version.
819 void cloog_program_block(CloogProgram *program,
820 CloogScatteringList *scattering, CloogOptions *options)
821 { int blocked_reference=0, blocked=0, nb_blocked=0 ;
822 CloogLoop * reference, * start, * loop ;
823 CloogScatteringList * scatt_reference, * scatt_loop, * scatt_start;
825 if ((program->loop == NULL) || (program->loop->next == NULL))
826 return ;
828 /* The process will use three variables for the linked list :
829 * - 'start' is the starting point of a new block,
830 * - 'reference' is the node of the block used for the block checking,
831 * - 'loop' is the candidate to be inserted inside the block.
832 * At the beginning of the process, the linked lists are as follow:
833 * O------>O------>O------>O------>NULL
834 * | |
835 * start loop
836 * reference
839 reference = program->loop ;
840 start = program->loop ;
841 loop = reference->next ;
842 scatt_reference = scattering ;
843 scatt_start = scattering ;
844 scatt_loop = scattering->next ;
846 while (loop != NULL)
847 { if (cloog_domain_lazy_equal(reference->domain,loop->domain) &&
848 cloog_scattering_lazy_block(scatt_reference->scatt, scatt_loop->scatt,
849 scattering,program->nb_scattdims))
850 { /* If we find a block we update the links:
851 * +---------------+
852 * | v
853 * O O------>O------>O------>NULL
854 * | |
855 * start loop
856 * reference
858 blocked = 1 ;
859 nb_blocked ++ ;
860 cloog_block_merge(start->block,loop->block); /* merge frees loop->block */
861 loop->block = NULL ;
862 start->next = loop->next ;
863 scatt_start->next = scatt_loop->next ;
865 else
866 { /* If we didn't find a block, the next start of a block is updated:
867 * O------>O------>O------>O------>NULL
868 * | |
869 * reference start
870 * loop
872 blocked= 0 ;
873 start = loop ;
874 scatt_start = scatt_loop ;
877 /* If the reference node has been included into a block, we can free it. */
878 if (blocked_reference)
879 { reference->next = NULL ;
880 cloog_loop_free(reference) ;
881 cloog_scattering_free(scatt_reference->scatt);
882 free(scatt_reference) ;
885 /* The reference and the loop are now updated for the next try, the
886 * starting position depends on the previous step.
887 * O ? O------>O------>O------>NULL
888 * | |
889 * reference loop
891 reference = loop ;
892 loop = loop->next ;
893 scatt_reference = scatt_loop ;
894 scatt_loop = scatt_loop->next ;
896 /* We mark the new reference as being blocked or not, if will be freed
897 * during the next while loop execution.
899 if (blocked)
900 blocked_reference = 1 ;
901 else
902 blocked_reference = 0 ;
905 /* We free the last blocked reference if any (since in the while loop it was
906 * freed during the next loop execution, it was not possible to free the
907 * last one inside).
909 if (blocked_reference)
910 { reference->next = NULL ;
911 cloog_loop_free(reference) ;
912 cloog_scattering_free(scatt_reference->scatt);
913 free(scatt_reference) ;
916 if (nb_blocked != 0)
917 cloog_msg(options, CLOOG_INFO, "%d domains have been blocked.\n", nb_blocked);
922 * cloog_program_extract_scalars function:
923 * this functions finds and removes the dimensions of the scattering functions
924 * when they are scalar (i.e. of the shape "dim + scalar = 0") for all
925 * scattering functions. The reason is that the processing of such dimensions
926 * is trivial and do not need neither a row and a column in the matrix
927 * representation of the domain (this will save memory) neither the full
928 * Quillere processing (this will save time). The scalar dimensions data are
929 * dispatched in the CloogProgram structure (the boolean vector scaldims will
930 * say which original dimensions are scalar or not) and to the CloogBlock
931 * structures (each one has a scaldims vector that contains the scalar values).
932 * - June 14th 2005: first developments.
933 * - June 30th 2005: first version.
935 void cloog_program_extract_scalars(CloogProgram *program,
936 CloogScatteringList *scattering, CloogOptions *options)
937 { int i, j, scalar, current, nb_scaldims=0 ;
938 CloogScatteringList *start;
939 CloogScattering *old;
940 CloogLoop *loop;
941 CloogBlock * block ;
943 start = scattering ;
945 for (i=0;i<program->nb_scattdims;i++)
946 { scalar = 1 ;
947 scattering = start ;
948 while (scattering != NULL)
949 { if (!cloog_scattering_lazy_isscalar(scattering->scatt, i, NULL))
950 { scalar = 0 ;
951 break ;
953 scattering = scattering->next ;
956 if (scalar)
957 { nb_scaldims ++ ;
958 program->scaldims[i] = 1 ;
962 /* If there are no scalar dimensions, we can continue directly. */
963 if (!nb_scaldims)
964 return ;
966 /* Otherwise, in each block, we have to put the number of scalar dimensions,
967 * and to allocate the memory for the scalar values.
969 for (loop = program->loop; loop; loop = loop->next) {
970 block = loop->block;
971 block->nb_scaldims = nb_scaldims ;
972 block->scaldims = (cloog_int_t *)malloc(nb_scaldims*sizeof(cloog_int_t));
973 for (i=0;i<nb_scaldims;i++)
974 cloog_int_init(block->scaldims[i]);
977 /* Then we have to fill these scalar values, so we can erase those dimensions
978 * from the scattering functions. It's easier to begin with the last one,
979 * since there would be an offset otherwise (if we remove the i^th dimension,
980 * then the next one is not the (i+1)^th but still the i^th...).
982 current = nb_scaldims - 1 ;
983 for (i=program->nb_scattdims-1;i>=0;i--)
984 if (program->scaldims[i])
986 scattering = start ;
987 for (loop = program->loop; loop; loop = loop->next) {
988 block = loop->block;
989 if (!cloog_scattering_lazy_isscalar(scattering->scatt, i,
990 &block->scaldims[current])) {
991 /* We should have found a scalar value: if not, there is an error. */
992 cloog_die("dimension %d is not scalar as expected.\n", i);
994 scattering = scattering->next ;
997 scattering = start ;
998 while (scattering != NULL) {
999 old = scattering->scatt;
1000 scattering->scatt = cloog_scattering_erase_dimension(old, i);
1001 cloog_scattering_free(old);
1002 scattering = scattering->next ;
1004 current-- ;
1007 /* We postprocess the scaldims array in such a way that each entry is how
1008 * many scalar dimensions follows + 1 (the current one). This will make
1009 * some other processing easier (e.g. knowledge of some offsets).
1011 for (i=0;i<program->nb_scattdims-1;i++)
1012 { if (program->scaldims[i])
1013 { j = i + 1 ;
1014 while ((j < program->nb_scattdims) && program->scaldims[j])
1015 { program->scaldims[i] ++ ;
1016 j ++ ;
1021 if (nb_scaldims != 0)
1022 cloog_msg(options, CLOOG_INFO, "%d dimensions (over %d) are scalar.\n",
1023 nb_scaldims,program->nb_scattdims) ;
1028 * cloog_program_scatter function:
1029 * This function adds the scattering (scheduling) informations in a program.
1030 * If names is NULL, this function create names itself such that the i^th
1031 * name is ci.
1032 * - November 6th 2001: first version.
1034 void cloog_program_scatter(CloogProgram *program,
1035 CloogScatteringList *scattering, CloogOptions *options)
1036 { int scattering_dim, scattering_dim2, not_enough_constraints=0 ;
1037 CloogLoop * loop ;
1039 if ((program != NULL) && (scattering != NULL))
1040 { loop = program->loop ;
1042 /* We compute the scattering dimension and check it is >=0. */
1043 scattering_dim = cloog_scattering_dimension(scattering->scatt, loop->domain);
1044 if (scattering_dim < 0)
1045 cloog_die("scattering has not enough dimensions.\n");
1046 if (!cloog_scattering_fully_specified(scattering->scatt, loop->domain))
1047 not_enough_constraints ++ ;
1049 /* The scattering dimension may have been modified by scalar extraction. */
1050 scattering_dim = cloog_scattering_dimension(scattering->scatt, loop->domain);
1052 /* Finally we scatter all loops. */
1053 cloog_loop_scatter(loop, scattering->scatt);
1054 loop = loop->next ;
1055 scattering = scattering->next ;
1057 while ((loop != NULL) && (scattering != NULL))
1058 { scattering_dim2 = cloog_scattering_dimension(scattering->scatt,
1059 loop->domain);
1060 if (scattering_dim2 != scattering_dim)
1061 cloog_die("scattering dimensions are not the same.\n") ;
1062 if (!cloog_scattering_fully_specified(scattering->scatt, loop->domain))
1063 not_enough_constraints ++ ;
1065 cloog_loop_scatter(loop, scattering->scatt);
1066 loop = loop->next ;
1067 scattering = scattering->next ;
1069 if ((loop != NULL) || (scattering != NULL))
1070 cloog_msg(options, CLOOG_WARNING,
1071 "there is not a scattering for each statement.\n");
1073 if (not_enough_constraints)
1074 cloog_msg(options, CLOOG_WARNING, "not enough constraints for "
1075 "%d scattering function(s).\n",not_enough_constraints) ;