clast traversal and node filtering support
[cloog.git] / source / program.c
blob2b3ec1a7d3fe5aaa17905b8a6d4a810ab54c85fc
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))
56 #ifdef OSL_SUPPORT
57 #include <osl/scop.h>
58 #include <osl/extensions/coordinates.h>
59 #endif
61 /******************************************************************************
62 * Structure display function *
63 ******************************************************************************/
66 /**
67 * cloog_program_print function:
68 * this function is a human-friendly way to display the CloogProgram data
69 * structure, it shows all the different fields and includes an indentation
70 * level (level) in order to work with others print_structure functions.
71 * - July 1st 2005: first version based on the old cloog_program_print function.
73 void cloog_program_print_structure(file, program, level)
74 FILE * file ;
75 CloogProgram * program ;
76 int level ;
77 { int i, j ;
79 /* Go to the right level. */
80 for (i=0; i<level; i++)
81 fprintf(file,"|\t") ;
83 fprintf(file,"+-- CloogProgram\n") ;
85 /* A blank line. */
86 for (i=0; i<=level+1; i++)
87 fprintf(file,"|\t") ;
88 fprintf(file,"\n") ;
90 /* Print the language. */
91 for (i=0; i<=level; i++)
92 fprintf(file,"|\t") ;
93 fprintf(file, "Language: %c\n",program->language) ;
95 /* A blank line. */
96 for (i=0; i<=level+1; i++)
97 fprintf(file,"|\t") ;
98 fprintf(file,"\n") ;
100 /* Print the scattering dimension number. */
101 for (i=0; i<=level; i++)
102 fprintf(file,"|\t") ;
103 fprintf(file,"Scattering dimension number: %d\n",program->nb_scattdims) ;
105 /* A blank line. */
106 for (i=0; i<=level+1; i++)
107 fprintf(file,"|\t") ;
108 fprintf(file,"\n") ;
110 /* Print the scalar scattering dimension informations. */
111 for (i=0; i<=level; i++)
112 fprintf(file,"|\t") ;
113 if (program->scaldims != NULL)
114 { fprintf(file,"Scalar dimensions:") ;
115 for (i=0;i<program->nb_scattdims;i++)
116 fprintf(file," %d:%d ",i,program->scaldims[i]) ;
117 fprintf(file,"\n") ;
119 else
120 fprintf(file,"No scalar scattering dimensions\n") ;
122 /* A blank line. */
123 for (i=0; i<=level+1; i++)
124 fprintf(file,"|\t") ;
125 fprintf(file,"\n") ;
127 /* Print the parameter and the iterator names. */
128 cloog_names_print_structure(file,program->names,level+1) ;
130 /* A blank line. */
131 for (i=0; i<=level+1; i++)
132 fprintf(file,"|\t") ;
133 fprintf(file,"\n") ;
135 /* Print the context. */
136 cloog_domain_print_structure(file, program->context, level+1, "Context");
138 /* Print the loop. */
139 cloog_loop_print_structure(file,program->loop,level+1) ;
141 /* One more time something that is here only for a better look. */
142 for (j=0; j<2; j++)
143 { for (i=0; i<=level; i++)
144 fprintf(file,"|\t") ;
146 fprintf(file,"\n") ;
152 * cloog_program_dump_cloog function:
153 * This function dumps a CloogProgram structure supposed to be completely
154 * filled in a CLooG input file (foo possibly stdout) such as CLooG can
155 * rebuild almost exactly the data structure from the input file.
157 * If the scattering is already applied, the scattering parameter is supposed to
158 * be NULL. In this case the number of scattering functions is lost, since they
159 * are included inside the iteration domains. This can only lead to a less
160 * beautiful pretty printing.
162 * In case the scattering is not yet applied it can be passed to this function
163 * and will be included in the CLooG input file dump.
165 void cloog_program_dump_cloog(FILE * foo, CloogProgram * program,
166 CloogScatteringList *scattering)
168 int i;
169 CloogLoop * loop ;
170 CloogScatteringList *tmp_scatt;
172 fprintf(foo,
173 "# CLooG -> CLooG\n"
174 "# This is an automatic dump of a CLooG input file from a CloogProgram data\n"
175 "# structure. WARNING: it is highly dangerous and MAY be correct ONLY if\n"
176 "# - it has been dumped before loop generation.\n"
177 "# - option -noscalars is used (it removes scalar dimensions otherwise)\n"
178 "# - option -l is at least the original scattering dimension number\n"
179 "# ASK THE AUTHOR IF YOU *NEED* SOMETHING MORE ROBUST\n") ;
181 /* Language. */
182 if (program->language == 'c')
183 fprintf(foo,"# Language: C\n") ;
184 else
185 fprintf(foo,"# Language: FORTRAN\n") ;
186 fprintf(foo,"%c\n\n",program->language) ;
188 /* Context. */
189 fprintf(foo, "# Context (%d parameter(s)):\n", program->names->nb_parameters);
190 cloog_domain_print_constraints(foo, program->context, 0);
191 fprintf(foo,"1 # Parameter name(s)\n") ;
192 for (i=0;i<program->names->nb_parameters;i++)
193 fprintf(foo,"%s ",program->names->parameters[i]) ;
195 /* Statement number. */
196 i = 0 ;
197 loop = program->loop ;
198 while (loop != NULL)
199 { i++ ;
200 loop = loop->next ;
202 fprintf(foo,"\n\n# Statement number:\n%d\n\n",i) ;
204 /* Iteration domains. */
205 i = 1 ;
206 loop = program->loop ;
207 while (loop != NULL)
208 { /* Name of the domain. */
209 fprintf(foo,"# Iteration domain of statement %d.\n",i) ;
211 cloog_domain_print_constraints(foo, loop->domain, 1);
212 fprintf(foo,"0 0 0 # For future options.\n\n") ;
214 i++ ;
215 loop = loop->next ;
217 fprintf(foo,"\n1 # Iterator name(s)\n") ;
219 /* Scattering already applied? In this case print the scattering names as
220 * additional iterator names. */
221 if (!scattering)
222 for (i = 0; i < program->names->nb_scattering; i++)
223 fprintf(foo, "%s ", program->names->scattering[i]);
224 for (i=0;i<program->names->nb_iterators;i++)
225 fprintf(foo,"%s ",program->names->iterators[i]);
226 fprintf(foo,"\n\n") ;
228 /* Exit, if scattering is already applied. */
229 if (!scattering) {
230 fprintf(foo, "# No scattering functions.\n0\n\n");
231 return;
234 /* Scattering relations. */
235 fprintf(foo, "# --------------------- SCATTERING --------------------\n");
237 i = 0;
238 for (tmp_scatt = scattering; tmp_scatt; tmp_scatt = tmp_scatt->next)
239 i++;
241 fprintf(foo, "%d # Scattering functions", i);
243 for (tmp_scatt = scattering; tmp_scatt; tmp_scatt = tmp_scatt->next)
244 cloog_scattering_print_constraints(foo, tmp_scatt->scatt);
246 fprintf(foo, "\n1 # Scattering dimension name(s)\n");
248 for (i = 0; i < program->names->nb_scattering; i++)
249 fprintf(foo, "%s ", program->names->scattering[i]);
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 == CLOOG_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");
283 static void print_macros(FILE *file)
285 fprintf(file, "/* Useful macros. */\n") ;
286 fprintf(file,
287 "#define floord(n,d) (((n)<0) ? -((-(n)+(d)-1)/(d)) : (n)/(d))\n");
288 fprintf(file,
289 "#define ceild(n,d) (((n)<0) ? -((-(n))/(d)) : ((n)+(d)-1)/(d))\n");
290 fprintf(file, "#define max(x,y) ((x) > (y) ? (x) : (y))\n") ;
291 fprintf(file, "#define min(x,y) ((x) < (y) ? (x) : (y))\n\n") ;
294 static void print_declarations(FILE *file, int n, char **names)
296 int i;
298 fprintf(file, " int %s", names[0]);
299 for (i = 1; i < n; i++)
300 fprintf(file, ", %s", names[i]);
302 fprintf(file, ";\n");
305 static void print_iterator_declarations(FILE *file, CloogProgram *program,
306 CloogOptions *options)
308 CloogNames *names = program->names;
310 if (names->nb_scattering) {
311 fprintf(file, " /* Scattering iterators. */\n");
312 print_declarations(file, names->nb_scattering, names->scattering);
314 if (names->nb_iterators) {
315 fprintf(file, " /* Original iterators. */\n");
316 print_declarations(file, names->nb_iterators, names->iterators);
320 static void print_callable_preamble(FILE *file, CloogProgram *program,
321 CloogOptions *options)
323 int j;
324 CloogBlockList *blocklist;
325 CloogBlock *block;
326 CloogStatement *statement;
328 fprintf(file, "extern void hash(int);\n\n");
330 print_macros(file);
332 for (blocklist = program->blocklist; blocklist; blocklist = blocklist->next) {
333 block = blocklist->block;
334 for (statement = block->statement; statement; statement = statement->next) {
335 fprintf(file, "#define S%d(", statement->number);
336 if (block->depth > 0) {
337 fprintf(file, "%s", program->names->iterators[0]);
338 for(j = 1; j < block->depth; j++)
339 fprintf(file, ",%s", program->names->iterators[j]);
341 fprintf(file,") { hash(%d);", statement->number);
342 for(j = 0; j < block->depth; j++)
343 fprintf(file, " hash(%s);", program->names->iterators[j]);
344 fprintf(file, " }\n");
347 fprintf(file, "\nvoid test(");
348 if (program->names->nb_parameters > 0) {
349 fprintf(file, "int %s", program->names->parameters[0]);
350 for(j = 1; j < program->names->nb_parameters; j++)
351 fprintf(file, ", int %s", program->names->parameters[j]);
353 fprintf(file, ")\n{\n");
354 print_iterator_declarations(file, program, options);
357 static void print_callable_postamble(FILE *file, CloogProgram *program)
359 fprintf(file, "}\n");
363 * cloog_program_osl_pprint function:
364 * this function pretty-prints the C or FORTRAN code generated from an
365 * OpenScop specification by overwriting SCoP in a given code, if the
366 * options -compilable or -callable are not set. The SCoP coordinates are
367 * provided through the OpenScop "Coordinates" extension. It returns 1 if
368 * it succeeds to find an OpenScop coordinates information
369 * to pretty-print the generated code, 0 otherwise.
370 * \param[in] file The output stream (possibly stdout).
371 * \param[in] program The generated pseudo-AST to pretty-print.
372 * \param[in] options CLooG options (contains the OpenSCop specification).
373 * \return 1 on success to pretty-print at the place of a SCoP, 0 otherwise.
375 int cloog_program_osl_pprint(FILE * file, CloogProgram * program,
376 CloogOptions * options) {
377 #ifdef OSL_SUPPORT
378 int lines = 0;
379 int read = 1;
380 char c;
381 osl_scop_p scop = options->scop;
382 osl_coordinates_p coordinates;
383 struct clast_stmt *root;
384 FILE * original;
386 if (scop && !options->compilable && !options->callable) {
387 coordinates = osl_generic_lookup(scop->extension, OSL_URI_COORDINATES);
388 if (coordinates) {
389 original = fopen(coordinates->name, "r");
390 if (!original) {
391 cloog_msg(options, CLOOG_WARNING,
392 "unable to open the file specified in the SCoP "
393 "coordinates\n");
394 return 0;
397 /* Print the macros the generated code may need. */
398 print_macros(file);
400 /* Print what was before the SCoP in the original file. */
401 while ((lines < coordinates->start) && (read != EOF)) {
402 read = fscanf(original, "%c", &c);
403 if (read != EOF) {
404 if (c == '\n')
405 lines ++;
406 fprintf(file, "%c", c);
410 /* Generate the clast from the pseudo-AST then pretty-print it. */
411 root = cloog_clast_create(program, options);
412 clast_pprint(file, root, coordinates->indent, options);
413 cloog_clast_free(root);
415 /* Print what was after the SCoP in the original file. */
416 while (read != EOF) {
417 read = fscanf(original, "%c", &c);
418 if (read != EOF) {
419 if (lines >= coordinates->end - 1)
420 fprintf(file, "%c", c);
421 if (c == '\n')
422 lines ++;
426 fclose(original);
427 return 1;
430 #endif
431 return 0;
435 * cloog_program_pprint function:
436 * This function prints the content of a CloogProgram structure (program) into a
437 * file (file, possibly stdout), in a C-like language.
438 * - June 22nd 2005: Adaptation for GMP.
440 void cloog_program_pprint(file, program, options)
441 FILE * file ;
442 CloogProgram * program ;
443 CloogOptions * options ;
445 int i, j, indentation = 0;
446 CloogStatement * statement ;
447 CloogBlockList * blocklist ;
448 CloogBlock * block ;
449 struct clast_stmt *root;
451 if (cloog_program_osl_pprint(file, program, options))
452 return;
454 if (program->language == 'f')
455 options->language = CLOOG_LANGUAGE_FORTRAN ;
456 else
457 options->language = CLOOG_LANGUAGE_C ;
459 #ifdef CLOOG_RUSAGE
460 print_comment(file, options, "Generated from %s by %s in %.2fs.",
461 options->name, cloog_version(), options->time);
462 #else
463 print_comment(file, options, "Generated from %s by %s.",
464 options->name, cloog_version());
465 #endif
466 #ifdef CLOOG_MEMORY
467 print_comment(file, options, "CLooG asked for %d KBytes.", options->memory);
468 cloog_msg(CLOOG_INFO, "%.2fs and %dKB used for code generation.\n",
469 options->time,options->memory);
470 #endif
472 /* If the option "compilable" is set, we provide the whole stuff to generate
473 * a compilable code. This code just do nothing, but now the user can edit
474 * the source and set the statement macros and parameters values.
476 if (options->compilable && (program->language == 'c'))
477 { /* The headers. */
478 fprintf(file,"/* DON'T FORGET TO USE -lm OPTION TO COMPILE. */\n\n") ;
479 fprintf(file,"/* Useful headers. */\n") ;
480 fprintf(file,"#include <stdio.h>\n") ;
481 fprintf(file,"#include <stdlib.h>\n") ;
482 fprintf(file,"#include <math.h>\n\n") ;
484 /* The value of parameters. */
485 fprintf(file,"/* Parameter value. */\n") ;
486 for (i = 1; i <= program->names->nb_parameters; i++)
487 fprintf(file, "#define PARVAL%d %d\n", i, options->compilable);
489 /* The macros. */
490 print_macros(file);
492 /* The statement macros. */
493 fprintf(file,"/* Statement macros (please set). */\n") ;
494 blocklist = program->blocklist ;
495 while (blocklist != NULL)
496 { block = blocklist->block ;
497 statement = block->statement ;
498 while (statement != NULL)
499 { fprintf(file,"#define S%d(",statement->number) ;
500 if (block->depth > 0)
501 { fprintf(file,"%s",program->names->iterators[0]) ;
502 for(j=1;j<block->depth;j++)
503 fprintf(file,",%s",program->names->iterators[j]) ;
505 fprintf(file,") {total++;") ;
506 if (block->depth > 0) {
507 fprintf(file, " printf(\"S%d %%d", statement->number);
508 for(j=1;j<block->depth;j++)
509 fprintf(file, " %%d");
511 fprintf(file,"\\n\",%s",program->names->iterators[0]) ;
512 for(j=1;j<block->depth;j++)
513 fprintf(file,",%s",program->names->iterators[j]) ;
514 fprintf(file,");") ;
516 fprintf(file,"}\n") ;
518 statement = statement->next ;
520 blocklist = blocklist->next ;
523 /* The iterator and parameter declaration. */
524 fprintf(file,"\nint main() {\n") ;
525 print_iterator_declarations(file, program, options);
526 if (program->names->nb_parameters > 0)
527 { fprintf(file," /* Parameters. */\n") ;
528 fprintf(file, " int %s=PARVAL1",program->names->parameters[0]);
529 for(i=2;i<=program->names->nb_parameters;i++)
530 fprintf(file, ", %s=PARVAL%d", program->names->parameters[i-1], i);
532 fprintf(file,";\n");
534 fprintf(file," int total=0;\n");
535 fprintf(file,"\n") ;
537 /* And we adapt the identation. */
538 indentation += 2 ;
539 } else if (options->callable && program->language == 'c') {
540 print_callable_preamble(file, program, options);
541 indentation += 2;
544 root = cloog_clast_create(program, options);
545 clast_pprint(file, root, indentation, options);
546 cloog_clast_free(root);
548 /* The end of the compilable code in case of 'compilable' option. */
549 if (options->compilable && (program->language == 'c'))
551 fprintf(file, "\n printf(\"Number of integral points: %%d.\\n\",total);");
552 fprintf(file, "\n return 0;\n}\n");
553 } else if (options->callable && program->language == 'c')
554 print_callable_postamble(file, program);
558 /******************************************************************************
559 * Memory deallocation function *
560 ******************************************************************************/
564 * cloog_program_free function:
565 * This function frees the allocated memory for a CloogProgram structure.
567 void cloog_program_free(CloogProgram * program)
568 { cloog_names_free(program->names) ;
569 cloog_loop_free(program->loop) ;
570 cloog_domain_free(program->context) ;
571 cloog_block_list_free(program->blocklist) ;
572 if (program->scaldims != NULL)
573 free(program->scaldims) ;
575 free(program) ;
579 /******************************************************************************
580 * Reading function *
581 ******************************************************************************/
584 static void cloog_program_construct_block_list(CloogProgram *p)
586 CloogLoop *loop;
587 CloogBlockList **next = &p->blocklist;
589 for (loop = p->loop; loop; loop = loop->next) {
590 *next = cloog_block_list_alloc(loop->block);
591 next = &(*next)->next;
597 * Construct a CloogProgram structure from a given context and
598 * union domain representing the iteration domains and scattering functions.
600 CloogProgram *cloog_program_alloc(CloogDomain *context, CloogUnionDomain *ud,
601 CloogOptions *options)
603 int i;
604 char prefix[] = "c";
605 CloogScatteringList * scatteringl;
606 CloogNames *n;
607 CloogProgram * p ;
609 /* Memory allocation for the CloogProgram structure. */
610 p = cloog_program_malloc() ;
612 if (options->language == CLOOG_LANGUAGE_FORTRAN)
613 p->language = 'f';
614 else
615 p->language = 'c';
617 p->names = n = cloog_names_alloc();
619 /* We then read the context data. */
620 p->context = context;
621 n->nb_parameters = ud->n_name[CLOOG_PARAM];
623 /* First part of the CloogNames structure: the parameter names. */
624 if (ud->name[CLOOG_PARAM]) {
625 n->parameters = ud->name[CLOOG_PARAM];
626 ud->name[CLOOG_PARAM] = NULL;
627 } else
628 n->parameters = cloog_names_generate_items(n->nb_parameters, NULL,
629 FIRST_PARAMETER);
631 n->nb_iterators = ud->n_name[CLOOG_ITER];
632 if (ud->name[CLOOG_ITER]) {
633 n->iterators = ud->name[CLOOG_ITER];
634 ud->name[CLOOG_ITER] = NULL;
635 } else
636 n->iterators = cloog_names_generate_items(n->nb_iterators, NULL,
637 FIRST_ITERATOR);
639 if (ud->domain) {
640 CloogNamedDomainList *l;
641 CloogLoop **next = &p->loop;
642 CloogScatteringList **next_scat = &scatteringl;
644 scatteringl = NULL;
645 for (i = 0, l = ud->domain; l; ++i, l = l->next) {
646 *next = cloog_loop_from_domain(options->state, l->domain, i);
647 l->domain = NULL;
648 (*next)->block->statement->name = l->name;
649 (*next)->block->statement->usr = l->usr;
650 l->name = NULL;
652 if (l->scattering) {
653 *next_scat = ALLOC(CloogScatteringList);
654 (*next_scat)->scatt = l->scattering;
655 l->scattering = NULL;
656 (*next_scat)->next = NULL;
658 next_scat = &(*next_scat)->next;
661 next = &(*next)->next;
664 if (scatteringl != NULL) {
665 p->nb_scattdims = cloog_scattering_dimension(scatteringl->scatt,
666 p->loop->domain);
667 n->nb_scattering = p->nb_scattdims;
668 if (ud->name[CLOOG_SCAT]) {
669 n->scattering = ud->name[CLOOG_SCAT];
670 ud->name[CLOOG_SCAT] = NULL;
671 } else
672 n->scattering = cloog_names_generate_items(n->nb_scattering, prefix, -1);
674 /* The boolean array for scalar dimensions is created and set to 0. */
675 p->scaldims = (int *)malloc(p->nb_scattdims*(sizeof(int))) ;
676 if (p->scaldims == NULL)
677 cloog_die("memory overflow.\n");
678 for (i=0;i<p->nb_scattdims;i++)
679 p->scaldims[i] = 0 ;
681 /* We try to find blocks in the input problem to reduce complexity. */
682 if (!options->noblocks)
683 cloog_program_block(p, scatteringl, options);
684 if (!options->noscalars)
685 cloog_program_extract_scalars(p, scatteringl, options);
687 cloog_program_scatter(p, scatteringl, options);
688 cloog_scattering_list_free(scatteringl);
690 if (!options->noblocks)
691 p->loop = cloog_loop_block(p->loop, p->scaldims, p->nb_scattdims);
693 else
694 { p->nb_scattdims = 0 ;
695 p->scaldims = NULL ;
698 cloog_names_scalarize(p->names,p->nb_scattdims,p->scaldims) ;
700 cloog_program_construct_block_list(p);
702 else
703 { p->loop = NULL ;
704 p->blocklist = NULL ;
705 p->scaldims = NULL ;
708 cloog_union_domain_free(ud);
710 return(p) ;
715 * cloog_program_read function:
716 * This function read the informations to put in a CloogProgram structure from
717 * a file (file, possibly stdin). It returns a pointer to a CloogProgram
718 * structure containing the read informations.
719 * - October 25th 2001: first version.
720 * - September 9th 2002: - the big reading function is now split in several
721 * functions (one per read data structure).
722 * - adaptation to the new file format with naming.
724 CloogProgram *cloog_program_read(FILE *file, CloogOptions *options)
726 CloogInput *input;
727 CloogProgram *p;
729 input = cloog_input_read(file, options);
730 p = cloog_program_alloc(input->context, input->ud, options);
731 free(input);
733 return p;
737 /******************************************************************************
738 * Processing functions *
739 ******************************************************************************/
743 * cloog_program_malloc function:
744 * This function allocates the memory space for a CloogProgram structure and
745 * sets its fields with default values. Then it returns a pointer to the
746 * allocated space.
747 * - November 21th 2005: first version.
749 CloogProgram * cloog_program_malloc()
750 { CloogProgram * program ;
752 /* Memory allocation for the CloogProgram structure. */
753 program = (CloogProgram *)malloc(sizeof(CloogProgram)) ;
754 if (program == NULL)
755 cloog_die("memory overflow.\n");
757 /* We set the various fields with default values. */
758 program->language = 'c' ;
759 program->nb_scattdims = 0 ;
760 program->context = NULL ;
761 program->loop = NULL ;
762 program->names = NULL ;
763 program->blocklist = NULL ;
764 program->scaldims = NULL ;
765 program->usr = NULL;
767 return program ;
772 * cloog_program_generate function:
773 * This function calls the Quillere algorithm for loop scanning. (see the
774 * Quillere paper) and calls the loop simplification function.
775 * - depth is the loop depth we want to optimize (guard free as possible),
776 * the first loop depth is 1 and anegative value is the infinity depth.
777 * - sep_level is the level number where we want to start loop separation.
779 * - October 26th 2001: first version.
780 * - April 19th 2005: some basic fixes and memory usage feature.
781 * - April 29th 2005: (bug fix, bug found by DaeGon Kim) see case 2 below.
783 CloogProgram * cloog_program_generate(program, options)
784 CloogProgram * program ;
785 CloogOptions * options ;
787 #ifdef CLOOG_RUSAGE
788 float time;
789 struct rusage start, end ;
790 #endif
791 CloogLoop * loop ;
792 #ifdef CLOOG_MEMORY
793 char status_path[MAX_STRING_VAL] ;
794 FILE * status ;
796 /* We initialize the memory need to 0. */
797 options->memory = 0 ;
798 #endif
800 if (options->override)
802 cloog_msg(options, CLOOG_WARNING,
803 "you are using -override option, be aware that the "
804 "generated\n code may be incorrect.\n") ;
806 else
807 { /* Playing with options may be dangerous, here are two possible issues :
808 * 1. Using -l option less than scattering dimension number may lead to
809 * an illegal target code (since the scattering is not respected), if
810 * it is the case, we set -l depth to the first acceptable value.
812 if ((program->nb_scattdims > options->l) && (options->l >= 0))
814 cloog_msg(options, CLOOG_WARNING,
815 "-l depth is less than the scattering dimension number "
816 "(the \n generated code may be incorrect), it has been "
817 "automaticaly set\n to this value (use option -override "
818 "to override).\n") ;
819 options->l = program->nb_scattdims ;
822 /* 2. Using -f option greater than one while -l depth is greater than the
823 * scattering dimension number may lead to iteration duplication (try
824 * test/daegon_lu_osp.cloog with '-f 3' to test) because of the step 4b
825 * of the cloog_loop_generate function, if it is the case, we set -l to
826 * the first acceptable value.
828 if (((options->f > 1) || (options->f < 0)) &&
829 ((options->l > program->nb_scattdims) || (options->l < 0)))
831 cloog_msg(options, CLOOG_WARNING,
832 "-f depth is more than one, -l depth has been "
833 "automaticaly set\n to the scattering dimension number "
834 "(target code may have\n duplicated iterations), -l depth "
835 "has been automaticaly set to\n this value (use option "
836 "-override to override).\n") ;
837 options->l = program->nb_scattdims ;
841 #ifdef CLOOG_RUSAGE
842 getrusage(RUSAGE_SELF, &start) ;
843 #endif
844 if (program->loop != NULL)
845 { loop = program->loop ;
847 /* Here we go ! */
848 loop = cloog_loop_generate(loop, program->context, 0, 0,
849 program->scaldims,
850 program->nb_scattdims,
851 options);
853 #ifdef CLOOG_MEMORY
854 /* We read into the status file of the process how many memory it uses. */
855 sprintf(status_path,"/proc/%d/status",getpid()) ;
856 status = fopen(status_path, "r") ;
857 while (fscanf(status,"%s",status_path) && strcmp(status_path,"VmData:")!=0);
858 fscanf(status,"%d",&(options->memory)) ;
859 fclose(status) ;
860 #endif
862 if ((!options->nosimplify) && (program->loop != NULL))
863 loop = cloog_loop_simplify(loop, program->context, 0,
864 program->nb_scattdims, options);
866 program->loop = loop ;
869 #ifdef CLOOG_RUSAGE
870 getrusage(RUSAGE_SELF, &end) ;
871 /* We calculate the time spent in code generation. */
872 time = (end.ru_utime.tv_usec - start.ru_utime.tv_usec)/(float)(MEGA) ;
873 time += (float)(end.ru_utime.tv_sec - start.ru_utime.tv_sec) ;
874 options->time = time ;
875 #endif
877 return program ;
882 * cloog_program_block function:
883 * this function gives a last chance to the lazy user to consider statement
884 * blocks instead of some statement lists where the whole list may be
885 * considered as a single statement from a code generation point of view.
886 * For instance two statements with the same iteration domain and the same
887 * scattering functions may be considered as a block. This function is lazy
888 * and can only find very simple forms of trivial blocks (see
889 * cloog_domain_lazy_block function for more details). The useless loops and
890 * scattering functions are removed and freed while the statement list of
891 * according blocks are filled.
892 * - program is the whole program structure (befaore applying scattering),
893 * - scattering is the list of scattering functions.
895 * - April 30th 2005: first attempt.
896 * - June 10-11th 2005: first working version.
898 void cloog_program_block(CloogProgram *program,
899 CloogScatteringList *scattering, CloogOptions *options)
900 { int blocked_reference=0, blocked=0, nb_blocked=0 ;
901 CloogLoop * reference, * start, * loop ;
902 CloogScatteringList * scatt_reference, * scatt_loop, * scatt_start;
904 if ((program->loop == NULL) || (program->loop->next == NULL))
905 return ;
907 /* The process will use three variables for the linked list :
908 * - 'start' is the starting point of a new block,
909 * - 'reference' is the node of the block used for the block checking,
910 * - 'loop' is the candidate to be inserted inside the block.
911 * At the beginning of the process, the linked lists are as follow:
912 * O------>O------>O------>O------>NULL
913 * | |
914 * start loop
915 * reference
918 reference = program->loop ;
919 start = program->loop ;
920 loop = reference->next ;
921 scatt_reference = scattering ;
922 scatt_start = scattering ;
923 scatt_loop = scattering->next ;
925 while (loop != NULL)
926 { if (cloog_domain_lazy_equal(reference->domain,loop->domain) &&
927 cloog_scattering_lazy_block(scatt_reference->scatt, scatt_loop->scatt,
928 scattering,program->nb_scattdims))
929 { /* If we find a block we update the links:
930 * +---------------+
931 * | v
932 * O O------>O------>O------>NULL
933 * | |
934 * start loop
935 * reference
937 blocked = 1 ;
938 nb_blocked ++ ;
939 cloog_block_merge(start->block,loop->block); /* merge frees loop->block */
940 loop->block = NULL ;
941 start->next = loop->next ;
942 scatt_start->next = scatt_loop->next ;
944 else
945 { /* If we didn't find a block, the next start of a block is updated:
946 * O------>O------>O------>O------>NULL
947 * | |
948 * reference start
949 * loop
951 blocked= 0 ;
952 start = loop ;
953 scatt_start = scatt_loop ;
956 /* If the reference node has been included into a block, we can free it. */
957 if (blocked_reference)
958 { reference->next = NULL ;
959 cloog_loop_free(reference) ;
960 cloog_scattering_free(scatt_reference->scatt);
961 free(scatt_reference) ;
964 /* The reference and the loop are now updated for the next try, the
965 * starting position depends on the previous step.
966 * O ? O------>O------>O------>NULL
967 * | |
968 * reference loop
970 reference = loop ;
971 loop = loop->next ;
972 scatt_reference = scatt_loop ;
973 scatt_loop = scatt_loop->next ;
975 /* We mark the new reference as being blocked or not, if will be freed
976 * during the next while loop execution.
978 if (blocked)
979 blocked_reference = 1 ;
980 else
981 blocked_reference = 0 ;
984 /* We free the last blocked reference if any (since in the while loop it was
985 * freed during the next loop execution, it was not possible to free the
986 * last one inside).
988 if (blocked_reference)
989 { reference->next = NULL ;
990 cloog_loop_free(reference) ;
991 cloog_scattering_free(scatt_reference->scatt);
992 free(scatt_reference) ;
995 if (nb_blocked != 0)
996 cloog_msg(options, CLOOG_INFO, "%d domains have been blocked.\n", nb_blocked);
1001 * cloog_program_extract_scalars function:
1002 * this functions finds and removes the dimensions of the scattering functions
1003 * when they are scalar (i.e. of the shape "dim + scalar = 0") for all
1004 * scattering functions. The reason is that the processing of such dimensions
1005 * is trivial and do not need neither a row and a column in the matrix
1006 * representation of the domain (this will save memory) neither the full
1007 * Quillere processing (this will save time). The scalar dimensions data are
1008 * dispatched in the CloogProgram structure (the boolean vector scaldims will
1009 * say which original dimensions are scalar or not) and to the CloogBlock
1010 * structures (each one has a scaldims vector that contains the scalar values).
1011 * - June 14th 2005: first developments.
1012 * - June 30th 2005: first version.
1014 void cloog_program_extract_scalars(CloogProgram *program,
1015 CloogScatteringList *scattering, CloogOptions *options)
1016 { int i, j, scalar, current, nb_scaldims=0 ;
1017 CloogScatteringList *start;
1018 CloogScattering *old;
1019 CloogLoop *loop;
1020 CloogBlock * block ;
1022 start = scattering ;
1024 for (i=0;i<program->nb_scattdims;i++)
1025 { scalar = 1 ;
1026 scattering = start ;
1027 while (scattering != NULL)
1028 { if (!cloog_scattering_lazy_isscalar(scattering->scatt, i, NULL))
1029 { scalar = 0 ;
1030 break ;
1032 scattering = scattering->next ;
1035 if (scalar)
1036 { nb_scaldims ++ ;
1037 program->scaldims[i] = 1 ;
1041 /* If there are no scalar dimensions, we can continue directly. */
1042 if (!nb_scaldims)
1043 return ;
1045 /* Otherwise, in each block, we have to put the number of scalar dimensions,
1046 * and to allocate the memory for the scalar values.
1048 for (loop = program->loop; loop; loop = loop->next) {
1049 block = loop->block;
1050 block->nb_scaldims = nb_scaldims ;
1051 block->scaldims = (cloog_int_t *)malloc(nb_scaldims*sizeof(cloog_int_t));
1052 for (i=0;i<nb_scaldims;i++)
1053 cloog_int_init(block->scaldims[i]);
1056 /* Then we have to fill these scalar values, so we can erase those dimensions
1057 * from the scattering functions. It's easier to begin with the last one,
1058 * since there would be an offset otherwise (if we remove the i^th dimension,
1059 * then the next one is not the (i+1)^th but still the i^th...).
1061 current = nb_scaldims - 1 ;
1062 for (i=program->nb_scattdims-1;i>=0;i--)
1063 if (program->scaldims[i])
1065 scattering = start ;
1066 for (loop = program->loop; loop; loop = loop->next) {
1067 block = loop->block;
1068 if (!cloog_scattering_lazy_isscalar(scattering->scatt, i,
1069 &block->scaldims[current])) {
1070 /* We should have found a scalar value: if not, there is an error. */
1071 cloog_die("dimension %d is not scalar as expected.\n", i);
1073 scattering = scattering->next ;
1076 scattering = start ;
1077 while (scattering != NULL) {
1078 old = scattering->scatt;
1079 scattering->scatt = cloog_scattering_erase_dimension(old, i);
1080 cloog_scattering_free(old);
1081 scattering = scattering->next ;
1083 current-- ;
1086 /* We postprocess the scaldims array in such a way that each entry is how
1087 * many scalar dimensions follows + 1 (the current one). This will make
1088 * some other processing easier (e.g. knowledge of some offsets).
1090 for (i=0;i<program->nb_scattdims-1;i++)
1091 { if (program->scaldims[i])
1092 { j = i + 1 ;
1093 while ((j < program->nb_scattdims) && program->scaldims[j])
1094 { program->scaldims[i] ++ ;
1095 j ++ ;
1100 if (nb_scaldims != 0)
1101 cloog_msg(options, CLOOG_INFO, "%d dimensions (over %d) are scalar.\n",
1102 nb_scaldims,program->nb_scattdims) ;
1107 * cloog_program_scatter function:
1108 * This function adds the scattering (scheduling) informations in a program.
1109 * If names is NULL, this function create names itself such that the i^th
1110 * name is ci.
1111 * - November 6th 2001: first version.
1113 void cloog_program_scatter(CloogProgram *program,
1114 CloogScatteringList *scattering, CloogOptions *options)
1115 { int scattering_dim, scattering_dim2, not_enough_constraints=0 ;
1116 CloogLoop * loop ;
1118 if ((program != NULL) && (scattering != NULL))
1119 { loop = program->loop ;
1121 /* We compute the scattering dimension and check it is >=0. */
1122 scattering_dim = cloog_scattering_dimension(scattering->scatt, loop->domain);
1123 if (scattering_dim < 0)
1124 cloog_die("scattering has not enough dimensions.\n");
1125 if (!cloog_scattering_fully_specified(scattering->scatt, loop->domain))
1126 not_enough_constraints ++ ;
1128 /* The scattering dimension may have been modified by scalar extraction. */
1129 scattering_dim = cloog_scattering_dimension(scattering->scatt, loop->domain);
1131 /* Finally we scatter all loops. */
1132 cloog_loop_scatter(loop, scattering->scatt);
1133 loop = loop->next ;
1134 scattering = scattering->next ;
1136 while ((loop != NULL) && (scattering != NULL))
1137 { scattering_dim2 = cloog_scattering_dimension(scattering->scatt,
1138 loop->domain);
1139 if (scattering_dim2 != scattering_dim)
1140 cloog_die("scattering dimensions are not the same.\n") ;
1141 if (!cloog_scattering_fully_specified(scattering->scatt, loop->domain))
1142 not_enough_constraints ++ ;
1144 cloog_loop_scatter(loop, scattering->scatt);
1145 loop = loop->next ;
1146 scattering = scattering->next ;
1148 if ((loop != NULL) || (scattering != NULL))
1149 cloog_msg(options, CLOOG_WARNING,
1150 "there is not a scattering for each statement.\n");
1152 if (not_enough_constraints)
1153 cloog_msg(options, CLOOG_WARNING, "not enough constraints for "
1154 "%d scattering function(s).\n",not_enough_constraints) ;