2 /**-------------------------------------------------------------------**
4 **-------------------------------------------------------------------**
6 **-------------------------------------------------------------------**
7 ** First version: october 25th 2001 **
8 **-------------------------------------------------------------------**/
11 /******************************************************************************
12 * CLooG : the Chunky Loop Generator (experimental) *
13 ******************************************************************************
15 * Copyright (C) 2001-2005 Cedric Bastoul *
17 * This is free software; you can redistribute it and/or modify it under the *
18 * terms of the GNU General Public License as published by the Free Software *
19 * Foundation; either version 2 of the License, or (at your option) any later *
22 * This software is distributed in the hope that it will be useful, but *
23 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
24 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
27 * You should have received a copy of the GNU General Public License along *
28 * with software; if not, write to the Free Software Foundation, Inc., *
29 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
31 * CLooG, the Chunky Loop Generator *
32 * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr *
34 ******************************************************************************/
35 /* CAUTION: the english used for comments is probably the worst you ever read,
36 * please feel free to correct and improve it !
40 # include <sys/types.h>
41 # include <sys/time.h>
42 # include <sys/resource.h>
48 # include "../include/cloog/cloog.h"
51 /******************************************************************************
52 * Memory leaks hunting *
53 ******************************************************************************/
57 * These global variables are devoted to memory leaks hunting: we
58 * want to know at each moment how many Value variables have been allocated
59 * since in GMP mode they have to be freed (see domain.c for the declaration).
60 * - July 3rd->11th 2003: first version (memory leaks hunt and correction).
63 extern int cloog_value_allocated
;
64 extern int cloog_value_freed
;
65 extern int cloog_value_max
;
68 /******************************************************************************
69 * Structure display function *
70 ******************************************************************************/
74 * cloog_program_print function:
75 * this function is a human-friendly way to display the CloogProgram data
76 * structure, it shows all the different fields and includes an indentation
77 * level (level) in order to work with others print_structure functions.
78 * - July 1st 2005: first version based on the old cloog_program_print function.
80 void cloog_program_print_structure(file
, program
, level
)
82 CloogProgram
* program
;
85 CloogMatrix
* matrix
;
87 /* Go to the right level. */
88 for (i
=0; i
<level
; i
++)
91 fprintf(file
,"+-- CloogProgram\n") ;
94 for (i
=0; i
<=level
+1; i
++)
98 /* Print the language. */
99 for (i
=0; i
<=level
; i
++)
100 fprintf(file
,"|\t") ;
101 fprintf(file
, "Language: %c\n",program
->language
) ;
104 for (i
=0; i
<=level
+1; i
++)
105 fprintf(file
,"|\t") ;
108 /* Print the scattering dimension number. */
109 for (i
=0; i
<=level
; i
++)
110 fprintf(file
,"|\t") ;
111 fprintf(file
,"Scattering dimension number: %d\n",program
->nb_scattdims
) ;
114 for (i
=0; i
<=level
+1; i
++)
115 fprintf(file
,"|\t") ;
118 /* Print the scalar scattering dimension informations. */
119 for (i
=0; i
<=level
; i
++)
120 fprintf(file
,"|\t") ;
121 if (program
->scaldims
!= NULL
)
122 { fprintf(file
,"Scalar dimensions:") ;
123 for (i
=0;i
<program
->nb_scattdims
;i
++)
124 fprintf(file
," %d:%d ",i
,program
->scaldims
[i
]) ;
128 fprintf(file
,"No scalar scattering dimensions\n") ;
131 for (i
=0; i
<=level
+1; i
++)
132 fprintf(file
,"|\t") ;
135 /* Print the parameter and the iterator names. */
136 cloog_names_print_structure(file
,program
->names
,level
+1) ;
139 for (i
=0; i
<=level
+1; i
++)
140 fprintf(file
,"|\t") ;
143 /* Print the context. */
144 for (i
=0; i
<=level
; i
++)
145 fprintf(file
,"|\t") ;
146 fprintf(file
,"+-- Context\n") ;
147 matrix
= cloog_domain_domain2matrix(program
->context
) ;
148 cloog_matrix_print_structure(file
,matrix
,level
+1) ;
149 cloog_matrix_free(matrix
) ;
151 /* A special blank line. */
152 for (i
=0; i
<=level
+1; i
++)
153 fprintf(file
,"|\t") ;
156 /* Print the loop. */
157 cloog_loop_print_structure(file
,program
->loop
,level
+1) ;
159 /* One more time something that is here only for a better look. */
161 { for (i
=0; i
<=level
; i
++)
162 fprintf(file
,"|\t") ;
170 * cloog_program_dump_cloog function:
171 * This function dumps a CloogProgram structure supposed to be completely
172 * filled in a CLooG input file (foo possibly stdout) such as CLooG can
173 * rebuild almost exactly the data structure from the input file (the number
174 * of scattering functions is lost since they are included inside the
175 * iteration domains, this can only lead to a less beautiful pretty printing).
176 * WARNING: this function do not respect CloogDomain as an object.
177 * - June 27th 2003: first version.
178 * - May 15th 2005: (debug) several patches by Kristof Beyls.
179 * - November 16th 2005: adaptation for CLooG 0.14.0 structures.
181 void cloog_program_dump_cloog(FILE * foo
, CloogProgram
* program
)
183 CloogMatrix
* matrix
;
184 Polyhedron
* polyhedron
;
189 "# This is an automatic dump of a CLooG input file from a CloogProgram data\n"
190 "# structure. WARNING: it is highly dangerous and MAY be correct ONLY if\n"
191 "# - it has been dumped before loop generation.\n"
192 "# - option -noscalars is used (it removes scalar dimensions otherwise)\n"
193 "# - option -l is at least the original scattering dimension number\n"
194 "# ASK THE AUTHOR IF YOU *NEED* SOMETHING MORE ROBUST\n") ;
197 if (program
->language
== 'c')
198 fprintf(foo
,"# Language: C\n") ;
200 fprintf(foo
,"# Language: FORTRAN\n") ;
201 fprintf(foo
,"%c\n\n",program
->language
) ;
204 fprintf(foo
,"# Context (%d parameter(s)):\n",
205 cloog_domain_dimension(program
->context
)) ;
206 matrix
= cloog_domain_domain2matrix(program
->context
) ;
207 cloog_matrix_print(foo
,matrix
) ;
208 cloog_matrix_free(matrix
) ;
209 fprintf(foo
,"1 # Parameter name(s)\n") ;
210 for (i
=0;i
<program
->names
->nb_parameters
;i
++)
211 fprintf(foo
,"%s ",program
->names
->parameters
[i
]) ;
213 /* Statement number. */
215 loop
= program
->loop
;
220 fprintf(foo
,"\n\n# Statement number:\n%d\n\n",i
) ;
222 /* Iteration domains. */
224 loop
= program
->loop
;
226 { /* Name of the domain. */
227 fprintf(foo
,"# Iteration domain of statement %d.\n",i
) ;
229 /* Number of polyhedron inside the union of disjoint polyhedra. */
231 polyhedron
= cloog_domain_polyhedron(loop
->domain
) ;
232 while (polyhedron
!= NULL
)
234 polyhedron
= polyhedron
->next
;
236 fprintf(foo
,"%d\n",j
) ;
238 /* The polyhedra themselves. */
239 polyhedron
= cloog_domain_polyhedron(loop
->domain
) ;
240 while (polyhedron
!= NULL
)
241 { matrix
= Polyhedron2Constraints(polyhedron
) ;
242 cloog_matrix_leak_up() ;
243 cloog_matrix_print(foo
,matrix
) ;
244 cloog_matrix_free(matrix
) ;
245 polyhedron
= polyhedron
->next
;
247 fprintf(foo
,"0 0 0 # For future options.\n\n") ;
252 fprintf(foo
,"\n1 # Iterator name(s)\n") ;
253 for (i
=0;i
<program
->names
->nb_iterators
;i
++)
254 fprintf(foo
,"%s ",program
->names
->iterators
[i
]) ;
255 fprintf(foo
,"\n\n") ;
257 /* Scattering functions (none since included inside domains). */
258 fprintf(foo
,"# No scattering functions.\n0\n\n") ;
263 * cloog_program_print function:
264 * This function prints the content of a CloogProgram structure (program) into a
265 * file (file, possibly stdout).
266 * - July 1st 2005: Now this very old function (probably as old as CLooG) is
267 * only a frontend to cloog_program_print_structure, with a
268 * quite better human-readable representation.
270 void cloog_program_print(FILE * file
, CloogProgram
* program
)
271 { cloog_program_print_structure(file
,program
,0) ;
276 * cloog_program_pprint function:
277 * This function prints the content of a CloogProgram structure (program) into a
278 * file (file, possibly stdout), in a C-like language.
279 * - June 22nd 2005: Adaptation for GMP.
281 void cloog_program_pprint(file
, program
, options
)
283 CloogProgram
* program
;
284 CloogOptions
* options
;
285 { int i
, j
, nb_levels
, nb_scattering
, indentation
=0 ;
286 CloogStatement
* statement
;
287 CloogBlockList
* blocklist
;
290 CloogMatrix
* equal
;
292 infos
= (CloogInfos
*)malloc(sizeof(CloogInfos
)) ;
293 infos
->names
= program
->names
;
294 infos
->options
= options
;
295 infos
->scaldims
= program
->scaldims
;
296 infos
->nb_scattdims
= program
->nb_scattdims
;
298 /* Allocation for the array of strides, there is a +1 since the statement can
299 * be included inside an external loop without iteration domain.
301 nb_levels
= infos
->names
->nb_scattering
+ infos
->names
->nb_iterators
+1 ;
302 infos
->stride
= (Value
*)malloc((nb_levels
)*sizeof(Value
)) ;
303 for (i
=0;i
<nb_levels
; i
++)
304 value_init_c(infos
->stride
[i
]) ;
306 equal
= cloog_matrix_alloc(nb_levels
,
307 nb_levels
+ program
->names
->nb_parameters
+ 1) ;
309 if (program
->language
== 'f')
310 infos
->language
= LANGUAGE_FORTRAN
;
312 infos
->language
= LANGUAGE_C
;
314 if (program
->language
== 'f')
315 { fprintf(file
,"! Generated from %s by CLooG v%s %s bits in %.2fs.\n",
316 options
->name
,CLOOG_RELEASE
,CLOOG_VERSION
,options
->time
) ;
318 fprintf(file
,"! CLooG asked for %d KBytes.\n",options
->memory
) ;
319 fprintf(stderr
,"[CLooG]INFO: %.2fs and %dKB used for code generation.\n",
320 options
->time
,options
->memory
) ;
324 { fprintf(file
,"/* Generated from %s by CLooG v%s %s bits in %.2fs. */\n",
325 options
->name
,CLOOG_RELEASE
,CLOOG_VERSION
,options
->time
) ;
327 fprintf(file
,"/* CLooG asked for %d KBytes. */\n",options
->memory
) ;
328 fprintf(stderr
,"[CLooG]INFO: %.2fs and %dKB used for code generation.\n",
329 options
->time
,options
->memory
) ;
333 /* If the option "compilable" is set, we provide the whole stuff to generate
334 * a compilable code. This code just do nothing, but now the user can edit
335 * the source and set the statement macros and parameters values.
337 nb_scattering
= program
->nb_scattdims
;
338 if (options
->compilable
&& (program
->language
== 'c'))
340 fprintf(file
,"/* DON'T FORGET TO USE -lm OPTION TO COMPILE. */\n\n") ;
341 fprintf(file
,"/* Useful headers. */\n") ;
342 fprintf(file
,"#include <stdio.h>\n") ;
343 fprintf(file
,"#include <stdlib.h>\n") ;
344 fprintf(file
,"#include <math.h>\n\n") ;
346 /* The value of parameters. */
347 fprintf(file
,"/* Parameter value. */\n") ;
348 fprintf(file
,"#define PARVAL %d\n\n",options
->compilable
) ;
351 fprintf(file
,"/* Useful macros. */\n") ;
352 fprintf(file
,"#define ceild(n,d) ceil(((double)(n))/((double)(d)))\n") ;
353 fprintf(file
,"#define floord(n,d) floor(((double)(n))/((double)(d)))\n") ;
354 fprintf(file
,"#define max(x,y) ((x) > (y)? (x) : (y)) \n") ;
355 fprintf(file
,"#define min(x,y) ((x) < (y)? (x) : (y)) \n\n") ;
357 /* The statement macros. */
358 fprintf(file
,"/* Statement macros (please set). */\n") ;
359 blocklist
= program
->blocklist
;
360 while (blocklist
!= NULL
)
361 { block
= blocklist
->block
;
362 statement
= block
->statement
;
363 while (statement
!= NULL
)
364 { fprintf(file
,"#define S%d(",statement
->number
+1) ;
365 if (block
->depth
> 0)
366 { fprintf(file
,"%s",program
->names
->iterators
[0]) ;
367 for(j
=1;j
<block
->depth
;j
++)
368 fprintf(file
,",%s",program
->names
->iterators
[j
]) ;
370 fprintf(file
,") {total++;") ;
371 if (block
->depth
> 0)
372 { fprintf(file
," printf(\"S%d \%%d",statement
->number
+1) ;
373 for(j
=1;j
<block
->depth
;j
++)
374 fprintf(file
," \%%d") ;
376 fprintf(file
,"\\n\",%s",program
->names
->iterators
[0]) ;
377 for(j
=1;j
<block
->depth
;j
++)
378 fprintf(file
,",%s",program
->names
->iterators
[j
]) ;
381 fprintf(file
,"}\n") ;
383 statement
= statement
->next
;
385 blocklist
= blocklist
->next
;
388 /* The iterator and parameter declaration. */
389 fprintf(file
,"\nint main() {\n") ;
390 if ((program
->names
->nb_scalars
> 0) && (!options
->csp
))
391 { fprintf(file
," /* Scalar dimension iterators. */\n") ;
392 fprintf(file
," int %s",program
->names
->scalars
[0]) ;
393 for(i
=2;i
<=program
->names
->nb_scalars
;i
++)
394 fprintf(file
,", %s",program
->names
->scalars
[i
-1]) ;
396 fprintf(file
," ;\n") ;
398 if (program
->names
->nb_scattering
> 0)
399 { fprintf(file
," /* Scattering iterators. */\n") ;
400 fprintf(file
," int %s",program
->names
->scattering
[0]) ;
401 for(i
=2;i
<=program
->names
->nb_scattering
;i
++)
402 fprintf(file
,", %s",program
->names
->scattering
[i
-1]) ;
404 fprintf(file
," ;\n") ;
406 if (program
->names
->nb_iterators
> 0)
407 { fprintf(file
," /* Original iterators. */\n") ;
408 fprintf(file
," int %s",program
->names
->iterators
[0]) ;
409 for(i
=2;i
<=program
->names
->nb_iterators
;i
++)
410 fprintf(file
,", %s",program
->names
->iterators
[i
-1]) ;
412 fprintf(file
," ;\n") ;
414 if (program
->names
->nb_parameters
> 0)
415 { fprintf(file
," /* Parameters. */\n") ;
416 fprintf(file
," int %s=PARVAL",program
->names
->parameters
[0]) ;
417 for(i
=2;i
<=program
->names
->nb_parameters
;i
++)
418 fprintf(file
,", %s=PARVAL",program
->names
->parameters
[i
-1]) ;
420 fprintf(file
,", total=0 ;\n") ;
424 /* And we adapt the identation. */
428 pprint(file
,program
->loop
,equal
,1,0,indentation
,infos
) ;
430 /* The end of the compilable code in case of 'compilable' option. */
431 if (options
->compilable
&& (program
->language
== 'c'))
432 { fprintf(file
,"\n printf(\"Number of integral points: %%d.\\n\",total) ;") ;
433 fprintf(file
,"\n return 0 ;\n}\n") ;
436 for (i
=0; i
<nb_levels
; i
++)
437 value_clear_c(infos
->stride
[i
]) ;
439 cloog_matrix_free(equal
) ;
440 free(infos
->stride
) ;
445 /******************************************************************************
446 * Memory deallocation function *
447 ******************************************************************************/
451 * cloog_program_free function:
452 * This function frees the allocated memory for a CloogProgram structure.
454 void cloog_program_free(CloogProgram
* program
)
455 { cloog_names_free(program
->names
) ;
456 cloog_loop_free(program
->loop
) ;
457 cloog_domain_free(program
->context
) ;
458 cloog_block_list_free(program
->blocklist
) ;
459 if (program
->scaldims
!= NULL
)
460 free(program
->scaldims
) ;
466 /******************************************************************************
468 ******************************************************************************/
472 * cloog_program_read function:
473 * This function read the informations to put in a CloogProgram structure from
474 * a file (file, possibly stdin). It returns a pointer to a CloogProgram
475 * structure containing the read informations.
476 * - October 25th 2001: first version.
477 * - September 9th 2002: - the big reading function is now split in several
478 * functions (one per read data structure).
479 * - adaptation to the new file format with naming.
481 CloogProgram
* cloog_program_read(FILE * file
, CloogOptions
* options
)
482 { int i
, nb_statements
, nb_parameters
, nb_iterators
, nb_scattering
;
483 char s
[MAX_STRING
], language
, prefix
[2]={'c','\0'},
484 ** scattering
, ** iterators
, ** parameters
;
485 CloogLoop
* current
, * next
;
486 CloogBlockList
* previous
;
487 CloogDomainList
* scatteringl
;
493 /* Memory allocation for the CloogProgram structure. */
494 p
= cloog_program_malloc() ;
496 /* First of all, we read the language to use. */
497 while (fgets(s
,MAX_STRING
,file
) == 0) ;
498 while ((*s
=='#'||*s
=='\n') || (sscanf(s
," %c",&language
)<1))
499 fgets(s
,MAX_STRING
,file
) ;
500 p
->language
= language
;
502 /* We then read the context data. */
503 p
->context
= cloog_domain_read(file
) ;
504 nb_parameters
= cloog_domain_dimension(p
->context
) ;
506 /* First part of the CloogNames structure: reading of the parameter names. */
507 parameters
=cloog_names_read_strings(file
,nb_parameters
,NULL
,FIRST_PARAMETER
) ;
509 /* We read the statement number. */
510 while (fgets(s
,MAX_STRING
,file
) == 0) ;
511 while ((*s
=='#'||*s
=='\n') || (sscanf(s
," %d",&nb_statements
)<1))
512 fgets(s
,MAX_STRING
,file
) ;
514 /* Statements and domains reading for each statement. */
515 if (nb_statements
> 0)
516 { /* Reading of the first domain. */
517 p
->loop
= cloog_loop_read(file
,0,nb_parameters
) ;
518 p
->blocklist
= cloog_block_list_alloc(p
->loop
->block
) ;
519 previous
= p
->blocklist
;
521 if (p
->loop
->domain
!= NULL
)
522 nb_iterators
= cloog_domain_dimension(p
->loop
->domain
) - nb_parameters
;
526 /* And the same for each next domain. */
528 for (i
=2;i
<=nb_statements
;i
++)
529 { next
= cloog_loop_read(file
,i
-1,nb_parameters
) ;
530 if (next
->domain
!= NULL
)
531 if (cloog_domain_dimension(next
->domain
) - nb_parameters
> nb_iterators
)
532 nb_iterators
= cloog_domain_dimension(next
->domain
) - nb_parameters
;
534 previous
->next
= cloog_block_list_alloc(next
->block
) ;
535 previous
= previous
->next
;
537 current
->next
= next
;
538 current
= current
->next
;
541 /* Reading of the iterator names. */
542 iterators
= cloog_names_read_strings(file
,nb_iterators
,NULL
,FIRST_ITERATOR
);
544 /* Reading and putting the scattering data in program structure. */
545 scatteringl
= cloog_domain_list_read(file
) ;
547 if (scatteringl
!= NULL
)
548 { if (cloog_domain_list_lazy_same(scatteringl
))
549 { fprintf(stderr
, "[CLooG]WARNING: some scattering functions are "
553 p
->nb_scattdims
= cloog_domain_dimension(scatteringl
->domain
) -
554 cloog_domain_dimension(p
->loop
->domain
) ;
555 nb_scattering
= p
->nb_scattdims
;
556 scattering
= cloog_names_read_strings(file
,p
->nb_scattdims
,prefix
,'1') ;
558 /* The boolean array for scalar dimensions is created and set to 0. */
559 p
->scaldims
= (int *)malloc(p
->nb_scattdims
*(sizeof(int))) ;
560 if (p
->scaldims
== NULL
)
561 { fprintf(stderr
, "[CLooG]ERROR: memory overflow.\n") ;
564 for (i
=0;i
<p
->nb_scattdims
;i
++)
567 /* We try to find blocks in the input problem to reduce complexity. */
568 if (!options
->noblocks
)
569 cloog_program_block(p
,scatteringl
) ;
570 if (!options
->noscalars
)
571 cloog_program_extract_scalars(p
,scatteringl
) ;
573 cloog_program_scatter(p
,scatteringl
) ;
574 cloog_domain_list_free(scatteringl
) ;
577 { p
->nb_scattdims
= 0 ;
581 p
->names
= cloog_names_alloc(0, nb_scattering
, nb_iterators
, nb_parameters
,
582 NULL
, scattering
, iterators
, parameters
);
584 cloog_names_scalarize(p
->names
,p
->nb_scattdims
,p
->scaldims
) ;
589 p
->blocklist
= NULL
;
597 /******************************************************************************
598 * Processing functions *
599 ******************************************************************************/
603 * cloog_program_malloc function:
604 * This function allocates the memory space for a CloogProgram structure and
605 * sets its fields with default values. Then it returns a pointer to the
607 * - November 21th 2005: first version.
609 CloogProgram
* cloog_program_malloc()
610 { CloogProgram
* program
;
612 /* Memory allocation for the CloogProgram structure. */
613 program
= (CloogProgram
*)malloc(sizeof(CloogProgram
)) ;
615 { fprintf(stderr
, "[CLooG]ERROR: memory overflow.\n") ;
619 /* We set the various fields with default values. */
620 program
->language
= 'c' ;
621 program
->nb_scattdims
= 0 ;
622 program
->context
= NULL
;
623 program
->loop
= NULL
;
624 program
->names
= NULL
;
625 program
->blocklist
= NULL
;
626 program
->scaldims
= NULL
;
633 * cloog_program_generate function:
634 * This function calls the Quillere algorithm for loop scanning. (see the
635 * Quillere paper) and calls the loop simplification function.
636 * - depth is the loop depth we want to optimize (guard free as possible),
637 * the first loop depth is 1 and anegative value is the infinity depth.
638 * - sep_level is the level number where we want to start loop separation.
640 * - October 26th 2001: first version.
641 * - April 19th 2005: some basic fixes and memory usage feature.
642 * - April 29th 2005: (bug fix, bug found by DaeGon Kim) see case 2 below.
644 CloogProgram
* cloog_program_generate(program
, options
)
645 CloogProgram
* program
;
646 CloogOptions
* options
;
648 struct rusage start
, end
;
651 char status_path
[MAX_STRING_VAL
] ;
654 /* We initialize the memory need to 0. */
655 options
->memory
= 0 ;
658 if (options
->override
)
660 "[CLooG]WARNING: you are using -override option, be aware that the "
661 "generated\n code may be incorrect.\n") ;
664 { /* Playing with options may be dangerous, here are two possible issues :
665 * 1. Using -l option less than scattering dimension number may lead to
666 * an illegal target code (since the scattering is not respected), if
667 * it is the case, we set -l depth to the first acceptable value.
669 if ((program
->nb_scattdims
> options
->l
) && (options
->l
> 0))
671 "[CLooG]WARNING: -l depth is less than the scattering dimension number "
672 "(the \n generated code may be incorrect), it has been "
673 "automaticaly set\n to this value (use option -override "
675 options
->l
= program
->nb_scattdims
;
678 /* 2. Using -f option greater than one while -l depth is greater than the
679 * scattering dimension number may lead to iteration duplication (try
680 * test/daegon_lu_osp.cloog with '-f 3' to test) because of the step 4b
681 * of the cloog_loop_generate function, if it is the case, we set -l to
682 * the first acceptable value.
684 if (((options
->f
> 1) || (options
->f
< 0)) &&
685 ((options
->l
> program
->nb_scattdims
) || (options
->l
< 0)))
687 "[CLooG]WARNING: -f depth is more than one, -l depth has been "
688 "automaticaly set\n to the scattering dimension number "
689 "(target code may have\n duplicated iterations), -l depth "
690 "has been automaticaly set to\n this value (use option "
691 "-override to override).\n") ;
692 options
->l
= program
->nb_scattdims
;
696 getrusage(RUSAGE_SELF
, &start
) ;
697 if (program
->loop
!= NULL
)
698 { loop
= program
->loop
;
701 loop
= cloog_loop_generate(loop
, program
->context
, 1, 0,
703 program
->nb_scattdims
,
704 cloog_domain_dimension(program
->context
),
708 /* We read into the status file of the process how many memory it uses. */
709 sprintf(status_path
,"/proc/%d/status",getpid()) ;
710 status
= fopen(status_path
, "r") ;
711 while (fscanf(status
,"%s",status_path
) && strcmp(status_path
,"VmData:")!=0);
712 fscanf(status
,"%d",&(options
->memory
)) ;
716 if ((!options
->nosimplify
) && (program
->loop
!= NULL
))
717 loop
= cloog_loop_simplify(loop
,program
->context
,1,
718 cloog_domain_dimension(program
->context
)) ;
720 program
->loop
= loop
;
723 getrusage(RUSAGE_SELF
, &end
) ;
724 /* We calculate the time spent in code generation. */
725 time
= (end
.ru_utime
.tv_usec
- start
.ru_utime
.tv_usec
)/(float)(MEGA
) ;
726 time
+= (float)(end
.ru_utime
.tv_sec
- start
.ru_utime
.tv_sec
) ;
727 options
->time
= time
;
734 * cloog_program_block function:
735 * this function gives a last chance to the lazy user to consider statement
736 * blocks instead of some statement lists where the whole list may be
737 * considered as a single statement from a code generation point of view.
738 * For instance two statements with the same iteration domain and the same
739 * scattering functions may be considered as a block. This function is lazy
740 * and can only find very simple forms of trivial blocks (see
741 * cloog_domain_lazy_block function for more details). The useless loops and
742 * scattering functions are removed and freed while the statement list of
743 * according blocks are filled.
744 * - program is the whole program structure (befaore applying scattering),
745 * - scattering is the list of scattering functions.
747 * - April 30th 2005: first attempt.
748 * - June 10-11th 2005: first working version.
750 void cloog_program_block(CloogProgram
* program
, CloogDomainList
* scattering
)
751 { int blocked_reference
=0, blocked
=0, nb_blocked
=0 ;
752 CloogLoop
* reference
, * start
, * loop
;
753 CloogDomainList
* scatt_reference
, * scatt_loop
, * scatt_start
;
754 CloogBlockList
* previous
;
756 if ((program
->loop
== NULL
) || (program
->loop
->next
== NULL
))
759 /* We will have to rebuild the block list. */
760 cloog_block_list_free(program
->blocklist
) ;
761 program
->blocklist
= cloog_block_list_alloc(program
->loop
->block
) ;
762 previous
= program
->blocklist
;
764 /* The process will use three variables for the linked list :
765 * - 'start' is the starting point of a new block,
766 * - 'reference' is the node of the block used for the block checking,
767 * - 'loop' is the candidate to be inserted inside the block.
768 * At the beginning of the process, the linked lists are as follow:
769 * O------>O------>O------>O------>NULL
775 reference
= program
->loop
;
776 start
= program
->loop
;
777 loop
= reference
->next
;
778 scatt_reference
= scattering
;
779 scatt_start
= scattering
;
780 scatt_loop
= scattering
->next
;
783 { if (cloog_domain_lazy_equal(reference
->domain
,loop
->domain
) &&
784 cloog_domain_lazy_block(scatt_reference
->domain
,scatt_loop
->domain
,
785 scattering
,program
->nb_scattdims
))
786 { /* If we find a block we update the links:
789 * O O------>O------>O------>NULL
796 cloog_block_merge(start
->block
,loop
->block
); /* merge frees loop->block */
798 start
->next
= loop
->next
;
799 scatt_start
->next
= scatt_loop
->next
;
802 { /* If we didn't find a block, the next start of a block is updated:
803 * O------>O------>O------>O------>NULL
810 scatt_start
= scatt_loop
;
812 /* We update the block list. */
813 previous
->next
= cloog_block_list_alloc(start
->block
) ;
814 previous
= previous
->next
;
817 /* If the reference node has been included into a block, we can free it. */
818 if (blocked_reference
)
819 { reference
->next
= NULL
;
820 cloog_loop_free(reference
) ;
821 cloog_domain_free(scatt_reference
->domain
) ;
822 free(scatt_reference
) ;
825 /* The reference and the loop are now updated for the next try, the
826 * starting position depends on the previous step.
827 * O ? O------>O------>O------>NULL
833 scatt_reference
= scatt_loop
;
834 scatt_loop
= scatt_loop
->next
;
836 /* We mark the new reference as being blocked or not, if will be freed
837 * during the next while loop execution.
840 blocked_reference
= 1 ;
842 blocked_reference
= 0 ;
845 /* We free the last blocked reference if any (since in the while loop it was
846 * freed during the next loop execution, it was not possible to free the
849 if (blocked_reference
)
850 { reference
->next
= NULL
;
851 cloog_loop_free(reference
) ;
852 cloog_domain_free(scatt_reference
->domain
) ;
853 free(scatt_reference
) ;
857 fprintf(stderr
, "[CLooG]INFO: %d domains have been blocked.\n",nb_blocked
) ;
862 * cloog_program_extract_scalars function:
863 * this functions finds and removes the dimensions of the scattering functions
864 * when they are scalar (i.e. of the shape "dim + scalar = 0") for all
865 * scattering functions. The reason is that the processing of such dimensions
866 * is trivial and do not need neither a row and a column in the matrix
867 * representation of the domain (this will save memory) neither the full
868 * Quillere processing (this will save time). The scalar dimensions data are
869 * dispatched in the CloogProgram structure (the boolean vector scaldims will
870 * say which original dimensions are scalar or not) and to the CloogBlock
871 * structures (each one has a scaldims vector that contains the scalar values).
872 * - June 14th 2005: first developments.
873 * - June 30th 2005: first version.
875 void cloog_program_extract_scalars(program
, scattering
)
876 CloogProgram
* program
;
877 CloogDomainList
* scattering
;
878 { int i
, j
, scalar
, current
, nb_scaldims
=0 ;
879 CloogDomainList
* start
;
881 CloogBlockList
* blocklist
;
886 for (i
=0;i
<program
->nb_scattdims
;i
++)
889 while (scattering
!= NULL
)
890 { if (!cloog_domain_lazy_isscalar(scattering
->domain
,i
))
894 scattering
= scattering
->next
;
899 program
->scaldims
[i
] = 1 ;
903 /* If there are no scalar dimensions, we can continue directly. */
907 /* Otherwise, in each block, we have to put the number of scalar dimensions,
908 * and to allocate the memory for the scalar values.
910 blocklist
= program
->blocklist
;
911 while (blocklist
!= NULL
)
912 { block
= blocklist
->block
;
913 block
->nb_scaldims
= nb_scaldims
;
914 block
->scaldims
= (Value
*)malloc(nb_scaldims
*sizeof(Value
)) ;
915 for (i
=0;i
<nb_scaldims
;i
++)
916 value_init_c(block
->scaldims
[i
]) ;
918 blocklist
= blocklist
->next
;
921 /* Then we have to fill these scalar values, so we can erase those dimensions
922 * from the scattering functions. It's easier to begin with the last one,
923 * since there would be an offset otherwise (if we remove the i^th dimension,
924 * then the next one is not the (i+1)^th but still the i^th...).
926 current
= nb_scaldims
- 1 ;
927 for (i
=program
->nb_scattdims
-1;i
>=0;i
--)
928 if (program
->scaldims
[i
])
929 { blocklist
= program
->blocklist
;
931 while (blocklist
!= NULL
)
932 { block
= blocklist
->block
;
933 cloog_domain_scalar(scattering
->domain
,i
,&block
->scaldims
[current
]) ;
934 blocklist
= blocklist
->next
;
935 scattering
= scattering
->next
;
939 while (scattering
!= NULL
)
940 { old
= scattering
->domain
;
941 scattering
->domain
= cloog_domain_erase_dimension(old
,i
) ;
942 cloog_domain_free(old
) ;
943 scattering
= scattering
->next
;
948 /* We postprocess the scaldims array in such a way that each entry is how
949 * many scalar dimensions follows + 1 (the current one). This will make
950 * some other processing easier (e.g. knowledge of some offsets).
952 for (i
=0;i
<program
->nb_scattdims
-1;i
++)
953 { if (program
->scaldims
[i
])
955 while ((j
< program
->nb_scattdims
) && program
->scaldims
[j
])
956 { program
->scaldims
[i
] ++ ;
962 if (nb_scaldims
!= 0)
963 fprintf(stderr
, "[CLooG]INFO: %d dimensions (over %d) are scalar.\n",
964 nb_scaldims
,program
->nb_scattdims
) ;
969 * cloog_program_scatter function:
970 * This function adds the scattering (scheduling) informations in a program.
971 * If names is NULL, this function create names itself such that the i^th
973 * - November 6th 2001: first version.
975 void cloog_program_scatter(program
, scattering
)
976 CloogProgram
* program
;
977 CloogDomainList
* scattering
;
978 { int scattering_dim
, scattering_dim2
, not_enough_constraints
=0 ;
981 if ((program
!= NULL
) && (scattering
!= NULL
))
982 { loop
= program
->loop
;
984 /* We compute the scattering dimension and check it is >=0. */
985 scattering_dim
= cloog_domain_dimension(scattering
->domain
) -
986 cloog_domain_dimension(loop
->domain
) ;
987 if (scattering_dim
< 0)
988 { fprintf(stderr
, "[CLooG]ERROR: scattering has not enough dimensions.\n") ;
991 if (scattering_dim
>= cloog_domain_nbconstraints(scattering
->domain
))
992 not_enough_constraints
++ ;
994 /* The scattering dimension may have been modified by scalar extraction. */
995 scattering_dim
= cloog_domain_dimension(scattering
->domain
) -
996 cloog_domain_dimension(loop
->domain
) ;
998 /* Finally we scatter all loops. */
999 cloog_loop_scatter(loop
,scattering
->domain
) ;
1001 scattering
= scattering
->next
;
1003 while ((loop
!= NULL
) && (scattering
!= NULL
))
1004 { scattering_dim2
= cloog_domain_dimension(scattering
->domain
) -
1005 cloog_domain_dimension(loop
->domain
) ;
1006 if (scattering_dim2
!= scattering_dim
)
1007 { fprintf(stderr
, "[CLooG]ERROR: "
1008 "scattering dimensions are not the same.\n") ;
1011 if (scattering_dim2
>= cloog_domain_nbconstraints(scattering
->domain
))
1012 not_enough_constraints
++ ;
1014 cloog_loop_scatter(loop
,scattering
->domain
) ;
1016 scattering
= scattering
->next
;
1018 if ((loop
!= NULL
) || (scattering
!= NULL
))
1019 fprintf(stderr
, "[CLooG]WARNING: "
1020 "there is not a scattering for each statement.\n");
1022 if (not_enough_constraints
)
1023 fprintf(stderr
, "[CLooG]WARNING: not enough constraints for "
1024 "%d scattering function(s).\n",not_enough_constraints
) ;