mirror of
https://review.haiku-os.org/buildtools
synced 2025-01-19 12:51:22 +01:00
5873a060ca
* these are dependencies for gcc 4 Graphite engine build. * CLooG 0.18.0 includes ISL 0.11.1 which is the backend that the build script enables. * PPL is needed by GCC build even if it isn't the chosen backend.
1157 lines
38 KiB
C
1157 lines
38 KiB
C
|
|
/**-------------------------------------------------------------------**
|
|
** CLooG **
|
|
**-------------------------------------------------------------------**
|
|
** program.c **
|
|
**-------------------------------------------------------------------**
|
|
** First version: october 25th 2001 **
|
|
**-------------------------------------------------------------------**/
|
|
|
|
|
|
/******************************************************************************
|
|
* CLooG : the Chunky Loop Generator (experimental) *
|
|
******************************************************************************
|
|
* *
|
|
* Copyright (C) 2001-2005 Cedric Bastoul *
|
|
* *
|
|
* This library is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU Lesser General Public *
|
|
* License as published by the Free Software Foundation; either *
|
|
* version 2.1 of the License, or (at your option) any later version. *
|
|
* *
|
|
* This library is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
|
* Lesser General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Lesser General Public *
|
|
* License along with this library; if not, write to the Free Software *
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, *
|
|
* Boston, MA 02110-1301 USA *
|
|
* *
|
|
* CLooG, the Chunky Loop Generator *
|
|
* Written by Cedric Bastoul, Cedric.Bastoul@inria.fr *
|
|
* *
|
|
******************************************************************************/
|
|
/* CAUTION: the english used for comments is probably the worst you ever read,
|
|
* please feel free to correct and improve it !
|
|
*/
|
|
|
|
|
|
# include <sys/types.h>
|
|
# include <sys/time.h>
|
|
#include <stdarg.h>
|
|
# include <stdlib.h>
|
|
# include <stdio.h>
|
|
# include <string.h>
|
|
# include <ctype.h>
|
|
# include <unistd.h>
|
|
# include "../include/cloog/cloog.h"
|
|
#ifdef CLOOG_RUSAGE
|
|
# include <sys/resource.h>
|
|
#endif
|
|
|
|
#define ALLOC(type) (type*)malloc(sizeof(type))
|
|
|
|
#ifdef OSL_SUPPORT
|
|
#include <osl/scop.h>
|
|
#include <osl/extensions/coordinates.h>
|
|
#endif
|
|
|
|
/******************************************************************************
|
|
* Structure display function *
|
|
******************************************************************************/
|
|
|
|
|
|
/**
|
|
* cloog_program_print function:
|
|
* this function is a human-friendly way to display the CloogProgram data
|
|
* structure, it shows all the different fields and includes an indentation
|
|
* level (level) in order to work with others print_structure functions.
|
|
* - July 1st 2005: first version based on the old cloog_program_print function.
|
|
*/
|
|
void cloog_program_print_structure(file, program, level)
|
|
FILE * file ;
|
|
CloogProgram * program ;
|
|
int level ;
|
|
{ int i, j ;
|
|
|
|
/* Go to the right level. */
|
|
for (i=0; i<level; i++)
|
|
fprintf(file,"|\t") ;
|
|
|
|
fprintf(file,"+-- CloogProgram\n") ;
|
|
|
|
/* A blank line. */
|
|
for (i=0; i<=level+1; i++)
|
|
fprintf(file,"|\t") ;
|
|
fprintf(file,"\n") ;
|
|
|
|
/* Print the language. */
|
|
for (i=0; i<=level; i++)
|
|
fprintf(file,"|\t") ;
|
|
fprintf(file, "Language: %c\n",program->language) ;
|
|
|
|
/* A blank line. */
|
|
for (i=0; i<=level+1; i++)
|
|
fprintf(file,"|\t") ;
|
|
fprintf(file,"\n") ;
|
|
|
|
/* Print the scattering dimension number. */
|
|
for (i=0; i<=level; i++)
|
|
fprintf(file,"|\t") ;
|
|
fprintf(file,"Scattering dimension number: %d\n",program->nb_scattdims) ;
|
|
|
|
/* A blank line. */
|
|
for (i=0; i<=level+1; i++)
|
|
fprintf(file,"|\t") ;
|
|
fprintf(file,"\n") ;
|
|
|
|
/* Print the scalar scattering dimension informations. */
|
|
for (i=0; i<=level; i++)
|
|
fprintf(file,"|\t") ;
|
|
if (program->scaldims != NULL)
|
|
{ fprintf(file,"Scalar dimensions:") ;
|
|
for (i=0;i<program->nb_scattdims;i++)
|
|
fprintf(file," %d:%d ",i,program->scaldims[i]) ;
|
|
fprintf(file,"\n") ;
|
|
}
|
|
else
|
|
fprintf(file,"No scalar scattering dimensions\n") ;
|
|
|
|
/* A blank line. */
|
|
for (i=0; i<=level+1; i++)
|
|
fprintf(file,"|\t") ;
|
|
fprintf(file,"\n") ;
|
|
|
|
/* Print the parameter and the iterator names. */
|
|
cloog_names_print_structure(file,program->names,level+1) ;
|
|
|
|
/* A blank line. */
|
|
for (i=0; i<=level+1; i++)
|
|
fprintf(file,"|\t") ;
|
|
fprintf(file,"\n") ;
|
|
|
|
/* Print the context. */
|
|
cloog_domain_print_structure(file, program->context, level+1, "Context");
|
|
|
|
/* Print the loop. */
|
|
cloog_loop_print_structure(file,program->loop,level+1) ;
|
|
|
|
/* One more time something that is here only for a better look. */
|
|
for (j=0; j<2; j++)
|
|
{ for (i=0; i<=level; i++)
|
|
fprintf(file,"|\t") ;
|
|
|
|
fprintf(file,"\n") ;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* cloog_program_dump_cloog function:
|
|
* This function dumps a CloogProgram structure supposed to be completely
|
|
* filled in a CLooG input file (foo possibly stdout) such as CLooG can
|
|
* rebuild almost exactly the data structure from the input file.
|
|
*
|
|
* If the scattering is already applied, the scattering parameter is supposed to
|
|
* be NULL. In this case the number of scattering functions is lost, since they
|
|
* are included inside the iteration domains. This can only lead to a less
|
|
* beautiful pretty printing.
|
|
*
|
|
* In case the scattering is not yet applied it can be passed to this function
|
|
* and will be included in the CLooG input file dump.
|
|
*/
|
|
void cloog_program_dump_cloog(FILE * foo, CloogProgram * program,
|
|
CloogScatteringList *scattering)
|
|
{
|
|
int i;
|
|
CloogLoop * loop ;
|
|
CloogScatteringList *tmp_scatt;
|
|
|
|
fprintf(foo,
|
|
"# CLooG -> CLooG\n"
|
|
"# This is an automatic dump of a CLooG input file from a CloogProgram data\n"
|
|
"# structure. WARNING: it is highly dangerous and MAY be correct ONLY if\n"
|
|
"# - it has been dumped before loop generation.\n"
|
|
"# - option -noscalars is used (it removes scalar dimensions otherwise)\n"
|
|
"# - option -l is at least the original scattering dimension number\n"
|
|
"# ASK THE AUTHOR IF YOU *NEED* SOMETHING MORE ROBUST\n") ;
|
|
|
|
/* Language. */
|
|
if (program->language == 'c')
|
|
fprintf(foo,"# Language: C\n") ;
|
|
else
|
|
fprintf(foo,"# Language: FORTRAN\n") ;
|
|
fprintf(foo,"%c\n\n",program->language) ;
|
|
|
|
/* Context. */
|
|
fprintf(foo, "# Context (%d parameter(s)):\n", program->names->nb_parameters);
|
|
cloog_domain_print_constraints(foo, program->context, 0);
|
|
fprintf(foo,"1 # Parameter name(s)\n") ;
|
|
for (i=0;i<program->names->nb_parameters;i++)
|
|
fprintf(foo,"%s ",program->names->parameters[i]) ;
|
|
|
|
/* Statement number. */
|
|
i = 0 ;
|
|
loop = program->loop ;
|
|
while (loop != NULL)
|
|
{ i++ ;
|
|
loop = loop->next ;
|
|
}
|
|
fprintf(foo,"\n\n# Statement number:\n%d\n\n",i) ;
|
|
|
|
/* Iteration domains. */
|
|
i = 1 ;
|
|
loop = program->loop ;
|
|
while (loop != NULL)
|
|
{ /* Name of the domain. */
|
|
fprintf(foo,"# Iteration domain of statement %d.\n",i) ;
|
|
|
|
cloog_domain_print_constraints(foo, loop->domain, 1);
|
|
fprintf(foo,"0 0 0 # For future options.\n\n") ;
|
|
|
|
i++ ;
|
|
loop = loop->next ;
|
|
}
|
|
fprintf(foo,"\n1 # Iterator name(s)\n") ;
|
|
|
|
/* Scattering already applied? In this case print the scattering names as
|
|
* additional iterator names. */
|
|
if (!scattering)
|
|
for (i = 0; i < program->names->nb_scattering; i++)
|
|
fprintf(foo, "%s ", program->names->scattering[i]);
|
|
for (i=0;i<program->names->nb_iterators;i++)
|
|
fprintf(foo,"%s ",program->names->iterators[i]);
|
|
fprintf(foo,"\n\n") ;
|
|
|
|
/* Exit, if scattering is already applied. */
|
|
if (!scattering) {
|
|
fprintf(foo, "# No scattering functions.\n0\n\n");
|
|
return;
|
|
}
|
|
|
|
/* Scattering relations. */
|
|
fprintf(foo, "# --------------------- SCATTERING --------------------\n");
|
|
|
|
i = 0;
|
|
for (tmp_scatt = scattering; tmp_scatt; tmp_scatt = tmp_scatt->next)
|
|
i++;
|
|
|
|
fprintf(foo, "%d # Scattering functions", i);
|
|
|
|
for (tmp_scatt = scattering; tmp_scatt; tmp_scatt = tmp_scatt->next)
|
|
cloog_scattering_print_constraints(foo, tmp_scatt->scatt);
|
|
|
|
fprintf(foo, "\n1 # Scattering dimension name(s)\n");
|
|
|
|
for (i = 0; i < program->names->nb_scattering; i++)
|
|
fprintf(foo, "%s ", program->names->scattering[i]);
|
|
}
|
|
|
|
|
|
/**
|
|
* cloog_program_print function:
|
|
* This function prints the content of a CloogProgram structure (program) into a
|
|
* file (file, possibly stdout).
|
|
* - July 1st 2005: Now this very old function (probably as old as CLooG) is
|
|
* only a frontend to cloog_program_print_structure, with a
|
|
* quite better human-readable representation.
|
|
*/
|
|
void cloog_program_print(FILE * file, CloogProgram * program)
|
|
{ cloog_program_print_structure(file,program,0) ;
|
|
}
|
|
|
|
|
|
static void print_comment(FILE *file, CloogOptions *options,
|
|
const char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start(args, fmt);
|
|
if (options->language == CLOOG_LANGUAGE_FORTRAN) {
|
|
fprintf(file, "! ");
|
|
vfprintf(file, fmt, args);
|
|
fprintf(file, "\n");
|
|
} else {
|
|
fprintf(file, "/* ");
|
|
vfprintf(file, fmt, args);
|
|
fprintf(file, " */\n");
|
|
}
|
|
}
|
|
|
|
static void print_macros(FILE *file)
|
|
{
|
|
fprintf(file, "/* Useful macros. */\n") ;
|
|
fprintf(file,
|
|
"#define floord(n,d) (((n)<0) ? -((-(n)+(d)-1)/(d)) : (n)/(d))\n");
|
|
fprintf(file,
|
|
"#define ceild(n,d) (((n)<0) ? -((-(n))/(d)) : ((n)+(d)-1)/(d))\n");
|
|
fprintf(file, "#define max(x,y) ((x) > (y) ? (x) : (y))\n") ;
|
|
fprintf(file, "#define min(x,y) ((x) < (y) ? (x) : (y))\n\n") ;
|
|
}
|
|
|
|
static void print_declarations(FILE *file, int n, char **names)
|
|
{
|
|
int i;
|
|
|
|
fprintf(file, " int %s", names[0]);
|
|
for (i = 1; i < n; i++)
|
|
fprintf(file, ", %s", names[i]);
|
|
|
|
fprintf(file, ";\n");
|
|
}
|
|
|
|
static void print_iterator_declarations(FILE *file, CloogProgram *program,
|
|
CloogOptions *options)
|
|
{
|
|
CloogNames *names = program->names;
|
|
|
|
if (names->nb_scattering) {
|
|
fprintf(file, " /* Scattering iterators. */\n");
|
|
print_declarations(file, names->nb_scattering, names->scattering);
|
|
}
|
|
if (names->nb_iterators) {
|
|
fprintf(file, " /* Original iterators. */\n");
|
|
print_declarations(file, names->nb_iterators, names->iterators);
|
|
}
|
|
}
|
|
|
|
static void print_callable_preamble(FILE *file, CloogProgram *program,
|
|
CloogOptions *options)
|
|
{
|
|
int j;
|
|
CloogBlockList *blocklist;
|
|
CloogBlock *block;
|
|
CloogStatement *statement;
|
|
|
|
fprintf(file, "extern void hash(int);\n\n");
|
|
|
|
print_macros(file);
|
|
|
|
for (blocklist = program->blocklist; blocklist; blocklist = blocklist->next) {
|
|
block = blocklist->block;
|
|
for (statement = block->statement; statement; statement = statement->next) {
|
|
fprintf(file, "#define S%d(", statement->number);
|
|
if (block->depth > 0) {
|
|
fprintf(file, "%s", program->names->iterators[0]);
|
|
for(j = 1; j < block->depth; j++)
|
|
fprintf(file, ",%s", program->names->iterators[j]);
|
|
}
|
|
fprintf(file,") { hash(%d);", statement->number);
|
|
for(j = 0; j < block->depth; j++)
|
|
fprintf(file, " hash(%s);", program->names->iterators[j]);
|
|
fprintf(file, " }\n");
|
|
}
|
|
}
|
|
fprintf(file, "\nvoid test(");
|
|
if (program->names->nb_parameters > 0) {
|
|
fprintf(file, "int %s", program->names->parameters[0]);
|
|
for(j = 1; j < program->names->nb_parameters; j++)
|
|
fprintf(file, ", int %s", program->names->parameters[j]);
|
|
}
|
|
fprintf(file, ")\n{\n");
|
|
print_iterator_declarations(file, program, options);
|
|
}
|
|
|
|
static void print_callable_postamble(FILE *file, CloogProgram *program)
|
|
{
|
|
fprintf(file, "}\n");
|
|
}
|
|
|
|
/**
|
|
* cloog_program_osl_pprint function:
|
|
* this function pretty-prints the C or FORTRAN code generated from an
|
|
* OpenScop specification by overwriting SCoP in a given code, if the
|
|
* options -compilable or -callable are not set. The SCoP coordinates are
|
|
* provided through the OpenScop "Coordinates" extension. It returns 1 if
|
|
* it succeeds to find an OpenScop coordinates information
|
|
* to pretty-print the generated code, 0 otherwise.
|
|
* \param[in] file The output stream (possibly stdout).
|
|
* \param[in] program The generated pseudo-AST to pretty-print.
|
|
* \param[in] options CLooG options (contains the OpenSCop specification).
|
|
* \return 1 on success to pretty-print at the place of a SCoP, 0 otherwise.
|
|
*/
|
|
int cloog_program_osl_pprint(FILE * file, CloogProgram * program,
|
|
CloogOptions * options) {
|
|
#ifdef OSL_SUPPORT
|
|
int lines = 0;
|
|
int read = 1;
|
|
char c;
|
|
osl_scop_p scop = options->scop;
|
|
osl_coordinates_p coordinates;
|
|
struct clast_stmt *root;
|
|
FILE * original;
|
|
|
|
if (scop && !options->compilable && !options->callable) {
|
|
coordinates = osl_generic_lookup(scop->extension, OSL_URI_COORDINATES);
|
|
if (coordinates) {
|
|
original = fopen(coordinates->name, "r");
|
|
if (!original) {
|
|
cloog_msg(options, CLOOG_WARNING,
|
|
"unable to open the file specified in the SCoP "
|
|
"coordinates\n");
|
|
return 0;
|
|
}
|
|
|
|
/* Print the macros the generated code may need. */
|
|
print_macros(file);
|
|
|
|
/* Print what was before the SCoP in the original file. */
|
|
while ((lines < coordinates->start) && (read != EOF)) {
|
|
read = fscanf(original, "%c", &c);
|
|
if (read != EOF) {
|
|
if (c == '\n')
|
|
lines ++;
|
|
fprintf(file, "%c", c);
|
|
}
|
|
}
|
|
|
|
/* Generate the clast from the pseudo-AST then pretty-print it. */
|
|
root = cloog_clast_create(program, options);
|
|
clast_pprint(file, root, coordinates->indent, options);
|
|
cloog_clast_free(root);
|
|
|
|
/* Print what was after the SCoP in the original file. */
|
|
while (read != EOF) {
|
|
read = fscanf(original, "%c", &c);
|
|
if (read != EOF) {
|
|
if (lines >= coordinates->end - 1)
|
|
fprintf(file, "%c", c);
|
|
if (c == '\n')
|
|
lines ++;
|
|
}
|
|
}
|
|
|
|
fclose(original);
|
|
return 1;
|
|
}
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* cloog_program_pprint function:
|
|
* This function prints the content of a CloogProgram structure (program) into a
|
|
* file (file, possibly stdout), in a C-like language.
|
|
* - June 22nd 2005: Adaptation for GMP.
|
|
*/
|
|
void cloog_program_pprint(file, program, options)
|
|
FILE * file ;
|
|
CloogProgram * program ;
|
|
CloogOptions * options ;
|
|
{
|
|
int i, j, indentation = 0;
|
|
CloogStatement * statement ;
|
|
CloogBlockList * blocklist ;
|
|
CloogBlock * block ;
|
|
struct clast_stmt *root;
|
|
|
|
if (cloog_program_osl_pprint(file, program, options))
|
|
return;
|
|
|
|
if (program->language == 'f')
|
|
options->language = CLOOG_LANGUAGE_FORTRAN ;
|
|
else
|
|
options->language = CLOOG_LANGUAGE_C ;
|
|
|
|
#ifdef CLOOG_RUSAGE
|
|
print_comment(file, options, "Generated from %s by %s in %.2fs.",
|
|
options->name, cloog_version(), options->time);
|
|
#else
|
|
print_comment(file, options, "Generated from %s by %s.",
|
|
options->name, cloog_version());
|
|
#endif
|
|
#ifdef CLOOG_MEMORY
|
|
print_comment(file, options, "CLooG asked for %d KBytes.", options->memory);
|
|
cloog_msg(CLOOG_INFO, "%.2fs and %dKB used for code generation.\n",
|
|
options->time,options->memory);
|
|
#endif
|
|
|
|
/* If the option "compilable" is set, we provide the whole stuff to generate
|
|
* a compilable code. This code just do nothing, but now the user can edit
|
|
* the source and set the statement macros and parameters values.
|
|
*/
|
|
if (options->compilable && (program->language == 'c'))
|
|
{ /* The headers. */
|
|
fprintf(file,"/* DON'T FORGET TO USE -lm OPTION TO COMPILE. */\n\n") ;
|
|
fprintf(file,"/* Useful headers. */\n") ;
|
|
fprintf(file,"#include <stdio.h>\n") ;
|
|
fprintf(file,"#include <stdlib.h>\n") ;
|
|
fprintf(file,"#include <math.h>\n\n") ;
|
|
|
|
/* The value of parameters. */
|
|
fprintf(file,"/* Parameter value. */\n") ;
|
|
for (i = 1; i <= program->names->nb_parameters; i++)
|
|
fprintf(file, "#define PARVAL%d %d\n", i, options->compilable);
|
|
|
|
/* The macros. */
|
|
print_macros(file);
|
|
|
|
/* The statement macros. */
|
|
fprintf(file,"/* Statement macros (please set). */\n") ;
|
|
blocklist = program->blocklist ;
|
|
while (blocklist != NULL)
|
|
{ block = blocklist->block ;
|
|
statement = block->statement ;
|
|
while (statement != NULL)
|
|
{ fprintf(file,"#define S%d(",statement->number) ;
|
|
if (block->depth > 0)
|
|
{ fprintf(file,"%s",program->names->iterators[0]) ;
|
|
for(j=1;j<block->depth;j++)
|
|
fprintf(file,",%s",program->names->iterators[j]) ;
|
|
}
|
|
fprintf(file,") {total++;") ;
|
|
if (block->depth > 0) {
|
|
fprintf(file, " printf(\"S%d %%d", statement->number);
|
|
for(j=1;j<block->depth;j++)
|
|
fprintf(file, " %%d");
|
|
|
|
fprintf(file,"\\n\",%s",program->names->iterators[0]) ;
|
|
for(j=1;j<block->depth;j++)
|
|
fprintf(file,",%s",program->names->iterators[j]) ;
|
|
fprintf(file,");") ;
|
|
}
|
|
fprintf(file,"}\n") ;
|
|
|
|
statement = statement->next ;
|
|
}
|
|
blocklist = blocklist->next ;
|
|
}
|
|
|
|
/* The iterator and parameter declaration. */
|
|
fprintf(file,"\nint main() {\n") ;
|
|
print_iterator_declarations(file, program, options);
|
|
if (program->names->nb_parameters > 0)
|
|
{ fprintf(file," /* Parameters. */\n") ;
|
|
fprintf(file, " int %s=PARVAL1",program->names->parameters[0]);
|
|
for(i=2;i<=program->names->nb_parameters;i++)
|
|
fprintf(file, ", %s=PARVAL%d", program->names->parameters[i-1], i);
|
|
|
|
fprintf(file,";\n");
|
|
}
|
|
fprintf(file," int total=0;\n");
|
|
fprintf(file,"\n") ;
|
|
|
|
/* And we adapt the identation. */
|
|
indentation += 2 ;
|
|
} else if (options->callable && program->language == 'c') {
|
|
print_callable_preamble(file, program, options);
|
|
indentation += 2;
|
|
}
|
|
|
|
root = cloog_clast_create(program, options);
|
|
clast_pprint(file, root, indentation, options);
|
|
cloog_clast_free(root);
|
|
|
|
/* The end of the compilable code in case of 'compilable' option. */
|
|
if (options->compilable && (program->language == 'c'))
|
|
{
|
|
fprintf(file, "\n printf(\"Number of integral points: %%d.\\n\",total);");
|
|
fprintf(file, "\n return 0;\n}\n");
|
|
} else if (options->callable && program->language == 'c')
|
|
print_callable_postamble(file, program);
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* Memory deallocation function *
|
|
******************************************************************************/
|
|
|
|
|
|
/**
|
|
* cloog_program_free function:
|
|
* This function frees the allocated memory for a CloogProgram structure.
|
|
*/
|
|
void cloog_program_free(CloogProgram * program)
|
|
{ cloog_names_free(program->names) ;
|
|
cloog_loop_free(program->loop) ;
|
|
cloog_domain_free(program->context) ;
|
|
cloog_block_list_free(program->blocklist) ;
|
|
if (program->scaldims != NULL)
|
|
free(program->scaldims) ;
|
|
|
|
free(program) ;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* Reading function *
|
|
******************************************************************************/
|
|
|
|
|
|
static void cloog_program_construct_block_list(CloogProgram *p)
|
|
{
|
|
CloogLoop *loop;
|
|
CloogBlockList **next = &p->blocklist;
|
|
|
|
for (loop = p->loop; loop; loop = loop->next) {
|
|
*next = cloog_block_list_alloc(loop->block);
|
|
next = &(*next)->next;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Construct a CloogProgram structure from a given context and
|
|
* union domain representing the iteration domains and scattering functions.
|
|
*/
|
|
CloogProgram *cloog_program_alloc(CloogDomain *context, CloogUnionDomain *ud,
|
|
CloogOptions *options)
|
|
{
|
|
int i;
|
|
char prefix[] = "c";
|
|
CloogScatteringList * scatteringl;
|
|
CloogNames *n;
|
|
CloogProgram * p ;
|
|
|
|
/* Memory allocation for the CloogProgram structure. */
|
|
p = cloog_program_malloc() ;
|
|
|
|
if (options->language == CLOOG_LANGUAGE_FORTRAN)
|
|
p->language = 'f';
|
|
else
|
|
p->language = 'c';
|
|
|
|
p->names = n = cloog_names_alloc();
|
|
|
|
/* We then read the context data. */
|
|
p->context = context;
|
|
n->nb_parameters = ud->n_name[CLOOG_PARAM];
|
|
|
|
/* First part of the CloogNames structure: the parameter names. */
|
|
if (ud->name[CLOOG_PARAM]) {
|
|
n->parameters = ud->name[CLOOG_PARAM];
|
|
ud->name[CLOOG_PARAM] = NULL;
|
|
} else
|
|
n->parameters = cloog_names_generate_items(n->nb_parameters, NULL,
|
|
FIRST_PARAMETER);
|
|
|
|
n->nb_iterators = ud->n_name[CLOOG_ITER];
|
|
if (ud->name[CLOOG_ITER]) {
|
|
n->iterators = ud->name[CLOOG_ITER];
|
|
ud->name[CLOOG_ITER] = NULL;
|
|
} else
|
|
n->iterators = cloog_names_generate_items(n->nb_iterators, NULL,
|
|
FIRST_ITERATOR);
|
|
|
|
if (ud->domain) {
|
|
CloogNamedDomainList *l;
|
|
CloogLoop **next = &p->loop;
|
|
CloogScatteringList **next_scat = &scatteringl;
|
|
|
|
scatteringl = NULL;
|
|
for (i = 0, l = ud->domain; l; ++i, l = l->next) {
|
|
*next = cloog_loop_from_domain(options->state, l->domain, i);
|
|
l->domain = NULL;
|
|
(*next)->block->statement->name = l->name;
|
|
(*next)->block->statement->usr = l->usr;
|
|
l->name = NULL;
|
|
|
|
if (l->scattering) {
|
|
*next_scat = ALLOC(CloogScatteringList);
|
|
(*next_scat)->scatt = l->scattering;
|
|
l->scattering = NULL;
|
|
(*next_scat)->next = NULL;
|
|
|
|
next_scat = &(*next_scat)->next;
|
|
}
|
|
|
|
next = &(*next)->next;
|
|
}
|
|
|
|
if (scatteringl != NULL) {
|
|
p->nb_scattdims = cloog_scattering_dimension(scatteringl->scatt,
|
|
p->loop->domain);
|
|
n->nb_scattering = p->nb_scattdims;
|
|
if (ud->name[CLOOG_SCAT]) {
|
|
n->scattering = ud->name[CLOOG_SCAT];
|
|
ud->name[CLOOG_SCAT] = NULL;
|
|
} else
|
|
n->scattering = cloog_names_generate_items(n->nb_scattering, prefix, -1);
|
|
|
|
/* The boolean array for scalar dimensions is created and set to 0. */
|
|
p->scaldims = (int *)malloc(p->nb_scattdims*(sizeof(int))) ;
|
|
if (p->scaldims == NULL)
|
|
cloog_die("memory overflow.\n");
|
|
for (i=0;i<p->nb_scattdims;i++)
|
|
p->scaldims[i] = 0 ;
|
|
|
|
/* We try to find blocks in the input problem to reduce complexity. */
|
|
if (!options->noblocks)
|
|
cloog_program_block(p, scatteringl, options);
|
|
if (!options->noscalars)
|
|
cloog_program_extract_scalars(p, scatteringl, options);
|
|
|
|
cloog_program_scatter(p, scatteringl, options);
|
|
cloog_scattering_list_free(scatteringl);
|
|
|
|
if (!options->noblocks)
|
|
p->loop = cloog_loop_block(p->loop, p->scaldims, p->nb_scattdims);
|
|
}
|
|
else
|
|
{ p->nb_scattdims = 0 ;
|
|
p->scaldims = NULL ;
|
|
}
|
|
|
|
cloog_names_scalarize(p->names,p->nb_scattdims,p->scaldims) ;
|
|
|
|
cloog_program_construct_block_list(p);
|
|
}
|
|
else
|
|
{ p->loop = NULL ;
|
|
p->blocklist = NULL ;
|
|
p->scaldims = NULL ;
|
|
}
|
|
|
|
cloog_union_domain_free(ud);
|
|
|
|
return(p) ;
|
|
}
|
|
|
|
|
|
/**
|
|
* cloog_program_read function:
|
|
* This function read the informations to put in a CloogProgram structure from
|
|
* a file (file, possibly stdin). It returns a pointer to a CloogProgram
|
|
* structure containing the read informations.
|
|
* - October 25th 2001: first version.
|
|
* - September 9th 2002: - the big reading function is now split in several
|
|
* functions (one per read data structure).
|
|
* - adaptation to the new file format with naming.
|
|
*/
|
|
CloogProgram *cloog_program_read(FILE *file, CloogOptions *options)
|
|
{
|
|
CloogInput *input;
|
|
CloogProgram *p;
|
|
|
|
input = cloog_input_read(file, options);
|
|
p = cloog_program_alloc(input->context, input->ud, options);
|
|
free(input);
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* Processing functions *
|
|
******************************************************************************/
|
|
|
|
|
|
/**
|
|
* cloog_program_malloc function:
|
|
* This function allocates the memory space for a CloogProgram structure and
|
|
* sets its fields with default values. Then it returns a pointer to the
|
|
* allocated space.
|
|
* - November 21th 2005: first version.
|
|
*/
|
|
CloogProgram * cloog_program_malloc()
|
|
{ CloogProgram * program ;
|
|
|
|
/* Memory allocation for the CloogProgram structure. */
|
|
program = (CloogProgram *)malloc(sizeof(CloogProgram)) ;
|
|
if (program == NULL)
|
|
cloog_die("memory overflow.\n");
|
|
|
|
/* We set the various fields with default values. */
|
|
program->language = 'c' ;
|
|
program->nb_scattdims = 0 ;
|
|
program->context = NULL ;
|
|
program->loop = NULL ;
|
|
program->names = NULL ;
|
|
program->blocklist = NULL ;
|
|
program->scaldims = NULL ;
|
|
program->usr = NULL;
|
|
|
|
return program ;
|
|
}
|
|
|
|
|
|
/**
|
|
* cloog_program_generate function:
|
|
* This function calls the Quillere algorithm for loop scanning. (see the
|
|
* Quillere paper) and calls the loop simplification function.
|
|
* - depth is the loop depth we want to optimize (guard free as possible),
|
|
* the first loop depth is 1 and anegative value is the infinity depth.
|
|
* - sep_level is the level number where we want to start loop separation.
|
|
**
|
|
* - October 26th 2001: first version.
|
|
* - April 19th 2005: some basic fixes and memory usage feature.
|
|
* - April 29th 2005: (bug fix, bug found by DaeGon Kim) see case 2 below.
|
|
*/
|
|
CloogProgram * cloog_program_generate(program, options)
|
|
CloogProgram * program ;
|
|
CloogOptions * options ;
|
|
{
|
|
#ifdef CLOOG_RUSAGE
|
|
float time;
|
|
struct rusage start, end ;
|
|
#endif
|
|
CloogLoop * loop ;
|
|
#ifdef CLOOG_MEMORY
|
|
char status_path[MAX_STRING_VAL] ;
|
|
FILE * status ;
|
|
|
|
/* We initialize the memory need to 0. */
|
|
options->memory = 0 ;
|
|
#endif
|
|
|
|
if (options->override)
|
|
{
|
|
cloog_msg(options, CLOOG_WARNING,
|
|
"you are using -override option, be aware that the "
|
|
"generated\n code may be incorrect.\n") ;
|
|
}
|
|
else
|
|
{ /* Playing with options may be dangerous, here are two possible issues :
|
|
* 1. Using -l option less than scattering dimension number may lead to
|
|
* an illegal target code (since the scattering is not respected), if
|
|
* it is the case, we set -l depth to the first acceptable value.
|
|
*/
|
|
if ((program->nb_scattdims > options->l) && (options->l >= 0))
|
|
{
|
|
cloog_msg(options, CLOOG_WARNING,
|
|
"-l depth is less than the scattering dimension number "
|
|
"(the \n generated code may be incorrect), it has been "
|
|
"automaticaly set\n to this value (use option -override "
|
|
"to override).\n") ;
|
|
options->l = program->nb_scattdims ;
|
|
}
|
|
|
|
/* 2. Using -f option greater than one while -l depth is greater than the
|
|
* scattering dimension number may lead to iteration duplication (try
|
|
* test/daegon_lu_osp.cloog with '-f 3' to test) because of the step 4b
|
|
* of the cloog_loop_generate function, if it is the case, we set -l to
|
|
* the first acceptable value.
|
|
*/
|
|
if (((options->f > 1) || (options->f < 0)) &&
|
|
((options->l > program->nb_scattdims) || (options->l < 0)))
|
|
{
|
|
cloog_msg(options, CLOOG_WARNING,
|
|
"-f depth is more than one, -l depth has been "
|
|
"automaticaly set\n to the scattering dimension number "
|
|
"(target code may have\n duplicated iterations), -l depth "
|
|
"has been automaticaly set to\n this value (use option "
|
|
"-override to override).\n") ;
|
|
options->l = program->nb_scattdims ;
|
|
}
|
|
}
|
|
|
|
#ifdef CLOOG_RUSAGE
|
|
getrusage(RUSAGE_SELF, &start) ;
|
|
#endif
|
|
if (program->loop != NULL)
|
|
{ loop = program->loop ;
|
|
|
|
/* Here we go ! */
|
|
loop = cloog_loop_generate(loop, program->context, 0, 0,
|
|
program->scaldims,
|
|
program->nb_scattdims,
|
|
options);
|
|
|
|
#ifdef CLOOG_MEMORY
|
|
/* We read into the status file of the process how many memory it uses. */
|
|
sprintf(status_path,"/proc/%d/status",getpid()) ;
|
|
status = fopen(status_path, "r") ;
|
|
while (fscanf(status,"%s",status_path) && strcmp(status_path,"VmData:")!=0);
|
|
fscanf(status,"%d",&(options->memory)) ;
|
|
fclose(status) ;
|
|
#endif
|
|
|
|
if ((!options->nosimplify) && (program->loop != NULL))
|
|
loop = cloog_loop_simplify(loop, program->context, 0,
|
|
program->nb_scattdims, options);
|
|
|
|
program->loop = loop ;
|
|
}
|
|
|
|
#ifdef CLOOG_RUSAGE
|
|
getrusage(RUSAGE_SELF, &end) ;
|
|
/* We calculate the time spent in code generation. */
|
|
time = (end.ru_utime.tv_usec - start.ru_utime.tv_usec)/(float)(MEGA) ;
|
|
time += (float)(end.ru_utime.tv_sec - start.ru_utime.tv_sec) ;
|
|
options->time = time ;
|
|
#endif
|
|
|
|
return program ;
|
|
}
|
|
|
|
|
|
/**
|
|
* cloog_program_block function:
|
|
* this function gives a last chance to the lazy user to consider statement
|
|
* blocks instead of some statement lists where the whole list may be
|
|
* considered as a single statement from a code generation point of view.
|
|
* For instance two statements with the same iteration domain and the same
|
|
* scattering functions may be considered as a block. This function is lazy
|
|
* and can only find very simple forms of trivial blocks (see
|
|
* cloog_domain_lazy_block function for more details). The useless loops and
|
|
* scattering functions are removed and freed while the statement list of
|
|
* according blocks are filled.
|
|
* - program is the whole program structure (befaore applying scattering),
|
|
* - scattering is the list of scattering functions.
|
|
**
|
|
* - April 30th 2005: first attempt.
|
|
* - June 10-11th 2005: first working version.
|
|
*/
|
|
void cloog_program_block(CloogProgram *program,
|
|
CloogScatteringList *scattering, CloogOptions *options)
|
|
{ int blocked_reference=0, blocked=0, nb_blocked=0 ;
|
|
CloogLoop * reference, * start, * loop ;
|
|
CloogScatteringList * scatt_reference, * scatt_loop, * scatt_start;
|
|
|
|
if ((program->loop == NULL) || (program->loop->next == NULL))
|
|
return ;
|
|
|
|
/* The process will use three variables for the linked list :
|
|
* - 'start' is the starting point of a new block,
|
|
* - 'reference' is the node of the block used for the block checking,
|
|
* - 'loop' is the candidate to be inserted inside the block.
|
|
* At the beginning of the process, the linked lists are as follow:
|
|
* O------>O------>O------>O------>NULL
|
|
* | |
|
|
* start loop
|
|
* reference
|
|
*/
|
|
|
|
reference = program->loop ;
|
|
start = program->loop ;
|
|
loop = reference->next ;
|
|
scatt_reference = scattering ;
|
|
scatt_start = scattering ;
|
|
scatt_loop = scattering->next ;
|
|
|
|
while (loop != NULL)
|
|
{ if (cloog_domain_lazy_equal(reference->domain,loop->domain) &&
|
|
cloog_scattering_lazy_block(scatt_reference->scatt, scatt_loop->scatt,
|
|
scattering,program->nb_scattdims))
|
|
{ /* If we find a block we update the links:
|
|
* +---------------+
|
|
* | v
|
|
* O O------>O------>O------>NULL
|
|
* | |
|
|
* start loop
|
|
* reference
|
|
*/
|
|
blocked = 1 ;
|
|
nb_blocked ++ ;
|
|
cloog_block_merge(start->block,loop->block); /* merge frees loop->block */
|
|
loop->block = NULL ;
|
|
start->next = loop->next ;
|
|
scatt_start->next = scatt_loop->next ;
|
|
}
|
|
else
|
|
{ /* If we didn't find a block, the next start of a block is updated:
|
|
* O------>O------>O------>O------>NULL
|
|
* | |
|
|
* reference start
|
|
* loop
|
|
*/
|
|
blocked= 0 ;
|
|
start = loop ;
|
|
scatt_start = scatt_loop ;
|
|
}
|
|
|
|
/* If the reference node has been included into a block, we can free it. */
|
|
if (blocked_reference)
|
|
{ reference->next = NULL ;
|
|
cloog_loop_free(reference) ;
|
|
cloog_scattering_free(scatt_reference->scatt);
|
|
free(scatt_reference) ;
|
|
}
|
|
|
|
/* The reference and the loop are now updated for the next try, the
|
|
* starting position depends on the previous step.
|
|
* O ? O------>O------>O------>NULL
|
|
* | |
|
|
* reference loop
|
|
*/
|
|
reference = loop ;
|
|
loop = loop->next ;
|
|
scatt_reference = scatt_loop ;
|
|
scatt_loop = scatt_loop->next ;
|
|
|
|
/* We mark the new reference as being blocked or not, if will be freed
|
|
* during the next while loop execution.
|
|
*/
|
|
if (blocked)
|
|
blocked_reference = 1 ;
|
|
else
|
|
blocked_reference = 0 ;
|
|
}
|
|
|
|
/* We free the last blocked reference if any (since in the while loop it was
|
|
* freed during the next loop execution, it was not possible to free the
|
|
* last one inside).
|
|
*/
|
|
if (blocked_reference)
|
|
{ reference->next = NULL ;
|
|
cloog_loop_free(reference) ;
|
|
cloog_scattering_free(scatt_reference->scatt);
|
|
free(scatt_reference) ;
|
|
}
|
|
|
|
if (nb_blocked != 0)
|
|
cloog_msg(options, CLOOG_INFO, "%d domains have been blocked.\n", nb_blocked);
|
|
}
|
|
|
|
|
|
/**
|
|
* cloog_program_extract_scalars function:
|
|
* this functions finds and removes the dimensions of the scattering functions
|
|
* when they are scalar (i.e. of the shape "dim + scalar = 0") for all
|
|
* scattering functions. The reason is that the processing of such dimensions
|
|
* is trivial and do not need neither a row and a column in the matrix
|
|
* representation of the domain (this will save memory) neither the full
|
|
* Quillere processing (this will save time). The scalar dimensions data are
|
|
* dispatched in the CloogProgram structure (the boolean vector scaldims will
|
|
* say which original dimensions are scalar or not) and to the CloogBlock
|
|
* structures (each one has a scaldims vector that contains the scalar values).
|
|
* - June 14th 2005: first developments.
|
|
* - June 30th 2005: first version.
|
|
*/
|
|
void cloog_program_extract_scalars(CloogProgram *program,
|
|
CloogScatteringList *scattering, CloogOptions *options)
|
|
{ int i, j, scalar, current, nb_scaldims=0 ;
|
|
CloogScatteringList *start;
|
|
CloogScattering *old;
|
|
CloogLoop *loop;
|
|
CloogBlock * block ;
|
|
|
|
start = scattering ;
|
|
|
|
for (i=0;i<program->nb_scattdims;i++)
|
|
{ scalar = 1 ;
|
|
scattering = start ;
|
|
while (scattering != NULL)
|
|
{ if (!cloog_scattering_lazy_isscalar(scattering->scatt, i, NULL))
|
|
{ scalar = 0 ;
|
|
break ;
|
|
}
|
|
scattering = scattering->next ;
|
|
}
|
|
|
|
if (scalar)
|
|
{ nb_scaldims ++ ;
|
|
program->scaldims[i] = 1 ;
|
|
}
|
|
}
|
|
|
|
/* If there are no scalar dimensions, we can continue directly. */
|
|
if (!nb_scaldims)
|
|
return ;
|
|
|
|
/* Otherwise, in each block, we have to put the number of scalar dimensions,
|
|
* and to allocate the memory for the scalar values.
|
|
*/
|
|
for (loop = program->loop; loop; loop = loop->next) {
|
|
block = loop->block;
|
|
block->nb_scaldims = nb_scaldims ;
|
|
block->scaldims = (cloog_int_t *)malloc(nb_scaldims*sizeof(cloog_int_t));
|
|
for (i=0;i<nb_scaldims;i++)
|
|
cloog_int_init(block->scaldims[i]);
|
|
}
|
|
|
|
/* Then we have to fill these scalar values, so we can erase those dimensions
|
|
* from the scattering functions. It's easier to begin with the last one,
|
|
* since there would be an offset otherwise (if we remove the i^th dimension,
|
|
* then the next one is not the (i+1)^th but still the i^th...).
|
|
*/
|
|
current = nb_scaldims - 1 ;
|
|
for (i=program->nb_scattdims-1;i>=0;i--)
|
|
if (program->scaldims[i])
|
|
{
|
|
scattering = start ;
|
|
for (loop = program->loop; loop; loop = loop->next) {
|
|
block = loop->block;
|
|
if (!cloog_scattering_lazy_isscalar(scattering->scatt, i,
|
|
&block->scaldims[current])) {
|
|
/* We should have found a scalar value: if not, there is an error. */
|
|
cloog_die("dimension %d is not scalar as expected.\n", i);
|
|
}
|
|
scattering = scattering->next ;
|
|
}
|
|
|
|
scattering = start ;
|
|
while (scattering != NULL) {
|
|
old = scattering->scatt;
|
|
scattering->scatt = cloog_scattering_erase_dimension(old, i);
|
|
cloog_scattering_free(old);
|
|
scattering = scattering->next ;
|
|
}
|
|
current-- ;
|
|
}
|
|
|
|
/* We postprocess the scaldims array in such a way that each entry is how
|
|
* many scalar dimensions follows + 1 (the current one). This will make
|
|
* some other processing easier (e.g. knowledge of some offsets).
|
|
*/
|
|
for (i=0;i<program->nb_scattdims-1;i++)
|
|
{ if (program->scaldims[i])
|
|
{ j = i + 1 ;
|
|
while ((j < program->nb_scattdims) && program->scaldims[j])
|
|
{ program->scaldims[i] ++ ;
|
|
j ++ ;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nb_scaldims != 0)
|
|
cloog_msg(options, CLOOG_INFO, "%d dimensions (over %d) are scalar.\n",
|
|
nb_scaldims,program->nb_scattdims) ;
|
|
}
|
|
|
|
|
|
/**
|
|
* cloog_program_scatter function:
|
|
* This function adds the scattering (scheduling) informations in a program.
|
|
* If names is NULL, this function create names itself such that the i^th
|
|
* name is ci.
|
|
* - November 6th 2001: first version.
|
|
*/
|
|
void cloog_program_scatter(CloogProgram *program,
|
|
CloogScatteringList *scattering, CloogOptions *options)
|
|
{ int scattering_dim, scattering_dim2, not_enough_constraints=0 ;
|
|
CloogLoop * loop ;
|
|
|
|
if ((program != NULL) && (scattering != NULL))
|
|
{ loop = program->loop ;
|
|
|
|
/* We compute the scattering dimension and check it is >=0. */
|
|
scattering_dim = cloog_scattering_dimension(scattering->scatt, loop->domain);
|
|
if (scattering_dim < 0)
|
|
cloog_die("scattering has not enough dimensions.\n");
|
|
if (!cloog_scattering_fully_specified(scattering->scatt, loop->domain))
|
|
not_enough_constraints ++ ;
|
|
|
|
/* The scattering dimension may have been modified by scalar extraction. */
|
|
scattering_dim = cloog_scattering_dimension(scattering->scatt, loop->domain);
|
|
|
|
/* Finally we scatter all loops. */
|
|
cloog_loop_scatter(loop, scattering->scatt);
|
|
loop = loop->next ;
|
|
scattering = scattering->next ;
|
|
|
|
while ((loop != NULL) && (scattering != NULL))
|
|
{ scattering_dim2 = cloog_scattering_dimension(scattering->scatt,
|
|
loop->domain);
|
|
if (scattering_dim2 != scattering_dim)
|
|
cloog_die("scattering dimensions are not the same.\n") ;
|
|
if (!cloog_scattering_fully_specified(scattering->scatt, loop->domain))
|
|
not_enough_constraints ++ ;
|
|
|
|
cloog_loop_scatter(loop, scattering->scatt);
|
|
loop = loop->next ;
|
|
scattering = scattering->next ;
|
|
}
|
|
if ((loop != NULL) || (scattering != NULL))
|
|
cloog_msg(options, CLOOG_WARNING,
|
|
"there is not a scattering for each statement.\n");
|
|
|
|
if (not_enough_constraints)
|
|
cloog_msg(options, CLOOG_WARNING, "not enough constraints for "
|
|
"%d scattering function(s).\n",not_enough_constraints) ;
|
|
}
|
|
}
|