From 1929ac1a60615ee86779790c46e04e53de75462f Mon Sep 17 00:00:00 2001 From: Tuowen Zhao Date: Thu, 22 Sep 2016 15:12:54 -0600 Subject: add CHILL_DEBUG_PRINT & CHILL_DEBUG_BEGIN & CHILL_DEBUG_END --- src/chillASTs.cc | 6492 +++++++++++++++++++++++++++++++++ src/chill_ast.cc | 6493 ---------------------------------- src/ir_clang.cc | 168 +- src/irtools.cc | 78 +- src/loop.cc | 4435 ----------------------- src/loop_basic.cc | 1839 ---------- src/loop_datacopy.cc | 1369 ------- src/loop_extra.cc | 224 -- src/loop_tile.cc | 587 --- src/loop_unroll.cc | 1222 ------- src/omegatools.cc | 2 +- src/transformations/loop.cc | 4433 +++++++++++++++++++++++ src/transformations/loop_basic.cc | 1839 ++++++++++ src/transformations/loop_datacopy.cc | 1369 +++++++ src/transformations/loop_extra.cc | 224 ++ src/transformations/loop_tile.cc | 587 +++ src/transformations/loop_unroll.cc | 1222 +++++++ 17 files changed, 16292 insertions(+), 16291 deletions(-) create mode 100644 src/chillASTs.cc delete mode 100644 src/chill_ast.cc delete mode 100644 src/loop.cc delete mode 100644 src/loop_basic.cc delete mode 100644 src/loop_datacopy.cc delete mode 100644 src/loop_extra.cc delete mode 100644 src/loop_tile.cc delete mode 100644 src/loop_unroll.cc create mode 100644 src/transformations/loop.cc create mode 100644 src/transformations/loop_basic.cc create mode 100644 src/transformations/loop_datacopy.cc create mode 100644 src/transformations/loop_extra.cc create mode 100644 src/transformations/loop_tile.cc create mode 100644 src/transformations/loop_unroll.cc (limited to 'src') diff --git a/src/chillASTs.cc b/src/chillASTs.cc new file mode 100644 index 0000000..ebb811c --- /dev/null +++ b/src/chillASTs.cc @@ -0,0 +1,6492 @@ + + + +#include +#include "chillAST.h" + +using namespace std; + +int chillAST_node::chill_scalar_counter = 0; +int chillAST_node::chill_array_counter = 1; + + +const char* Chill_AST_Node_Names[] = { + "Unknown AST node type", + "SourceFile", + "TypedefDecl", + "VarDecl", + // "ParmVarDecl", not used any more + "FunctionDecl", + "RecordDecl", + "MacroDefinition", + "CompoundStmt", + "ForStmt", + "TernaryOperator", + "BinaryOperator", + "UnaryOperator", + "ArraySubscriptExpr", + "MemberExpr", + "DeclRefExpr", + "IntegerLiteral", + "FloatingLiteral", + "ImplicitCastExpr", // not sure we need this + "ReturnStmt", + "CallExpr", + "DeclStmt", + "ParenExpr", + "CStyleCastExpr", + "CStyleAddressOf", + "IfStmt", + "SizeOf", + "Malloc", + "Free", + "NoOp", +// CUDA specific + "CudaMalloc", + "CudaFree", + "CudaMemcpy", + "CudaKernelCall", + "CudaSyncthreads", + "fake1", + "fake2", + "fake3" +}; + +char *parseUnderlyingType( char *sometype ) { + int len = strlen(sometype); + //fprintf(stderr, "parseUnderlyingType( %s )\n", sometype); + char *underlying = strdup(sometype); + char *p; + char *start = underlying; + + // ugly. we want to turn "float *" into "float" but "struct abc *" into struct abc. + // there are probably many more cases. have an approved list? TODO + if (strstr(underlying, "struct ")) start += 7; // (length("struct ")) + //fprintf(stderr, "sometype '%s' start '%s'\n", sometype, start); + if (p = index(start, ' ')) *p = '\0'; // end at first space leak + if (p = index(start, '[')) *p = '\0'; // leak + if (p = index(start, '*')) *p = '\0'; // leak + + return underlying; +} + +void printSymbolTable( chillAST_SymbolTable *st ) { + //printf("%d entries\n", st->size()); + if (!st) return; + for (int i=0; isize(); i++) { printf("%d ", i ); (*st)[i]->printName(); printf("\n"); } + if (st->size() )printf("\n"); + fflush(stdout); +} + +void printSymbolTableMoreInfo( chillAST_SymbolTable *st ) { + //printf("%d entries\n", st->size()); + if (!st) return; + for (int i=0; isize(); i++) { printf("%d ", i ); (*st)[i]->print(); printf("\n"); } + if (st->size() )printf("\n"); + fflush(stdout); +} + + +bool symbolTableHasVariableNamed( chillAST_SymbolTable *table, const char *name ) { + if (!table) return false; // ?? + int numvars = table->size(); + for (int i=0; ivarname)) return true; // need to check type? + } + return false; +} + + + +chillAST_VarDecl *symbolTableFindVariableNamed( chillAST_SymbolTable *table, const char *name ){ // fwd decl TODO too many similar named functions + if (!table) return NULL; // ?? + + // see if name has a dot or arrow (->) indicating that it is a structure/class + const char *cdot = strstr( name, "." ); + const char *carrow = strstr(name, "->"); // initial 'c' for const - can't change those + + char *varname; + char *subpart = NULL; + + if (cdot || carrow) { + fprintf(stderr, "symbolTableFindVariableNamed(), name '%s' looks like a struct\n", name); + + // so, look for the first part in the symbol table. + // warning, this could be looking for a->b.c.d->e.f->g + varname = strdup( name ); + + char *dot = strstr(varname, "." ); + char *arrow = strstr( varname, "->" ); + if (dot != NULL && arrow != NULL ) { // dot AND arrow, + fprintf(stderr, "chillast.cc symbolTableFindVariableNamed(), name '%s' has both dot and arrow? TODO\n"); + exit(-1); + } + else if (dot != NULL && !arrow) { // just dot(s). dot points to the first one + //fprintf(stderr, "name '%s' has dot(s)\n", varname); + *dot = '\0'; // end string at the dot + subpart = &(dot[1]); + fprintf(stderr, "will now look for a struct/class named %s that has member %s\n", varname, subpart); + + } + else if (arrow != NULL && !dot) { // just arrow(s) arrow points to the first one + //fprintf(stderr, "name '%s' has arrow(s)\n", varname); + *arrow = '\0'; // end string at the arrow + subpart = &(arrow[2]); + fprintf(stderr, "will now look for a struct/class named %s that has member %s\n", varname, subpart); + } + else { // impossible + fprintf(stderr, "chillast.cc symbolTableFindVariableNamed(), varname '%s', looks like a struct, but I can't figure it out\n", varname); + exit(-1); + } + } + else { + varname = strdup(name); + } + + int numvars = table->size(); + for (int i=0; ivarname)) { + fprintf(stderr, "found variable named %s\n", varname); + + if (!subpart) return vd; // need to check type? + + // OK, we have a variable, which looks like a struct/class, and a subpart that is some member names + //fprintf(stderr, "but I don't know how to check if it has member %s\n", subpart); + + char *dot = strstr(subpart, "." ); + char *arrow = strstr(subpart, "->" ); + + if (!dot && !arrow) { // whew, only one level of struct + //fprintf(stderr, "whew, only one level of struct\n"); + + // make sure this variable definition is a struct + if (vd->isAStruct()) { + //fprintf(stderr, "%s is a struct of type %s\n", varname, vd->getTypeString()); + if (vd->isVarDecl()) { + chillAST_RecordDecl *rd = vd->getStructDef(); + if (rd) { + //fprintf(stderr, "has a recordDecl\n"); + + chillAST_VarDecl *sp = rd->findSubpart( subpart ); + if (sp) fprintf(stderr, "found a struct member named %s\n", subpart); + else fprintf(stderr, "DIDN'T FIND a struct member named %s\n", subpart); + return sp; // return the subpart?? + } + else { + fprintf(stderr, "no recordDecl\n"); + exit(-1); + } + } + else { + fprintf(stderr, "NOT a VarDecl???\n"); // impossible + } + } + else { + fprintf(stderr, "false alarm. %s is a variable, but doesn't have subparts\n", varname); + return NULL; // false alarm. a variable of the correct name exists, but is not a struct + } + } + + fprintf(stderr, "chillast.cc symbolTableFindVariableNamed(), name '%s' can't figure out multiple levels of struct yet!\n"); + + exit(-1); + } + } + return NULL; +} + + + +char *ulhack( char *brackets ) // remove UL from numbers, MODIFIES the argument! +{ + //fprintf(stderr, "ulhack( \"%s\" -> ", brackets); + // another hack. remove "UL" from integers + int len = strlen(brackets); + for (int i=0; i< len-2; i++) { + if (isdigit(brackets[i])) { + if (brackets[i+1] == 'U' && brackets[i+2] == 'L') { + // remove + for (int j=i+3; j %s\n", sometype, arraypart); + return arraypart; +} + + + + + + + +char *splitTypeInfo( char *underlyingtype ) { // return the bracketed part of a type + char *ap = ulhack(parseArrayParts( underlyingtype )); // return this + + // now need to remove all that from the underlyingtype to get + char *arraypart = strdup(""); // leak + if (index(underlyingtype, '[')) { + // looks like an array + free(arraypart); + char *start = index(underlyingtype, '['); // wrong. can have int *buh[32] + arraypart = strdup( start ); + if (*(start-1) == ' ') start--; // hack + *start = '\0'; + + // ugly. very leaky + strcpy( underlyingtype, parseUnderlyingType( underlyingtype )); + + // ulhack( arraypart ); + } + return ap; // leak unless caller frees this +} + + + +bool isRestrict( const char *sometype ) { // does not modify sometype + string r( "__restrict__" ); + string t( sometype ); + return (std::string::npos != t.find( r ) ); +} + + + +bool streq( const char *a, const char *b) { return !strcmp(a,b); }; // slightly less ugly // TODO enums + +void chillindent( int howfar, FILE *fp ) { for (int i=0; ifindVariableNamed( name ); +} + + +chillAST_RecordDecl * chillAST_node::findRecordDeclNamed( const char *name ) { // recursive + fprintf(stderr, "%s::findRecordDeclNamed( %s )\n", getTypeString(), name); + // look in children + int numchildren = children.size(); + fprintf(stderr, "%d children\n", numchildren); + for (int i=0; igetTypeString()); + if (children[i]->isRecordDecl()) { + chillAST_RecordDecl *RD = (chillAST_RecordDecl *)children[i]; + fprintf(stderr, "it is a recordDecl named '%s' vs '%s'\n", RD->getName(), name); + if (!strcmp( RD->getName(), name )) { + fprintf(stderr, "FOUND IT\n"); + return RD; + } + } + } + + if (!parent) return NULL; // no more recursion available + // recurse upwards + return parent->findRecordDeclNamed( name ); +} + + +void chillAST_node::printPreprocBEFORE( int indent, FILE *fp ) { + int numstmts = preprocessinginfo.size(); + //if (0 != numstmts) { + // fprintf(fp, "chillAST_node::printPreprocBEFORE() %d statements\n", numstmts); + //} + + + for (int i=0; i< numstmts; i++) { + //fprintf(fp, "stmt %d %d\n", i, preprocessinginfo[i]->position); + if (preprocessinginfo[i]->position == CHILL_PREPROCESSING_LINEBEFORE || + preprocessinginfo[i]->position == CHILL_PREPROCESSING_IMMEDIATELYBEFORE) { + //fprintf(stderr, "before %d\n", preprocessinginfo[i]->position); + preprocessinginfo[i]->print(indent, fp); + } + } +} + +void chillAST_node::printPreprocAFTER( int indent, FILE *fp ) { + for (int i=0; i< preprocessinginfo.size(); i++) { + if (preprocessinginfo[i]->position == CHILL_PREPROCESSING_LINEAFTER || + preprocessinginfo[i]->position == CHILL_PREPROCESSING_TOTHERIGHT) { + //fprintf(stderr, "after %d\n", preprocessinginfo[i]->position); + preprocessinginfo[i]->print(indent, fp); + } + } +} + + +chillAST_SourceFile::chillAST_SourceFile::chillAST_SourceFile() { + SourceFileName = strdup("No Source File"); + asttype = CHILLAST_NODETYPE_SOURCEFILE; + parent = NULL; // top node + metacomment = NULL; + global_symbol_table = NULL; + global_typedef_table = NULL; + FileToWrite = NULL; + frontend = strdup("unknown"); + isFromSourceFile = true; + filename = NULL; +}; + +chillAST_SourceFile::chillAST_SourceFile(const char *filename ) { + SourceFileName = strdup(filename); + asttype = CHILLAST_NODETYPE_SOURCEFILE; + parent = NULL; // top node + metacomment = NULL; + global_symbol_table = NULL; + global_typedef_table = NULL; + FileToWrite = NULL; + frontend = strdup("unknown"); + isFromSourceFile = true; + filename = NULL; +}; + +void chillAST_SourceFile::print( int indent, FILE *fp ) { + //fprintf(stderr, "chillAST_SourceFile::print()\n"); + fflush(fp); + fprintf(fp, "\n// this source derived from CHILL AST originally from file '%s' as parsed by frontend compiler %s\n\n", SourceFileName, frontend); + std::vector< char * > includedfiles; + int sofar = 0; + + //fprintf(fp, "#define __rose_lt(x,y) ((x)<(y)?(x):(y))\n#define __rose_gt(x,y) ((x)>(y)?(x):(y))\n"); // help diff figure out what's going on + + int numchildren = children.size(); + //fprintf(stderr, "// sourcefile has %d children\n", numchildren); + //fprintf(stderr, "they are\n"); + //for (int i=0; igetTypeString()); + // if (children[i]->isFunctionDecl()) { + // fprintf(stderr, "%s ", ((chillAST_FunctionDecl *)children[i])->functionName); + // } + // fprintf(stderr, "\n"); + //} + + for (int i=0; igetTypeString()); + if (children[i]->isFromSourceFile) { + if (children[i]->isFunctionDecl()) { + fprintf(stderr, "\nchild %d function %s\n",i,((chillAST_FunctionDecl *)children[i])->functionName); + } + //fprintf(stderr, "child %d IS from source file\n", i); + //if (children[i]->isMacroDefinition()) fprintf(fp, "\n"); fflush(fp); + children[i]->print( indent, fp ); + if (children[i]->isVarDecl()) fprintf(fp, ";\n"); fflush(fp); // top level vardecl\n"); + } + else { + //fprintf(stderr, "child %d is not from source file\n", i); + // this should all go away + +#ifdef NOPE + if (children[i]->filename // not null and not empty string + //&& 0 != strlen(children[i]->filename) + ) { // should not be necessary + //fprintf(fp, "// need an include for %s\n", children[i]->filename); + bool rddid = false; + sofar = includedfiles.size(); + + for (int j=0; jfilename ); + if (!strcmp( includedfiles[j], children[i]->filename) ) { // this file has already been included + rddid = true; + //fprintf(stderr, "already did that one\n"); + } + } + + if (false == rddid) { // we need to include it now + fprintf(fp, "#include \"%s\"\n", children[i]->filename); + includedfiles.push_back(strdup( children[i]->filename )); + } + //else { + // fprintf(fp, "already did\n"); + //} + } +#endif // NOPE + + + } + } + + fflush(fp); + + //fprintf(fp, "\n\n// functions??\n"); + //for (int i=0; iprint(0,fp); fflush(fp); + //} +}; + + + + +void chillAST_SourceFile::printToFile( char *filename ) { + char fn[1024]; + + if (NULL == filename) { // build up a filename using original name and frontend if known + if (FileToWrite) { + strcpy( fn, FileToWrite ); + } + else { + // input name with name of frontend compiler prepended + if (frontend) sprintf(fn, "%s_%s\0", frontend, SourceFileName); + else sprintf(fn, "UNKNOWNFRONTEND_%s\0", SourceFileName); // should never happen + } + } + else strcpy( fn, filename ); + + FILE *fp = fopen(fn, "w"); + if (!fp) { + fprintf(stderr, "can't open file '%s' for writing\n", fn); + exit(-1); + } + + //fprintf(fp, "\n\n"); + //dump(0, fp); + fprintf(fp, "\n\n"); + print(0, fp); + +} + + + +void chillAST_SourceFile::dump( int indent, FILE *fp ) { + fflush(fp); + fprintf(fp, "\n//CHILL AST originally from file '%s'\n", SourceFileName); + int numchildren = children.size(); + for (int i=0; idump( indent, fp ); + } + fflush(fp); +}; + + + +chillAST_MacroDefinition * chillAST_SourceFile::findMacro( const char *name ) { + //fprintf(stderr, "chillAST_SourceFile::findMacro( %s )\n", name ); + + int numMacros = macrodefinitions.size(); + for (int i=0; imacroName, name )) return macrodefinitions[i]; + } + return NULL; // not found +} + + +chillAST_FunctionDecl * chillAST_SourceFile::findFunction( const char *name ) { + //fprintf(stderr, "chillAST_SourceFile::findMacro( %s )\n", name ); + + int numFuncs = functions.size(); + for (int i=0; ifunctionName, name )) return functions[i]; + } + return NULL; +} + + +chillAST_node *chillAST_SourceFile::findCall( const char *name ) { + chillAST_MacroDefinition *macro = findMacro( name ); + if (macro) return (chillAST_node *)macro; + chillAST_FunctionDecl *func =findFunction( name ); + return func; +} + + +chillAST_VarDecl * chillAST_SourceFile::findVariableNamed( const char *name ) { + fprintf(stderr, "SOURCEFILE SPECIAL %s findVariableNamed( %s )\n", getTypeString(), name ); + if (hasSymbolTable()) { // look in my symbol table if I have one + fprintf(stderr, "%s has a symbol table\n", getTypeString()); + chillAST_VarDecl *vd = symbolTableFindVariableNamed( getSymbolTable(), name); + if (vd) { + fprintf(stderr, "found it\n"); + return vd; // found locally + } + fprintf(stderr, "%s has a symbol table but couldn't find %s\n", getTypeString(), name ); + } + + fprintf(stderr, "looking for %s in SourceFile global_symbol_table\n", name); + chillAST_VarDecl *vd = symbolTableFindVariableNamed( global_symbol_table, name ); + if (vd) { + fprintf(stderr, "found it\n"); + return vd; // found locally + } + + if (!parent) { + fprintf(stderr, "%s has no parent\n", getTypeString()); + return NULL; // no more recursion available + } + // recurse upwards + //fprintf(stderr, "recursing from %s up to parent %p\n", getTypeString(), parent); + fprintf(stderr, "recursing from %s up to parent\n", getTypeString()); + return parent->findVariableNamed( name ); +} + + + +chillAST_TypedefDecl::chillAST_TypedefDecl() { + underlyingtype = newtype = arraypart = NULL; + asttype = CHILLAST_NODETYPE_TYPEDEFDECL; + parent = NULL; + metacomment = NULL; + isStruct = isUnion = false; + structname = NULL; + rd = NULL; + isFromSourceFile = true; // default + filename = NULL; +}; + + +chillAST_TypedefDecl::chillAST_TypedefDecl(char *t, const char *nt, chillAST_node *par) { + //fprintf(stderr, "chillAST_TypedefDecl::chillAST_TypedefDecl( underlying type %s, newtype %s )\n", t, nt); + underlyingtype = strdup(t); + newtype = strdup(nt); + arraypart = NULL; + asttype = CHILLAST_NODETYPE_TYPEDEFDECL; + parent = NULL; + metacomment = NULL; + isStruct = isUnion = false; + structname = NULL; + rd = NULL; + isFromSourceFile = true; // default + filename = NULL; +}; + + +chillAST_TypedefDecl::chillAST_TypedefDecl(char *t, const char *a, char *p, chillAST_node *par) { + underlyingtype = strdup(t); + //fprintf(stderr, "chillAST_TypedefDecl::chillAST_TypedefDecl( underlying type %s )\n", underlyingtype); + newtype = strdup(a); // the new named type ?? + + arraypart = strdup(p); // array (p)art? + // splitarraypart(); // TODO + + asttype = CHILLAST_NODETYPE_TYPEDEFDECL; + parent = par; + metacomment = NULL; + isStruct = isUnion = false; + structname = NULL; + rd = NULL; + isFromSourceFile = true; // default + filename = NULL; +}; + + + + +void chillAST_TypedefDecl::print( int indent, FILE *fp ) { + //fprintf(fp, "typedefdecl->print()\n"); + + printPreprocBEFORE(indent, fp); + + if (isStruct) { + fprintf(fp, "\n/* A typedef STRUCT */\n"); chillindent(indent, fp); + } + + chillindent(indent, fp); + fprintf(fp, "typedef "); fflush(fp); + + if (rd) { + rd->print(indent, fp); // needs to not print the ending semicolon ?? + } + + else if (isStruct) { + fprintf(stderr, "/* no rd */\n"); + + //fprintf(fp, "struct %s\n", structname); + chillindent(indent, fp); + fprintf(fp, "{\n"); + for (int i=0; igetTypeString()); + subparts[i]->print(indent+1, fp); + fprintf(fp, ";\n"); + } + fprintf(fp, "};\n"); + } + else { + fprintf(fp, "/* NOT A STRUCT */ typedef %s %s%s;\n", underlyingtype, newtype, arraypart ); + dump(); printf("\n\n"); fflush(stdout); + } + + // then the newname + fprintf(fp, "%s;\n", newtype); + fflush(fp); + printPreprocAFTER(indent, fp); + + return; +} + + +chillAST_VarDecl *chillAST_TypedefDecl::findSubpart( const char *name ) { + //fprintf(stderr, "chillAST_TypedefDecl::findSubpart( %s )\n", name); + //fprintf(stderr, "typedef %s %s\n", structname, newtype); + + if (rd) { // we have a record decl look there + chillAST_VarDecl *sub = rd->findSubpart( name ); + //fprintf(stderr, "rd found subpart %p\n", sub); + return sub; + } + + // can this ever happen now ??? + int nsub = subparts.size(); + //fprintf(stderr, "%d subparts\n", nsub); + for (int i=0; ivarname )) return subparts[i]; + } + //fprintf(stderr, "subpart not found\n"); + + + return NULL; +} + + +chillAST_RecordDecl * chillAST_TypedefDecl::getStructDef() { + if (rd) return rd; + return NULL; +} + + + +chillAST_RecordDecl::chillAST_RecordDecl() { + asttype = CHILLAST_NODETYPE_RECORDDECL; + name = strdup("unknown"); // ?? + originalname = NULL; // ?? + isStruct = isUnion = false; + parent = NULL; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_RecordDecl::chillAST_RecordDecl( const char *nam, chillAST_node *p ) { + //fprintf(stderr, "chillAST_RecordDecl::chillAST_RecordDecl()\n"); + asttype = CHILLAST_NODETYPE_RECORDDECL; + parent = p; + if (nam) name = strdup(nam); + else name = strdup("unknown"); // ?? + originalname = NULL; // ?? // make them do it manually? + isStruct = isUnion = false; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_RecordDecl::chillAST_RecordDecl( const char *nam, const char *orig, chillAST_node *p ) { + fprintf(stderr, "chillAST_RecordDecl::chillAST_RecordDecl( %s, ( AKA %s ) )\n", nam, orig); + asttype = CHILLAST_NODETYPE_RECORDDECL; + parent = p; + if (p) p->addChild( this ); + + if (nam) name = strdup(nam); + else name = strdup("unknown"); // ?? + + originalname = NULL; + if (orig) originalname = strdup(orig); + + isStruct = isUnion = false; + isFromSourceFile = true; // default + filename = NULL; +} + + + +chillAST_VarDecl * chillAST_RecordDecl::findSubpart( const char *nam ){ + //fprintf(stderr, "chillAST_RecordDecl::findSubpart( %s )\n", nam); + int nsub = subparts.size(); + //fprintf(stderr, "%d subparts\n", nsub); + for (int i=0; ivarname); + if ( !strcmp( nam, subparts[i]->varname )) return subparts[i]; + } + fprintf(stderr, "chillAST_RecordDecl::findSubpart() couldn't find member NAMED %s in ", nam); print(); printf("\n\n"); fflush(stdout); + + return NULL; +} + + +chillAST_VarDecl * chillAST_RecordDecl::findSubpartByType( const char *typ ){ + //fprintf(stderr, "chillAST_RecordDecl::findSubpart( %s )\n", nam); + int nsub = subparts.size(); + //fprintf(stderr, "%d subparts\n", nsub); + for (int i=0; ivartype); + if ( !strcmp( typ, subparts[i]->vartype )) return subparts[i]; + } + //fprintf(stderr, "chillAST_RecordDecl::findSubpart() couldn't find member of TYPE %s in ", typ); print(); printf("\n\n"); fflush(stdout); + + return NULL; +} + + +void chillAST_RecordDecl::print( int indent, FILE *fp ) { + //fprintf(fp, "chillAST_RecordDecl::print()\n"); + if (isUnnamed) return; + + printPreprocBEFORE(indent, fp); + + chillindent(indent, fp); + if (isStruct) { + //fprintf(fp, "\n/* A Record Decl STRUCT */\n"); chillindent(indent, fp); + fprintf(fp, "struct "); + if ( strncmp( "unnamed", name, 7) ) fprintf(fp, "%s\n", name); + + chillindent(indent, fp); + fprintf(fp, "{\n"); + for (int i=0; igetTypeString()); + subparts[i]->print(indent+1, fp); + fprintf(fp, ";\n"); + } + fprintf(fp, "} "); + fprintf(fp, "\n"); // TODO need semicolon when defining struct. can't have it when part of a typedef. One of the following lines is correct in each case. + //fprintf(fp, ";\n"); + } + else { + fprintf(fp, "/* UNKNOWN RECORDDECL print() */ "); + exit(-1); + } + printPreprocAFTER(indent, fp); + fflush(fp); +} + + +chillAST_SymbolTable * chillAST_RecordDecl::addVariableToSymbolTable( chillAST_VarDecl *vd ){ + // for now, just bail. or do we want the struct to have an actual symbol table? + //fprintf(stderr, "chillAST_RecordDecl::addVariableToSymbolTable() ignoring struct member %s vardecl\n", vd->varname); + return NULL; // damn, I hope nothing uses this! +} + +void chillAST_RecordDecl::printStructure( int indent, FILE *fp ) { + //fprintf(stderr, "chillAST_RecordDecl::printStructure()\n"); + chillindent(indent, fp); + if (isStruct) { + fprintf(fp, "struct { ", name); + for (int i=0; iprint( 0, fp); // ?? TODO indent level + fprintf(fp, "; "); + } + fprintf(fp, "} "); + } + else { + fprintf(fp, "/* UNKNOWN RECORDDECL printStructure() */ "); + exit(-1); + } + fflush(fp); +} + + + +void chillAST_RecordDecl::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + +} + + +chillAST_FunctionDecl::chillAST_FunctionDecl() { + functionName = strdup("YouScrewedUp"); + asttype = CHILLAST_NODETYPE_FUNCTIONDECL; + forwarddecl = externfunc = builtin = false; + uniquePtr = (void *) NULL; + this->setFunctionCPU(); + parent = NULL; + metacomment = NULL; + //symbol_table = NULL; // eventually, pointing to body's symbol table + typedef_table = NULL; + body = new chillAST_CompoundStmt(); + isFromSourceFile = true; // default + filename = NULL; +}; + + +chillAST_FunctionDecl::chillAST_FunctionDecl(const char *rt, const char *fname, chillAST_node *par) { + returnType = strdup(rt); + functionName = strdup(fname); + this->setFunctionCPU(); + //fprintf(stderr, "functionName %s\n", functionName); + forwarddecl = externfunc = builtin = false; + + asttype = CHILLAST_NODETYPE_FUNCTIONDECL; + parent = par; + metacomment = NULL; + if (par) par->getSourceFile()->addFunc( this ); + // symbol_table = NULL; //use body's instead + typedef_table = NULL; + body = new chillAST_CompoundStmt(); + isFromSourceFile = true; // default + filename = NULL; +}; + + +chillAST_FunctionDecl::chillAST_FunctionDecl(const char *rt, const char *fname, chillAST_node *par, void *unique) { + CHILL_DEBUG_PRINT("chillAST_FunctionDecl::chillAST_FunctionDecl with unique %p\n", unique); + returnType = strdup(rt); + functionName = strdup(fname); + this->setFunctionCPU(); + //fprintf(stderr, "functionName %s\n", functionName); + forwarddecl = externfunc = builtin = false; + + body = new chillAST_CompoundStmt(); + asttype = CHILLAST_NODETYPE_FUNCTIONDECL; + uniquePtr = unique; // a quick way to check equivalence. DO NOT ACCESS THROUGH THIS + parent = par; + metacomment = NULL; + if (par) par->getSourceFile()->addFunc( this ); + //symbol_table = NULL; // use body's + typedef_table = NULL; + isFromSourceFile = true; // default + filename = NULL; +}; + + +void chillAST_FunctionDecl::addParameter( chillAST_VarDecl *p) { + CHILL_DEBUG_PRINT("%s chillAST_FunctionDecl::addParameter( 0x%x param %s) total of %d parameters\n", functionName, p, p->varname, 1+parameters.size()); + + if (symbolTableHasVariableNamed( ¶meters, p->varname)) { // NOT recursive. just in FunctionDecl + CHILL_DEBUG_PRINT("chillAST_FunctionDecl::addParameter( %s ), parameter already exists?\n", p->varname); + // exit(-1); // ?? + return; // error? + } + + parameters.push_back(p); + //addSymbolToTable( parameters, p ); + CHILL_DEBUG_PRINT("setting %s isAParameter\n", p->varname); + p->isAParameter = true; + + p->setParent( this ); // ?? unclear TODO + //p->dump(); printf("\naddparameter done\n\n"); fflush(stdout); +} + + + +void chillAST_FunctionDecl::addDecl( chillAST_VarDecl *vd) { // to symbol table ONLY + CHILL_DEBUG_PRINT("chillAST_FunctionDecl::addDecl( %s )\n", vd->varname); + if (!body) { + //fprintf(stderr, "had no body\n"); + body = new chillAST_CompoundStmt(); + + //body->symbol_table = symbol_table; // probably wrong if this ever does something + } + + //fprintf(stderr, "before body->addvar(), func symbol table had %d entries\n", symbol_table->size()); + //fprintf(stderr, "before body->addvar(), body symbol table was %p\n", body->symbol_table); + //fprintf(stderr, "before body->addvar(), body symbol table had %d entries\n", body->symbol_table->size()); + //adds to body symbol table, and makes sure function has a copy. probably dumb + body->symbol_table = body->addVariableToSymbolTable( vd ); + //fprintf(stderr, "after body->addvar(), func symbol table had %d entries\n", symbol_table->size()); +} + +chillAST_VarDecl *chillAST_FunctionDecl::hasParameterNamed( const char *name ) { + int numparams = parameters.size(); + for (int i=0; ivarname)) return parameters[i]; // need to check type? + } + return NULL; +} + + +// similar to symbolTableHasVariableNamed() but returns the variable definition +chillAST_VarDecl *chillAST_FunctionDecl::funcHasVariableNamed( const char *name ) { // NOT recursive + //fprintf(stderr, "chillAST_FunctionDecl::funcHasVariableNamed( %s )\n", name ); + + // first check the parameters + int numparams = parameters.size(); + for (int i=0; ivarname)) { + //fprintf(stderr, "yep, it's parameter %d\n", i); + return vd; // need to check type? + } + } + //fprintf(stderr, "no parameter named %s\n", name); + + chillAST_SymbolTable *st = getSymbolTable(); + if (!st) { + fprintf(stderr,"and no symbol_table, so no variable named %s\n", name); + return NULL; // no symbol table so no variable by that name + } + + + int numvars = st->size(); + //fprintf(stderr, "checking against %d variables\n", numvars); + for (int i=0; ivarname); + if (!strcmp(name, vd->varname)) { + //fprintf(stderr, "yep, it's variable %d\n", i); + CHILL_DEBUG_PRINT("%s was already defined in the function body\n", vd->varname); + return vd; // need to check type? + } + } + CHILL_DEBUG_PRINT("not a parameter or variable named %s\n", name); + return NULL; +} + + + + +void chillAST_FunctionDecl::setBody( chillAST_node * bod ) { + //fprintf(stderr, "%s chillAST_FunctionDecl::setBody( 0x%x ) total of %d children\n", functionName, bod, 1+children.size()); + if (bod->isCompoundStmt()) body = (chillAST_CompoundStmt *)bod; + else { + body = new chillAST_CompoundStmt(); + body->addChild( bod ); + } + //symbol_table = body->getSymbolTable(); + //addChild(bod); + bod->setParent( this ); // well, ... +} + + +void chillAST_FunctionDecl::insertChild(int i, chillAST_node* node) { + fprintf(stderr, "chillAST_FunctionDecl::insertChild() "); node->print(0,stderr); fprintf(stderr, "\n\n"); + body->insertChild( i, node ); + + if (node->isVarDecl()) { + chillAST_VarDecl *vd = ((chillAST_VarDecl *) node); + fprintf(stderr, "functiondecl %s inserting a VarDecl named %s\n", functionName, vd->varname); + chillAST_SymbolTable *st = getSymbolTable(); + if (!st) { + fprintf(stderr, "symbol table is NULL!\n"); + } + else { + fprintf(stderr, "%d entries in the symbol table\n", st->size()); + printSymbolTable( getSymbolTable() ); + } + fprintf(stderr, "\n\n"); + } +} + +void chillAST_FunctionDecl::addChild(chillAST_node* node) { + CHILL_DEBUG_BEGIN + node->print(0,stderr); fprintf(stderr, "\n\n"); + CHILL_DEBUG_END + if (node->isVarDecl()) { + chillAST_VarDecl *vd = ((chillAST_VarDecl *) node); + CHILL_DEBUG_PRINT("functiondecl %s adding a VarDecl named %s\n", functionName, vd->varname); + } + + body->addChild( node ); + node->parent = this; // this, or body?? +} + + +void chillAST_FunctionDecl::printParameterTypes( FILE *fp ) { // also prints names + //fprintf(stderr, "\n\n%s chillAST_FunctionDecl::printParameterTypes()\n", functionName); + fprintf(fp, "( "); + int numparameters = parameters.size(); + for (int i=0; iprint(0, fp); // note: no indent, as this is in the function parens + } + fprintf(fp, " )"); // end of input parameters + +} + + + + +void chillAST_FunctionDecl::print( int indent, FILE *fp ) { + //fprintf(fp, "\n// functiondecl %p \n", this); + //chillindent(indent, fp); + //fprintf(fp, "//(functiondecl) %d parameters\n", numparameters); + + printPreprocBEFORE(indent, fp); + + fprintf(fp, "\n"); + chillindent(indent, fp); + + if (externfunc) fprintf(fp, "extern "); + + if (function_type == CHILL_FUNCTION_GPU) fprintf(fp, "__global__ "); + fprintf(fp, "%s %s", returnType, functionName ); + printParameterTypes(fp); + + + + // non-parameter variables (now must have explicit vardecl in the body) + //int numvars = symbol_table.size(); + //for (int i=0; iprint(1,fp); + // fprintf(fp, ";\n"); + //} + + // now the body + if (!(externfunc || forwarddecl)) { + if (body) { + fprintf(fp, "\n{\n"); + //chillindent(indent+1, fp); fprintf(fp, "//body\n"); fflush(fp); + body->print( indent+1, fp); + fprintf(fp, "\n"); + //chillindent(indent+1, fp); fprintf(fp, "//END body\n"); fflush(fp); + + // tidy up + chillindent(indent, fp); + fprintf(fp, "}\n"); + } // if body + else { + fprintf(fp, "{}\n"); // should never happen, but not external and no body + } + } + else { // extern func or forward decl. just end forward declaration + fprintf(fp, "; // fwd decl\n"); + } + + printPreprocAFTER(indent, fp); + + fflush(fp); +} + + + +void chillAST_FunctionDecl::dump( int indent, FILE *fp ) { + fprintf(fp, "\n"); + fprintf(fp, "// isFromSourceFile "); + if (filename) fprintf(fp, "%s ", filename); + if (isFromSourceFile) fprintf(fp, "true\n"); + else fprintf(fp, "false\n"); + chillindent(indent, fp); + fprintf(fp, "(FunctionDecl %s %s(", returnType, functionName ); + + int numparameters = parameters.size(); + for (int i=0; igetTypeString(), p->vartype); + p->print(0, fp); // note: no indent, as this is in the function parens, ALSO print, not dump + } + fprintf(fp, ")\n"); // end of input parameters + + // now the body - + if (body) body->dump( indent+1 , fp); + + // tidy up + chillindent(indent, fp); + fprintf(fp, ")\n"); + fflush(fp); +} + + + + + + +void chillAST_FunctionDecl::gatherVarDecls( vector &decls ) { + //fprintf(stderr, "chillAST_FunctionDecl::gatherVarDecls()\n"); + //if (0 < children.size()) fprintf(stderr, "functiondecl has %d children\n", children.size()); + //fprintf(stderr, "functiondecl has %d parameters\n", numParameters()); + for (int i=0; igatherVarDecls( decls ); + //fprintf(stderr, "after parms, %d decls\n", decls.size()); + for (int i=0; igatherVarDecls( decls ); + //fprintf(stderr, "after children, %d decls\n", decls.size()); + body->gatherVarDecls( decls ); // todo, figure out if functiondecl has actual children + //fprintf(stderr, "after body, %d decls\n", decls.size()); + //for (int d=0; dprint(0,stderr); fprintf(stderr, "\n"); + //} +} + + +void chillAST_FunctionDecl::gatherScalarVarDecls( vector &decls ) { + //if (0 < children.size()) fprintf(stderr, "functiondecl has %d children\n", children.size()); + + for (int i=0; igatherScalarVarDecls( decls ); + for (int i=0; igatherScalarVarDecls( decls ); + body->gatherScalarVarDecls( decls ); // todo, figure out if functiondecl has actual children +} + + +void chillAST_FunctionDecl::gatherArrayVarDecls( vector &decls ) { + //if (0 < children.size()) fprintf(stderr, "functiondecl has %d children\n", children.size()); + + for (int i=0; igatherArrayVarDecls( decls ); + for (int i=0; igatherArrayVarDecls( decls ); + body->gatherArrayVarDecls( decls ); // todo, figure out if functiondecl has actual children +} + + +chillAST_VarDecl *chillAST_FunctionDecl::findArrayDecl( const char *name ) { + //fprintf(stderr, "chillAST_FunctionDecl::findArrayDecl( %s )\n", name ); + chillAST_VarDecl *p = hasParameterNamed( name ); + //if (p) fprintf(stderr, "function %s has parameter named %s\n", functionName, name ); + if (p && p->isArray()) return p; + + chillAST_VarDecl *v = funcHasVariableNamed ( name ); + //if (v) fprintf(stderr, "function %s has symbol table variable named %s\n", functionName, name ); + if (v && v->isArray()) return v; + + // declared variables that may not be in symbol table but probably should be + vector decls ; + gatherArrayVarDecls( decls ); + for (int i=0; ivarname, name ) && vd->isArray()) return vd; + } + + //fprintf(stderr, "can't find array named %s in function %s \n", name, functionName); + return NULL; +} + + +void chillAST_FunctionDecl::gatherVarUsage( vector &decls ) { + for (int i=0; igatherVarUsage( decls ); + body->gatherVarUsage( decls ); // todo, figure out if functiondecl has actual children +} + + +void chillAST_FunctionDecl::gatherDeclRefExprs( vector&refs ) { + for (int i=0; igatherDeclRefExprs( refs ); + body->gatherDeclRefExprs( refs ); // todo, figure out if functiondecl has actual children +} + + + +void chillAST_FunctionDecl::cleanUpVarDecls() { + //fprintf(stderr, "\ncleanUpVarDecls() for function %s\n", functionName); + vector used; + vector defined; + vector deletethese; + + gatherVarUsage( used ); + gatherVarDecls( defined ); + + //fprintf(stderr, "\nvars used: \n"); + //for ( int i=0; i< used.size(); i++) { + //used[i]->print(0, stderr); fprintf(stderr, "\n"); + //} + //fprintf(stderr, "\n"); + //fprintf(stderr, "\nvars defined: \n"); + //for ( int i=0; i< defined.size(); i++) { + // defined[i]->print(0, stderr); fprintf(stderr, "\n"); + //} + //fprintf(stderr, "\n"); + + for ( int j=0; j < defined.size(); j++) { + //fprintf(stderr, "j %d defined %s\n", j, defined[j]->varname); + bool definedandused = false; + for ( int i=0; i < used.size(); i++) { + if (used[i] == defined[j]) { + //fprintf(stderr, "i %d used %s\n", i, used[i]->varname); + //fprintf(stderr, "\n"); + definedandused = true; + break; + } + } + + if (!definedandused) { + if ( defined[j]->isParmVarDecl() ) { + //fprintf(stderr, "we'd remove %s except that it's a parameter. Maybe someday\n", defined[j]->varname); + } + else { + //fprintf(stderr, "we can probably remove the definition of %s\n", defined[j]->varname); + deletethese.push_back( defined[j] ); + } + } + } + + + //fprintf(stderr, "deleting %d vardecls\n", deletethese.size()); + for (int i=0; ivarname); + chillAST_node *par = deletethese[i]->parent; + par->removeChild( par->findChild( deletethese[i] )); + } + + + //fprintf(stderr, "\n\nnow check for vars used but not defined\n"); + // now check for vars used but not defined? + for ( int j=0; j < used.size(); j++) { + //fprintf(stderr, "%s is used\n", used[j]->varname); + bool definedandused = false; + for ( int i=0; i < defined.size(); i++) { + if (used[j] == defined[i]) { + //fprintf(stderr, "%s is defined\n", defined[i]->varname); + definedandused = true; + break; + } + } + if (!definedandused) { + //fprintf(stderr, "%s is used but not defined?\n", used[j]->varname); + // add it to the beginning of the function + insertChild(0, used[j]); + } + } + +} + +//void chillAST_FunctionDecl::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl ) { +// for (int i=0; ireplaceVarDecls( olddecl, newdecl ); +//} + + +bool chillAST_FunctionDecl::findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync ) { + if (body) body->findLoopIndexesToReplace( symtab, false ); + return false; +} + + + + chillAST_node *chillAST_FunctionDecl::constantFold() { + //fprintf(stderr, "chillAST_FunctionDecl::constantFold()\n"); + // parameters can't have constants? + int numparameters = parameters.size(); + for (int i=0; iconstantFold(); + } + if (body) body = (chillAST_CompoundStmt *)body->constantFold(); + return this; + } + + +chillAST_MacroDefinition::chillAST_MacroDefinition() { + macroName = strdup("UNDEFINEDMACRO"); + rhsString = NULL; + asttype = CHILLAST_NODETYPE_MACRODEFINITION; + parent = NULL; + metacomment = NULL; + symbol_table = NULL; + //rhsideString = NULL; + isFromSourceFile = true; // default + filename = NULL; +}; + + +chillAST_MacroDefinition::chillAST_MacroDefinition(const char *mname, chillAST_node *par) { + macroName = strdup(mname); + rhsString = NULL; + asttype = CHILLAST_NODETYPE_MACRODEFINITION; + parent = par; + metacomment = NULL; + symbol_table = NULL; + //rhsideString = NULL; + + if (par) par->getSourceFile()->addMacro( this ); + + //fprintf(stderr, "chillAST_MacroDefinition::chillAST_MacroDefinition( %s, ", mname); + //if (par) fprintf(stderr, " parent NOT NULL);\n"); + //else fprintf(stderr, " parent NULL);\n"); + isFromSourceFile = true; // default + filename = NULL; +}; + + +chillAST_MacroDefinition::chillAST_MacroDefinition(const char *mname, const char *rhs, chillAST_node *par) { + macroName = strdup(mname); + rhsString = strdup(rhs); + asttype = CHILLAST_NODETYPE_MACRODEFINITION; + parent = par; + metacomment = NULL; + symbol_table = NULL; + + if (par) par->getSourceFile()->addMacro( this ); + + //fprintf(stderr, "chillAST_MacroDefinition::chillAST_MacroDefinition( %s, ", mname); + //if (par) fprintf(stderr, " parent NOT NULL);\n"); + //else fprintf(stderr, " parent NULL);\n"); + isFromSourceFile = true; // default + filename = NULL; +}; + + +chillAST_node* chillAST_MacroDefinition::clone() { + + // TODO ?? cloning a macro makes no sense + return this; +#ifdef CONFUSED + + //fprintf(stderr, "chillAST_MacroDefinition::clone() for %s\n", macroName); + chillAST_MacroDefinition *clo = new chillAST_MacroDefinition( macroName, parent); + for (int i=0; iaddParameter( parameters[i] ); + clo->setBody( body->clone() ); + return clo; +#endif + +} + + +void chillAST_MacroDefinition::setBody( chillAST_node * bod ) { + fprintf(stderr, "%s chillAST_MacroDefinition::setBody( 0x%x )\n", macroName, bod); + body = bod; + fprintf(stderr, "body is:\n"); body->print(0,stderr); fprintf(stderr, "\n\n"); + rhsString = body->stringRep(); + bod->setParent( this ); // well, ... +} + + +void chillAST_MacroDefinition::addParameter( chillAST_VarDecl *p) { + //fprintf(stderr, "%s chillAST_MacroDefinition::addParameter( 0x%x ) total of %d children\n", functionName, p, 1+children.size()); + parameters.push_back(p); + fprintf(stderr, "macro setting %s isAParameter\n", p->varname); + p->isAParameter = true; + p->setParent( this ); + + addVariableToSymbolTable( p ); +} + + +chillAST_VarDecl *chillAST_MacroDefinition::hasParameterNamed( const char *name ) { + int numparams = parameters.size(); + for (int i=0; ivarname)) return parameters[i]; // need to check type? + } + return NULL; +} + + +void chillAST_MacroDefinition::insertChild(int i, chillAST_node* node) { + body->insertChild( i, node ); +} + +void chillAST_MacroDefinition::addChild(chillAST_node* node) { + body->addChild( node ); + node->parent = this; // this, or body?? +} + + +void chillAST_MacroDefinition::dump( int indent, FILE *fp ) { + fprintf(fp, "\n"); + chillindent(indent, fp); + fprintf(fp, "(MacroDefinition %s(", macroName); + for (int i=0; ivarname); + } + fprintf(fp, ")\n"); + body->dump( indent+1, fp); + if (rhsString) fprintf(fp, " (aka %s)"); + fprintf(fp, "\n"); + fflush(fp); +} + + +void chillAST_MacroDefinition::print( int indent, FILE *fp ) { // UHOH TODO + //fprintf(fp, "\n"); // ignore indentation + //fprintf(stderr, "macro has %d parameters\n", numParameters()); + + printPreprocBEFORE(indent, fp); + + fprintf(fp, "#define %s", macroName); + if (0 != numParameters()) { + fprintf(fp, "("); + for (int i=0; ivarname); + } + fprintf(fp, ") "); + } + + if (body) body->print(0, fp); // TODO should force newlines out of multiline macros + fprintf(fp, "\n"); +} + + + + +chillAST_ForStmt::chillAST_ForStmt() { + init = cond = incr = NULL; + body = new chillAST_CompoundStmt(); + + asttype = CHILLAST_NODETYPE_LOOP; // breaking with tradition, this was CHILL_AST_FORSTMT + conditionoperator = IR_COND_UNKNOWN; + parent = NULL; + metacomment = NULL; + symbol_table = NULL; + isFromSourceFile = true; // default + filename = NULL; +} + + +chillAST_ForStmt::chillAST_ForStmt( chillAST_node *ini, chillAST_node *con, chillAST_node *inc, chillAST_node *bod, chillAST_node *par) { + parent = par; + metacomment = NULL; + init = ini; + cond = con; + incr = inc; + body = bod; + init->setParent( this ); + cond->setParent( this ); + incr->setParent( this ); + + //fprintf(stderr, "chillAST_ForStmt::chillAST_ForStmt() bod %p\n", bod); + + if (body) body->setParent( this ); // not sure this should be legal + + asttype = CHILLAST_NODETYPE_LOOP; // breaking with tradition, this was CHILL_AST_FORSTMT + + if (!cond->isBinaryOperator()) { + fprintf(stderr, "ForStmt conditional is of type %s. Expecting a BinaryOperator\n", cond->getTypeString()); + exit(-1); + } + chillAST_BinaryOperator *bo = (chillAST_BinaryOperator *)cond; + char *condstring = bo->op; + if (!strcmp(condstring, "<")) conditionoperator = IR_COND_LT; + else if (!strcmp(condstring, "<=")) conditionoperator = IR_COND_LE; + else if (!strcmp(condstring, ">")) conditionoperator = IR_COND_GT; + else if (!strcmp(condstring, ">=")) conditionoperator = IR_COND_GE; + else { + fprintf(stderr, "ForStmt, illegal/unhandled end condition \"%s\"\n", condstring); + fprintf(stderr, "currently can only handle <, >, <=, >=\n"); + exit(1); + } + isFromSourceFile = true; // default + filename = NULL; +} + + +bool chillAST_ForStmt::lowerBound( int &l ) { // l is an output (passed as reference) + + // above, cond must be a binaryoperator ... ??? + if (conditionoperator == IR_COND_LT || + conditionoperator == IR_COND_LE ) { + + // lower bound is rhs of init + if (!init->isBinaryOperator()) { + fprintf(stderr, "chillAST_ForStmt::lowerBound() init is not a chillAST_BinaryOperator\n"); + exit(-1); + } + + chillAST_BinaryOperator *bo = (chillAST_BinaryOperator *)init; + if (!init->isAssignmentOp()) { + fprintf(stderr, "chillAST_ForStmt::lowerBound() init is not an assignment chillAST_BinaryOperator\n"); + exit(-1); + } + + //fprintf(stderr, "rhs "); bo->rhs->print(0,stderr); fprintf(stderr, " "); + l = bo->rhs->evalAsInt(); // float could be legal I suppose + //fprintf(stderr, " %d\n", l); + return true; + } + else if (conditionoperator == IR_COND_GT || + conditionoperator == IR_COND_GE ) { // decrementing + // lower bound is rhs of cond (not init) + chillAST_BinaryOperator *bo = (chillAST_BinaryOperator *)cond; + l = bo->rhs->evalAsInt(); // float could be legal I suppose + return true; + } + + // some case we don't handle ?? + fprintf(stderr, "chillAST_ForStmt::lowerBound() can't find lower bound of "); + print(0,stderr); + fprintf(stderr, "\n\n"); + return false; // or exit ??? +} + + +bool chillAST_ForStmt::upperBound( int &u ) { // u is an output (passed as reference) + + // above, cond must be a binaryoperator ... ??? + if (conditionoperator == IR_COND_GT || + conditionoperator == IR_COND_GE ) { // decrementing + + // upper bound is rhs of init + if (!init->isBinaryOperator()) { + fprintf(stderr, "chillAST_ForStmt::upperBound() init is not a chillAST_BinaryOperator\n"); + exit(-1); + } + + chillAST_BinaryOperator *bo = (chillAST_BinaryOperator *)init; + if (!init->isAssignmentOp()) { + fprintf(stderr, "chillAST_ForStmt::upperBound() init is not an assignment chillAST_BinaryOperator\n"); + exit(-1); + } + + u = bo->rhs->evalAsInt(); // float could be legal I suppose + return true; + } + else if (conditionoperator == IR_COND_LT || + conditionoperator == IR_COND_LE ) { + //fprintf(stderr, "upper bound is rhs of cond "); + // upper bound is rhs of cond (not init) + chillAST_BinaryOperator *bo = (chillAST_BinaryOperator *)cond; + //bo->rhs->print(0,stderr); + u = bo->rhs->evalAsInt(); // float could be legal I suppose + + if (conditionoperator == IR_COND_LT) u -= 1; + + //fprintf(stderr, " %d\n", u); + return true; + } + + // some case we don't handle ?? + fprintf(stderr, "chillAST_ForStmt::upperBound() can't find upper bound of "); + print(0,stderr); + fprintf(stderr, "\n\n"); + return false; // or exit ??? +} + + + + +void chillAST_ForStmt::printControl( int in, FILE *fp ) { + chillindent(in, fp); + fprintf(fp, "for ("); + init->print(0, fp); + fprintf(fp, "; "); + cond->print(0, fp); + fprintf(fp, "; "); + incr->print(0, fp); + fprintf(fp, ")"); + fflush(fp); +} + + +void chillAST_ForStmt::print( int indent, FILE *fp ) { + printPreprocBEFORE(indent, fp); + //fprintf(fp, "chillAST_ForStmt::print()\n"); + if (metacomment) { + chillindent(indent, fp); + //for(int i=0; igetNumChildren()); + //fprintf(fp, "body child 0 of type %s\n", b->children[0]->getTypeString()); + //fprintf(stderr, "forstmt body type %s\n", Chill_AST_Node_Names[b->asttype] ); + // deal with a tree of compound statements, in an ugly way. leave the ugliness + while (1 == b->getNumChildren() && b->children[0]->isCompoundStmt()) { + b = b->children[0]; + } + + + // this was to sometimes not enclose in a bracket. stupid. always enclose in a bracket. + //if (1 == b->getNumChildren() && b->children[0]->isForStmt()) fprintf(fp, ") {\n" ); + //else if (1 == b->getNumChildren() ) fprintf(fp, ") { ?? \n" ); // to allow for() for( ) to not have open bracket? + //else { + //fprintf(fp, ")\n"); + //chillindent(in, fp); + //fprintf(fp, "{\n" ); + + //fprintf(fp, ")"); + //} + + b->print(indent+1, fp ); + + // I think this can't happen any more. body is always a compound statement + if (b->asttype == CHILLAST_NODETYPE_BINARYOPERATOR) { // a single assignment statement + fprintf(fp, ";\n"); + } + + // always print brackets + + //if ((1 == b->getNumChildren() && b->children[0]->isForStmt()) || + // (1 != b->getNumChildren() )) { + chillindent(indent, fp); + fprintf(fp, "}\n" ); + //} + + printPreprocAFTER(indent, fp); + fflush(fp); // +} + +void chillAST_ForStmt::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(ForStmt \n"); + + init->dump(indent+1, fp); + cond->dump(indent+1, fp); + incr->dump(indent+1, fp); + body->dump(indent+1, fp); + + chillindent(indent, fp); + fprintf(fp, ")\n"); +} + +chillAST_node *chillAST_ForStmt::constantFold() { + init = init->constantFold(); + cond = cond->constantFold(); + incr = incr->constantFold(); + body = body->constantFold(); + return this; + } + + + chillAST_node *chillAST_ForStmt::clone() { + chillAST_ForStmt *fs = new chillAST_ForStmt( init->clone(), cond->clone(), incr->clone(), body->clone(), parent); + fs->isFromSourceFile = isFromSourceFile; + if (filename) fs->filename = strdup(filename); + return fs; + } + +void chillAST_ForStmt::gatherVarDecls( vector &decls ) { + //fprintf(stderr, "chillAST_ForStmt::gatherVarDecls()\n"); + //fprintf(stderr, "chillAST_ForStmt::gatherVarDecls() before %d\n", decls.size()); + // TODO clear a loop_var_decls variable and then walk it ? + init->gatherVarDecls( decls ); + cond->gatherVarDecls( decls ); + incr->gatherVarDecls( decls ); + body->gatherVarDecls( decls ); + //fprintf(stderr, "after %d\n", decls.size()); +} + +void chillAST_ForStmt::gatherScalarVarDecls( vector &decls ) { + //fprintf(stderr, "chillAST_ForStmt::gatherScalarVarDecls() before %d\n", decls.size()); + init->gatherScalarVarDecls( decls ); + cond->gatherScalarVarDecls( decls ); + incr->gatherScalarVarDecls( decls ); + body->gatherScalarVarDecls( decls ); +} + +void chillAST_ForStmt::gatherArrayVarDecls( vector &decls ) { + //fprintf(stderr, "chillAST_ForStmt::gatherArrayVarDecls() before %d\n", decls.size()); + init->gatherArrayVarDecls( decls ); + cond->gatherArrayVarDecls( decls ); + incr->gatherArrayVarDecls( decls ); + body->gatherArrayVarDecls( decls ); +} + +void chillAST_ForStmt::gatherArrayRefs( std::vector &refs, bool writtento ) { + init->gatherArrayRefs( refs, 0 ); // 0 ?? + cond->gatherArrayRefs( refs, 0 ); // 0 ?? + incr->gatherArrayRefs( refs, 0 ); // 0 ?? + body->gatherArrayRefs( refs, 0 ); // 0 ?? +} + +void chillAST_ForStmt::gatherScalarRefs( std::vector &refs, bool writtento ) { + init->gatherScalarRefs( refs, 0 ); // 0 ?? + cond->gatherScalarRefs( refs, 0 ); // 0 ?? + incr->gatherScalarRefs( refs, 0 ); // 0 ?? + body->gatherScalarRefs( refs, 0 ); // 0 ?? +} + +void chillAST_ForStmt::gatherDeclRefExprs( vector&refs ) { + init->gatherDeclRefExprs( refs ); + cond->gatherDeclRefExprs( refs ); + incr->gatherDeclRefExprs( refs ); + body->gatherDeclRefExprs( refs ); +} + + + +void chillAST_ForStmt::gatherVarUsage( vector &decls ) { + init->gatherVarUsage( decls ); + cond->gatherVarUsage( decls ); + incr->gatherVarUsage( decls ); + body->gatherVarUsage( decls ); +} + +void chillAST_ForStmt::gatherStatements(std::vector &statements ){ + + // for completeness, should do all 4. Maybe someday + //init->gatherStatements( statements ); + //cond->gatherStatements( statements ); + //incr->gatherStatements( statements ); + body->gatherStatements( statements ); +} + + + +void chillAST_ForStmt::addSyncs() { + //fprintf(stderr, "\nchillAST_ForStmt::addSyncs() "); + //fprintf(stderr, "for ("); + //init->print(0, stderr); + //fprintf(stderr, "; "); + //cond->print(0, stderr); + //fprintf(stderr, "; "); + //incr->print(0, stderr); + //fprintf(stderr, ")\n"); + + if (!parent) { + fprintf(stderr, "uhoh, chillAST_ForStmt::addSyncs() ForStmt has no parent!\n"); + fprintf(stderr, "for ("); + init->print(0, stderr); + fprintf(stderr, "; "); + cond->print(0, stderr); + fprintf(stderr, "; "); + incr->print(0, stderr); + fprintf(stderr, ")\n"); + + return; // exit? + } + + if (parent->isCompoundStmt()) { + //fprintf(stderr, "ForStmt parent is CompoundStmt 0x%x\n", parent); + vector chillin = parent->getChildren(); + int numc = chillin.size(); + //fprintf(stderr, "ForStmt parent is CompoundStmt 0x%x with %d children\n", parent, numc); + for (int i=0; igetChild(i)) { + //fprintf(stderr, "forstmt 0x%x is child %d of %d\n", this, i, numc); + chillAST_CudaSyncthreads *ST = new chillAST_CudaSyncthreads(); + parent->insertChild(i+1, ST); // corrupts something ... + //fprintf(stderr, "Create a call to __syncthreads() 2\n"); + //parent->addChild(ST); // wrong, but safer still kills + } + } + + chillin = parent->getChildren(); + int nowc = chillin.size(); + //fprintf(stderr, "old, new number of children = %d %d\n", numc, nowc); + + } + else { + fprintf(stderr, "chillAST_ForStmt::addSyncs() unhandled parent type %s\n", parent->getTypeString()); + exit(-1); + } + + //fprintf(stderr, "leaving addSyncs()\n"); +} + + + + +void chillAST_ForStmt::removeSyncComment() { + //fprintf(stderr, "chillAST_ForStmt::removeSyncComment()\n"); + if (metacomment && strstr(metacomment, "~cuda~") && strstr(metacomment, "preferredIdx: ")) { + char *ptr = strlen( "preferredIdx: " ) + strstr(metacomment, "preferredIdx: "); + *ptr = '\0'; + } +} + + +bool chillAST_ForStmt::findLoopIndexesToReplace(chillAST_SymbolTable *symtab, bool forcesync ) { + fprintf(stderr, "\nchillAST_ForStmt::findLoopIndexesToReplace( force = %d )\n", forcesync); + //if (metacomment) fprintf(stderr, "metacomment '%s'\n", metacomment); + + bool force = forcesync; + bool didasync = false; + if (forcesync) { + //fprintf(stderr, "calling addSyncs() because PREVIOUS ForStmt in a block had preferredIdx\n"); + addSyncs(); + didasync = true; + } + + //fprintf(stderr, "chillAST_ForStmt::findLoopIndexesToReplace()\n"); + if (metacomment && strstr(metacomment, "~cuda~") && strstr(metacomment, "preferredIdx: ")) { + //fprintf(stderr, "metacomment '%s'\n", metacomment); + + char *copy = strdup(metacomment); + char *ptr = strstr(copy, "preferredIdx: "); + char *vname = ptr + strlen( "preferredIdx: " ); + char *space = strstr(vname, " "); // TODO index() + if (space) { + //fprintf(stderr, "vname = '%s'\n", vname); + force = true; + } + + if ((!didasync) && force ) { + //fprintf(stderr, "calling addSyncs() because ForStmt metacomment had preferredIdx '%s'\n", vname); + addSyncs(); + removeSyncComment(); + didasync = true; + } + + if (space) *space = '\0'; // if this is multiple words, grab the first one + //fprintf(stderr, "vname = '%s'\n", vname); + + //fprintf(stderr, "\nfor ("); + //init->print(0, stderr); + //fprintf(stderr, "; "); + //cond->print(0, stderr); + //fprintf(stderr, "; "); + //incr->print(0, stderr); + //fprintf(stderr, ") %s\n", metacomment ); + //fprintf(stderr, "prefer '%s'\n", vname ); + + vector decls; + init->gatherVarLHSUsage( decls ); + //cond->gatherVarUsage( decls ); + //incr->gatherVarUsage( decls ); + //fprintf(stderr, "forstmt has %d vardecls in init, cond, inc\n", decls.size()); + + if ( 1 != decls.size()) { + fprintf(stderr, "uhoh, preferred index in for statement, but multiple variables used\n"); + print(0,stderr); + fprintf(stderr, "\nvariables are:\n"); + for (int i=0; iprint(0,stderr); fprintf(stderr, "\n"); + } + exit(0); + } + chillAST_VarDecl* olddecl = decls[0]; + + // RIGHT NOW, change all the references that this loop wants swapped out + // find vardecl for named preferred index. it has to already exist + fprintf(stderr, "RIGHT NOW, change all the references that this loop wants swapped out \n"); + + chillAST_VarDecl *newguy = findVariableNamed( vname ); // recursive + if (!newguy) { + fprintf(stderr, "there was no variable named %s anywhere I could find\n", vname); + } + + // wrong - this only looks at variables defined in the forstmt, not + // in parents of the forstmt + //int numsym = symtab->size(); + //fprintf(stderr, "%d symbols\n", numsym); + //for (int i=0; ivarname); + // if (!strcmp(vname, (*symtab)[i]->varname)) { + // newguy = (*symtab)[i]; + // } + //} + if (!newguy) { + fprintf(stderr, "chillAST_ForStmt::findLoopIndexesToReplace() there is no defined variable %s\n", vname); + + // make one ?? seems like this should never happen + newguy = new chillAST_VarDecl( olddecl->vartype, vname, ""/*?*/, NULL ); + // insert actual declaration in code location? how? + + // find parent of the ForStmt? + // find parent^n of the ForStmt that is not a Forstmt? + // find parent^n of the Forstmt that is a FunctionDecl? + chillAST_node *contain = findContainingNonLoop(); + if (contain == NULL) { + fprintf(stderr, "nothing but loops all the way up?\n"); + exit(0); + } + fprintf(stderr, "containing non-loop is a %s\n", contain->getTypeString()); + + contain->print(0,stderr); + contain->insertChild( 0, newguy ); // ugly order TODO + contain->addVariableToSymbolTable( newguy ); // adds to first enclosing symbolTable + + if (! symbolTableHasVariableNamed( contain->getSymbolTable(), vname )) { + fprintf(stderr, "container doesn't have a var names %s afterwards???\n", vname); + exit(-1); + } + } + + + // swap out old for new in init, cond, incr, body + if (newguy) { + fprintf(stderr, "\nwill replace %s with %s in init, cond, incr\n", olddecl->varname, newguy->varname); + fprintf(stderr, "was: for ("); + init->print(0, stderr); + fprintf(stderr, "; "); + cond->print(0, stderr); + fprintf(stderr, "; "); + incr->print(0, stderr); + fprintf(stderr, ")\n"); + + + init->replaceVarDecls( olddecl, newguy ); + cond->replaceVarDecls( olddecl, newguy ); + incr->replaceVarDecls( olddecl, newguy ); + + fprintf(stderr, " is: for ("); + init->print(0, stderr); + fprintf(stderr, "; "); + cond->print(0, stderr); + fprintf(stderr, "; "); + incr->print(0, stderr); + fprintf(stderr, ")\n\n"); + + fprintf(stderr,"recursing to ForStmt body of type %s\n", body->getTypeString()); + body->replaceVarDecls( olddecl, newguy ); + + fprintf(stderr, "\nafter recursing to body, this loop is (there should be no %s)\n", olddecl->varname); + print(0, stderr); fprintf(stderr, "\n"); + + } + + //if (!space) // there was only one preferred + //fprintf(stderr, "removing metacomment\n"); + metacomment = NULL; // memleak + + } + + // check for more loops. We may have already swapped variables out in body (right above here) + body->findLoopIndexesToReplace( symtab, false ) ; + + return force; +} + +void chillAST_ForStmt::replaceChild( chillAST_node *old, chillAST_node *newchild ){ + //fprintf(stderr, "chillAST_ForStmt::replaceChild() REALLY CALLING BODY->ReplaceCHILD\n"); + body->replaceChild( old, newchild ); +} + + + +void chillAST_ForStmt::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ + // logic problem if my loop var is olddecl! + + //fprintf(stderr, "chillAST_ForStmt::replaceVarDecls( old %s, new %s )\n", olddecl->varname, newdecl->varname); + + // this is called for inner loops! + init->replaceVarDecls( olddecl, newdecl ); + cond->replaceVarDecls( olddecl, newdecl ); + incr->replaceVarDecls( olddecl, newdecl ); + body->replaceVarDecls( olddecl, newdecl ); +} + + +void chillAST_ForStmt::gatherLoopIndeces( std::vector &indeces ) { + //fprintf(stderr, "chillAST_ForStmt::gatherLoopIndeces()\nloop is:\n"); print(0,stderr); + + vector decls; + init->gatherVarLHSUsage( decls ); + cond->gatherVarLHSUsage( decls ); + incr->gatherVarLHSUsage( decls ); + // note: NOT GOING INTO BODY OF THE LOOP + + int numdecls = decls.size(); + //fprintf(stderr, "gatherLoopIndeces(), %d lhs vardecls for this ForStmt\n", numdecls); + + for (int i=0; ivarname, decls[i] ); + indeces.push_back( decls[i] ); + } + + // Don't forget to keep heading upwards! + if (parent) { + //fprintf(stderr, "loop %p has parent of type %s\n", this, parent->getTypeString()); + parent->gatherLoopIndeces( indeces ); + } + //else fprintf(stderr, "this loop has no parent???\n"); + +} + + +void chillAST_ForStmt::gatherLoopVars( std::vector &loopvars ) { + //fprintf(stderr, "gathering loop vars for loop for ("); + //init->print(0, stderr); + //fprintf(stderr, "; "); + //cond->print(0, stderr); + //fprintf(stderr, "; "); + //incr->print(0, stderr); + //fprintf(stderr, ")\n" ); + + //init->dump(0, stderr); + + + vector decls; + init->gatherVarLHSUsage( decls ); + cond->gatherVarLHSUsage( decls ); + incr->gatherVarLHSUsage( decls ); + // note: NOT GOING INTO BODY OF THE LOOP + + for (int i=0; ivarname )); + +} + + +void chillAST_ForStmt::loseLoopWithLoopVar( char *var ) { + + //fprintf(stderr, "\nchillAST_ForStmt::loseLoopWithLoopVar( %s )\n", var ); + + // now recurse (could do first, I suppose) + // if you DON'T do this first, you may have already replaced yourself with this loop body + // the body will no longer have this forstmt as parent, it will have the forstmt's parent as its parent + //fprintf(stderr, "forstmt 0x%x, recursing loseLoop to body 0x%x of type %s with parent 0x%x of type %s\n", this, body, body->getTypeString(), body->parent, body->parent->getTypeString()); + body->loseLoopWithLoopVar( var ) ; + + + + + // if *I* am a loop to be replaced, tell my parent to replace me with my loop body + + std::vector loopvars; + gatherLoopVars( loopvars ); + + if (loopvars.size() != 1) { + fprintf(stderr, "uhoh, loop has more than a single loop var and trying to loseLoopWithLoopVar()\n"); + print(0,stderr); + fprintf(stderr, "\nvariables are:\n"); + for (int i=0; iprint(0, stderr); + //fprintf(stderr, "; "); + //cond->print(0, stderr); + //fprintf(stderr, "; "); + //incr->print(0, stderr); + //fprintf(stderr, ")\n" ); + + if (!parent) { + fprintf(stderr, "chillAST_ForStmt::loseLoopWithLoopVar() I have no parent!\n"); + exit(-1); + } + + vector decls; + init->gatherVarLHSUsage( decls ); // this can fail if init is outside the loop + cond->gatherVarLHSUsage( decls ); + incr->gatherVarLHSUsage( decls ); + if (decls.size() > 1) { + fprintf(stderr, "chill_ast.cc multiple loop variables confuses me\n"); + exit(-1); + } + chillAST_node *newstmt = body; + + // ACTUALLY, if I am being replaced, and my loop conditional is a min (Ternary), then wrap my loop body in an if statement + if (cond->isBinaryOperator()) { // what else could it be? + chillAST_BinaryOperator *BO = (chillAST_BinaryOperator *) cond; + if (BO->rhs->isTernaryOperator()) { + + chillAST_TernaryOperator *TO = (chillAST_TernaryOperator *)BO->rhs; + chillAST_BinaryOperator *C = (chillAST_BinaryOperator *)TO->condition; + + //fprintf(stderr, "loop condition RHS is ternary\nCondition RHS"); + C->print(); printf("\n"); fflush(stdout); + chillAST_node *l = C->lhs; + if (l->isParenExpr()) l = ((chillAST_ParenExpr *)l)->subexpr; + chillAST_node *r = C->rhs; + if (r->isParenExpr()) r = ((chillAST_ParenExpr *)r)->subexpr; + + //fprintf(stderr, "lhs is %s rhs is %s\n", l->getTypeString(), r->getTypeString()); + + chillAST_node *ifcondrhs = NULL; + if (!(l->isConstant())) ifcondrhs = l; + else if (!(r->isConstant())) ifcondrhs = r; + else { + // should never happen. 2 constants. infinite loop + fprintf(stderr, "chill_ast.cc INIFNITE LOOP?\n"); + this->print(0,stderr); fprintf(stderr, "\n\n"); + exit(-1); + } + + // wrap the loop body in an if + chillAST_DeclRefExpr *DRE = new chillAST_DeclRefExpr( decls[0] ); + chillAST_BinaryOperator *ifcond = new chillAST_BinaryOperator( DRE, "<=", ifcondrhs ); + chillAST_IfStmt *ifstmt = new chillAST_IfStmt( ifcond, body, NULL, NULL ); + + newstmt = ifstmt; + } + } + + //fprintf(stderr, "forstmt 0x%x has parent 0x%x of type %s\n", this, parent, parent->getTypeString()); + //fprintf(stderr, "forstmt will be replaced by\n"); + //newstmt->print(0,stderr); fprintf(stderr, "\n\n"); + + parent->replaceChild( this, newstmt ); + } + + +} + + + + + +chillAST_BinaryOperator::chillAST_BinaryOperator() { + //fprintf(stderr, "chillAST_BinaryOperator::chillAST_BinaryOperator() %p no parent\n", this); + CHILL_DEBUG_PRINT("chillAST_BinaryOperator::chillAST_BinaryOperator() no parent\n"); + lhs = rhs = NULL; + op = NULL; + asttype = CHILLAST_NODETYPE_BINARYOPERATOR; + isFromSourceFile = true; // default + filename = NULL; +} + + +chillAST_BinaryOperator::chillAST_BinaryOperator(chillAST_node *l, const char *oper, chillAST_node *r, chillAST_node *par) { + //fprintf(stderr, "chillAST_BinaryOperator::chillAST_BinaryOperator( l %p %s r %p, parent %p) this %p\n", l, oper, r, par, this); + CHILL_DEBUG_PRINT("chillAST_BinaryOperator::chillAST_BinaryOperator( l %s r )\n", oper); + + //if (l && r ) { + // fprintf(stderr, "("); l->print(0,stderr); fprintf(stderr, ") %s (", oper); r->print(0,stderr); fprintf(stderr, ")\n\n"); + //} + + lhs = l; + rhs = r; + parent = par; + + if (lhs) lhs->setParent( this ); + if (rhs) rhs->setParent( this ); // may only have part of the lhs and rhs when binop is created + op = strdup(oper); + asttype = CHILLAST_NODETYPE_BINARYOPERATOR; + + // if this writes to lhs and lhs type has an 'imwrittento' concept, set that up + if (isAssignmentOp()) { + if (lhs && lhs->isArraySubscriptExpr()) { + ((chillAST_ArraySubscriptExpr*)lhs)->imwrittento = true; + //fprintf(stderr, "chillAST_BinaryOperator, op '=', lhs is an array reference LVALUE\n"); + } + } + if (isAugmentedAssignmentOp()) { // += etc + //fprintf(stderr, "isAugmentedAssignmentOp() "); print(); fflush(stdout); + if (lhs && lhs->isArraySubscriptExpr()) { + //fprintf(stderr, "lhs is also read from "); lhs->print(); fflush(stdout); + ((chillAST_ArraySubscriptExpr*)lhs)->imreadfrom = true; // note will ALSO have imwrittento true + } + } + + isFromSourceFile = true; // default + filename = NULL; +} + + +int chillAST_BinaryOperator::evalAsInt() { + // very limited. allow +-*/ and integer literals ... + if (isAssignmentOp()) return rhs->evalAsInt(); // ?? ignores/loses lhs info + + if (!strcmp("+", op)) { + //fprintf(stderr, "chillAST_BinaryOperator::evalAsInt() %d + %d\n", lhs->evalAsInt(), rhs->evalAsInt()); + return lhs->evalAsInt() + rhs->evalAsInt(); + } + if (!strcmp("-", op)) return lhs->evalAsInt() - rhs->evalAsInt(); + if (!strcmp("*", op)) return lhs->evalAsInt() * rhs->evalAsInt(); + if (!strcmp("/", op)) return lhs->evalAsInt() / rhs->evalAsInt(); + + fprintf(stderr, "chillAST_BinaryOperator::evalAsInt() unhandled op '%s'\n", op); + segfault(); +} + +chillAST_IntegerLiteral *chillAST_BinaryOperator::evalAsIntegerLiteral() { + return new chillAST_IntegerLiteral( evalAsInt() ); // ?? +} + +void chillAST_BinaryOperator::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(BinaryOperator '%s'\n", op); + + if (lhs) lhs->dump(indent+1, fp); // lhs could be null + else { chillindent(indent+1, fp); fprintf(fp, "(NULL)\n"); } + fflush(fp); + + if (rhs) rhs->dump(indent+1, fp); // rhs could be null + else { chillindent(indent+1, fp); fprintf(fp, "(NULL)\n"); } + fflush(fp); + + chillindent(indent, fp); + fprintf(fp, ")\n"); + fflush(fp); +} + +void chillAST_BinaryOperator::print( int indent, FILE *fp ) { // TODO this needparens logic is wrong + printPreprocBEFORE(indent, fp); + + chillindent( indent, fp ); + bool needparens = false; + if (lhs) { + if (lhs->isImplicitCastExpr()) { + // fprintf(stderr, "\nlhs 0x%x isImplicitCastExpr()\n", lhs); + // fprintf(stderr, "lhs subexpr 0x%x\n", ((chillAST_ImplicitCastExpr*)lhs)->subexpr); + // fprintf(stderr, "lhs subexpr type %s\n", ((chillAST_ImplicitCastExpr*)lhs)->subexpr->getTypeString()); + // + if (((chillAST_ImplicitCastExpr*)lhs)->subexpr->isNotLeaf()) needparens = true; + } + else if (lhs->isNotLeaf()) { + if (isMinusOp() && lhs->isPlusOp()) needparens = false; + else if (isPlusMinusOp() && lhs->isMultDivOp()) needparens = false; + else needparens = true; + } + } + + //fprintf(stderr, "\n\nbinop "); + //lhs->printonly(0,stderr); + //fprintf(stderr," %s ",op); + //rhs->printonly(0,stderr); + //fprintf(stderr,"\n"); + //fprintf(stderr, "op is %s lhs %s rhs %s\n", op, lhs->getTypeString(), rhs->getTypeString()); + //fprintf(stderr, "lhs "); lhs->printonly(0, stderr); fprintf(stderr, " "); + //fprintf(stderr, "lhs needparens = %d\n", needparens); + + + if (needparens) fprintf(fp, "("); + if (lhs) lhs->print( 0, fp ); + else fprintf(fp, "(NULL)"); + if (needparens) fprintf(fp, ")"); + + fprintf( fp, " %s ", op); + + needparens = false; + //fprintf(stderr, "binop rhs is of type %s\n", rhs->getTypeString()); + if (rhs) { + if (rhs->isImplicitCastExpr()) { + if (((chillAST_ImplicitCastExpr*)rhs)->subexpr->isNotLeaf()) needparens = true; + } + //else if (rhs->isNotLeaf()) needparens = true; // too many parens. test too simple + else if (rhs->isNotLeaf()) { + // really need the precedence ordering, and check relative of op and rhs op + if (isMinusOp() ) needparens = true; // safer. perhaps complicated thing on rhs of a minus + else if (isPlusMinusOp() && rhs->isMultDivOp()) needparens = false; + else needparens = true; + } + } + //fprintf(stderr, "rhs "); rhs->printonly(0, stderr); fprintf(stderr, " "); + //fprintf(stderr, "rhs needparens = %d\n\n", needparens); + //if (!needparens) fprintf(stderr, "rhs isNotLeaf() = %d\n", rhs->isNotLeaf()); + + if (needparens) fprintf(fp, "("); + if (rhs) rhs->print( 0, fp ); + else fprintf(fp, "(NULL)"); + if (needparens) fprintf(fp, ")"); + fflush(fp); + printPreprocAFTER(indent, fp); + +} + + +char *chillAST_BinaryOperator::stringRep(int indent ) { + std::string s = string( lhs->stringRep() ) + " " + op + " " + string(lhs->stringRep() ); + return strdup( s.c_str() ); +} + + + +void chillAST_BinaryOperator::printonly( int indent, FILE *fp ) { + + lhs->printonly( indent, fp ); + fprintf( fp, " %s ", op); + rhs->printonly( 0, fp ); + fflush(fp); + + + +} + + +class chillAST_node* chillAST_BinaryOperator::constantFold() { + //fprintf(stderr, "\nchillAST_BinaryOperator::constantFold() "); + //print(0,stderr); fprintf(stderr, "\n"); + + lhs = lhs->constantFold(); + rhs = rhs->constantFold(); + + chillAST_node *returnval = this; + + if (lhs->isConstant() && rhs->isConstant() ) { + //fprintf(stderr, "binop folding constants\n"); print(0,stderr); fprintf(stderr, "\n"); + + if (streq(op, "+") || streq(op, "-") || streq(op, "*")) { + if (lhs->isIntegerLiteral() && rhs->isIntegerLiteral()) { + chillAST_IntegerLiteral *l = (chillAST_IntegerLiteral *)lhs; + chillAST_IntegerLiteral *r = (chillAST_IntegerLiteral *)rhs; + chillAST_IntegerLiteral *I; + + if (streq(op, "+")) I = new chillAST_IntegerLiteral(l->value+r->value, parent); + if (streq(op, "-")) I = new chillAST_IntegerLiteral(l->value-r->value, parent); + if (streq(op, "*")) I = new chillAST_IntegerLiteral(l->value*r->value, parent); + + returnval = I; + //fprintf(stderr, "%d %s %d becomes %d\n", l->value,op, r->value, I->value); + } + else { // at least one is a float + + // usually don't want to do this for floats or doubles + // could probably check for special cases like 0.0/30.0 or X/X or X/1.0 +#ifdef FOLDFLOATS + float lval, rval; + if (lhs->isIntegerLiteral()) { + lval = (float) ((chillAST_IntegerLiteral *)lhs)->value; + } + else { + lval = ((chillAST_FloatingLiteral *)lhs)->value; + } + + if (rhs->isIntegerLiteral()) { + rval = (float) ((chillAST_IntegerLiteral *)rhs)->value; + } + else { + rval = ((chillAST_FloatingLiteral *)rhs)->value; + } + + chillAST_FloatingLiteral *F; + if (streq(op, "+")) F = new chillAST_FloatingLiteral(lval + rval, parent); + if (streq(op, "-")) F = new chillAST_FloatingLiteral(lval - rval, parent); + if (streq(op, "*")) F = new chillAST_FloatingLiteral(lval * rval, parent); + + returnval = F; +#endif + + } + } + //else fprintf(stderr, "can't fold op '%s' yet\n", op); + } + + //fprintf(stderr, "returning "); returnval->print(0,stderr); fprintf(stderr, "\n"); + return returnval; +} + + +class chillAST_node* chillAST_BinaryOperator::clone() { + //fprintf(stderr, "chillAST_BinaryOperator::clone() "); print(); printf("\n"); fflush(stdout); + + chillAST_node* l = lhs->clone(); + chillAST_node* r = rhs->clone(); + chillAST_BinaryOperator *bo = new chillAST_BinaryOperator( l, op, r, parent ); + l->setParent( bo ); + r->setParent( bo ); + bo->isFromSourceFile = isFromSourceFile; + if (filename) bo->filename = strdup(filename); + return bo; +} + +void chillAST_BinaryOperator::gatherArrayRefs( std::vector &refs, bool w ) { + //fprintf(stderr, "chillAST_BinaryOperator::gatherArrayRefs()\n"); + //print(); fflush(stdout); fprintf(stderr, "\n"); + //if (isAugmentedAssignmentOp()) { + // fprintf(stderr, "%s is augmented assignment\n", op); + //} + + //if (isAssignmentOp()) { + // fprintf(stderr, "%s is assignment\n", op); + //} + + //if (isAugmentedAssignmentOp()) { // lhs is ALSO on the RHS, NOT as a write + // if (lhs->isArraySubscriptExpr()) { // probably some case where this fails + // ((chillAST_ArraySubscriptExpr *) lhs)->imreadfrom = true; + // //lhs->&gatherArrayRefs( refs, 0 ); + // } + //} + + //fprintf(stderr, "in chillAST_BinaryOperator::gatherArrayRefs(), %d &arrayrefs before\n", refs.size()); + lhs->gatherArrayRefs( refs, isAssignmentOp() ); + //fprintf(stderr, "in chillAST_BinaryOperator::gatherArrayRefs(), %d &arrayrefs after lhs\n", refs.size()); + rhs->gatherArrayRefs( refs, 0 ); + //fprintf(stderr, "in chillAST_BinaryOperator::gatherArrayRefs(), %d &refs\n", refs.size()); + + //for (int i=0; ibasedecl->varname); + //} + +} + +void chillAST_BinaryOperator::gatherScalarRefs( std::vector &refs, bool writtento ) { + lhs->gatherScalarRefs( refs, isAssignmentOp() ); + rhs->gatherScalarRefs( refs, 0 ); +} + + +void chillAST_BinaryOperator::replaceChild( chillAST_node *old, chillAST_node *newchild ) { + //fprintf(stderr, "\nbinop::replaceChild( old 0x%x, new ) lhs 0x%x rhd 0x%x\n", old, lhs, rhs); + + // will pointers match?? + if (lhs == old) setLHS( newchild ); + else if (rhs == old) setRHS( newchild ); + + // silently ignore? + //else { + // fprintf(stderr, "\nERROR chillAST_BinaryOperator::replaceChild( old 0x%x, new ) lhs 0x%x rhd 0x%x\n", old, lhs, rhs); + // fprintf(stderr, "old is not a child of this BinaryOperator\n"); + // print(); + // dump(); + // exit(-1); + //} +} + + + +void chillAST_BinaryOperator::gatherVarDecls( vector &decls ) { + //fprintf(stderr, "chillAST_BinaryOperator::gatherVarDecls()\n"); + + //fprintf(stderr, "chillAST_BinaryOperator::gatherVarDecls() before %d\n", decls.size()); + //print(0,stderr); fprintf(stderr, "\n"); + //fprintf(stderr, "lhs is %s\n", lhs->getTypeString()); + if (lhs) lhs->gatherVarDecls( decls ); // 'if' to deal with partially formed + if (rhs) rhs->gatherVarDecls( decls ); + //fprintf(stderr, "after %d\n", decls.size()); +} + + +void chillAST_BinaryOperator::gatherScalarVarDecls( vector &decls ) { + //fprintf(stderr, "chillAST_BinaryOperator::gatherScalarVarDecls() before %d\n", decls.size()); + //fprintf(stderr, "lhs is %s\n", lhs->getTypeString()); + lhs->gatherScalarVarDecls( decls ); + rhs->gatherScalarVarDecls( decls ); + //fprintf(stderr, "after %d\n", decls.size()); +} + + +void chillAST_BinaryOperator::gatherArrayVarDecls( vector &decls ) { + //fprintf(stderr, "chillAST_BinaryOperator::gatherArrayVarDecls() before %d\n", decls.size()); + //fprintf(stderr, "lhs is %s\n", lhs->getTypeString()); + lhs->gatherArrayVarDecls( decls ); + rhs->gatherArrayVarDecls( decls ); + //fprintf(stderr, "after %d\n", decls.size()); +} + + + +void chillAST_BinaryOperator::gatherDeclRefExprs( vector&refs ) { + lhs->gatherDeclRefExprs( refs ); + rhs->gatherDeclRefExprs( refs ); +} + + +void chillAST_BinaryOperator::gatherStatements(std::vector &statements ){ + + // what's legit? + if (isAssignmentOp()) { + statements.push_back( this ); + } + +} + + + + +void chillAST_BinaryOperator::gatherVarUsage( vector &decls ) { + lhs->gatherVarUsage( decls ); + rhs->gatherVarUsage( decls ); +} + +void chillAST_BinaryOperator::gatherVarLHSUsage( vector &decls ) { + lhs->gatherVarUsage( decls ); +} + + void chillAST_BinaryOperator::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) { + //if (!strcmp(op, "<=")) { + // fprintf(stderr, "chillAST_BinaryOperator::replaceVarDecls( old %s, new %s)\n", olddecl->varname, newdecl->varname ); + // print(); printf("\n"); fflush(stdout); + // fprintf(stderr, "binaryoperator, lhs is of type %s\n", lhs->getTypeString()); + // fprintf(stderr, "binaryoperator, rhs is of type %s\n", rhs->getTypeString()); + //} + lhs->replaceVarDecls( olddecl, newdecl ); + rhs->replaceVarDecls( olddecl, newdecl ); + //if (!strcmp(op, "<=")) { + // print(); printf("\n\n"); fflush(stdout); + //} + } + + +bool chillAST_BinaryOperator::isSameAs( chillAST_node *other ){ + if (!other->isBinaryOperator()) return false; + chillAST_BinaryOperator *o = (chillAST_BinaryOperator *)other; + if (strcmp(op, o->op)) return false; // different operators + return lhs->isSameAs( o->lhs ) && rhs->isSameAs( o->rhs ); // recurse +} + + + + +chillAST_TernaryOperator::chillAST_TernaryOperator() { + op = strdup("?"); // the only one so far + condition = lhs = rhs = NULL; + asttype = CHILLAST_NODETYPE_TERNARYOPERATOR; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_TernaryOperator::chillAST_TernaryOperator(const char *oper, chillAST_node *c, chillAST_node *l, chillAST_node *r, chillAST_node *par) { + + op = strdup(oper); + condition = c; condition->setParent( this ); + lhs = l; lhs->setParent( this ); + rhs = r; rhs->setParent( this ); + asttype = CHILLAST_NODETYPE_TERNARYOPERATOR; + isFromSourceFile = true; // default + filename = NULL; +} + +void chillAST_TernaryOperator::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(TernaryOperator '%s'\n", op); + condition->dump(indent+1, fp); + lhs->dump(indent+1, fp); + rhs->dump(indent+1, fp); + chillindent(indent, fp); + fprintf(fp, ")\n"); + fflush(fp); +} + +void chillAST_TernaryOperator::print( int indent, FILE *fp ) { + printPreprocBEFORE(indent, fp); + chillindent(indent, fp); + fprintf(fp, "("); + condition->print(0,fp); + fprintf(fp, "%s", op); + lhs->print(0,fp); + fprintf(fp, ":"); + rhs->print(0,fp); + fprintf(fp, ")"); + fflush(fp); +} + +void chillAST_TernaryOperator::replaceChild( chillAST_node *old, chillAST_node *newchild ) { + //fprintf(stderr, "\nbinop::replaceChild( old 0x%x, new ) lhs 0x%x rhd 0x%x\n", old, lhs, rhs); + + // will pointers match?? + if (lhs == old) setLHS( newchild ); + else if (rhs == old) setRHS( newchild ); + else if (condition == old) setCond( newchild ); + + // silently ignore? + //else { + //} +} + + +void chillAST_TernaryOperator::gatherVarDecls( vector &decls ) { + condition->gatherVarDecls( decls ); + lhs->gatherVarDecls( decls ); + rhs->gatherVarDecls( decls ); +} + +void chillAST_TernaryOperator::gatherScalarVarDecls( vector &decls ) { + condition->gatherScalarVarDecls( decls ); + lhs->gatherScalarVarDecls( decls ); + rhs->gatherScalarVarDecls( decls ); +} + + +void chillAST_TernaryOperator::gatherArrayVarDecls( vector &decls ) { + condition->gatherArrayVarDecls( decls ); + lhs->gatherArrayVarDecls( decls ); + rhs->gatherArrayVarDecls( decls ); +} + + + +void chillAST_TernaryOperator::gatherDeclRefExprs( vector&refs ) { + condition->gatherDeclRefExprs( refs ); + lhs->gatherDeclRefExprs( refs ); + rhs->gatherDeclRefExprs( refs ); +} + + + +void chillAST_TernaryOperator::gatherVarUsage( vector &decls ) { + condition->gatherVarUsage( decls ); + lhs->gatherVarUsage( decls ); + rhs->gatherVarUsage( decls ); +} + +void chillAST_TernaryOperator::gatherVarLHSUsage( vector &decls ) { + // this makes no sense for ternary ?? +} + +void chillAST_TernaryOperator::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) { + condition->replaceVarDecls( olddecl, newdecl ); + lhs->replaceVarDecls( olddecl, newdecl ); + rhs->replaceVarDecls( olddecl, newdecl ); +} + +void chillAST_TernaryOperator::printonly( int indent, FILE *fp ) { + fprintf(fp, "("); + condition->printonly(0,fp); + fprintf(fp, "%s", op); + lhs->printonly(0,fp); + fprintf(fp, ":"); + rhs->printonly(0,fp); + fprintf(fp, ")"); + fflush(fp); +} + + +class chillAST_node* chillAST_TernaryOperator::constantFold() { + condition = condition->constantFold(); + lhs = lhs->constantFold(); + rhs = rhs->constantFold(); + + chillAST_node *returnval = this; + + if (condition->isConstant()) { + //fprintf(stderr, "ternop folding constants\n"); + //print(0,stderr); + //fprintf(stderr, "\n"); + + // assume op is "?" + // TODO + /* + + if (streq(op, "+") || streq(op, "-") || streq(op, "*")) { + if (lhs->isIntegerLiteral() && rhs->isIntegerLiteral()) { + chillAST_IntegerLiteral *l = (chillAST_IntegerLiteral *)lhs; + chillAST_IntegerLiteral *r = (chillAST_IntegerLiteral *)rhs; + chillAST_IntegerLiteral *I; + + if (streq(op, "+")) I = new chillAST_IntegerLiteral(l->value+r->value, parent); + if (streq(op, "-")) I = new chillAST_IntegerLiteral(l->value-r->value, parent); + if (streq(op, "*")) I = new chillAST_IntegerLiteral(l->value*r->value, parent); + + returnval = I; + //fprintf(stderr, "%d %s %d becomes %d\n", l->value,op, r->value, I->value); + } + else { // at least one is a float + float lval, rval; + if (lhs->isIntegerLiteral()) { + lval = (float) ((chillAST_IntegerLiteral *)lhs)->value; + } + else { + lval = ((chillAST_FloatingLiteral *)lhs)->value; + } + if (rhs->isIntegerLiteral()) { + rval = (float) ((chillAST_IntegerLiteral *)rhs)->value; + } + else { + rval = ((chillAST_FloatingLiteral *)rhs)->value; + } + + chillAST_FloatingLiteral *F; + if (streq(op, "+")) F = new chillAST_FloatingLiteral(lval + rval, parent); + if (streq(op, "-")) F = new chillAST_FloatingLiteral(lval - rval, parent); + if (streq(op, "*")) F = new chillAST_FloatingLiteral(lval * rval, parent); + + returnval = F; + } + } + else fprintf(stderr, "can't fold op '%s' yet\n", op); + */ + } + + return returnval; +} + +class chillAST_node* chillAST_TernaryOperator::clone() { + chillAST_node* c = condition->clone(); + chillAST_node* l = lhs->clone(); + chillAST_node* r = rhs->clone(); + chillAST_TernaryOperator *to = new chillAST_TernaryOperator( op, l, r, parent ); + c->setParent( to ); + l->setParent( to ); + r->setParent( to ); + to->isFromSourceFile = isFromSourceFile; + filename = NULL; + return to; +} + +void chillAST_TernaryOperator::gatherArrayRefs( std::vector &refs, bool w ) { + condition->gatherArrayRefs( refs, isAssignmentOp() ); + lhs->gatherArrayRefs( refs, isAssignmentOp() ); + rhs->gatherArrayRefs( refs, 0 ); +} + +void chillAST_TernaryOperator::gatherScalarRefs( std::vector &refs, bool writtento ) { + condition->gatherScalarRefs( refs, isAssignmentOp() ); + lhs->gatherScalarRefs( refs, isAssignmentOp() ); + rhs->gatherScalarRefs( refs, 0 ); +} + + + + + + + +chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() { + //fprintf(stderr, "\n%p chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() 0\n", this); + asttype = CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR; + base = index = NULL; + basedecl = NULL; //fprintf(stderr, "setting basedecl NULL for ASE %p\n", this); + imwrittento = false; // ?? + imreadfrom = false; // ?? + parent = NULL; + metacomment = NULL; + //fprintf(stderr, "chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() NEED TO FAKE A LOCATION\n"); + isFromSourceFile = true; // default + filename = NULL; + //fprintf(stderr, "\nASE %p is empty\n", this); +} + + + +chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr( chillAST_node *bas, chillAST_node *indx, chillAST_node *par, void *unique ) { + + //fprintf(stderr, "\nchillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() 1\n"); + //fprintf(stderr, "ASE index %p ", indx); indx->print(0,stderr); fprintf(stderr, "\n"); + asttype = CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR; + bas->setParent( this ); + if (bas->isImplicitCastExpr()) base = ((chillAST_ImplicitCastExpr*)bas)->subexpr; // probably wrong + else base = bas; + if (indx->isImplicitCastExpr()) index = ((chillAST_ImplicitCastExpr*)indx)->subexpr; // probably wrong + else index = indx; + + base->setParent( this ); + index->setParent( this ); + + imwrittento = false; // ?? + imreadfrom = false; // ?? + uniquePtr = (void *) unique; + //fprintf(stderr,"chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() original = 0x%x\n", uniquePtr); + //fprintf(stderr, "chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() 1 calling multibase()\n"); + basedecl = multibase();//fprintf(stderr, "%p ASE 1 basedecl = %p\n",this,basedecl); + //basedecl->print(); printf("\n"); + //basedecl->dump(); printf("\n"); fflush(stdout); + //fprintf(stderr, "basedecl varname %s\n", basedecl->varname); + isFromSourceFile = true; // default + filename = NULL; + + //fprintf(stderr, "\nASE %p parent %p ", this, parent); print(0,stderr); fprintf(stderr, "\n\n"); +} + + + +chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr( chillAST_node *bas, chillAST_node *indx, bool writtento, chillAST_node *par, void *unique ) { + //fprintf(stderr, "\nchillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() 2 parent %p\n", par ); + //fprintf(stderr, "ASE %p index %p ", this, indx); indx->print(0,stderr); fprintf(stderr, "\n"); + + asttype = CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR; + bas->setParent( this ); + if (bas->isImplicitCastExpr()) base = ((chillAST_ImplicitCastExpr*)bas)->subexpr; // probably wrong + else base = bas; + + if (indx->isImplicitCastExpr()) index = ((chillAST_ImplicitCastExpr*)indx)->subexpr; // probably wrong + else index = indx; + + //fprintf(stderr, "setting parent of base %p to %p\n", base, this); + //fprintf(stderr, "setting parent of index %p to %p\n", index, this); + base->setParent( this ); + index->setParent( this ); + + imwrittento = writtento; // ?? + //fprintf(stderr, "ASE %p imwrittento %d\n", this, imwrittento); + imreadfrom = false; // ?? + + uniquePtr = (void *) unique; + //fprintf(stderr,"chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() original = 0x%x\n", uniquePtr); + + basedecl = multibase(); + + //fprintf(stderr, "%p ASE 2 basedecl = %p\n", this, basedecl); + //printf("basedecl is "); fflush(stdout); basedecl->print(); printf("\n"); fflush(stdout); + //basedecl->dump(); printf("\n"); fflush(stdout); + //fprintf(stderr, "basedecl varname %s\n", basedecl->varname); + isFromSourceFile = true; // default + filename = NULL; + + //fprintf(stderr, "chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() 2 DONE\n"); + //print(0,stderr); fprintf(stderr, "\n\n"); + //fprintf(stderr, "\nASE %p parent %p ", this, parent); print(0,stderr); fprintf(stderr, "\n\n"); + } + + + +chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr( chillAST_VarDecl *v, std::vector indeces, chillAST_node *par) { + //fprintf(stderr, "\nchillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() 4\n"); + //fprintf(stderr,"chillAST_ArraySubscriptExpr( chillAST_VarDecl *v, std::vector indeces)\n"); + asttype = CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR; + parent = par; + //if (parent == NULL) { + // fprintf(stderr, "dammit. ASE %p has no parent\n", this); + //} + + + int numindeces = indeces.size(); + for (int i=0; iprint(0,stderr); fprintf(stderr, "\n"); + // printf("["); + // indeces[i]->print(); + // printf("]"); + } + //fflush(stdout); + //fprintf(stderr, "\n"); + + chillAST_DeclRefExpr *DRE = new chillAST_DeclRefExpr( v->vartype, v->varname, v, NULL); + basedecl = v; // ?? + //fprintf(stderr, "%p ASE 3 basedecl = %p ", this, basedecl); + //fprintf(stderr, "of type %s\n", basedecl->getTypeString()); + //basedecl->print(); printf("\n"); + //basedecl->dump(); printf("\n"); fflush(stdout); + //fprintf(stderr, "basedecl varname %s\n", basedecl->varname); + + chillAST_ArraySubscriptExpr *rent = this; // parent for subnodes + + // these are on the top level ASE that we're creating here + base = (chillAST_node *) DRE; + index = indeces[ numindeces-1]; + + base->setParent( this ); + index->setParent(this); + + for (int i=numindeces-2; i>=0; i--) { + + chillAST_ArraySubscriptExpr *ASE = new chillAST_ArraySubscriptExpr( DRE, indeces[i], rent, 0); + rent->base = ASE; // + rent = ASE; + } + + imwrittento = false; + imreadfrom = false; + //fprintf(stderr, "ASE is "); print(); printf("\n\n"); fflush(stdout); + isFromSourceFile = true; // default + filename = NULL; + + //fprintf(stderr, "\nASE %p parent %p ", this, parent); print(0,stderr); fprintf(stderr, "\n\n"); +} + + + +chillAST_node *chillAST_node::getEnclosingStatement( int level ) { // TODO do for subclasses? + + //fprintf(stderr, "chillAST_node::getEnclosingStatement( level %d ) node type %s\n", level, getTypeString()); + //print(); printf("\n"); fflush(stdout); + + // so far, user will ONLY call this directly on an array subscript expression + if (isArraySubscriptExpr()) return parent->getEnclosingStatement( level+1); + + if (level != 0) { + if (isBinaryOperator() || + isUnaryOperator() || + isTernaryOperator() || + isReturnStmt() || + isCallExpr() + ) return this; + + + // things that are not endpoints. recurse through parent + if (isMemberExpr()) return parent->getEnclosingStatement( level+1 ); + if (isImplicitCastExpr()) return parent->getEnclosingStatement( level+1 ); + if (isSizeof()) return parent->getEnclosingStatement( level+1 ); + if (isCStyleCastExpr()) return parent->getEnclosingStatement( level+1 ); + return NULL; + } + + fprintf(stderr, "getEnclosingStatement() level %d type %s, returning NULL\n", level, getTypeString()); + segfault(); + + return NULL; +} + + + +void chillAST_ArraySubscriptExpr::gatherIndeces(std::vector&ind) { + if (base->isArraySubscriptExpr()) ((chillAST_ArraySubscriptExpr *)base)->gatherIndeces( ind ); + ind.push_back( index ); +} + + + +void chillAST_ArraySubscriptExpr::dump( int indent, FILE *fp ) { +// fprintf(stderr, "\n%p chillAST_ArraySubscriptExpr::dump() basedecl %p\n", basedecl); + + char *local; + if (basedecl && basedecl->vartype) { + local = strdup( basedecl->vartype ); + } + else { + fprintf(stderr, "%p chillAST_ArraySubscriptExpr::dump(), no basedecl ???\n",this); + local = strdup(""); + //fprintf(stderr, "base is "); base->dump(); printf("\n"); base->print(); printf("\n"); fflush(stdout); + //print(); printf("\n"); fflush(stdout); + } + + + char *space = rindex(local, ' '); // can't use index because it's a class member! + if (space) *space = '\0'; // turn "float *" into "float" + + chillindent(indent, fp); + //fprintf(fp, "(ArraySubscriptExpr '%s' ", local); + if (basedecl) { + //fprintf(stderr, " chillAST_ArraySubscriptExpr::dump() basedecl is of type %s\n", basedecl->getTypeString()); + fprintf(fp, "(ArraySubscriptExpr (%s) '%s' ", basedecl->varname, local); + } + else fprintf(stderr, " chillAST_ArraySubscriptExpr::dump() has no basedecl\n"); + free(local); + + if (imwrittento) { + if (imreadfrom) fprintf(fp, "lvalue AND rvalue\n"); + else fprintf(fp, "lvalue\n"); + } + else fprintf(fp, "rvalue\n"); + base->dump( indent+1, fp ); + index->dump(indent+1, fp); + + chillindent(indent, fp); + fprintf(fp, ")\n"); + fflush(fp); +} + + + +void chillAST_ArraySubscriptExpr::print( int indent, FILE *fp ) { + base->print( indent, fp ); + fprintf(fp, "["); + index->print(0, fp); + fprintf(fp, "]"); + fflush(fp); +} + +char *chillAST_ArraySubscriptExpr::stringRep(int indent ) { + fprintf(stderr, "chillAST_ArraySubscriptExpr::stringRep\n"); + + char *blurb; + char *b = base->stringRep(0); + char *i = index->stringRep(0); + // combine. shoudl be using strings. much cleaner TODO + std::string s = string(b) + "[" + string(i) + "]"; + fprintf(stderr, "ASE stringrep %s\n", s.c_str()); + return strdup( s.c_str()); + + +} + + +void chillAST_ArraySubscriptExpr::printonly( int indent, FILE *fp ) { + base->printonly( indent, fp ); + fprintf(fp, "["); + index->printonly(0, fp); + fprintf(fp, "]"); + fflush(fp); +} + + +void chillAST_ArraySubscriptExpr::print( int indent, FILE *fp ) const { + base->print( indent, fp ); + fprintf(fp, "["); + index->print(0, fp); + fprintf(fp, "]"); + fflush(fp); +}; + + +chillAST_VarDecl *chillAST_ArraySubscriptExpr::multibase() { + // return the VARDECL of the thing the subscript is an index into + //this should probably be a chillAST_node function instead of having all these ifs + //print(); printf("\n"); fflush(stdout); + //base->print(); printf("\n"); fflush(stdout); + //fprintf(stderr, "chillAST_ArraySubscriptExpr::multibase() base of type %s\n", base->getTypeString()); + + return base->multibase(); + + // this will be used to SET basedecl + //basedecl = NULL; // do this so we don't confuse ourselves looking at uninitialized basedecl + + chillAST_node *b = base; + //fprintf(stderr, "base is of type %s\n", b->getTypeString()); + + if (!b) return NULL; // just in case ?? + + if (base->asttype == CHILLAST_NODETYPE_IMPLICITCASTEXPR) { // bad coding + b = ((chillAST_ImplicitCastExpr*)b)->subexpr; + } + + if (b->asttype == CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR) { // multidimensional array! + // recurse + return ((chillAST_ArraySubscriptExpr *)b)->multibase(); + } + + if (b->asttype == CHILLAST_NODETYPE_DECLREFEXPR) return(((chillAST_DeclRefExpr*)b)->getVarDecl()); + + + if (b->isBinaryOperator()) { + // presumably a dot or pointer ref that resolves to an array + chillAST_BinaryOperator *BO = (chillAST_BinaryOperator *) b; + if ( strcmp(BO->op, ".") ) { + fprintf(stderr, "chillAST_ArraySubscriptExpr::multibase(), UNHANDLED case:\n"); + fprintf(stderr, "base is binary operator, of type %s\n", BO->op); + exit(-1); + } + + chillAST_node *l = BO->lhs; + chillAST_node *r = BO->rhs; + printf("L %s\nR %s\n", l->getTypeString(), r->getTypeString()); + exit(-1); + + return NULL; // TODO do checks? + } + + if (b->isMemberExpr()) { + //c.i[c.count] we want i member of inspector + + chillAST_MemberExpr *ME = (chillAST_MemberExpr *) b; + //fprintf(stderr, "multibase() Member Expression "); ME->print(); printf("\n"); fflush(stdout); + + chillAST_node *n = ME->base; // WRONG want the MEMBER + //fprintf(stderr, "chillAST_ArraySubscriptExpr::multibase() Member Expression base of type %s\n", n->getTypeString()); + //fprintf(stderr, "base is "); ME->base->dump(); + + // NEED to be able to get lowest level recorddecl or typedef from this base + + fprintf(stderr, "chillast.cc, L2315, bailing??\n"); + exit(0); + + if (!n->isDeclRefExpr()) { + fprintf(stderr, "MemberExpr member is not chillAST_DeclRefExpr\n"); + exit(-1); + } + chillAST_DeclRefExpr *DRE = (chillAST_DeclRefExpr *)n; + n = DRE->decl; + //fprintf(stderr, "DRE decl is of type %s\n", n->getTypeString()); + assert( n->isVarDecl() ); + chillAST_VarDecl *vd = (chillAST_VarDecl *) n; + vd->print(); printf("\n"); fflush(stdout); + + chillAST_TypedefDecl *tdd = vd->typedefinition; + chillAST_RecordDecl *rd = vd->vardef; + //fprintf(stderr, "tdd %p rd %p\n", tdd, rd); + + print(); printf("\n"); + dump(); printf("\n"); fflush(stdout); + + assert( tdd != NULL || rd != NULL ); + + chillAST_VarDecl *sub; + if (tdd) sub = tdd->findSubpart( ME->member ); + if (rd) sub = rd->findSubpart( ME->member ); + + //fprintf(stderr, "subpart is "); sub->print(); printf("\n"); fflush(stdout); + + return sub; // what if the sub is an array ?? TODO + } + + + fprintf(stderr, "chillAST_ArraySubscriptExpr::multibase(), UNHANDLED case %s\n", + b->getTypeString()); + print(); printf("\n"); fflush(stdout); + fprintf(stderr, "base is: "); b->print(); printf("\n"); fflush(stdout); + segfault(); +} + + +chillAST_node *chillAST_ArraySubscriptExpr::getIndex(int dim) { + //fprintf(stderr, "chillAST_ArraySubscriptExpr::getIndex( %d )\n", dim); + + chillAST_node *b = base; + + int depth = 0; + std::vector ind; + chillAST_node *curindex = index; + for (;;) { + if (b->asttype == CHILLAST_NODETYPE_IMPLICITCASTEXPR) b = ((chillAST_ImplicitCastExpr*)b)->subexpr; + else if (b->asttype == CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR) { + //fprintf(stderr, "base "); b->print(); fprintf(stderr, "\n"); + //fprintf(stderr, "index "); curindex->print(); fprintf(stderr, "\n"); + ind.push_back(curindex); + curindex = ((chillAST_ArraySubscriptExpr*)b)->index; + b = ((chillAST_ArraySubscriptExpr*)b)->base; + depth++; + } + else { + //fprintf(stderr, "base "); b->print(); fprintf(stderr, "\n"); + //fprintf(stderr, "index "); curindex->print(); fprintf(stderr, "\n"); + //fprintf(stderr, "stopping at base type %s\n", b->getTypeString()); + ind.push_back(curindex); + break; + } + } + //fprintf(stderr, "depth %d\n", depth ); + //for (int i=0; iprint(); fprintf(stderr, "\n"); } + + return ind[ depth - dim ]; + /* + if (dim == 0) return index; // single dimension + fprintf(stderr, "DIM NOT 0\n"); + // multidimension + chillAST_node *b = base; + if (base->asttype == CHILLAST_NODETYPE_IMPLICITCASTEXPR) { // bad coding + b = ((chillAST_ImplicitCastExpr*)b)->subexpr; + } + if (b->asttype == CHILLAST_NODETYPE_IMPLICITCASTEXPR) { // bad coding + b = ((chillAST_ImplicitCastExpr*)b)->subexpr; + } + + b->print(); printf("\n"); fflush(stdout); + if (b->asttype == CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR) { + return ((chillAST_ArraySubscriptExpr *)b)->getIndex(dim-1); + } + + fprintf(stderr, "chillAST_ArraySubscriptExpr::getIndex() failed\n"); + */ + exit(-1); +} + + + + +class chillAST_node* chillAST_ArraySubscriptExpr::constantFold() { + //fprintf(stderr, "chillAST_ArraySubscriptExpr::constantFold()\n"); + base = base->constantFold(); + index = index->constantFold(); + return this; +} + +class chillAST_node* chillAST_ArraySubscriptExpr::clone() { + //fprintf(stderr,"chillAST_ArraySubscriptExpr::clone() old imwrittento %d\n", imwrittento); + //fprintf(stderr, "cloning ASE %p ", this); print(0,stderr); printf(" with parent %p\n", parent); fflush(stdout); + //fprintf(stderr, "base %p base->parent %p index %p index->parent %p\n", base, base->parent, index, index->parent); + + //fprintf(stderr, "old base "); base->print(); printf("\n"); fflush(stdout); + //fprintf(stderr, "old base "); base->dump(); printf("\n"); fflush(stdout); + if (base->isDeclRefExpr()) { + chillAST_VarDecl *vd = (chillAST_VarDecl *)(((chillAST_DeclRefExpr *)base)->decl); + //fprintf(stderr, "old decl "); vd->print(); printf("\n");fflush(stdout); + //fprintf(stderr, "old decl "); vd->dump(); printf("\n");fflush(stdout); + } + chillAST_node *b = base->clone(); + //fprintf(stderr, "new base "); b->print(); printf("\n"); fflush(stdout); + //fprintf(stderr, "new base "); b->dump(); printf("\n"); fflush(stdout); + + chillAST_node *i = index->clone(); + //fprintf(stderr, "new index "); i->print(); printf("\n"); fflush(stdout); + + + //if (!index->parent) { + // fprintf(stderr, "ASE %p SOURCE OF CLONE INDEX %p of type %s HAS NO PARENT\n", this, index, index->getTypeString()); + // fprintf(stderr, "ASE SOURCE IS "); print(0,stderr); fprintf(stderr, "\n\n"); + //} + //fprintf(stderr, "cloning AST %p, after cloning base and index, creating a new ASE\n", this); + chillAST_ArraySubscriptExpr *ASE = new chillAST_ArraySubscriptExpr( b, i, imwrittento, parent, uniquePtr /* ?? */ ); + //fprintf(stderr, "cloned AST will be %p with parent %p and base %p index %p\n", ASE, parent, b, i); + + ASE->imreadfrom = false; // don't know this yet + //ASE->imreadfrom = imreadfrom; // ?? + //if (ASE->imreadfrom) { + // fprintf(stderr, "in chillAST_ArraySubscriptExpr::clone(), imreadfrom is being set. \n"); + // ASE->print(); fflush(stdout); fprintf(stderr, "\n"); + //} + + //fprintf(stderr, "cloned result "); ASE->print(); printf("\n\n\n"); fflush(stdout); + //fprintf(stderr, "ASE clone() this 0x%x clone 0x%x\n", this, ASE); + ASE->isFromSourceFile = isFromSourceFile; + if (filename) ASE->filename = strdup(filename); + return ASE; +} + +void chillAST_ArraySubscriptExpr::gatherArrayRefs( std::vector &refs, bool writtento ) { + //fprintf(stderr, "chillAST_ArraySubscriptExpr::gatherArrayRefs setting imwrittento %d for ", writtento); +//fprintf(stderr, "%s ", base->getTypeString()); +//base->print(); printf("\n"); fflush(stdout); + + //fprintf(stderr, "found an array subscript. &refs 0x%x ", refs); + if (!imwrittento) imwrittento = writtento; // may be both written and not for += + fflush(stdout); + + //fprintf(stderr, "recursing on index "); index->print(0,stderr); fprintf(stderr, "\n"); + index->gatherArrayRefs( refs, 0 ); // recurse first + //fprintf(stderr, "adding this "); print(0,stderr); fprintf(stderr, "\n"); + //fprintf(stderr, "refs[%d] = 0x%x = ", refs.size(), this); print(); fflush(stdout); + refs.push_back( this ); + + //fprintf(stderr, " size now %d\n", refs.size()); + +} + +void chillAST_ArraySubscriptExpr::gatherScalarRefs( std::vector &refs, bool writtento ) { + index->gatherScalarRefs( refs, 0 ); +} + +void chillAST_ArraySubscriptExpr::gatherVarDecls( vector &decls ) { + //fprintf(stderr, "chillAST_ArraySubscriptExpr::gatherVarDecls()\n"); + + base->gatherVarDecls( decls ); + index->gatherVarDecls( decls ); +} + + +void chillAST_ArraySubscriptExpr::gatherScalarVarDecls( vector &decls ) { + //fprintf(stderr, "chillAST_ArraySubscriptExpr::gatherScalarVarDecls()\n"); + //fprintf(stderr, "base %s index %s\n", base->getTypeString(), index->getTypeString()); + base->gatherScalarVarDecls( decls ); + index->gatherScalarVarDecls( decls ); +} + + +void chillAST_ArraySubscriptExpr::gatherArrayVarDecls( vector &decls ) { + //fprintf(stderr, "chillAST_ArraySubscriptExpr::gatherArrayVarDecls()\n"); + //fprintf(stderr, "base %s index %s\n", base->getTypeString(), index->getTypeString()); + base->gatherArrayVarDecls( decls ); + index->gatherArrayVarDecls( decls ); +} + + +void chillAST_ArraySubscriptExpr::gatherDeclRefExprs( vector&refs ) { + base->gatherDeclRefExprs( refs ); + index->gatherDeclRefExprs( refs ); +} + + +void chillAST_ArraySubscriptExpr::gatherVarUsage( vector &decls ) { + base->gatherVarUsage( decls ); + index->gatherVarUsage( decls ); +} + + +void chillAST_ArraySubscriptExpr::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ + base->replaceVarDecls( olddecl, newdecl ); + index->replaceVarDecls( olddecl, newdecl ); +} + + +void chillAST_ArraySubscriptExpr::replaceChild( chillAST_node *old, chillAST_node *newchild ) { + //fprintf(stderr,"chillAST_ArraySubscriptExpr::replaceChild()\n"); + + // arraysubscriptexpression doesn t really have children (should it?) + // try index ??? + if (old == index) { + //fprintf(stderr, "old is index\n"); + index = newchild; + index->parent = this; + return; + } + + // try base ??? unclear if this makes sense TODO + if (old == base) { + //fprintf(stderr, "old is base\n"); + base = newchild; + base->parent = this; + return; + } + + fprintf(stderr, "chillAST_ArraySubscriptExpr::replaceChild() old is not base or index\n"); + print(0,stderr); fprintf(stderr, "\nchild: "); + if (!old) fprintf(stderr, "oldchild NULL!\n"); + old->print(0,stderr); fprintf(stderr, "\nnew: "); + newchild->print(0,stderr); fprintf(stderr, "\n"); + segfault(); // make easier for gdb +}; + + +bool chillAST_ArraySubscriptExpr::operator!=( const chillAST_ArraySubscriptExpr &other) { + bool opposite = *this == other; + return !opposite; +} + + + +bool chillAST_ArraySubscriptExpr::operator==( const chillAST_ArraySubscriptExpr &other) { + //fprintf(stderr, "chillAST_ArraySubscriptExpr::operator==\n"); + //fprintf(stderr, "this->basedecl 0x%x other.basedecl 0x%x\n", this->basedecl, other.basedecl); + //this->basedecl->print(); printf("\n\n"); + //other.basedecl->print(); printf("\n"); fflush(stdout); + + //this->print(); printf(" 0x%x == 0x%x ",this->uniquePtr, other.uniquePtr ); other.print(); printf(" ?? "); fflush(stdout); + //if ( this->uniquePtr == other.uniquePtr) fprintf(stderr, "t\n"); + //else fprintf(stderr, "f\n"); + return this->uniquePtr == other.uniquePtr; +} + + + + + +chillAST_MemberExpr::chillAST_MemberExpr() { + asttype = CHILLAST_NODETYPE_MEMBEREXPR; + base = NULL; + member = NULL; + parent = NULL; + metacomment = NULL; + exptype = CHILL_MEMBER_EXP_DOT; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_MemberExpr::chillAST_MemberExpr( chillAST_node *bas, const char *mem, chillAST_node *p, void *unique, CHILL_MEMBER_EXP_TYPE t ) { + asttype = CHILLAST_NODETYPE_MEMBEREXPR; + base = bas; + if (base) base->setParent( this ); + if (mem) member = strdup( mem ); + parent = p; + metacomment = NULL; + uniquePtr = unique; + exptype = t; + isFromSourceFile = true; // default + filename = NULL; + + return; // ignore tests below ?? TODO ?? + + + // base needs to RESOLVE to a decl ref expr but may not BE one + // A.b . c lhs is a binop or memberexpr + + if (bas->isBinaryOperator()) { + //fprintf(stderr, "checking binop to see if it resolved to a declrefexpr\n"); + // cheat for now or just remove the check below + return; + } + + if (! ( bas->isDeclRefExpr() || bas->isArraySubscriptExpr() )) { + fprintf(stderr, "chillAST_MemberExpr::chillAST_MemberExpr(), base is of type %s\n", bas->getTypeString()); + fprintf(stderr, "chillAST_MemberExpr::chillAST_MemberExpr(), base is not DeclRefExpr\n"); + + base->print(); printf(".%s\n", mem); fflush(stdout); + segfault(); + } +} + + +void chillAST_MemberExpr::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(MemberExpr \n"); + + base->dump( indent+1, fp ); + chillindent(indent+1, fp); + if (exptype == CHILL_MEMBER_EXP_ARROW) fprintf(fp, "->"); + else fprintf(fp, "."); + + fprintf(fp, "%s\n", member); + + chillindent(indent, fp); + fprintf(fp, ")\n"); +} + + +void chillAST_MemberExpr::print( int indent, FILE *fp ) { + if (base) base->print( indent, fp ); + else { + chillindent( indent, fp ); + fprintf(fp, "(NULL)"); + } + if (exptype == CHILL_MEMBER_EXP_ARROW) fprintf(fp, "->"); + else fprintf(fp, "."); + if (member) fprintf(fp, "%s", member); + else fprintf(fp, "(NULL)"); + fflush(fp); +} + + +void chillAST_MemberExpr::printonly( int indent, FILE *fp ) { + base->print( indent, fp ); + if (exptype == CHILL_MEMBER_EXP_ARROW) fprintf(fp, "->"); + else fprintf(fp, "."); + fprintf(fp, "%s", member); + fflush(fp); +} + +char *chillAST_MemberExpr::stringRep( int indent ) { // char pointer to what we'd print + fprintf(stderr, "*chillAST_MemberExpr::stringRep()\n"); + if (base->isDeclRefExpr()) { // + chillAST_VarDecl *vd = (chillAST_VarDecl *) ((chillAST_DeclRefExpr *)base)->decl; + char *leak = (char *)malloc(128); + if (exptype == CHILL_MEMBER_EXP_ARROW) sprintf(leak, "%s->%s", vd->varname, member); + else sprintf(leak, "%s.%s", vd->varname, member); + printstring = leak; + return leak; + } + + + // else + // TODO + return strdup("chillAST_MemberExpr::getStringRep()hadanerror"); +} + + +class chillAST_node* chillAST_MemberExpr::constantFold() { + base = base->constantFold(); + //member = member->constantFold(); + return this; +} + +class chillAST_node* chillAST_MemberExpr::clone() { + chillAST_node *b = base->clone(); + char *m = strdup( member ); // ?? + chillAST_MemberExpr *ME = new chillAST_MemberExpr( b, m, parent, uniquePtr /* ?? */ ); + ME->isFromSourceFile = isFromSourceFile; + if (filename) ME->filename = strdup(filename); + return ME; +} + +void chillAST_MemberExpr::gatherArrayRefs( std::vector &refs, bool writtento ) { + fprintf(stderr, "chillAST_MemberExpr::gatherArrayRefs() "); print(0,stderr); fprintf(stderr, "\n"); + fprintf(stderr, "base of of type %s\n", base->getTypeString()); + base->gatherArrayRefs( refs, writtento ); // + +} + +void chillAST_MemberExpr::gatherScalarRefs( std::vector &refs, bool writtento ) { + base->gatherScalarRefs( refs, writtento ); +} + +void chillAST_MemberExpr::gatherVarDecls( vector &decls ) { + base->gatherVarDecls( decls ); +} + +void chillAST_MemberExpr::gatherScalarVarDecls( vector &decls ) { + base->gatherScalarVarDecls( decls ); +} + + +void chillAST_MemberExpr::gatherArrayVarDecls( vector &decls ) { + base->gatherArrayVarDecls( decls ); +} + + +void chillAST_MemberExpr::gatherDeclRefExprs( vector&refs ) { + base->gatherDeclRefExprs( refs ); +} + + +void chillAST_MemberExpr::gatherVarUsage( vector &decls ) { + base->gatherVarUsage( decls ); +} + + +void chillAST_MemberExpr::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ + base->replaceVarDecls( olddecl, newdecl ); +} + +bool chillAST_MemberExpr::operator!=( const chillAST_MemberExpr &other) { + bool opposite = *this == other; + return !opposite; +} + +bool chillAST_MemberExpr::operator==( const chillAST_MemberExpr &other) { + return this->uniquePtr == other.uniquePtr; +} + + +void chillAST_MemberExpr::replaceChild( chillAST_node *old, chillAST_node *newchild ) { + //printf("\nMemberExpr::replaceChild( )\n"); + //printf("old: "); + //old->print(); + //printf("\nnew: "); + //newchild->print(); + //printf("\n"); fflush(stdout); + + // will pointers match?? + if (base == old) { + //fprintf(stderr, "old matches base of MemberExpr\n"); + base = newchild; + } + else { + base->replaceChild( old, newchild ); + } +} + +chillAST_node *chillAST_MemberExpr::multibase2() { /*fprintf(stderr, "ME MB2\n" );*/ return (chillAST_node *)this; } + +chillAST_VarDecl* chillAST_MemberExpr::getUnderlyingVarDecl() { + fprintf(stderr, "chillAST_MemberExpr:getUnderlyingVarDecl()\n"); + print(); printf("\n"); fflush(stdout); + exit(-1); + // find the member with the correct name + +} + + + + +chillAST_VarDecl *chillAST_MemberExpr::multibase() { + //c.i[c.count] we want i member of c + //fprintf(stderr, "ME MB\n" ); + + //fprintf(stderr, "chillAST_MemberExpr::multibase()\n"); + //print(); printf("\n"); fflush(stdout); + //fprintf(stderr, "MemberExpr base is type %s, member %s\n", base->getTypeString(), member); + + //chillAST_VarDecl *vd = base->getUnderlyingVarDecl(); // this is the only thing that ever calls this ??? + chillAST_VarDecl *vd = base->multibase(); // ?? + + + //fprintf(stderr, "vd "); vd->print(); printf("\n"); fflush(stdout); + + chillAST_RecordDecl *rd = vd->getStructDef(); + if (!rd) { + fprintf(stderr, "chillAST_MemberExpr::multibase() vardecl is not a struct??\n"); + fprintf(stderr, "vd "); vd->print(); printf("\n"); fflush(stdout); + fprintf(stderr, "vd "); vd->dump(); printf("\n"); fflush(stdout); + exit(-1); + } + + // OK, we have the recorddecl that defines the structure + // now find the member with the correct name + chillAST_VarDecl *sub = rd->findSubpart( member ); + //fprintf(stderr, "sub %s:\n", member); + if (!sub) { + fprintf(stderr, "can't find member %s in \n", member); + rd->print(); + } + //sub->print(); printf("\n"); fflush(stdout); + //sub->dump() ; printf("\n"); fflush(stdout); + + return sub; + //find vardecl of member in def of base + + +} + + + + +chillAST_DeclRefExpr::chillAST_DeclRefExpr() { + asttype = CHILLAST_NODETYPE_DECLREFEXPR; + declarationType = strdup("UNKNOWN"); + declarationName = strdup("NONE"); + decl = NULL; + parent = NULL; + metacomment = NULL; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_DeclRefExpr::chillAST_DeclRefExpr( const char *varname, chillAST_node *par ) { + asttype = CHILLAST_NODETYPE_DECLREFEXPR; + declarationType = strdup("UNKNOWN"); + declarationName = strdup(varname); + decl = NULL; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_DeclRefExpr::chillAST_DeclRefExpr( const char *vartype, const char *varname, chillAST_node *par) { + //fprintf(stderr, "DRE::DRE 0x%x %s %s\n", this, vartype, varname ); + asttype = CHILLAST_NODETYPE_DECLREFEXPR; + declarationType = strdup(vartype); + declarationName = strdup(varname); + decl = NULL; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_DeclRefExpr::chillAST_DeclRefExpr( const char *vartype, const char *varname, chillAST_node *d, chillAST_node *par ) { + //fprintf(stderr, "DRE::DRE2 0x%x %s %s 0x%x\n", this, vartype, varname, d ); + asttype = CHILLAST_NODETYPE_DECLREFEXPR; + declarationType = strdup(vartype); + declarationName = strdup(varname); + decl = d; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_DeclRefExpr::chillAST_DeclRefExpr( chillAST_VarDecl *vd, chillAST_node *par ){ // variable def + //fprintf(stderr, "DRE::DRE3 (VD) 0x%x %s %s 0x%x\n", this, vd->vartype, vd->varname, vd ); + + asttype = CHILLAST_NODETYPE_DECLREFEXPR; + declarationType = strdup(vd->vartype); + declarationName = strdup(vd->varname); + decl = vd; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + + +chillAST_DeclRefExpr::chillAST_DeclRefExpr( chillAST_FunctionDecl *fd, chillAST_node *par ){ // function def + asttype = CHILLAST_NODETYPE_DECLREFEXPR; + declarationType = strdup(fd->returnType); + declarationName = strdup(fd->functionName); + decl = fd; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + + + +chillAST_DeclRefExpr *buildDeclRefExpr( chillAST_VarDecl *vd) { + chillAST_DeclRefExpr *dre = new chillAST_DeclRefExpr( vd, NULL ); + +} + +void chillAST_DeclRefExpr::print( int indent, FILE *fp) { + chillindent(indent, fp); + //fprintf(fp, "%s %s", declarationType, declarationName); // this is printing float *A + fprintf(fp, "%s", declarationName); // this is printing A + fflush(fp); +} + + +char *chillAST_DeclRefExpr::stringRep( int indent ) { + return strdup( declarationName ); +} + + +void chillAST_DeclRefExpr::dump( int indent, FILE *fp) { + chillindent(indent, fp); + fprintf(fp, "(DeclRefExpr '%s' ", declarationType); + chillAST_VarDecl *vd = getVarDecl(); + if (vd) { + if (vd->isAParameter) fprintf(fp, "ParmVar "); + else fprintf(fp, "Var "); + } + fprintf(fp, "'%s' ", declarationName); // variable or function name + + if (chillAST_FunctionDecl *fd = getFunctionDecl()) { + // print parameter types for functions + fd->printParameterTypes( fp ); + } + + fprintf(fp, ")\n"); + fflush(fp); +} + +class chillAST_node* chillAST_DeclRefExpr::constantFold() { // can never do anything? + return this; +} + +class chillAST_node* chillAST_DeclRefExpr::clone() { + //fprintf(stderr, "chillAST_DeclRefExpr::clone()\n"); + chillAST_DeclRefExpr *DRE = new chillAST_DeclRefExpr( declarationType, declarationName, decl, parent ); + DRE->isFromSourceFile = isFromSourceFile; + if (filename) DRE->filename = strdup(filename); + return DRE; +} + + +void chillAST_DeclRefExpr::gatherVarDeclsMore( vector &decls ) { + //fprintf(stderr, "chillAST_DeclRefExpr::gatherVarDeclsMore()\n"); + decl->gatherVarDeclsMore( decls ); +} + + +void chillAST_DeclRefExpr::gatherScalarVarDecls( vector &decls ) { + //fprintf(stderr, "chillAST_DeclRefExpr::gatherScalarVarDecls()\n"); + decl->gatherScalarVarDecls(decls); + //fprintf(stderr, "now %d scalar vardecls\n", decls.size()); +} + + +void chillAST_DeclRefExpr::gatherArrayVarDecls( vector &decls ) { + //fprintf(stderr, "chillAST_DeclRefExpr::gatherArrayVarDecls()\n"); + decl->gatherArrayVarDecls(decls); + //fprintf(stderr, "now %d Array vardecls\n", decls.size()); +} + + +void chillAST_DeclRefExpr::gatherDeclRefExprs( vector&refs ) { + refs.push_back(this); +} + +void chillAST_DeclRefExpr::gatherScalarRefs( std::vector &refs, bool writtento ) { + refs.push_back(this); +} + +void chillAST_DeclRefExpr::gatherVarUsage( vector &decls ) { + //fprintf(stderr, "chillAST_DeclRefExpr::gatherVarUsage()\n"); + for (int i=0; ivarname)) { + if (streq(declarationType, decls[i]->vartype)) { + //fprintf(stderr, "decl was already there\n"); + return; + } + } + } + chillAST_VarDecl *vd = getVarDecl(); // null for functiondecl + if (vd) decls.push_back( vd ); + +} + + + + +void chillAST_DeclRefExpr::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ + //fprintf(stderr, "chillAST_DeclRefExpr::replaceVarDecls()\n"); + if (decl == olddecl) { + //fprintf(stderr, "replacing old %s with %s\n", olddecl->varname, newdecl->varname); + //fprintf(stderr, "DRE was "); print(); + decl = newdecl; + declarationType = strdup(newdecl->vartype); + declarationName = strdup(newdecl->varname); + //fprintf(stderr, "\nDRE is "); print(); fprintf(stderr, "\n\n"); + } + else { + if (!strcmp(olddecl->varname, declarationName)) { + //fprintf(stderr, "uhoh, chillAST_DeclRefExpr::replaceVarDecls()\n"); + decl = newdecl; + declarationType = strdup(newdecl->vartype); + declarationName = strdup(newdecl->varname); + } + } +} + +chillAST_VarDecl *chillAST_ImplicitCastExpr::multibase() { + return subexpr->multibase(); +} + + +chillAST_VarDecl *chillAST_DeclRefExpr::multibase() { + // presumably, this is being called because this DRE is the base of an ArraySubscriptExpr + return getVarDecl(); +} + + + + + + + + + +void chillAST_VarDecl::gatherVarDecls( vector &decls ) { + //fprintf(stderr, "chillAST_VarDecl::gatherVarDecls()\n"); + for (int i=0; ivarname, varname)) { + if (streq(decls[i]->vartype, vartype)) { + //fprintf(stderr, "VarDecl (direct) decl was already there\n"); + return; + } + } + } + decls.push_back( this ); +} + + +void chillAST_VarDecl::gatherScalarVarDecls( vector &decls ) { + //fprintf(stderr, "chillAST_VarDecl::gatherScalarVarDecls(), %s numdimensions %d\n", varname, numdimensions); + + if (numdimensions != 0) return; // not a scalar + + for (int i=0; ivarname, varname)) { // wrong. scoping. TODO + if (streq(decls[i]->vartype, vartype)) { + //fprintf(stderr, "VarDecl (direct) decl was already there\n"); + return; + } + } + } + //fprintf(stderr, "adding vardecl for %s to decls\n", varname); + decls.push_back( this ); +} + + +void chillAST_VarDecl::gatherArrayVarDecls( vector &decls ) { + //fprintf(stderr, "chillAST_VarDecl::gatherScalarVarDecls(), %s numdimensions %d\n", varname, numdimensions); + + if (numdimensions == 0) return; // not an array + + for (int i=0; ivarname, varname)) { // wrong. scoping. TODO + if (streq(decls[i]->vartype, vartype)) { + //fprintf(stderr, "VarDecl (direct) decl was already there\n"); + return; + } + } + } + //fprintf(stderr, "adding vardecl for %s to decls\n", varname); + decls.push_back( this ); +} + + + +chillAST_node *chillAST_VarDecl::constantFold() { return this; } + +chillAST_node* chillAST_VarDecl::clone() { + fprintf(stderr, "\nchillAST_VarDecl::clone() cloning vardecl for %s\n", varname); + if (isAParameter) fprintf(stderr, "old vardecl IS a parameter\n"); + //else fprintf(stderr, "old vardecl IS NOT a parameter\n"); + + chillAST_VarDecl *vd = new chillAST_VarDecl( vartype, strdup(varname), arraypart, NULL); // NULL so we don't add the variable AGAIN to the (presumably) function + + vd->typedefinition = typedefinition; + vd->vardef = vardef; // perhaps should not do this TODO + //vd->isStruct = (vardef != NULL); // ?? + + vd->underlyingtype = strdup(underlyingtype); + + vd->arraysizes = NULL; + vd->knownArraySizes = knownArraySizes; + vd->numdimensions = numdimensions; + vd->arraypointerpart = NULL; + + if (arraypart != NULL && NULL!=arraysizes) { // !strcmp(arraypart, "")) { + //fprintf(stderr, "in chillAST_VarDecl::clone(), cloning the array info\n"); + //fprintf(stderr, "numdimensions %d arraysizes 0x%x\n", numdimensions, arraysizes) ; + vd->numdimensions = numdimensions; + + if (arraysizes) { + vd->arraysizes = (int *)malloc( sizeof(int *) * numdimensions ); + for (int i=0; i< numdimensions; i++) { + //fprintf(stderr, "i %d\n", i); + vd->arraysizes[i] = arraysizes[i]; + } + } + } + + if ( arraypointerpart ) { + //fprintf(stderr, "copying arraypointerpart\n"); + vd->arraypointerpart = strdup( arraypointerpart); + } + + vd->isStruct = this->isStruct; + //vd->insideAStruct = this->insideAStruct; + + //if (vd->isStruct) fprintf(stderr, "vardecl::clone() %s is a struct\n", varname); + //else fprintf(stderr, "vardecl::clone() %s is NOT a struct\n", varname); + + + vd->knownArraySizes = this->knownArraySizes; + vd->isFromSourceFile = isFromSourceFile; + if (filename) vd->filename = strdup(filename); + return vd; +} + + +void chillAST_VarDecl::splitarraypart() { + if (arraypart) CHILL_DEBUG_PRINT("%s\n", arraypart); + + // split arraypart into (leading??) asterisks and known sizes [1][2][3] + if (!arraypart || // NULL + (arraypart && (*arraypart == '\0'))) { // or empty string + + // parts are both empty string + if (arraypointerpart) free(arraypointerpart); + arraypointerpart = strdup(""); + if (arraysetpart) free(arraysetpart); + arraysetpart = strdup(""); + return; + } + + // arraypart exists and is not empty + int asteriskcount = 0; + int fixedcount = 0; + for ( int i=0; iisFromSourceFile = isFromSourceFile; + if (filename) IL->filename = strdup(filename); + return IL; + +} + +chillAST_FloatingLiteral::chillAST_FloatingLiteral(float val, chillAST_node *par){ + value = val; + precision = 1; + float0double1 = 0; // which is live! + allthedigits = NULL; + asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_FloatingLiteral::chillAST_FloatingLiteral(double val, chillAST_node *par){ + doublevalue = val; + precision = 2; + float0double1 = 1; // which is live! + allthedigits = NULL; + asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_FloatingLiteral::chillAST_FloatingLiteral(float val, int precis, chillAST_node *par){ + value = val; + precision = 1; + float0double1 = 0; // which is live! + precision = precis; // + allthedigits = NULL; + asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_FloatingLiteral::chillAST_FloatingLiteral(double val, int precis, chillAST_node *par){ + doublevalue = val; + float0double1 = 1; // which is live! + precision = precis; // + allthedigits = NULL; + asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_FloatingLiteral::chillAST_FloatingLiteral(float val, const char *printthis, chillAST_node *par){ + value = val; + float0double1 = 0; // which is live! + precision = 1; + allthedigits = NULL; + if (printthis) allthedigits = strdup( printthis ); + //fprintf(stderr, "\nfloatingliteral allthedigits = '%s'\n", allthedigits); + asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_FloatingLiteral::chillAST_FloatingLiteral(float val, int precis, const char *printthis, chillAST_node *par){ + value = val; + float0double1 = 0; // which is live! + precision = precis; // but value is a float?? TODO + allthedigits = NULL; + if (printthis) { + //fprintf(stderr, "\nchillAST_FloatingLiteral constructor, printthis "); + //fprintf(stderr, "%p\n", printthis); + allthedigits = strdup( printthis ); + } + //fprintf(stderr, "\nfloatingliteral allthedigits = '%s'\n", allthedigits); + asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + + +chillAST_FloatingLiteral::chillAST_FloatingLiteral( chillAST_FloatingLiteral *old ) { + //fprintf(stderr, "chillAST_FloatingLiteral::chillAST_FloatingLiteral( old ) allthedigits %p\n", old->allthedigits); + + asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; + value = old->value; + doublevalue = old->doublevalue; + float0double1 = old->float0double1; + allthedigits = NULL; + if (old->allthedigits) allthedigits = strdup(old->allthedigits); + precision = old->precision; + isFromSourceFile = true; // default + filename = NULL; +} + + + +void chillAST_FloatingLiteral::print( int indent, FILE *fp) { + chillindent(indent, fp); + //fprintf(fp, "%f", value); + // attempt to be more like rose output + char output[1024]; // warning, hardcoded + + if (allthedigits != NULL) { + strcpy(output, allthedigits ); // if they have specified 100 digits of pi, give 'em 100 digits + //fprintf(stderr, "floatingliteral allthedigits = '%s'\n", allthedigits); + } + else { + if (float0double1 == 0) sprintf(output, "%f", value); + else sprintf(output, "%f", doublevalue); + + // next part to avoid printing 123.4560000000000000000000000000 + char *dot = index(output, '.'); + if (dot) { + char *end = output + strlen(output); + char *onechar; + char *lastnonzero = dot; + for (onechar = output; onechar < end; onechar ++) { + if (*onechar != '0') lastnonzero = onechar; + } + + if (lastnonzero == dot) + lastnonzero[2] = '\0'; // may be after end of string, but that should be OK + else lastnonzero[1] = '\0'; // may be after end of string, but that should be OK + } + } + if (precision == 1) { + int len = strlen(output); + output[len] = 'f'; // explicit single precision + output[len+1] = '\0'; + } + + fprintf(fp, "%s", output); + fflush(fp); +} + +void chillAST_FloatingLiteral::dump( int indent, FILE *fp) { + chillindent(indent, fp); + // 2x2 cases ??? + if (precision == 1) + fprintf(fp, "(FloatingLiteral 'float' "); + else fprintf(fp, "(FloatingLiteral 'double' "); + + if (float0double1 == 0) fprintf(fp, "%f)\n", value); // %f gives enough digits + else fprintf(fp, "%f)\n", doublevalue); // %f gives enough digits + fflush(fp); +} + + +chillAST_node* chillAST_FloatingLiteral::constantFold() { return this; }; // NOOP + +chillAST_node* chillAST_FloatingLiteral::clone() { + //fprintf(stderr, "chillAST_FloatingLiteral::clone() "); + //fprintf(stderr, "allthedigits %p \n", allthedigits); + chillAST_FloatingLiteral *newone = new chillAST_FloatingLiteral( this ); + + newone->isFromSourceFile = isFromSourceFile; + if (filename) newone->filename = strdup(filename); + //print(); printf(" "); newone->print(); printf("\n"); fflush(stdout); + return newone; +} + +bool chillAST_FloatingLiteral::isSameAs( chillAST_node *other ){ + if (!other->isFloatingLiteral()) return false; + chillAST_FloatingLiteral *o = (chillAST_FloatingLiteral *)other; + // should we care about single vs double precision? + if (float0double1 != o->float0double1) return false; + if (float0double1 == 0) { + return value == o->value; // WARNING, comparing floats with == + } + return doublevalue == o->doublevalue; // WARNING, comparing doubless with == +} + + + + + +chillAST_UnaryOperator::chillAST_UnaryOperator( const char *oper, bool pre, chillAST_node *sub, chillAST_node *par ) { + op = strdup(oper); + prefix = pre; + subexpr = sub; + subexpr->setParent( this ); + asttype = CHILLAST_NODETYPE_UNARYOPERATOR; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +void chillAST_UnaryOperator::gatherArrayRefs( std::vector &refs, bool w ) { + subexpr->gatherArrayRefs( refs, isAssignmentOp()); // +} + + + +void chillAST_UnaryOperator::print( int indent, FILE *fp) { + bool needparens = false; + if (subexpr->isNotLeaf()) needparens = true; // may get more complicated + + chillindent( indent, fp); // will this ever be invoked? + if (prefix) fprintf(fp, "%s", op); + if (needparens) fprintf(fp, "("); + subexpr->print( 0, fp ); + if (needparens) fprintf(fp, ")"); + if (!prefix) fprintf(fp, "%s", op); + fflush(fp); +} + + +void chillAST_UnaryOperator::dump( int indent, FILE *fp) { + chillindent( indent, fp); + fprintf(fp, "(UnaryOperator "); + if (prefix) fprintf(fp, "prefix "); + else fprintf(fp, "postfix "); + fprintf(fp, "%s\n", op); + subexpr->dump(indent+1, fp); + + chillindent( indent, fp); + fprintf(fp, ")\n"); +} + + +void chillAST_UnaryOperator::gatherVarLHSUsage( vector &decls ) { + if ((!strcmp("++", op)) || (!strcmp("--", op))) { + subexpr->gatherVarUsage( decls ); // do all unary modify the subexpr? (no, - ) + } +} + + + +chillAST_node* chillAST_UnaryOperator::constantFold() { + //fprintf(stderr, "chillAST_UnaryOperator::constantFold() "); + //print(); fprintf(stderr, "\n"); + + subexpr = subexpr->constantFold(); + chillAST_node *returnval = this; + if (subexpr->isConstant()) { + //fprintf(stderr, "unary op folding constants\n"); + //print(0,stderr); fprintf(stderr, "\n"); + + if (streq(op, "-")) { + if (subexpr->isIntegerLiteral()) { + int intval = ((chillAST_IntegerLiteral*)subexpr)->value; + chillAST_IntegerLiteral *I = new chillAST_IntegerLiteral( -intval, parent); + returnval = I; + //fprintf(stderr, "integer -%d becomes %d\n", intval, I->value); + } + else { + chillAST_FloatingLiteral *FL = (chillAST_FloatingLiteral*)subexpr; + chillAST_FloatingLiteral *F = new chillAST_FloatingLiteral( FL ); // clone + F->parent = FL->parent; + + F->value = -F->value; + F->doublevalue = -F->doublevalue; + + F->print(); fprintf(stderr, "\n"); + + returnval = F; + } + } + else fprintf(stderr, "can't fold op '%s' yet\n", op); + } + return returnval; +} + + +class chillAST_node* chillAST_UnaryOperator::clone() { + chillAST_UnaryOperator *UO = new chillAST_UnaryOperator( op, prefix, subexpr->clone(), parent ); + UO->isFromSourceFile = isFromSourceFile; + if (filename) UO->filename = strdup(filename); + return UO; +} + + +void chillAST_UnaryOperator::gatherVarDecls( vector &decls ) { + subexpr->gatherVarDecls( decls ); +} + + +void chillAST_UnaryOperator::gatherScalarVarDecls( vector &decls ) { + subexpr->gatherScalarVarDecls( decls ); +} + + +void chillAST_UnaryOperator::gatherArrayVarDecls( vector &decls ) { + subexpr->gatherArrayVarDecls( decls ); +} + + +void chillAST_UnaryOperator::gatherDeclRefExprs( vector&refs ) { + subexpr->gatherDeclRefExprs( refs ); +} + + +void chillAST_UnaryOperator::gatherVarUsage( vector &decls ) { + subexpr->gatherVarUsage( decls ); +} + + void chillAST_UnaryOperator::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) { + subexpr->replaceVarDecls( olddecl, newdecl ); + } + + +int chillAST_UnaryOperator::evalAsInt() { + if (!strcmp("+", op)) return subexpr->evalAsInt(); + if (!strcmp("-", op)) return -subexpr->evalAsInt(); + if (!strcmp("++", op)) return 1 + subexpr->evalAsInt(); + if (!strcmp("--", op)) return subexpr->evalAsInt() - 1; + + fprintf(stderr, "chillAST_UnaryOperator::evalAsInt() unhandled op '%s'\n", op); + segfault(); + +} + +bool chillAST_UnaryOperator::isSameAs( chillAST_node *other ){ + if (!other->isUnaryOperator()) return false; + chillAST_UnaryOperator *o = (chillAST_UnaryOperator *)other; + if (strcmp(op, o->op)) return false; // different operators + return subexpr->isSameAs( o->subexpr ); // recurse +} + + +chillAST_ImplicitCastExpr::chillAST_ImplicitCastExpr( chillAST_node *sub, chillAST_node *par ) { + subexpr = sub; + subexpr->setParent( this ); + asttype = CHILLAST_NODETYPE_IMPLICITCASTEXPR; + parent = par; + //fprintf(stderr, "ImplicitCastExpr 0x%x has subexpr 0x%x", this, subexpr); + //fprintf(stderr, " of type %s\n", subexpr->getTypeString()); + isFromSourceFile = true; // default + filename = NULL; +} + +void chillAST_ImplicitCastExpr::print( int indent, FILE *fp) { + // No need to print anything, simply forward to the sub expression. + subexpr->print( indent, fp ); + fflush(fp); +}; + +void chillAST_ImplicitCastExpr::printonly( int indent, FILE *fp) { + // No need to print anything, simply forward to the sub expression. + subexpr->printonly( indent, fp ); + fflush(fp); +}; + +void chillAST_ImplicitCastExpr::replaceChild( chillAST_node *old, chillAST_node *newchild ){ + if (subexpr == old) { // should be the case for this to get called + subexpr = newchild; + subexpr->setParent( this ); + //old->parent = NULL; + return; + } + + fprintf(stderr, "chillAST_ImplicitCastExpr::replaceChild() called with bad 'old'\n"); + exit(-1); // ?? +} + +class chillAST_node* chillAST_ImplicitCastExpr::constantFold() { + chillAST_node *child = subexpr->constantFold(); + child->setParent( parent ) ; // remove myself !! probably a bad idea. TODO + return child; +} + + +class chillAST_node* chillAST_ImplicitCastExpr::clone() { + chillAST_ImplicitCastExpr *ICE = new chillAST_ImplicitCastExpr( subexpr->clone(), parent); + ICE->isFromSourceFile = isFromSourceFile; + if (filename) ICE->filename = strdup(filename); + return ICE; +} + + +void chillAST_ImplicitCastExpr::gatherArrayRefs( std::vector &refs, bool w ) { + subexpr->gatherArrayRefs( refs, w ); +} + +void chillAST_ImplicitCastExpr::gatherScalarRefs( std::vector &refs, bool writtento ) { + subexpr->gatherScalarRefs( refs, writtento ); +} + +void chillAST_ImplicitCastExpr::gatherVarDecls( vector &decls ) { + subexpr->gatherVarDecls( decls ); +} + + +void chillAST_ImplicitCastExpr::gatherScalarVarDecls( vector &decls ) { + subexpr->gatherScalarVarDecls( decls ); +} + + +void chillAST_ImplicitCastExpr::gatherArrayVarDecls( vector &decls ) { + subexpr->gatherArrayVarDecls( decls ); +} + + +void chillAST_ImplicitCastExpr::gatherDeclRefExprs( vector&refs ) { + subexpr->gatherDeclRefExprs( refs ); +} + + +void chillAST_ImplicitCastExpr::gatherVarUsage( vector &decls ) { + subexpr->gatherVarUsage( decls ); +} + + + +chillAST_CStyleCastExpr::chillAST_CStyleCastExpr( const char *to, chillAST_node *sub, chillAST_node *par ) { + + //fprintf(stderr, "chillAST_CStyleCastExpr::chillAST_CStyleCastExpr( %s, ...)\n", to); + towhat = strdup(to); + subexpr = sub; + if (subexpr) subexpr->setParent( this ); + asttype = CHILLAST_NODETYPE_CSTYLECASTEXPR; + parent = par; + //fprintf(stderr, "chillAST_CStyleCastExpr (%s) sub 0x%x\n", towhat, sub ); + isFromSourceFile = true; // default + filename = NULL; +} + +void chillAST_CStyleCastExpr::replaceChild( chillAST_node *old, chillAST_node *newchild ){ + if (subexpr == old) { // should be the case for this to get called + subexpr = newchild; + subexpr->setParent( this ); + //old->parent = NULL; + return; + } + + fprintf(stderr, "chillAST_CStyleCastExpr::replaceChild() called with bad 'old'\n"); + exit(-1); // ?? +} + + void chillAST_CStyleCastExpr::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) { + subexpr->replaceVarDecls( olddecl, newdecl); + } + +void chillAST_CStyleCastExpr::print( int indent, FILE *fp) { + //fprintf(stderr, "CStyleCastExpr::print()\n"); + chillindent(indent, fp); + + // special cases? should probably walk the AST and change the literal itself + if ( !strcmp("float", towhat) && subexpr->isIntegerLiteral()) { // (float) 3 => 3.0f + subexpr->print( 0, fp ); fprintf(fp, ".0f"); + } + else if ( !strcmp("double", towhat) && subexpr->isIntegerLiteral()) { // (double) 3 => 3.0 + subexpr->print( 0, fp ); fprintf(fp, ".0"); + } + else if ( !strcmp("float", towhat) && subexpr->isFloatingLiteral()) { // (float) 3.0 => 3.0f + subexpr->print( 0, fp ); fprintf(fp, "f"); + } + else { // general case + fprintf(fp, "((%s) ", towhat); + //fprintf(fp, "\ntowhat '%s'\n", towhat ); + + if (subexpr->isVarDecl()) fprintf(fp, "%s", ((chillAST_VarDecl *)subexpr)->varname); + else subexpr->print( indent, fp ); + //fprintf(fp, "subexpr '%s' ", subexpr->getTypeString()); + fprintf(fp, ")"); + } + fflush(fp); +}; + + +void chillAST_CStyleCastExpr::dump( int indent, FILE *fp) { + chillindent(indent, fp); + fprintf(fp, "(CStyleCastExpr (%s) \n", towhat); + subexpr->dump( indent+1, fp ); + chillindent(indent, fp); + fprintf(fp, ")\n"); + fflush(fp); +} + +class chillAST_node* chillAST_CStyleCastExpr::constantFold() { + subexpr = subexpr->constantFold(); + return this; +} + + +class chillAST_node* chillAST_CStyleCastExpr::clone() { + chillAST_CStyleCastExpr *CSCE = new chillAST_CStyleCastExpr( towhat, subexpr->clone(), parent ); + CSCE->isFromSourceFile = isFromSourceFile; + if (filename) CSCE->filename = strdup(filename); + return CSCE; +} + +void chillAST_CStyleCastExpr::gatherArrayRefs( std::vector &refs, bool w ) { + subexpr->gatherArrayRefs( refs, w ); +} + +void chillAST_CStyleCastExpr::gatherScalarRefs( std::vector &refs, bool writtento ) { + subexpr->gatherScalarRefs( refs, writtento ); +} + + +void chillAST_CStyleCastExpr::gatherVarDecls( vector &decls ) { + subexpr->gatherVarDecls( decls ); +} + + +void chillAST_CStyleCastExpr::gatherScalarVarDecls( vector &decls ) { + subexpr->gatherScalarVarDecls( decls ); +} + + +void chillAST_CStyleCastExpr::gatherArrayVarDecls( vector &decls ) { + subexpr->gatherArrayVarDecls( decls ); +} + + +void chillAST_CStyleCastExpr::gatherDeclRefExprs( vector&refs ) { + subexpr->gatherDeclRefExprs( refs ); +} + + +void chillAST_CStyleCastExpr::gatherVarUsage( vector &decls ) { + subexpr->gatherVarUsage( decls ); +} + + + + +chillAST_CStyleAddressOf::chillAST_CStyleAddressOf( chillAST_node *sub, chillAST_node *par ) { + subexpr = sub; + subexpr->setParent( this ); + asttype = CHILLAST_NODETYPE_CSTYLEADDRESSOF; + parent = par; + //fprintf(stderr, "chillAST_CStyleCastExpr (%s) sub 0x%x\n", towhat, sub ); + isFromSourceFile = true; // default + filename = NULL; +} + +void chillAST_CStyleAddressOf::print( int indent, FILE *fp) { + //fprintf(stderr, "CStyleAddressOf::print()\n"); + chillindent(indent, fp); + fprintf(fp, "(&"); + subexpr->print( 0, fp ); + fprintf(fp, ")"); + fflush(fp); +}; + +void chillAST_CStyleAddressOf::dump( int indent, FILE *fp) { + chillindent(indent, fp); + fprintf(fp, "(CStyleAddressOf \n"); + subexpr->print( indent+1, fp ); + chillindent(indent, fp); + fprintf(fp, ")\n"); + fflush(fp); +} + +class chillAST_node* chillAST_CStyleAddressOf::constantFold() { + subexpr = subexpr->constantFold(); + return this; +} + +class chillAST_node* chillAST_CStyleAddressOf::clone() { + chillAST_CStyleAddressOf *CSAO = new chillAST_CStyleAddressOf( subexpr->clone(), parent ); + CSAO->isFromSourceFile = isFromSourceFile; + if (filename) CSAO->filename = strdup(filename); + return CSAO; +} + +void chillAST_CStyleAddressOf::gatherArrayRefs( std::vector &refs, bool w ) { + subexpr->gatherArrayRefs( refs, w ); +} + +void chillAST_CStyleAddressOf::gatherScalarRefs( std::vector &refs, bool writtento ) { + subexpr->gatherScalarRefs( refs, writtento ); +} + +void chillAST_CStyleAddressOf::gatherVarDecls( vector &decls ) { + subexpr->gatherVarDecls( decls ); +} + +void chillAST_CStyleAddressOf::gatherScalarVarDecls( vector &decls ) { + subexpr->gatherScalarVarDecls( decls ); +} + + +void chillAST_CStyleAddressOf::gatherArrayVarDecls( vector &decls ) { + subexpr->gatherArrayVarDecls( decls ); +} + + +void chillAST_CStyleAddressOf::gatherDeclRefExprs( vector&refs ) { + subexpr->gatherDeclRefExprs( refs ); +} + + +void chillAST_CStyleAddressOf::gatherVarUsage( vector &decls ) { + subexpr->gatherVarUsage( decls ); +} + + + + +chillAST_Malloc::chillAST_Malloc(chillAST_node *size, chillAST_node *p) { + thing = NULL; + sizeexpr = size; // probably a multiply like sizeof(int) * 1024 + asttype = CHILLAST_NODETYPE_MALLOC; + parent = p; + isFromSourceFile = true; // default + filename = NULL; +}; + +chillAST_Malloc::chillAST_Malloc(char *thething, chillAST_node *numthings, chillAST_node *p) { + thing = strdup(thething); // "int" or "float" or "struct widget" + sizeexpr = numthings; + asttype = CHILLAST_NODETYPE_MALLOC; + parent = p; + isFromSourceFile = true; // default + filename = NULL; +}; + +chillAST_node* chillAST_Malloc::constantFold() { + sizeexpr->constantFold(); +} + +chillAST_node* chillAST_Malloc::clone() { + chillAST_Malloc *M = new chillAST_Malloc( thing, sizeexpr, parent); // the general version + M->isFromSourceFile = isFromSourceFile; + if (filename) M->filename = strdup(filename); + return M; +}; + +void chillAST_Malloc::gatherArrayRefs( std::vector &refs, bool writtento ) { + sizeexpr->gatherArrayRefs( refs, writtento ); +}; + + +void chillAST_Malloc::gatherScalarRefs( std::vector &refs, bool writtento ) { + sizeexpr->gatherScalarRefs( refs, writtento ); +}; + +void chillAST_Malloc::gatherVarDecls( vector &decls ) { + sizeexpr->gatherVarDecls(decls); +}; + +void chillAST_Malloc::gatherScalarVarDecls( vector &decls ){ + sizeexpr->gatherScalarVarDecls(decls); +}; + +void chillAST_Malloc::gatherArrayVarDecls ( vector &decls ) { + sizeexpr->gatherArrayVarDecls(decls); +}; + +void chillAST_Malloc::gatherVarUsage( vector &decls ){ + sizeexpr->gatherVarUsage(decls); +}; + + + +void chillAST_Malloc::print( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "malloc("); + + if (thing) { + fprintf(fp, " sizeof(%s) * ", thing ); + } + sizeexpr->print(0,fp); + fprintf(fp, ")"); + fflush(fp); +}; + + +void chillAST_Malloc::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(Malloc \n"); + sizeexpr->dump( indent+1, fp ); + chillindent(indent, fp); + fprintf(fp, ")\n"); + fflush(fp); +}; + + + +chillAST_CudaMalloc::chillAST_CudaMalloc(chillAST_node *devmemptr, chillAST_node *size, chillAST_node *p) { + devPtr = devmemptr; + sizeinbytes = size; // probably a multiply like sizeof(int) * 1024 + asttype = CHILLAST_NODETYPE_CUDAMALLOC; + parent = p; + isFromSourceFile = true; // default + filename = NULL; +}; + +void chillAST_CudaMalloc::print( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "cudaMalloc("); + devPtr->print( 0, fp ); + fprintf(fp, ","); + sizeinbytes->print( 0, fp ); + fprintf(fp, ")"); + fflush(fp); +}; + +void chillAST_CudaMalloc::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(CudaMalloc \n"); + devPtr->dump( indent+1, fp ); + fprintf(fp, "\n"); + sizeinbytes->dump( indent+1, fp ); + fprintf(fp, ")\n"); + fflush(fp); +}; + +class chillAST_node* chillAST_CudaMalloc::constantFold() { + devPtr = devPtr->constantFold(); + return this; +} + +class chillAST_node* chillAST_CudaMalloc::clone() { + chillAST_CudaMalloc *CM = new chillAST_CudaMalloc( devPtr->clone(), sizeinbytes->clone(), parent ); + CM->isFromSourceFile = isFromSourceFile; + if (filename) CM->filename = strdup(filename); + return CM; +} + +void chillAST_CudaMalloc::gatherArrayRefs( std::vector &refs, bool w ) { + devPtr->gatherArrayRefs( refs, false ); + sizeinbytes->gatherArrayRefs( refs, false ); +} + +void chillAST_CudaMalloc::gatherScalarRefs( std::vector &refs, bool writtento ) { + devPtr->gatherScalarRefs( refs, false ); + sizeinbytes->gatherScalarRefs( refs, false ); +} + +void chillAST_CudaMalloc::gatherVarDecls( vector &decls ) { + devPtr->gatherVarDecls( decls ); + sizeinbytes->gatherVarDecls( decls ); +} + + +void chillAST_CudaMalloc::gatherScalarVarDecls( vector &decls ) { + devPtr->gatherScalarVarDecls( decls ); + sizeinbytes->gatherScalarVarDecls( decls ); +} + + + +void chillAST_CudaMalloc::gatherArrayVarDecls( vector &decls ) { + devPtr->gatherArrayVarDecls( decls ); + sizeinbytes->gatherArrayVarDecls( decls ); +} + + + +void chillAST_CudaMalloc::gatherVarUsage( vector &decls ) { + devPtr->gatherVarUsage( decls ); + sizeinbytes->gatherVarUsage( decls ); +} + + + +chillAST_CudaFree::chillAST_CudaFree(chillAST_VarDecl *var, chillAST_node *p) { + variable = var; + parent = p; + asttype = CHILLAST_NODETYPE_CUDAFREE; + isFromSourceFile = true; // default + filename = NULL; +}; + +void chillAST_CudaFree::print( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "cudaFree(%s)", variable->varname); + fflush(fp); +}; + +void chillAST_CudaFree::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(CudaFree %s )\n", variable->varname); + fflush(fp); +}; + +class chillAST_node* chillAST_CudaFree::constantFold() { + return this; +} + +class chillAST_node* chillAST_CudaFree::clone() { + chillAST_CudaFree *CF = new chillAST_CudaFree( variable, parent ); + CF->isFromSourceFile = isFromSourceFile; + if (filename) CF->filename = strdup(filename); + return CF; +} + +void chillAST_CudaFree::gatherArrayRefs( std::vector &refs, bool w ) {} +void chillAST_CudaFree::gatherScalarRefs( std::vector &refs, bool writtento ) {} + +void chillAST_CudaFree::gatherVarDecls( vector &decls ) { + variable->gatherVarDecls( decls ); +} + + +void chillAST_CudaFree::gatherScalarVarDecls( vector &decls ) { + variable->gatherScalarVarDecls( decls ); +} + + +void chillAST_CudaFree::gatherArrayVarDecls( vector &decls ) { + variable->gatherArrayVarDecls( decls ); +} + + + +void chillAST_CudaFree::gatherVarUsage( vector &decls ) { + variable->gatherVarUsage( decls ); +} + + + + + + + + + +chillAST_CudaMemcpy::chillAST_CudaMemcpy(chillAST_VarDecl *d, chillAST_VarDecl *s, chillAST_node *siz, char *kind, chillAST_node *par) { + dest = d; + src = s; + //fprintf(stderr, "chillAST_CudaMemcpy::chillAST_CudaMemcpy( dest %s, src %s, ...)\n", d->varname, s->varname ); + size = siz; + cudaMemcpyKind = kind; + asttype = CHILLAST_NODETYPE_CUDAMEMCPY; + isFromSourceFile = true; // default + filename = NULL; + parent = par; +}; + +void chillAST_CudaMemcpy::print( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "cudaMemcpy(%s,%s,", dest->varname, src->varname); + //dest->print( 0, fp ); + //fprintf(fp, ","); + // src->print( 0, fp ); just want the src NAME, not name and array info + //fprintf(fp, ","); + size->print( 0, fp ); + fprintf(fp, ",%s)", cudaMemcpyKind); + fflush(fp); +}; + +void chillAST_CudaMemcpy::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(CudaMemcpy \n"); + dest->dump( indent+1, fp ); + src->dump( indent+1, fp ); + size->dump( indent+1, fp ); + chillindent(indent+1, fp); + fprintf(fp, ",%s\n", cudaMemcpyKind); + fflush(fp); +}; + +class chillAST_node* chillAST_CudaMemcpy::constantFold() { + dest = (chillAST_VarDecl *)dest->constantFold(); + src = (chillAST_VarDecl *)src->constantFold(); + size = size->constantFold(); + return this; +} + +class chillAST_node* chillAST_CudaMemcpy::clone() { + chillAST_CudaMemcpy *CMCPY = new chillAST_CudaMemcpy((chillAST_VarDecl *)(dest->clone()),(chillAST_VarDecl *)(src->clone()), size->clone(), strdup(cudaMemcpyKind), parent ); + CMCPY->isFromSourceFile = isFromSourceFile; + if (filename) CMCPY->filename = strdup(filename); + return CMCPY; +} + +void chillAST_CudaMemcpy::gatherArrayRefs( std::vector &refs, bool w ) { + dest->gatherArrayRefs( refs, false ); + src ->gatherArrayRefs( refs, false ); + size->gatherArrayRefs( refs, false ); +} + +void chillAST_CudaMemcpy::gatherScalarRefs( std::vector &refs, bool writtento ) { + dest->gatherScalarRefs( refs, false ); + src ->gatherScalarRefs( refs, false ); + size->gatherScalarRefs( refs, false ); +} + +void chillAST_CudaMemcpy::gatherVarDecls( vector &decls ) { + dest->gatherVarDecls( decls ); + src ->gatherVarDecls( decls ); + size->gatherVarDecls( decls ); +} + + +void chillAST_CudaMemcpy::gatherScalarVarDecls( vector &decls ) { + dest->gatherScalarVarDecls( decls ); + src ->gatherScalarVarDecls( decls ); + size->gatherScalarVarDecls( decls ); +} + + +void chillAST_CudaMemcpy::gatherArrayVarDecls( vector &decls ) { + dest->gatherArrayVarDecls( decls ); + src ->gatherArrayVarDecls( decls ); + size->gatherArrayVarDecls( decls ); +} + + +void chillAST_CudaMemcpy::gatherVarUsage( vector &decls ) { + dest->gatherVarUsage( decls ); + src ->gatherVarUsage( decls ); + size->gatherVarUsage( decls ); +} + + + +chillAST_CudaSyncthreads::chillAST_CudaSyncthreads( chillAST_node *par) { + asttype = CHILLAST_NODETYPE_CUDASYNCTHREADS; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + + void chillAST_CudaSyncthreads::print( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "__syncthreads()"); + fflush(fp); + } + + void chillAST_CudaSyncthreads::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(syncthreads)\n"); + fflush(fp); + } + + + + + + + + + + +chillAST_ReturnStmt::chillAST_ReturnStmt( chillAST_node *retval, chillAST_node *par ) { + asttype = CHILLAST_NODETYPE_RETURNSTMT; + returnvalue = retval; + if (returnvalue) returnvalue->setParent( this ); + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + + +void chillAST_ReturnStmt::print( int indent, FILE *fp) { + printPreprocBEFORE(indent, fp); + chillindent(indent, fp); + if (returnvalue != NULL) { + fprintf(fp, "return("); + returnvalue->print( 0, fp ); + fprintf(fp, ")" ); // parent will add ";\n" ?? + } + else { + fprintf(fp, "return"); + } + fflush(fp); +} + + +void chillAST_ReturnStmt::dump( int indent, FILE *fp) { + chillindent(indent, fp); + fprintf(fp, "(ReturnStmt"); + if (returnvalue) { + fprintf(fp, "\n"); + returnvalue->dump(indent+1,fp); + chillindent(indent, fp); + } + fprintf(fp, ")\n"); +} + + +class chillAST_node* chillAST_ReturnStmt::constantFold() { + if (returnvalue) returnvalue = returnvalue->constantFold(); + return this; +} + + + +class chillAST_node* chillAST_ReturnStmt::clone() { + chillAST_node *val = NULL; + if ( returnvalue ) val = returnvalue->clone(); + chillAST_ReturnStmt *RS = new chillAST_ReturnStmt( val, parent ); + RS->isFromSourceFile = isFromSourceFile; + if (filename) RS->filename = strdup(filename); + return RS; +} + + +void chillAST_ReturnStmt::gatherVarDecls( vector &decls ) { + if (returnvalue) returnvalue->gatherVarDecls( decls ); +} + + +void chillAST_ReturnStmt::gatherScalarVarDecls( vector &decls ) { + if (returnvalue) returnvalue->gatherScalarVarDecls( decls ); +} + + +void chillAST_ReturnStmt::gatherArrayVarDecls( vector &decls ) { + if (returnvalue) returnvalue->gatherArrayVarDecls( decls ); +} + + + +void chillAST_ReturnStmt::gatherDeclRefExprs( vector&refs ) { + if (returnvalue) returnvalue->gatherDeclRefExprs( refs ); +} + + + +void chillAST_ReturnStmt::gatherVarUsage( vector &decls ) { + if (returnvalue) returnvalue->gatherVarUsage( decls ); +} + + + + +chillAST_CallExpr::chillAST_CallExpr(chillAST_node *c, chillAST_node *par) { //, int numofargs, chillAST_node **theargs ) { + + //fprintf(stderr, "chillAST_CallExpr::chillAST_CallExpr callee type %s\n", c->getTypeString()); + asttype = CHILLAST_NODETYPE_CALLEXPR; + callee = c; + //callee->setParent( this ); // ?? + numargs = 0; + parent = par; + grid = block = NULL; + isFromSourceFile = true; // default + filename = NULL; +} + + +void chillAST_CallExpr::addArg( chillAST_node *a ) { + args.push_back( a ); + a->setParent( this ); + numargs += 1; +} + + +void chillAST_CallExpr::print( int indent, FILE *fp) { + printPreprocBEFORE(indent, fp); + chillindent(indent, fp); + chillAST_FunctionDecl *FD = NULL; + chillAST_MacroDefinition *MD = NULL; + + if (callee->isDeclRefExpr()) { + chillAST_DeclRefExpr *DRE = (chillAST_DeclRefExpr *) callee; + //fprintf(stderr, "DRE decl is 0x%x\n", DRE->decl); + if (!DRE->decl) { + // a macro? + fprintf(fp, "%s ", DRE->declarationName); + return; // ?? + } + + //fprintf(stderr, "DRE decl of type %s\n", DRE->decl->getTypeString()); + if ( (DRE->decl)->isFunctionDecl()) FD = (chillAST_FunctionDecl *)DRE->decl; + else { + fprintf(stderr, "chillAST_CallExpr::print() DRE decl of type %s\n", DRE->decl->getTypeString()); + exit(-1); + } + } + else if (callee->isFunctionDecl()) FD = (chillAST_FunctionDecl *) callee; + else if (callee->isMacroDefinition()) { + MD = (chillAST_MacroDefinition *) callee; + fprintf(fp, "%s(", MD->macroName); + } + else { + fprintf(stderr, "\nchillAST_CallExpr::print() callee of unhandled type %s\n", callee->getTypeString()); + callee->dump(); + exit(-1); + } + + if (FD) { + fprintf(fp, "%s", FD->functionName ); fflush(fp); + if (grid && block) { + fprintf(fp, "<<<%s,%s>>>(", grid->varname, block->varname); // a + } + else fprintf(fp, "("); + } + + + //callee->print( indent, fp); + for (int i=0; iprint(0, fp); + } + fprintf(fp, ")"); //a + fflush(fp); +} + +void chillAST_CallExpr::dump( int indent, FILE *fp) { + chillindent(indent, fp); + fprintf(fp, "(CallExpr "); + //fprintf(stderr, "callee type %s\n", callee->getTypeString()); + chillAST_FunctionDecl *fd = NULL; + if (callee->isDeclRefExpr()) { // always? + chillAST_DeclRefExpr *dre = (chillAST_DeclRefExpr *)callee; + fd = dre->getFunctionDecl(); // if NULL, we've got a Vardecl instead + if (fd) { + //fd->print(); + fprintf(fp, "%s\n", fd->returnType); + } + + callee->dump(indent+1, fp); + if (fd) { + int numparams = fd->parameters.size(); + for (int i=0; iparameters[i]->dump(indent+1, fp); + } + } + chillindent(indent, fp); + fprintf(fp, ")\n"); +} + +void chillAST_CallExpr::gatherArrayRefs( std::vector &refs, bool writtento ) { + for (int i=0; igatherArrayRefs( refs, writtento ); + } +} +void chillAST_CallExpr::gatherScalarRefs( std::vector &refs, bool writtento ) { + for (int i=0; igatherScalarRefs( refs, writtento ); + } +} + + +void chillAST_CallExpr::gatherVarDecls( vector &decls ) { + for (int i=0; igatherVarDecls( decls ); + } +} + + +void chillAST_CallExpr::gatherScalarVarDecls( vector &decls ) { + for (int i=0; igatherScalarVarDecls( decls ); + } +} + + +void chillAST_CallExpr::gatherArrayVarDecls( vector &decls ) { + for (int i=0; igatherArrayVarDecls( decls ); + } +} + + +void chillAST_CallExpr::gatherDeclRefExprs( vector&refs ) { + for (int i=0; igatherDeclRefExprs( refs ); + } +} + +void chillAST_CallExpr::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ + for (int i=0; ireplaceVarDecls( olddecl, newdecl ); +} + +void chillAST_CallExpr::gatherVarUsage( vector &decls ) { + for (int i=0; igatherVarUsage( decls ); + } +} + + +chillAST_node* chillAST_CallExpr::constantFold() { + numargs = args.size(); // wrong place for this + for (int i=0; iconstantFold(); + } + return this; +} + +chillAST_node* chillAST_CallExpr::clone() { + //fprintf(stderr, "chillAST_CallExpr::clone()\n"); + //print(0, stderr); fprintf(stderr, "\n"); + + chillAST_CallExpr *CE = new chillAST_CallExpr( callee->clone(), NULL ); + for (int i=0; iaddArg( args[i]->clone() ); + CE->isFromSourceFile = isFromSourceFile; + if (filename) CE->filename = strdup(filename); + return CE; +} + + + + +chillAST_VarDecl::chillAST_VarDecl() { + //fprintf(stderr, "0chillAST_VarDecl::chillAST_VarDecl() %p\n", this); + fprintf(stderr, "0chillAST_VarDecl::chillAST_VarDecl()\n"); + vartype = underlyingtype = varname = arraypart = arraypointerpart = arraysetpart = NULL; + typedefinition = NULL; + + //fprintf(stderr, "setting underlying type NULL\n" ); + init = NULL; + numdimensions=0; arraysizes = NULL; + asttype = CHILLAST_NODETYPE_VARDECL; // + parent = NULL; + metacomment = NULL; + + vardef = NULL; + isStruct = false; + + //insideAStruct = false; + isAParameter = false; + byreference = false; + isABuiltin = false; + isRestrict = isDevice = isShared = false; // fprintf(stderr, "RDS = false\n"); + knownArraySizes = false; + isFromSourceFile = true; // default + filename = NULL; +}; + + + +chillAST_VarDecl::chillAST_VarDecl( const char *t, const char *n, const char *a, chillAST_node *par) { + //fprintf(stderr, "1chillAST_VarDecl::chillAST_VarDecl( type %s, name %s, arraypart %s, parent %p) %p\n", t, n, a, par, this); + fprintf(stderr, "1chillAST_VarDecl::chillAST_VarDecl( type %s, name %s, arraypart %s)\n", t, n, a); + vartype = strdup(t); + typedefinition = NULL; + + underlyingtype = parseUnderlyingType( vartype ); + //fprintf(stderr, "setting underlying type %s from %s\n", underlyingtype, vartype ); + varname = strdup(n); + arraypointerpart = arraysetpart = NULL; + if (a) arraypart = strdup(a); + else arraypart = strdup(""); + splitarraypart(); + + init = NULL; + numdimensions=0; arraysizes = NULL; + uniquePtr = NULL; + asttype = CHILLAST_NODETYPE_VARDECL; + parent = par; + + + + knownArraySizes = false; + //fprintf(stderr, "arraypart len %d\n", strlen(a)); + for (int i=0; iaddVariableToSymbolTable( this ); // should percolate up until something has a symbol table + + } + isFromSourceFile = true; // default + filename = NULL; +}; + + + +chillAST_VarDecl::chillAST_VarDecl( chillAST_RecordDecl *astruct, const char *nam, const char *array, chillAST_node *par) { + // define a variable whose type is a struct! + + fprintf(stderr, "3chillAST_VarDecl::chillAST_VarDecl( %s %p struct ", nam, this ); + const char *type = astruct->getName(); + fprintf (stderr, "%s, name %s, arraypart %s parent ) %p\n", type, nam, array, this); // , par); + + vartype = strdup(type); + + // these always go together ?? + vardef = astruct;// pointer to the thing that says what is inside the struct + isStruct = true; // ?? wrong if it's a union ?? TODO + + //insideAStruct = false; + //fprintf(stderr, "setting vardef of %s to %p\n", nam, vardef); + + underlyingtype = parseUnderlyingType( vartype ); + //fprintf(stderr, "setting underlying type %s from %s\n", underlyingtype, vartype ); + varname = strdup(nam); + arraypart = strdup(array); + arraypointerpart = arraysetpart = NULL; + splitarraypart(); + + init = NULL; + numdimensions=0; arraysizes = NULL; + uniquePtr = NULL; + asttype = CHILLAST_NODETYPE_VARDECL; + parent = par; + + knownArraySizes = false; + //fprintf(stderr, "arraypart len %d\n", strlen(a)); + for (int i=0; iaddVariableToSymbolTable( this ); // should percolate up until something has a symbol table + + isFromSourceFile = true; // default + filename = NULL; + +}; + + + + + +chillAST_VarDecl::chillAST_VarDecl( chillAST_TypedefDecl *tdd, const char *n, const char *a, chillAST_node *par) { + fprintf(stderr, "4chillAST_VarDecl::chillAST_VarDecl( %s typedef ", n); + const char *type = tdd->getStructName(); + //fprintf (stderr, "%s, name %s, arraypart %s parent ) %p\n", type, n, a,this); // , par); + typedefinition = tdd; + vartype = strdup(type); + underlyingtype = parseUnderlyingType( vartype ); + //fprintf(stderr, "setting underlying type %s from %s\n", underlyingtype, vartype ); + varname = strdup(n); + arraypart = strdup(a); + arraypointerpart = arraysetpart = NULL; + splitarraypart(); + + init = NULL; + numdimensions=0; arraysizes = NULL; + uniquePtr = NULL; + asttype = CHILLAST_NODETYPE_VARDECL; + parent = par; + + knownArraySizes = false; + //fprintf(stderr, "arraypart len %d\n", strlen(a)); + for (int i=0; iisAStruct(); + + //insideAStruct = false; + + vardef = NULL; + + + isAParameter = false; + byreference = false; + isABuiltin = false; + isRestrict = isDevice = isShared = false; // //fprintf(stderr, "RDS = false\n"); + if (parent) parent->addVariableToSymbolTable( this ); // should percolate up until something has a symbol table + isFromSourceFile = true; // default + filename = NULL; +}; + + + + + +chillAST_VarDecl::chillAST_VarDecl( const char *t, const char *n, const char *a, void *ptr, chillAST_node *par) { + CHILL_DEBUG_PRINT("chillAST_VarDecl::chillAST_VarDecl( type %s, name %s, arraypart '%s' ) %p\n", t, n, a, this); + + + vartype = strdup(t); + typedefinition = NULL; + underlyingtype = parseUnderlyingType( vartype ); + //fprintf(stderr, "setting underlying type %s from %s\n", underlyingtype, vartype ); + varname = strdup(n); + + vardef = NULL; // not a struct + isStruct = false; + isAParameter = false; + + if (a) arraypart = strdup(a); + else arraypart = strdup(""); // should catch this earlier + arraypointerpart = arraysetpart = NULL; + splitarraypart(); + + init = NULL; + numdimensions=0; arraysizes = NULL; + uniquePtr = ptr; + asttype = CHILLAST_NODETYPE_VARDECL; + parent = par; + knownArraySizes = false; + + if (par) par->addChild(this); // ?? + + //fprintf(stderr, "name arraypart len %d\n", strlen(a)); + //fprintf(stderr, "arraypart '%s'\n", arraypart); + for (int i=0; iaddVariableToSymbolTable( this ); // should percolate up until something has a symbol table + + + isFromSourceFile = true; // default + filename = NULL; + + CHILL_DEBUG_PRINT("LEAVING\n"); + //parent->print(); fprintf(stderr, "\n\n"); + + +}; + + +void chillAST_VarDecl::print( int indent, FILE *fp ) { + //fprintf(fp, "chillAST_VarDecl::print()\n"); + + printPreprocBEFORE(indent, fp); + + //fprintf(fp, "VarDecl vartype '%s' varname %s ", vartype, varname); + //if (isAStruct()) fprintf(fp, "isAStruct()\n"); + //else fprintf(fp, "NOT A Struct\n"); + + // fprintf(fp, "\n"); fflush(fp); dump(0,fp); fflush(fp); // debug + + chillindent(indent, fp); + //fprintf(fp, "vardecl->print vartype '%s'\n", vartype); + if (isDevice) fprintf(fp, "__device__ "); + if (isShared) fprintf(fp, "__shared__ "); + + //if (isAStruct()) fprintf(fp, "/* isAStruct() */ "); + //else fprintf(fp, "/* NOT A Struct() */ "); + //if (vardef) fprintf(fp, "/* vardef */ "); + //else fprintf(fp, "/* NOT vardef */ "); + + + //fprintf(stderr, "chillAST_VarDecl::print() %s\n", varname ); + //if (isParmVarDecl()) fprintf(stderr, "%s is a parameter\n", varname); + //if (isAStruct()) fprintf(stderr, "%s is a struct\n", varname); + //else fprintf(stderr, "%s is NOT a struct\n", varname); + //if (!parent) fprintf(stderr, "VARDECL HAS NO PARENT\n"); + //else fprintf(stderr, "parent of %s is type %s\n", varname, parent->getTypeString()); + + // this logic is probably wrong (what about pointer to struct? ) + + //fprintf(stderr, "checking for unnamed only used here\n"); + + if ((!isAParameter) && isAStruct() && vardef) { // an unnamed struct used only here ?? + + //fprintf(fp, "i%s sAStruct() && vardef ?? vardecl of type UNNAMED ONLY USED HERE \n", varname ); + // print the internals of the struct and then the name + vardef->printStructure( 0, fp ); + fprintf(fp, "%s", varname ); + + return; + } + + //fprintf(fp, "ugly logic\n"); + // ugly logic TODO + + if (typedefinition && typedefinition->isAStruct()) fprintf(fp, "struct "); + + if (isAParameter) { + //fprintf(fp, "%s isaparameter\n", varname); + //if (isAStruct()) fprintf(fp, "struct "); + //fprintf(fp, "(param) nd %d", numdimensions ); + //dump(); + if (numdimensions > 0) { + if (knownArraySizes) { // just [12][34][56] + fprintf(fp, "%s ", vartype); + if (byreference) fprintf(fp, "&"); + fprintf(fp, "%s", varname); + for (int n=0; n< (numdimensions); n++) fprintf(fp, "[%d]", arraysizes[n]); + } + else { // some unknown array part float *a; or float **a; or float (*)a[1234] + + //fprintf(fp, "\nsome unknown\n"); + //fprintf(fp, "arraypointerpart '%s'\n", arraypointerpart); + //fprintf(fp, "arraysetpart '%s'\n", arraysetpart); + + if (numdimensions == 1) { + //fprintf(fp, "\nnd1, vartype %s\n", vartype); + + // TODO this if means I have probably made a mistake somewhere + if (!index(vartype, '*')) fprintf(fp, "%s *%s", vartype, varname ); // float *x + else fprintf(fp, "%s%s", vartype, varname); // float *a; + + + } + else { // more than one dimension + + if ( !strcmp("", arraysetpart) ) { // no known dimensions float ***a; + fprintf(fp, "%s %s%s", vartype, arraypointerpart, varname); + } + else if ( !strcmp("", arraypointerpart)) { // ALL known float a[2][7]; + fprintf(fp, "%s %s", vartype, varname); + for (int n=0; n< numdimensions; n++) fprintf(fp, "[%d]", arraysizes[n]); + } + else { // float (*)a[1234] + // this seems really wrong + // float (*)a[1234] + fprintf(fp, "%s (", vartype); + for (int n=0; n< (numdimensions-1); n++) fprintf(fp, "*"); + fprintf(fp, "%s)", varname); + fprintf(fp, "[%d]", arraysizes[numdimensions-1]); + } + + } + } + } // if numdimensions > 0 + else { // parameter float x + fprintf(fp, "%s ", vartype); + if (byreference) fprintf(fp, "&"); + fprintf(fp, "%s", varname); + } + } // end parameter + + else { // NOT A PARAMETER + //fprintf(fp, "NOT A PARAM ... vartype '%s'\n", vartype); + //if (isArray()) fprintf(stderr, "an array, numdimensions %d\n", numdimensions); + //fprintf(stderr, "arraysizes %p\n", arraysizes); + + + + //if (isArray() && arraysizes == NULL) { + // // we just know the number of dimensions but no sizes + // // int ***something + // fprintf(fp, "%s ", vartype); // "int " + // for (int i=0; igetStructDef(); + return NULL; +} + + + + + +chillAST_CompoundStmt::chillAST_CompoundStmt() { + //fprintf(stderr, "chillAST_CompoundStmt::chillAST_CompoundStmt() %p\n", this); + asttype = CHILLAST_NODETYPE_COMPOUNDSTMT; + parent = NULL; + symbol_table = new chillAST_SymbolTable; + typedef_table = NULL; + isFromSourceFile = true; // default + filename = NULL; +}; + + +void chillAST_CompoundStmt::print( int indent, FILE *fp ) { + printPreprocBEFORE(indent, fp); + int numchildren = children.size(); + //fprintf(stderr, "NUMCHILDREN %d\n", numchildren); sleep(1); + for (int i=0; iprint(indent, fp); + if (children[i]->asttype != CHILLAST_NODETYPE_FORSTMT + && children[i]->asttype != CHILLAST_NODETYPE_IFSTMT + && children[i]->asttype != CHILLAST_NODETYPE_COMPOUNDSTMT + //&& children[i]->asttype != CHILLAST_NODETYPE_VARDECL // vardecl does its own ";\n" + ) + { + fprintf(fp, ";\n"); // probably wrong + } + } + fflush(fp); +} + +void chillAST_CompoundStmt::replaceChild( chillAST_node *old, chillAST_node *newchild ){ + //fprintf(stderr, "chillAST_CompoundStmt::replaceChild( old %s, new %s)\n", old->getTypeString(), newchild->getTypeString() ); + vector dupe = children; + int numdupe = dupe.size(); + int any = 0; + + for (int i=0; igetTypeString()); + //} + + + if (dupe[i] == old) { + //fprintf(stderr, "replacing child %d of %d\n", i, numdupe); + //fprintf(stderr, "was \n"); print(); + children[i] = newchild; + newchild->setParent( this ); + //fprintf(stderr, "is \n"); print(); fprintf(stderr, "\n\n"); + // old->parent = NULL; + any = 1; + } + } + + if (!any) { + fprintf(stderr, "chillAST_CompoundStmt::replaceChild(), could not find old\n"); + exit(-1); + } +} + + +void chillAST_CompoundStmt::loseLoopWithLoopVar( char *var ) { + //fprintf(stderr, "chillAST_CompoundStmt::loseLoopWithLoopVar( %s )\n", var); + + //fprintf(stderr, "CompoundStmt 0x%x has parent 0x%x ", this, this->parent); + //fprintf(stderr, "%s\n", parent->getTypeString()); + + + //fprintf(stderr, "CompoundStmt node has %d children\n", children.size()); + //fprintf(stderr, "before doing a damned thing, \n"); + //print(); + //dump(); fflush(stdout); + //fprintf(stderr, "\n\n"); + +#ifdef DAMNED + for (int j=0; jasttype); + fprintf(stderr, "%s ", children[j]->getTypeString()); + if (children[j]->isForStmt()) { + chillAST_ForStmt *FS = ((chillAST_ForStmt *) children[j]); + fprintf(stderr, "for ("); + FS->init->print(0, stderr); + fprintf(stderr, "; "); + FS->cond->print(0, stderr); + fprintf(stderr, "; "); + FS->incr->print(0, stderr); + fprintf(stderr, ") with %d statements in body 0x%x\n", FS->body->getNumChildren(), FS->body ); + } + else fprintf(stderr, "\n"); + } +#endif + + + vector dupe = children; // simple enough? + for (int i=0; igetTypeString()); + // if (children[j]->isForStmt()) { + // chillAST_ForStmt *FS = ((chillAST_ForStmt *) children[j]); + // fprintf(stderr, "for ("); + // FS->init->print(0, stderr); + // fprintf(stderr, "; "); + // FS->cond->print(0, stderr); + // fprintf(stderr, "; "); + // FS->incr->print(0, stderr); + // fprintf(stderr, ") with %d statements in body 0x%x\n", FS->body->getNumChildren(), FS->body ); + //} + //else fprintf(stderr, "\n"); + //} + + //fprintf(stderr, "CompoundStmt 0x%x recursing to child %d/%d\n", this, i, dupe.size()); + dupe[i]->loseLoopWithLoopVar( var ); + } + //fprintf(stderr, "CompoundStmt node 0x%x done recursing\n", this ); +} + + + +void chillAST_CompoundStmt::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(CompoundStmt \n" ); + int numchildren = children.size(); + + //for (int i=0; igetTypeString(), children[i]); + //} + //fprintf(fp, "\n"); + + for (int i=0; idump(indent+1, fp); + fprintf(fp, "\n"); // ??? + fflush(fp); + } + chillindent(indent, fp); + fprintf(fp, ")\n"); +}; + + + +chillAST_node* chillAST_CompoundStmt::constantFold(){ + //fprintf(stderr, "chillAST_CompoundStmt::constantFold()\n"); + for (int i=0; iconstantFold(); + return this; +} + + +chillAST_node* chillAST_CompoundStmt::clone(){ + chillAST_CompoundStmt *cs = new chillAST_CompoundStmt(); + for (int i=0; iaddChild( children[i]->clone() ); + cs->setParent( parent ); + cs->isFromSourceFile = isFromSourceFile; + if (filename) cs->filename = strdup(filename); + return cs; +} + + +void chillAST_CompoundStmt::gatherVarDecls( vector &decls ) { + //fprintf(stderr, "chillAST_CompoundStmt::gatherVarDecls()\n"); + for (int i=0; igatherVarDecls( decls ); +} + + +void chillAST_CompoundStmt::gatherScalarVarDecls( vector &decls ) { + for (int i=0; igatherScalarVarDecls( decls ); +} + + +void chillAST_CompoundStmt::gatherArrayVarDecls( vector &decls ) { + for (int i=0; igatherArrayVarDecls( decls ); +} + + +void chillAST_CompoundStmt::gatherDeclRefExprs( vector&refs ) { + for (int i=0; igatherDeclRefExprs( refs ); +} + + +void chillAST_CompoundStmt::gatherVarUsage( vector &decls ) { + for (int i=0; igatherVarUsage( decls ); +} + + +void chillAST_CompoundStmt::gatherArrayRefs( std::vector &refs, bool writtento ) { + for (int i=0; igatherArrayRefs( refs, 0); +} + +void chillAST_CompoundStmt::gatherScalarRefs( std::vector &refs, bool writtento ) { + for (int i=0; igatherScalarRefs( refs, 0); +} + +void chillAST_CompoundStmt::gatherStatements(std::vector &statements ){ + for (int i=0; igatherStatements( statements ); +} + + + +void chillAST_CompoundStmt::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ + for (int i=0; ireplaceVarDecls( olddecl, newdecl ); +} + + +bool chillAST_CompoundStmt::findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync ) { + + // see how many elements we currently have + int sofar = children.size(); + + // make big enough to add a sync after each statement. wasteful. TODO + // this prevents inserts happening at the forstmt::addSync() from causing a + // reallocation, which screwsup the loop below here + children.reserve( 2 * sofar ); + //fprintf(stderr, "sofar %d reserved %d\n", sofar, 2*sofar); + + bool force = false; + for (int i=0; i sofar ) { + //fprintf(stderr, "HEY! CompoundStmt::findLoopIndexesToReplace() noticed that children increased from %d to %d\n", sofar, children.size()); + sofar = children.size(); + } + + //fprintf(stderr, "compound child %d of type %s force %d\n", i, children[i]->getTypeString(), force ); + bool thisforces = children[i]->findLoopIndexesToReplace( symtab, force ); + force = force || thisforces; // once set, always + } + + return false; + +/* + vector childrencopy; + for (int i=0; igetTypeString() ); + origtypes[i] = strdup( children[i]->getTypeString() ); + fprintf(stderr, "ORIGINAL compound child %d of type %s\n", i, children[i]->getTypeString() ); + } + + for (int i=0; igetTypeString(), force ); + force = force || childrencopy[i]->findLoopIndexesToReplace( symtab, force ); // once set, always + } + + fprintf(stderr, "\n"); + for (int i=0; igetTypeString() ); + } + + return false; +*/ +} + + + + + +chillAST_ParenExpr::chillAST_ParenExpr( chillAST_node *sub, chillAST_node *par ){ + subexpr = sub; + subexpr->setParent( this ); + asttype = CHILLAST_NODETYPE_PARENEXPR; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +void chillAST_ParenExpr::print( int indent, FILE *fp ) { + //fprintf(stderr, "chillAST_ParenExpr::print()\n"); + chillindent(indent, fp); // hard to believe this will ever do anything + fprintf(fp, "(" ); + subexpr->print( 0, fp ); + fprintf(fp, ")" ); + fflush(fp); +} + +void chillAST_ParenExpr::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(ParenExpr \n"); + subexpr->dump( indent+1, fp ); + chillindent(indent, fp); + fprintf(fp, ")\n"); +} + + +void chillAST_ParenExpr::gatherArrayRefs( std::vector &refs, bool writtento ) { + subexpr->gatherArrayRefs( refs, writtento ); +} + +void chillAST_ParenExpr::gatherScalarRefs( std::vector &refs, bool writtento ) { + subexpr->gatherScalarRefs( refs, writtento ); +} + + + +chillAST_node* chillAST_ParenExpr::constantFold() { + subexpr = subexpr->constantFold(); + return this; +} + + +chillAST_node* chillAST_ParenExpr::clone() { + chillAST_ParenExpr *PE = new chillAST_ParenExpr( subexpr->clone(), NULL ); + PE->isFromSourceFile = isFromSourceFile; + if (filename) PE->filename = strdup(filename); + return PE; +} + +void chillAST_ParenExpr::gatherVarDecls( vector &decls ) { + subexpr->gatherVarDecls( decls ); +} + + +void chillAST_ParenExpr::gatherScalarVarDecls( vector &decls ) { + subexpr->gatherScalarVarDecls( decls ); +} + + +void chillAST_ParenExpr::gatherArrayVarDecls( vector &decls ) { + subexpr->gatherArrayVarDecls( decls ); +} + + +void chillAST_ParenExpr::gatherDeclRefExprs( vector&refs ) { + subexpr->gatherDeclRefExprs( refs ); +} + +void chillAST_ParenExpr::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ + subexpr->replaceVarDecls( olddecl, newdecl ); +} + +void chillAST_ParenExpr::gatherVarUsage( vector &decls ) { + subexpr->gatherVarUsage( decls ); +} + + + +chillAST_Sizeof::chillAST_Sizeof( char *athing, chillAST_node *par ){ + thing = strdup( athing ); // memory leak + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +void chillAST_Sizeof::print( int indent, FILE *fp ) { + //fprintf(stderr, "chillAST_Sizeof::print()\n"); + chillindent(indent, fp); // hard to believe this will ever do anything + fprintf(fp, "sizeof(" ); + fprintf(fp, "%s)", thing ); + fflush(fp); +} + + +void chillAST_Sizeof::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(Sizeof %s )\n", thing); +} + +void chillAST_Sizeof::gatherArrayRefs( std::vector &refs, bool writtento ) {} +void chillAST_Sizeof::gatherScalarRefs( std::vector &refs, bool writtento ) {} + +chillAST_node* chillAST_Sizeof::constantFold() { + return this; +} + +chillAST_node* chillAST_Sizeof::clone() { + chillAST_Sizeof *SO = new chillAST_Sizeof( thing, NULL ); + SO->isFromSourceFile = isFromSourceFile; + if (filename) SO->filename = strdup(filename); + return SO; +} + +void chillAST_Sizeof::gatherVarDecls( vector &decls ) { // TODO +} + + +void chillAST_Sizeof::gatherScalarVarDecls( vector &decls ) { // TODO +} + + +void chillAST_Sizeof::gatherArrayVarDecls( vector &decls ) { // TODO +} + + +void chillAST_Sizeof::gatherDeclRefExprs( vector&refs ) { + // TODO +} + + +void chillAST_Sizeof::gatherVarUsage( vector &decls ) { +} + + +void insertNewDeclAtLocationOfOldIfNeeded( chillAST_VarDecl *newdecl, chillAST_VarDecl *olddecl) { + //fprintf(stderr, "insertNewDeclAtLocationOfOldIfNeeded( new 0x%x old 0x%x\n", newdecl, olddecl ); + + if (newdecl == NULL || olddecl == NULL) { + fprintf(stderr, "chill_ast.cc insertNewDeclAtLocationOfOldIfNeeded() NULL decl\n"); + exit(-1); + } + + if (newdecl == olddecl) return; + + newdecl->vartype = strdup(olddecl->vartype); + + chillAST_node *newparent = newdecl->parent; + chillAST_node *oldparent = olddecl->parent; + //fprintf(stderr, "newparent 0x%x oldparent 0x%x\n", newparent, oldparent ); + if (newparent == oldparent) return; + + if (newparent != NULL) + //fprintf(stderr, "chill_ast.cc insertNewDeclAtLocationOfOldIfNeeded() new decl already has parent?? probably wrong\n"); + newdecl->parent = oldparent; // will be true soon + + // find actual location of old decl and insert new one there + //fprintf(stderr, "oldparent is of type %s\n", oldparent->getTypeString()); // better be compoundstmt ?? + vector children = oldparent->getChildren(); + + int numchildren = children.size(); + //fprintf(stderr, "oldparent has %d children\n", numchildren); + + if (numchildren == 0) { + fprintf(stderr, "chill_ast.cc insertNewDeclAtLocationOfOldIfNeeded() impossible number of oldparent children (%d)\n", numchildren); + exit(-1); + } + + bool newalreadythere = false; + int index = -1; + //fprintf(stderr, "olddecl is 0x%x\n", olddecl); + //fprintf(stderr, "I know of %d variables\n", numchildren); + for (int i=0; igetChild(i); + //fprintf(stderr, "child %d @ 0x%x is of type %s\n", i, child, child->getTypeString()); + if (children[i] == olddecl) { + index = i; + //fprintf(stderr, "found old decl at index %d\n", index); + } + if (children[i] == newdecl) { + newalreadythere = true; + //fprintf(stderr, "new already there @ index %d\n", i); + } + } + if (index == -1) { + fprintf(stderr, "chill_ast.cc insertNewDeclAtLocationOfOldIfNeeded() can't find old decl for %s\n", olddecl->varname); + exit(-1); + } + + if (!newalreadythere) oldparent->insertChild( index, newdecl ); + +} + + +void gatherVarDecls( vector &code, vector &decls) { + //fprintf(stderr, "gatherVarDecls()\n"); + + int numcode = code.size(); + //fprintf(stderr, "%d top level statements\n", numcode); + for (int i=0; igatherVarDecls( decls ); + } + +} + + +void gatherVarUsage( vector &code, vector &decls) { + //fprintf(stderr, "gatherVarUsage()\n"); + + int numcode = code.size(); + //fprintf(stderr, "%d top level statements\n", numcode); + for (int i=0; igatherVarUsage( decls ); + } + +} + + + + +chillAST_IfStmt::chillAST_IfStmt() { + cond = thenpart = elsepart = NULL; + asttype = CHILLAST_NODETYPE_IFSTMT; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_IfStmt::chillAST_IfStmt(chillAST_node *c, chillAST_node *t, chillAST_node *e, chillAST_node *p){ + cond = c; + if (cond) cond->setParent( this ); + thenpart = t; + if (thenpart) thenpart->setParent( this ); + elsepart = e; + if (elsepart) elsepart->setParent( this ); + parent = p; + asttype = CHILLAST_NODETYPE_IFSTMT; + isFromSourceFile = true; // default + filename = NULL; +} + +void chillAST_IfStmt::gatherVarDecls( vector &decls ) { + if (cond) cond->gatherVarDecls( decls ); + if (thenpart) thenpart->gatherVarDecls( decls ); + if (elsepart) elsepart->gatherVarDecls( decls ); +} + + +void chillAST_IfStmt::gatherScalarVarDecls( vector &decls ) { + if (cond) cond->gatherScalarVarDecls( decls ); + if (thenpart) thenpart->gatherScalarVarDecls( decls ); + if (elsepart) elsepart->gatherScalarVarDecls( decls ); +} + + +void chillAST_IfStmt::gatherArrayVarDecls( vector &decls ) { + if (cond) cond->gatherArrayVarDecls( decls ); + if (thenpart) thenpart->gatherArrayVarDecls( decls ); + if (elsepart) elsepart->gatherArrayVarDecls( decls ); +} + + +void chillAST_IfStmt::gatherDeclRefExprs( vector&refs ) { + if (cond) cond->gatherDeclRefExprs( refs ); + if (thenpart) thenpart->gatherDeclRefExprs( refs ); + if (elsepart) elsepart->gatherDeclRefExprs( refs ); +} + + +void chillAST_IfStmt::gatherVarUsage( vector &decls ) { + if (cond) cond->gatherVarUsage( decls ); + if (thenpart) thenpart->gatherVarUsage( decls ); + if (elsepart) elsepart->gatherVarUsage( decls ); +} + + +void chillAST_IfStmt::gatherArrayRefs( std::vector &refs, bool writtento ) { + cond->gatherArrayRefs( refs, 0 ); // 0 ?? + thenpart->gatherArrayRefs( refs, 0 ); // 0 ?? + if (elsepart) elsepart->gatherArrayRefs( refs, 0 ); // 0 ?? +} + +void chillAST_IfStmt::gatherScalarRefs( std::vector &refs, bool writtento ) { + cond->gatherScalarRefs( refs, 0 ); // 0 ?? + thenpart->gatherScalarRefs( refs, 0 ); // 0 ?? + if (elsepart) elsepart->gatherScalarRefs( refs, 0 ); // 0 ?? +} + + +chillAST_node *chillAST_IfStmt::constantFold() { + if (cond) cond = cond->constantFold(); + if (thenpart) thenpart = thenpart->constantFold(); + if (elsepart) elsepart = elsepart->constantFold(); + return this; +} + +void chillAST_IfStmt::gatherStatements(std::vector &statements ){ + + //print(); printf("\n"); fflush(stdout); + thenpart->gatherStatements( statements ); + //fprintf(stderr, "ifstmt, after then, %d statements\n", statements.size()); + if (elsepart){ + //fprintf(stderr, "there is an elsepart of type %s\n", elsepart->getTypeString()); + elsepart->gatherStatements( statements ); + } + //fprintf(stderr, "ifstmt, after else, %d statements\n", statements.size()); +} + + + +chillAST_node *chillAST_IfStmt::clone() { + chillAST_node *c, *t, *e; + c = t = e = NULL; + if (cond) c = cond->clone(); // has to be one, right? + if (thenpart) t = thenpart->clone(); + if (elsepart) e = elsepart->clone(); + + chillAST_IfStmt *IS = new chillAST_IfStmt( c, t, e, parent); + IS->isFromSourceFile = isFromSourceFile; + if (filename) IS->filename = strdup(filename); + return IS; +} + + + +void chillAST_IfStmt::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(if "); + fprintf(fp, "\n"); + + cond->dump(indent+1, fp); + fprintf(fp, "\n"); + + thenpart->dump(indent+1, fp); + fprintf(fp, "\n"); + + if (elsepart) { + elsepart->dump(indent+1, fp); + fprintf(fp, "\n"); + } + chillindent(indent, fp); + fprintf(fp, ")\n"); +} + + + +void chillAST_IfStmt::print(int indent, FILE *fp ) { + printPreprocBEFORE(indent, fp); + chillindent(indent, fp); + fprintf(fp, "if ("); + if (cond) cond->print(0, fp); + else fprintf(fp, "(NULL cond)"); + + bool needbracket = true; + if (thenpart) { + if (thenpart->isBinaryOperator()) needbracket = false; + if (thenpart->isCompoundStmt()) { // almost always true + chillAST_CompoundStmt *CS = (chillAST_CompoundStmt*) thenpart; + if (CS->children.size() == 1 && CS->children[0]->isBinaryOperator()) needbracket = false; + } + + if(needbracket) fprintf(fp, ") {\n"); + else fprintf(fp, ")\n"); + + thenpart->print(indent+1, fp); // end of line + + if(needbracket) { + //fprintf(fp, "\n"); + chillindent(indent, fp); + fprintf(fp, "}\n"); + } + } + else fprintf(fp, "(NULL thenpart)"); + + + needbracket = true; + if (elsepart) { + if (elsepart->isBinaryOperator()) needbracket = false; + if (elsepart->isCompoundStmt()) { // almost always true + chillAST_CompoundStmt *CS = (chillAST_CompoundStmt*) elsepart; + + if (CS->children.size() == 1 && CS->children[0]->isBinaryOperator()) needbracket = false; + + } + + fprintf(fp, "\n"); + chillindent(indent, fp); + + if (needbracket) fprintf(fp, "else {\n"); + else fprintf(fp, "else\n"); + + elsepart->print(indent+1, fp); + + if(needbracket) { + fprintf(fp, "\n"); + chillindent(indent, fp); + fprintf(fp, "}\n"); + } + } + //else fprintf(fp, "else { /* NOTHING */ }"); +} + + + +bool chillAST_IfStmt::findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync ) { + thenpart->findLoopIndexesToReplace( symtab ); + elsepart->findLoopIndexesToReplace( symtab ); + return false; // ?? +} + + + +chillAST_node *lessthanmacro( chillAST_node *left, chillAST_node *right) { + + chillAST_ParenExpr *lp1 = new chillAST_ParenExpr( left ); + chillAST_ParenExpr *rp1 = new chillAST_ParenExpr( right ); + chillAST_BinaryOperator *cond = new chillAST_BinaryOperator( lp1, "<", rp1 ); + + chillAST_ParenExpr *lp2 = new chillAST_ParenExpr( left ); + chillAST_ParenExpr *rp2 = new chillAST_ParenExpr( right ); + + chillAST_TernaryOperator *t = new chillAST_TernaryOperator("?", cond, lp2, rp2); + + return t; +} + + + + +// look for function declaration with a given name, in the tree with root "node" +void findFunctionDeclRecursive( chillAST_node *node, const char *procname, vector& funcs ) +{ + //fprintf(stderr, "findmanually() CHILL AST node of type %s\n", node->getTypeString()); + + if (node->isFunctionDecl()) { + char *name = ((chillAST_FunctionDecl *) node)->functionName; // compare name with desired name + //fprintf(stderr, "node name 0x%x ", name); + //fprintf(stderr, "%s procname ", name); + //fprintf(stderr, "0x%x ", procname); + //fprintf(stderr, "%s\n", procname); + if (!strcmp( name, procname)) { + //fprintf(stderr, "found procedure %s\n", procname ); + funcs.push_back( (chillAST_FunctionDecl*) node ); // this is it + // quit recursing. probably not correct in some horrible case + return; + } + //else fprintf(stderr, "this is not the function we're looking for\n"); + } + + + // this is where the children can be used effectively. + // we don't really care what kind of node we're at. We just check the node itself + // and then its children is needed. + + int numc = node->children.size(); + fprintf(stderr, "(top)node has %d children\n", numc); + + for (int i=0; iisSourceFile()) { + fprintf(stderr, "node of type %s is recursing to child %d of type %s\n", node->getTypeString(), i, node->children[i]->getTypeString()); + if (node->children[i]->isFunctionDecl()) { + chillAST_FunctionDecl *fd = (chillAST_FunctionDecl*) node->children[i]; + fprintf(stderr, "child %d is functiondecl %s\n", i, fd->functionName); + } + } + findFunctionDeclRecursive( node->children[i], procname, funcs ); + + } + return; +} + + +chillAST_FunctionDecl *findFunctionDecl( chillAST_node *node, const char *procname) +{ + vector functions; + findFunctionDeclRecursive( node, procname, functions ); + + if ( functions.size() == 0 ) { + fprintf(stderr, "could not find function named '%s'\n", procname); + exit(-1); + } + + if ( functions.size() > 1 ) { + fprintf(stderr, "oddly, found %d functions named '%s'\n", functions.size(), procname); + fprintf(stderr, "I am unsure what to do\n"); + + for (int f = 0; f < functions.size(); f++) { + fprintf(stderr, "function %d %p %s\n", f, functions[f], functions[f]->functionName); + } + exit(-1); + } + + //fprintf(stderr, "found the procedure named %s\n", procname); + return functions[0]; +} + + +chillAST_SymbolTable *addSymbolToTable( chillAST_SymbolTable *st, chillAST_VarDecl *vd ) // definition +{ + chillAST_SymbolTable *s = st; + if (!s) s = new chillAST_SymbolTable; + + int tablesize = s->size(); + + for (int i=0; ivarname, vd->varname); + if (!strcmp( (*s)[i]->varname, vd->varname)) { + //fprintf(stderr, "symbol with the same name was already there\n"); + return s; // already there + } + } + + //fprintf(stderr, "adding %s %s to a symbol table that didn't already have it\n", vd->vartype, vd->varname); + + //printf("before:\n"); + //printSymbolTable( s ); fflush(stdout); + + s->push_back(vd); // add it + + //printf("after:\n"); + //printSymbolTable( s ); fflush(stdout); + return s; +} + + +chillAST_TypedefTable *addTypedefToTable( chillAST_TypedefTable *tdt, chillAST_TypedefDecl *td ) +{ + + chillAST_TypedefTable *t = tdt; + if (!t) t = new chillAST_TypedefTable; + + int tablesize = t->size(); + + for (int i=0; ipush_back(td); // add it + return t; +} + + +chillAST_NoOp::chillAST_NoOp( chillAST_node *p ) { + parent = p; + isFromSourceFile = true; // default + filename = NULL; +}; // so we have SOMETHING for NoOp in the cc file ??? + + +chillAST_Preprocessing::chillAST_Preprocessing() { + position = CHILL_PREPROCESSING_POSITIONUNKNOWN; + pptype = CHILL_PREPROCESSING_TYPEUNKNOWN; + blurb = strdup(""); // never use null. ignore the leak ?? +} + + + chillAST_Preprocessing::chillAST_Preprocessing(CHILL_PREPROCESSING_POSITION pos, + CHILL_PREPROCESSING_TYPE t, + char *text ) + { + position = pos; + pptype = t; + blurb = strdup( text ); + } + +void chillAST_Preprocessing::print( int indent, FILE *fp ) { // probably very wrong + if (position == CHILL_PREPROCESSING_LINEAFTER ) { + fprintf(fp, "\n"); + chillindent(indent, fp); + } + if (position == CHILL_PREPROCESSING_LINEBEFORE) { // ??? + //fprintf(fp, "\n"); + chillindent(indent, fp); + } + + fprintf(fp, "%s", blurb); + + if (position == CHILL_PREPROCESSING_TOTHERIGHT) { + fprintf(fp, "\n"); + } + + + if (position == CHILL_PREPROCESSING_LINEBEFORE) { + //fprintf(fp, "\n"); // comment seems to have \n at the end already + //chillindent(indent, fp); + } + + + //if (pptype != CHILL_PREPROCESSING_IMMEDIATELYBEFORE && pptype != CHILL_PREPROCESSING_UNKNOWN) fprint(fp, "\n"); + + } diff --git a/src/chill_ast.cc b/src/chill_ast.cc deleted file mode 100644 index 978e303..0000000 --- a/src/chill_ast.cc +++ /dev/null @@ -1,6493 +0,0 @@ - - - -#include "chill_ast.hh" - -using namespace std; - -int chillAST_node::chill_scalar_counter = 0; -int chillAST_node::chill_array_counter = 1; - - -const char* Chill_AST_Node_Names[] = { - "Unknown AST node type", - "SourceFile", - "TypedefDecl", - "VarDecl", - // "ParmVarDecl", not used any more - "FunctionDecl", - "RecordDecl", - "MacroDefinition", - "CompoundStmt", - "ForStmt", - "TernaryOperator", - "BinaryOperator", - "UnaryOperator", - "ArraySubscriptExpr", - "MemberExpr", - "DeclRefExpr", - "IntegerLiteral", - "FloatingLiteral", - "ImplicitCastExpr", // not sure we need this - "ReturnStmt", - "CallExpr", - "DeclStmt", - "ParenExpr", - "CStyleCastExpr", - "CStyleAddressOf", - "IfStmt", - "SizeOf", - "Malloc", - "Free", - "NoOp", -// CUDA specific - "CudaMalloc", - "CudaFree", - "CudaMemcpy", - "CudaKernelCall", - "CudaSyncthreads", - "fake1", - "fake2", - "fake3" -}; - -char *parseUnderlyingType( char *sometype ) { - int len = strlen(sometype); - //fprintf(stderr, "parseUnderlyingType( %s )\n", sometype); - char *underlying = strdup(sometype); - char *p; - char *start = underlying; - - // ugly. we want to turn "float *" into "float" but "struct abc *" into struct abc. - // there are probably many more cases. have an approved list? TODO - if (strstr(underlying, "struct ")) start += 7; // (length("struct ")) - //fprintf(stderr, "sometype '%s' start '%s'\n", sometype, start); - if (p = index(start, ' ')) *p = '\0'; // end at first space leak - if (p = index(start, '[')) *p = '\0'; // leak - if (p = index(start, '*')) *p = '\0'; // leak - - return underlying; -} - -void printSymbolTable( chillAST_SymbolTable *st ) { - //printf("%d entries\n", st->size()); - if (!st) return; - for (int i=0; isize(); i++) { printf("%d ", i ); (*st)[i]->printName(); printf("\n"); } - if (st->size() )printf("\n"); - fflush(stdout); -} - -void printSymbolTableMoreInfo( chillAST_SymbolTable *st ) { - //printf("%d entries\n", st->size()); - if (!st) return; - for (int i=0; isize(); i++) { printf("%d ", i ); (*st)[i]->print(); printf("\n"); } - if (st->size() )printf("\n"); - fflush(stdout); -} - - -bool symbolTableHasVariableNamed( chillAST_SymbolTable *table, const char *name ) { - if (!table) return false; // ?? - int numvars = table->size(); - for (int i=0; ivarname)) return true; // need to check type? - } - return false; -} - - - -chillAST_VarDecl *symbolTableFindVariableNamed( chillAST_SymbolTable *table, const char *name ){ // fwd decl TODO too many similar named functions - if (!table) return NULL; // ?? - - // see if name has a dot or arrow (->) indicating that it is a structure/class - const char *cdot = strstr( name, "." ); - const char *carrow = strstr(name, "->"); // initial 'c' for const - can't change those - - char *varname; - char *subpart = NULL; - - if (cdot || carrow) { - fprintf(stderr, "symbolTableFindVariableNamed(), name '%s' looks like a struct\n", name); - - // so, look for the first part in the symbol table. - // warning, this could be looking for a->b.c.d->e.f->g - varname = strdup( name ); - - char *dot = strstr(varname, "." ); - char *arrow = strstr( varname, "->" ); - if (dot != NULL && arrow != NULL ) { // dot AND arrow, - fprintf(stderr, "chillast.cc symbolTableFindVariableNamed(), name '%s' has both dot and arrow? TODO\n"); - exit(-1); - } - else if (dot != NULL && !arrow) { // just dot(s). dot points to the first one - //fprintf(stderr, "name '%s' has dot(s)\n", varname); - *dot = '\0'; // end string at the dot - subpart = &(dot[1]); - fprintf(stderr, "will now look for a struct/class named %s that has member %s\n", varname, subpart); - - } - else if (arrow != NULL && !dot) { // just arrow(s) arrow points to the first one - //fprintf(stderr, "name '%s' has arrow(s)\n", varname); - *arrow = '\0'; // end string at the arrow - subpart = &(arrow[2]); - fprintf(stderr, "will now look for a struct/class named %s that has member %s\n", varname, subpart); - } - else { // impossible - fprintf(stderr, "chillast.cc symbolTableFindVariableNamed(), varname '%s', looks like a struct, but I can't figure it out\n", varname); - exit(-1); - } - } - else { - varname = strdup(name); - } - - int numvars = table->size(); - for (int i=0; ivarname)) { - fprintf(stderr, "found variable named %s\n", varname); - - if (!subpart) return vd; // need to check type? - - // OK, we have a variable, which looks like a struct/class, and a subpart that is some member names - //fprintf(stderr, "but I don't know how to check if it has member %s\n", subpart); - - char *dot = strstr(subpart, "." ); - char *arrow = strstr(subpart, "->" ); - - if (!dot && !arrow) { // whew, only one level of struct - //fprintf(stderr, "whew, only one level of struct\n"); - - // make sure this variable definition is a struct - if (vd->isAStruct()) { - //fprintf(stderr, "%s is a struct of type %s\n", varname, vd->getTypeString()); - if (vd->isVarDecl()) { - chillAST_RecordDecl *rd = vd->getStructDef(); - if (rd) { - //fprintf(stderr, "has a recordDecl\n"); - - chillAST_VarDecl *sp = rd->findSubpart( subpart ); - if (sp) fprintf(stderr, "found a struct member named %s\n", subpart); - else fprintf(stderr, "DIDN'T FIND a struct member named %s\n", subpart); - return sp; // return the subpart?? - } - else { - fprintf(stderr, "no recordDecl\n"); - exit(-1); - } - } - else { - fprintf(stderr, "NOT a VarDecl???\n"); // impossible - } - } - else { - fprintf(stderr, "false alarm. %s is a variable, but doesn't have subparts\n", varname); - return NULL; // false alarm. a variable of the correct name exists, but is not a struct - } - } - - fprintf(stderr, "chillast.cc symbolTableFindVariableNamed(), name '%s' can't figure out multiple levels of struct yet!\n"); - - exit(-1); - } - } - return NULL; -} - - - -char *ulhack( char *brackets ) // remove UL from numbers, MODIFIES the argument! -{ - //fprintf(stderr, "ulhack( \"%s\" -> ", brackets); - // another hack. remove "UL" from integers - int len = strlen(brackets); - for (int i=0; i< len-2; i++) { - if (isdigit(brackets[i])) { - if (brackets[i+1] == 'U' && brackets[i+2] == 'L') { - // remove - for (int j=i+3; j %s\n", sometype, arraypart); - return arraypart; -} - - - - - - - -char *splitTypeInfo( char *underlyingtype ) { // return the bracketed part of a type - char *ap = ulhack(parseArrayParts( underlyingtype )); // return this - - // now need to remove all that from the underlyingtype to get - char *arraypart = strdup(""); // leak - if (index(underlyingtype, '[')) { - // looks like an array - free(arraypart); - char *start = index(underlyingtype, '['); // wrong. can have int *buh[32] - arraypart = strdup( start ); - if (*(start-1) == ' ') start--; // hack - *start = '\0'; - - // ugly. very leaky - strcpy( underlyingtype, parseUnderlyingType( underlyingtype )); - - // ulhack( arraypart ); - } - return ap; // leak unless caller frees this -} - - - -bool isRestrict( const char *sometype ) { // does not modify sometype - string r( "__restrict__" ); - string t( sometype ); - return (std::string::npos != t.find( r ) ); -} - - - -bool streq( const char *a, const char *b) { return !strcmp(a,b); }; // slightly less ugly // TODO enums - -void chillindent( int howfar, FILE *fp ) { for (int i=0; ifindVariableNamed( name ); -} - - -chillAST_RecordDecl * chillAST_node::findRecordDeclNamed( const char *name ) { // recursive - fprintf(stderr, "%s::findRecordDeclNamed( %s )\n", getTypeString(), name); - // look in children - int numchildren = children.size(); - fprintf(stderr, "%d children\n", numchildren); - for (int i=0; igetTypeString()); - if (children[i]->isRecordDecl()) { - chillAST_RecordDecl *RD = (chillAST_RecordDecl *)children[i]; - fprintf(stderr, "it is a recordDecl named '%s' vs '%s'\n", RD->getName(), name); - if (!strcmp( RD->getName(), name )) { - fprintf(stderr, "FOUND IT\n"); - return RD; - } - } - } - - if (!parent) return NULL; // no more recursion available - // recurse upwards - return parent->findRecordDeclNamed( name ); -} - - -void chillAST_node::printPreprocBEFORE( int indent, FILE *fp ) { - int numstmts = preprocessinginfo.size(); - //if (0 != numstmts) { - // fprintf(fp, "chillAST_node::printPreprocBEFORE() %d statements\n", numstmts); - //} - - - for (int i=0; i< numstmts; i++) { - //fprintf(fp, "stmt %d %d\n", i, preprocessinginfo[i]->position); - if (preprocessinginfo[i]->position == CHILL_PREPROCESSING_LINEBEFORE || - preprocessinginfo[i]->position == CHILL_PREPROCESSING_IMMEDIATELYBEFORE) { - //fprintf(stderr, "before %d\n", preprocessinginfo[i]->position); - preprocessinginfo[i]->print(indent, fp); - } - } -} - -void chillAST_node::printPreprocAFTER( int indent, FILE *fp ) { - for (int i=0; i< preprocessinginfo.size(); i++) { - if (preprocessinginfo[i]->position == CHILL_PREPROCESSING_LINEAFTER || - preprocessinginfo[i]->position == CHILL_PREPROCESSING_TOTHERIGHT) { - //fprintf(stderr, "after %d\n", preprocessinginfo[i]->position); - preprocessinginfo[i]->print(indent, fp); - } - } -} - - -chillAST_SourceFile::chillAST_SourceFile::chillAST_SourceFile() { - SourceFileName = strdup("No Source File"); - asttype = CHILLAST_NODETYPE_SOURCEFILE; - parent = NULL; // top node - metacomment = NULL; - global_symbol_table = NULL; - global_typedef_table = NULL; - FileToWrite = NULL; - frontend = strdup("unknown"); - isFromSourceFile = true; - filename = NULL; -}; - -chillAST_SourceFile::chillAST_SourceFile(const char *filename ) { - SourceFileName = strdup(filename); - asttype = CHILLAST_NODETYPE_SOURCEFILE; - parent = NULL; // top node - metacomment = NULL; - global_symbol_table = NULL; - global_typedef_table = NULL; - FileToWrite = NULL; - frontend = strdup("unknown"); - isFromSourceFile = true; - filename = NULL; -}; - -void chillAST_SourceFile::print( int indent, FILE *fp ) { - //fprintf(stderr, "chillAST_SourceFile::print()\n"); - fflush(fp); - fprintf(fp, "\n// this source derived from CHILL AST originally from file '%s' as parsed by frontend compiler %s\n\n", SourceFileName, frontend); - std::vector< char * > includedfiles; - int sofar = 0; - - //fprintf(fp, "#define __rose_lt(x,y) ((x)<(y)?(x):(y))\n#define __rose_gt(x,y) ((x)>(y)?(x):(y))\n"); // help diff figure out what's going on - - int numchildren = children.size(); - //fprintf(stderr, "// sourcefile has %d children\n", numchildren); - //fprintf(stderr, "they are\n"); - //for (int i=0; igetTypeString()); - // if (children[i]->isFunctionDecl()) { - // fprintf(stderr, "%s ", ((chillAST_FunctionDecl *)children[i])->functionName); - // } - // fprintf(stderr, "\n"); - //} - - for (int i=0; igetTypeString()); - if (children[i]->isFromSourceFile) { - if (children[i]->isFunctionDecl()) { - fprintf(stderr, "\nchild %d function %s\n",i,((chillAST_FunctionDecl *)children[i])->functionName); - } - //fprintf(stderr, "child %d IS from source file\n", i); - //if (children[i]->isMacroDefinition()) fprintf(fp, "\n"); fflush(fp); - children[i]->print( indent, fp ); - if (children[i]->isVarDecl()) fprintf(fp, ";\n"); fflush(fp); // top level vardecl\n"); - } - else { - //fprintf(stderr, "child %d is not from source file\n", i); - // this should all go away - -#ifdef NOPE - if (children[i]->filename // not null and not empty string - //&& 0 != strlen(children[i]->filename) - ) { // should not be necessary - //fprintf(fp, "// need an include for %s\n", children[i]->filename); - bool rddid = false; - sofar = includedfiles.size(); - - for (int j=0; jfilename ); - if (!strcmp( includedfiles[j], children[i]->filename) ) { // this file has already been included - rddid = true; - //fprintf(stderr, "already did that one\n"); - } - } - - if (false == rddid) { // we need to include it now - fprintf(fp, "#include \"%s\"\n", children[i]->filename); - includedfiles.push_back(strdup( children[i]->filename )); - } - //else { - // fprintf(fp, "already did\n"); - //} - } -#endif // NOPE - - - } - } - - fflush(fp); - - //fprintf(fp, "\n\n// functions??\n"); - //for (int i=0; iprint(0,fp); fflush(fp); - //} -}; - - - - -void chillAST_SourceFile::printToFile( char *filename ) { - char fn[1024]; - - if (NULL == filename) { // build up a filename using original name and frontend if known - if (FileToWrite) { - strcpy( fn, FileToWrite ); - } - else { - // input name with name of frontend compiler prepended - if (frontend) sprintf(fn, "%s_%s\0", frontend, SourceFileName); - else sprintf(fn, "UNKNOWNFRONTEND_%s\0", SourceFileName); // should never happen - } - } - else strcpy( fn, filename ); - - FILE *fp = fopen(fn, "w"); - if (!fp) { - fprintf(stderr, "can't open file '%s' for writing\n", fn); - exit(-1); - } - - //fprintf(fp, "\n\n"); - //dump(0, fp); - fprintf(fp, "\n\n"); - print(0, fp); - -} - - - -void chillAST_SourceFile::dump( int indent, FILE *fp ) { - fflush(fp); - fprintf(fp, "\n//CHILL AST originally from file '%s'\n", SourceFileName); - int numchildren = children.size(); - for (int i=0; idump( indent, fp ); - } - fflush(fp); -}; - - - -chillAST_MacroDefinition * chillAST_SourceFile::findMacro( const char *name ) { - //fprintf(stderr, "chillAST_SourceFile::findMacro( %s )\n", name ); - - int numMacros = macrodefinitions.size(); - for (int i=0; imacroName, name )) return macrodefinitions[i]; - } - return NULL; // not found -} - - -chillAST_FunctionDecl * chillAST_SourceFile::findFunction( const char *name ) { - //fprintf(stderr, "chillAST_SourceFile::findMacro( %s )\n", name ); - - int numFuncs = functions.size(); - for (int i=0; ifunctionName, name )) return functions[i]; - } - return NULL; -} - - -chillAST_node *chillAST_SourceFile::findCall( const char *name ) { - chillAST_MacroDefinition *macro = findMacro( name ); - if (macro) return (chillAST_node *)macro; - chillAST_FunctionDecl *func =findFunction( name ); - return func; -} - - -chillAST_VarDecl * chillAST_SourceFile::findVariableNamed( const char *name ) { - fprintf(stderr, "SOURCEFILE SPECIAL %s findVariableNamed( %s )\n", getTypeString(), name ); - if (hasSymbolTable()) { // look in my symbol table if I have one - fprintf(stderr, "%s has a symbol table\n", getTypeString()); - chillAST_VarDecl *vd = symbolTableFindVariableNamed( getSymbolTable(), name); - if (vd) { - fprintf(stderr, "found it\n"); - return vd; // found locally - } - fprintf(stderr, "%s has a symbol table but couldn't find %s\n", getTypeString(), name ); - } - - fprintf(stderr, "looking for %s in SourceFile global_symbol_table\n", name); - chillAST_VarDecl *vd = symbolTableFindVariableNamed( global_symbol_table, name ); - if (vd) { - fprintf(stderr, "found it\n"); - return vd; // found locally - } - - if (!parent) { - fprintf(stderr, "%s has no parent\n", getTypeString()); - return NULL; // no more recursion available - } - // recurse upwards - //fprintf(stderr, "recursing from %s up to parent %p\n", getTypeString(), parent); - fprintf(stderr, "recursing from %s up to parent\n", getTypeString()); - return parent->findVariableNamed( name ); -} - - - -chillAST_TypedefDecl::chillAST_TypedefDecl() { - underlyingtype = newtype = arraypart = NULL; - asttype = CHILLAST_NODETYPE_TYPEDEFDECL; - parent = NULL; - metacomment = NULL; - isStruct = isUnion = false; - structname = NULL; - rd = NULL; - isFromSourceFile = true; // default - filename = NULL; -}; - - -chillAST_TypedefDecl::chillAST_TypedefDecl(char *t, const char *nt, chillAST_node *par) { - //fprintf(stderr, "chillAST_TypedefDecl::chillAST_TypedefDecl( underlying type %s, newtype %s )\n", t, nt); - underlyingtype = strdup(t); - newtype = strdup(nt); - arraypart = NULL; - asttype = CHILLAST_NODETYPE_TYPEDEFDECL; - parent = NULL; - metacomment = NULL; - isStruct = isUnion = false; - structname = NULL; - rd = NULL; - isFromSourceFile = true; // default - filename = NULL; -}; - - -chillAST_TypedefDecl::chillAST_TypedefDecl(char *t, const char *a, char *p, chillAST_node *par) { - underlyingtype = strdup(t); - //fprintf(stderr, "chillAST_TypedefDecl::chillAST_TypedefDecl( underlying type %s )\n", underlyingtype); - newtype = strdup(a); // the new named type ?? - - arraypart = strdup(p); // array (p)art? - // splitarraypart(); // TODO - - asttype = CHILLAST_NODETYPE_TYPEDEFDECL; - parent = par; - metacomment = NULL; - isStruct = isUnion = false; - structname = NULL; - rd = NULL; - isFromSourceFile = true; // default - filename = NULL; -}; - - - - -void chillAST_TypedefDecl::print( int indent, FILE *fp ) { - //fprintf(fp, "typedefdecl->print()\n"); - - printPreprocBEFORE(indent, fp); - - if (isStruct) { - fprintf(fp, "\n/* A typedef STRUCT */\n"); chillindent(indent, fp); - } - - chillindent(indent, fp); - fprintf(fp, "typedef "); fflush(fp); - - if (rd) { - rd->print(indent, fp); // needs to not print the ending semicolon ?? - } - - else if (isStruct) { - fprintf(stderr, "/* no rd */\n"); - - //fprintf(fp, "struct %s\n", structname); - chillindent(indent, fp); - fprintf(fp, "{\n"); - for (int i=0; igetTypeString()); - subparts[i]->print(indent+1, fp); - fprintf(fp, ";\n"); - } - fprintf(fp, "};\n"); - } - else { - fprintf(fp, "/* NOT A STRUCT */ typedef %s %s%s;\n", underlyingtype, newtype, arraypart ); - dump(); printf("\n\n"); fflush(stdout); - } - - // then the newname - fprintf(fp, "%s;\n", newtype); - fflush(fp); - printPreprocAFTER(indent, fp); - - return; -} - - -chillAST_VarDecl *chillAST_TypedefDecl::findSubpart( const char *name ) { - //fprintf(stderr, "chillAST_TypedefDecl::findSubpart( %s )\n", name); - //fprintf(stderr, "typedef %s %s\n", structname, newtype); - - if (rd) { // we have a record decl look there - chillAST_VarDecl *sub = rd->findSubpart( name ); - //fprintf(stderr, "rd found subpart %p\n", sub); - return sub; - } - - // can this ever happen now ??? - int nsub = subparts.size(); - //fprintf(stderr, "%d subparts\n", nsub); - for (int i=0; ivarname )) return subparts[i]; - } - //fprintf(stderr, "subpart not found\n"); - - - return NULL; -} - - -chillAST_RecordDecl * chillAST_TypedefDecl::getStructDef() { - if (rd) return rd; - return NULL; -} - - - -chillAST_RecordDecl::chillAST_RecordDecl() { - asttype = CHILLAST_NODETYPE_RECORDDECL; - name = strdup("unknown"); // ?? - originalname = NULL; // ?? - isStruct = isUnion = false; - parent = NULL; - isFromSourceFile = true; // default - filename = NULL; -} - -chillAST_RecordDecl::chillAST_RecordDecl( const char *nam, chillAST_node *p ) { - //fprintf(stderr, "chillAST_RecordDecl::chillAST_RecordDecl()\n"); - asttype = CHILLAST_NODETYPE_RECORDDECL; - parent = p; - if (nam) name = strdup(nam); - else name = strdup("unknown"); // ?? - originalname = NULL; // ?? // make them do it manually? - isStruct = isUnion = false; - isFromSourceFile = true; // default - filename = NULL; -} - -chillAST_RecordDecl::chillAST_RecordDecl( const char *nam, const char *orig, chillAST_node *p ) { - fprintf(stderr, "chillAST_RecordDecl::chillAST_RecordDecl( %s, ( AKA %s ) )\n", nam, orig); - asttype = CHILLAST_NODETYPE_RECORDDECL; - parent = p; - if (p) p->addChild( this ); - - if (nam) name = strdup(nam); - else name = strdup("unknown"); // ?? - - originalname = NULL; - if (orig) originalname = strdup(orig); - - isStruct = isUnion = false; - isFromSourceFile = true; // default - filename = NULL; -} - - - -chillAST_VarDecl * chillAST_RecordDecl::findSubpart( const char *nam ){ - //fprintf(stderr, "chillAST_RecordDecl::findSubpart( %s )\n", nam); - int nsub = subparts.size(); - //fprintf(stderr, "%d subparts\n", nsub); - for (int i=0; ivarname); - if ( !strcmp( nam, subparts[i]->varname )) return subparts[i]; - } - fprintf(stderr, "chillAST_RecordDecl::findSubpart() couldn't find member NAMED %s in ", nam); print(); printf("\n\n"); fflush(stdout); - - return NULL; -} - - -chillAST_VarDecl * chillAST_RecordDecl::findSubpartByType( const char *typ ){ - //fprintf(stderr, "chillAST_RecordDecl::findSubpart( %s )\n", nam); - int nsub = subparts.size(); - //fprintf(stderr, "%d subparts\n", nsub); - for (int i=0; ivartype); - if ( !strcmp( typ, subparts[i]->vartype )) return subparts[i]; - } - //fprintf(stderr, "chillAST_RecordDecl::findSubpart() couldn't find member of TYPE %s in ", typ); print(); printf("\n\n"); fflush(stdout); - - return NULL; -} - - -void chillAST_RecordDecl::print( int indent, FILE *fp ) { - //fprintf(fp, "chillAST_RecordDecl::print()\n"); - if (isUnnamed) return; - - printPreprocBEFORE(indent, fp); - - chillindent(indent, fp); - if (isStruct) { - //fprintf(fp, "\n/* A Record Decl STRUCT */\n"); chillindent(indent, fp); - fprintf(fp, "struct "); - if ( strncmp( "unnamed", name, 7) ) fprintf(fp, "%s\n", name); - - chillindent(indent, fp); - fprintf(fp, "{\n"); - for (int i=0; igetTypeString()); - subparts[i]->print(indent+1, fp); - fprintf(fp, ";\n"); - } - fprintf(fp, "} "); - fprintf(fp, "\n"); // TODO need semicolon when defining struct. can't have it when part of a typedef. One of the following lines is correct in each case. - //fprintf(fp, ";\n"); - } - else { - fprintf(fp, "/* UNKNOWN RECORDDECL print() */ "); - exit(-1); - } - printPreprocAFTER(indent, fp); - fflush(fp); -} - - -chillAST_SymbolTable * chillAST_RecordDecl::addVariableToSymbolTable( chillAST_VarDecl *vd ){ - // for now, just bail. or do we want the struct to have an actual symbol table? - //fprintf(stderr, "chillAST_RecordDecl::addVariableToSymbolTable() ignoring struct member %s vardecl\n", vd->varname); - return NULL; // damn, I hope nothing uses this! -} - -void chillAST_RecordDecl::printStructure( int indent, FILE *fp ) { - //fprintf(stderr, "chillAST_RecordDecl::printStructure()\n"); - chillindent(indent, fp); - if (isStruct) { - fprintf(fp, "struct { ", name); - for (int i=0; iprint( 0, fp); // ?? TODO indent level - fprintf(fp, "; "); - } - fprintf(fp, "} "); - } - else { - fprintf(fp, "/* UNKNOWN RECORDDECL printStructure() */ "); - exit(-1); - } - fflush(fp); -} - - - -void chillAST_RecordDecl::dump( int indent, FILE *fp ) { - chillindent(indent, fp); - -} - - -chillAST_FunctionDecl::chillAST_FunctionDecl() { - functionName = strdup("YouScrewedUp"); - asttype = CHILLAST_NODETYPE_FUNCTIONDECL; - forwarddecl = externfunc = builtin = false; - uniquePtr = (void *) NULL; - this->setFunctionCPU(); - parent = NULL; - metacomment = NULL; - //symbol_table = NULL; // eventually, pointing to body's symbol table - typedef_table = NULL; - body = new chillAST_CompoundStmt(); - isFromSourceFile = true; // default - filename = NULL; -}; - - -chillAST_FunctionDecl::chillAST_FunctionDecl(const char *rt, const char *fname, chillAST_node *par) { - returnType = strdup(rt); - functionName = strdup(fname); - this->setFunctionCPU(); - //fprintf(stderr, "functionName %s\n", functionName); - forwarddecl = externfunc = builtin = false; - - asttype = CHILLAST_NODETYPE_FUNCTIONDECL; - parent = par; - metacomment = NULL; - if (par) par->getSourceFile()->addFunc( this ); - // symbol_table = NULL; //use body's instead - typedef_table = NULL; - body = new chillAST_CompoundStmt(); - isFromSourceFile = true; // default - filename = NULL; -}; - - -chillAST_FunctionDecl::chillAST_FunctionDecl(const char *rt, const char *fname, chillAST_node *par, void *unique) { - fprintf(stderr, "chillAST_FunctionDecl::chillAST_FunctionDecl with unique %p\n", unique); - returnType = strdup(rt); - functionName = strdup(fname); - this->setFunctionCPU(); - //fprintf(stderr, "functionName %s\n", functionName); - forwarddecl = externfunc = builtin = false; - - body = new chillAST_CompoundStmt(); - asttype = CHILLAST_NODETYPE_FUNCTIONDECL; - uniquePtr = unique; // a quick way to check equivalence. DO NOT ACCESS THROUGH THIS - parent = par; - metacomment = NULL; - if (par) par->getSourceFile()->addFunc( this ); - //symbol_table = NULL; // use body's - typedef_table = NULL; - isFromSourceFile = true; // default - filename = NULL; -}; - - -void chillAST_FunctionDecl::addParameter( chillAST_VarDecl *p) { - fprintf(stderr, "%s chillAST_FunctionDecl::addParameter( 0x%x param %s) total of %d parameters\n", functionName, p, p->varname, 1+parameters.size()); - - if (symbolTableHasVariableNamed( ¶meters, p->varname)) { // NOT recursive. just in FunctionDecl - fprintf(stderr, "chillAST_FunctionDecl::addParameter( %s ), parameter already exists?\n", p->varname); - // exit(-1); // ?? - return; // error? - } - - parameters.push_back(p); - //addSymbolToTable( parameters, p ); - fprintf(stderr, "setting %s isAParameter\n", p->varname); - p->isAParameter = true; - - p->setParent( this ); // ?? unclear TODO - //p->dump(); printf("\naddparameter done\n\n"); fflush(stdout); -} - - - -void chillAST_FunctionDecl::addDecl( chillAST_VarDecl *vd) { // to symbol table ONLY - fprintf(stderr, "chillAST_FunctionDecl::addDecl( %s )\n", vd->varname); - if (!body) { - //fprintf(stderr, "had no body\n"); - body = new chillAST_CompoundStmt(); - - //body->symbol_table = symbol_table; // probably wrong if this ever does something - } - - //fprintf(stderr, "before body->addvar(), func symbol table had %d entries\n", symbol_table->size()); - //fprintf(stderr, "before body->addvar(), body symbol table was %p\n", body->symbol_table); - //fprintf(stderr, "before body->addvar(), body symbol table had %d entries\n", body->symbol_table->size()); - //adds to body symbol table, and makes sure function has a copy. probably dumb - body->symbol_table = body->addVariableToSymbolTable( vd ); - //fprintf(stderr, "after body->addvar(), func symbol table had %d entries\n", symbol_table->size()); -} - -chillAST_VarDecl *chillAST_FunctionDecl::hasParameterNamed( const char *name ) { - int numparams = parameters.size(); - for (int i=0; ivarname)) return parameters[i]; // need to check type? - } - return NULL; -} - - -// similar to symbolTableHasVariableNamed() but returns the variable definition -chillAST_VarDecl *chillAST_FunctionDecl::funcHasVariableNamed( const char *name ) { // NOT recursive - //fprintf(stderr, "chillAST_FunctionDecl::funcHasVariableNamed( %s )\n", name ); - - // first check the parameters - int numparams = parameters.size(); - for (int i=0; ivarname)) { - //fprintf(stderr, "yep, it's parameter %d\n", i); - return vd; // need to check type? - } - } - //fprintf(stderr, "no parameter named %s\n", name); - - chillAST_SymbolTable *st = getSymbolTable(); - if (!st) { - fprintf(stderr,"and no symbol_table, so no variable named %s\n", name); - return NULL; // no symbol table so no variable by that name - } - - - int numvars = st->size(); - //fprintf(stderr, "checking against %d variables\n", numvars); - for (int i=0; ivarname); - if (!strcmp(name, vd->varname)) { - //fprintf(stderr, "yep, it's variable %d\n", i); - fprintf(stderr, "%s was already defined in the function body\n", vd->varname); - return vd; // need to check type? - } - } - fprintf(stderr, "not a parameter or variable named %s\n", name); - return NULL; -} - - - - -void chillAST_FunctionDecl::setBody( chillAST_node * bod ) { - //fprintf(stderr, "%s chillAST_FunctionDecl::setBody( 0x%x ) total of %d children\n", functionName, bod, 1+children.size()); - if (bod->isCompoundStmt()) body = (chillAST_CompoundStmt *)bod; - else { - body = new chillAST_CompoundStmt(); - body->addChild( bod ); - } - //symbol_table = body->getSymbolTable(); - //addChild(bod); - bod->setParent( this ); // well, ... -} - - -void chillAST_FunctionDecl::insertChild(int i, chillAST_node* node) { - fprintf(stderr, "chillAST_FunctionDecl::insertChild() "); node->print(0,stderr); fprintf(stderr, "\n\n"); - body->insertChild( i, node ); - - if (node->isVarDecl()) { - chillAST_VarDecl *vd = ((chillAST_VarDecl *) node); - fprintf(stderr, "functiondecl %s inserting a VarDecl named %s\n", functionName, vd->varname); - chillAST_SymbolTable *st = getSymbolTable(); - if (!st) { - fprintf(stderr, "symbol table is NULL!\n"); - } - else { - fprintf(stderr, "%d entries in the symbol table\n", st->size()); - printSymbolTable( getSymbolTable() ); - } - fprintf(stderr, "\n\n"); - } -} - -void chillAST_FunctionDecl::addChild(chillAST_node* node) { - fprintf(stderr, "chillAST_FunctionDecl::addChild( ) "); node->print(0,stderr); fprintf(stderr, "\n\n"); - if (node->isVarDecl()) { - chillAST_VarDecl *vd = ((chillAST_VarDecl *) node); - fprintf(stderr, "functiondecl %s adding a VarDecl named %s\n", functionName, vd->varname); - } - - body->addChild( node ); - node->parent = this; // this, or body?? -} - - -void chillAST_FunctionDecl::printParameterTypes( FILE *fp ) { // also prints names - //fprintf(stderr, "\n\n%s chillAST_FunctionDecl::printParameterTypes()\n", functionName); - fprintf(fp, "( "); - int numparameters = parameters.size(); - for (int i=0; iprint(0, fp); // note: no indent, as this is in the function parens - } - fprintf(fp, " )"); // end of input parameters - -} - - - - -void chillAST_FunctionDecl::print( int indent, FILE *fp ) { - //fprintf(fp, "\n// functiondecl %p \n", this); - //chillindent(indent, fp); - //fprintf(fp, "//(functiondecl) %d parameters\n", numparameters); - - printPreprocBEFORE(indent, fp); - - fprintf(fp, "\n"); - chillindent(indent, fp); - - if (externfunc) fprintf(fp, "extern "); - - if (function_type == CHILL_FUNCTION_GPU) fprintf(fp, "__global__ "); - fprintf(fp, "%s %s", returnType, functionName ); - printParameterTypes(fp); - - - - // non-parameter variables (now must have explicit vardecl in the body) - //int numvars = symbol_table.size(); - //for (int i=0; iprint(1,fp); - // fprintf(fp, ";\n"); - //} - - // now the body - if (!(externfunc || forwarddecl)) { - if (body) { - fprintf(fp, "\n{\n"); - //chillindent(indent+1, fp); fprintf(fp, "//body\n"); fflush(fp); - body->print( indent+1, fp); - fprintf(fp, "\n"); - //chillindent(indent+1, fp); fprintf(fp, "//END body\n"); fflush(fp); - - // tidy up - chillindent(indent, fp); - fprintf(fp, "}\n"); - } // if body - else { - fprintf(fp, "{}\n"); // should never happen, but not external and no body - } - } - else { // extern func or forward decl. just end forward declaration - fprintf(fp, "; // fwd decl\n"); - } - - printPreprocAFTER(indent, fp); - - fflush(fp); -} - - - -void chillAST_FunctionDecl::dump( int indent, FILE *fp ) { - fprintf(fp, "\n"); - fprintf(fp, "// isFromSourceFile "); - if (filename) fprintf(fp, "%s ", filename); - if (isFromSourceFile) fprintf(fp, "true\n"); - else fprintf(fp, "false\n"); - chillindent(indent, fp); - fprintf(fp, "(FunctionDecl %s %s(", returnType, functionName ); - - int numparameters = parameters.size(); - for (int i=0; igetTypeString(), p->vartype); - p->print(0, fp); // note: no indent, as this is in the function parens, ALSO print, not dump - } - fprintf(fp, ")\n"); // end of input parameters - - // now the body - - if (body) body->dump( indent+1 , fp); - - // tidy up - chillindent(indent, fp); - fprintf(fp, ")\n"); - fflush(fp); -} - - - - - - -void chillAST_FunctionDecl::gatherVarDecls( vector &decls ) { - //fprintf(stderr, "chillAST_FunctionDecl::gatherVarDecls()\n"); - //if (0 < children.size()) fprintf(stderr, "functiondecl has %d children\n", children.size()); - //fprintf(stderr, "functiondecl has %d parameters\n", numParameters()); - for (int i=0; igatherVarDecls( decls ); - //fprintf(stderr, "after parms, %d decls\n", decls.size()); - for (int i=0; igatherVarDecls( decls ); - //fprintf(stderr, "after children, %d decls\n", decls.size()); - body->gatherVarDecls( decls ); // todo, figure out if functiondecl has actual children - //fprintf(stderr, "after body, %d decls\n", decls.size()); - //for (int d=0; dprint(0,stderr); fprintf(stderr, "\n"); - //} -} - - -void chillAST_FunctionDecl::gatherScalarVarDecls( vector &decls ) { - //if (0 < children.size()) fprintf(stderr, "functiondecl has %d children\n", children.size()); - - for (int i=0; igatherScalarVarDecls( decls ); - for (int i=0; igatherScalarVarDecls( decls ); - body->gatherScalarVarDecls( decls ); // todo, figure out if functiondecl has actual children -} - - -void chillAST_FunctionDecl::gatherArrayVarDecls( vector &decls ) { - //if (0 < children.size()) fprintf(stderr, "functiondecl has %d children\n", children.size()); - - for (int i=0; igatherArrayVarDecls( decls ); - for (int i=0; igatherArrayVarDecls( decls ); - body->gatherArrayVarDecls( decls ); // todo, figure out if functiondecl has actual children -} - - -chillAST_VarDecl *chillAST_FunctionDecl::findArrayDecl( const char *name ) { - //fprintf(stderr, "chillAST_FunctionDecl::findArrayDecl( %s )\n", name ); - chillAST_VarDecl *p = hasParameterNamed( name ); - //if (p) fprintf(stderr, "function %s has parameter named %s\n", functionName, name ); - if (p && p->isArray()) return p; - - chillAST_VarDecl *v = funcHasVariableNamed ( name ); - //if (v) fprintf(stderr, "function %s has symbol table variable named %s\n", functionName, name ); - if (v && v->isArray()) return v; - - // declared variables that may not be in symbol table but probably should be - vector decls ; - gatherArrayVarDecls( decls ); - for (int i=0; ivarname, name ) && vd->isArray()) return vd; - } - - //fprintf(stderr, "can't find array named %s in function %s \n", name, functionName); - return NULL; -} - - -void chillAST_FunctionDecl::gatherVarUsage( vector &decls ) { - for (int i=0; igatherVarUsage( decls ); - body->gatherVarUsage( decls ); // todo, figure out if functiondecl has actual children -} - - -void chillAST_FunctionDecl::gatherDeclRefExprs( vector&refs ) { - for (int i=0; igatherDeclRefExprs( refs ); - body->gatherDeclRefExprs( refs ); // todo, figure out if functiondecl has actual children -} - - - -void chillAST_FunctionDecl::cleanUpVarDecls() { - //fprintf(stderr, "\ncleanUpVarDecls() for function %s\n", functionName); - vector used; - vector defined; - vector deletethese; - - gatherVarUsage( used ); - gatherVarDecls( defined ); - - //fprintf(stderr, "\nvars used: \n"); - //for ( int i=0; i< used.size(); i++) { - //used[i]->print(0, stderr); fprintf(stderr, "\n"); - //} - //fprintf(stderr, "\n"); - //fprintf(stderr, "\nvars defined: \n"); - //for ( int i=0; i< defined.size(); i++) { - // defined[i]->print(0, stderr); fprintf(stderr, "\n"); - //} - //fprintf(stderr, "\n"); - - for ( int j=0; j < defined.size(); j++) { - //fprintf(stderr, "j %d defined %s\n", j, defined[j]->varname); - bool definedandused = false; - for ( int i=0; i < used.size(); i++) { - if (used[i] == defined[j]) { - //fprintf(stderr, "i %d used %s\n", i, used[i]->varname); - //fprintf(stderr, "\n"); - definedandused = true; - break; - } - } - - if (!definedandused) { - if ( defined[j]->isParmVarDecl() ) { - //fprintf(stderr, "we'd remove %s except that it's a parameter. Maybe someday\n", defined[j]->varname); - } - else { - //fprintf(stderr, "we can probably remove the definition of %s\n", defined[j]->varname); - deletethese.push_back( defined[j] ); - } - } - } - - - //fprintf(stderr, "deleting %d vardecls\n", deletethese.size()); - for (int i=0; ivarname); - chillAST_node *par = deletethese[i]->parent; - par->removeChild( par->findChild( deletethese[i] )); - } - - - //fprintf(stderr, "\n\nnow check for vars used but not defined\n"); - // now check for vars used but not defined? - for ( int j=0; j < used.size(); j++) { - //fprintf(stderr, "%s is used\n", used[j]->varname); - bool definedandused = false; - for ( int i=0; i < defined.size(); i++) { - if (used[j] == defined[i]) { - //fprintf(stderr, "%s is defined\n", defined[i]->varname); - definedandused = true; - break; - } - } - if (!definedandused) { - //fprintf(stderr, "%s is used but not defined?\n", used[j]->varname); - // add it to the beginning of the function - insertChild(0, used[j]); - } - } - -} - -//void chillAST_FunctionDecl::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl ) { -// for (int i=0; ireplaceVarDecls( olddecl, newdecl ); -//} - - -bool chillAST_FunctionDecl::findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync ) { - if (body) body->findLoopIndexesToReplace( symtab, false ); - return false; -} - - - - chillAST_node *chillAST_FunctionDecl::constantFold() { - //fprintf(stderr, "chillAST_FunctionDecl::constantFold()\n"); - // parameters can't have constants? - int numparameters = parameters.size(); - for (int i=0; iconstantFold(); - } - if (body) body = (chillAST_CompoundStmt *)body->constantFold(); - return this; - } - - -chillAST_MacroDefinition::chillAST_MacroDefinition() { - macroName = strdup("UNDEFINEDMACRO"); - rhsString = NULL; - asttype = CHILLAST_NODETYPE_MACRODEFINITION; - parent = NULL; - metacomment = NULL; - symbol_table = NULL; - //rhsideString = NULL; - isFromSourceFile = true; // default - filename = NULL; -}; - - -chillAST_MacroDefinition::chillAST_MacroDefinition(const char *mname, chillAST_node *par) { - macroName = strdup(mname); - rhsString = NULL; - asttype = CHILLAST_NODETYPE_MACRODEFINITION; - parent = par; - metacomment = NULL; - symbol_table = NULL; - //rhsideString = NULL; - - if (par) par->getSourceFile()->addMacro( this ); - - //fprintf(stderr, "chillAST_MacroDefinition::chillAST_MacroDefinition( %s, ", mname); - //if (par) fprintf(stderr, " parent NOT NULL);\n"); - //else fprintf(stderr, " parent NULL);\n"); - isFromSourceFile = true; // default - filename = NULL; -}; - - -chillAST_MacroDefinition::chillAST_MacroDefinition(const char *mname, const char *rhs, chillAST_node *par) { - macroName = strdup(mname); - rhsString = strdup(rhs); - asttype = CHILLAST_NODETYPE_MACRODEFINITION; - parent = par; - metacomment = NULL; - symbol_table = NULL; - - if (par) par->getSourceFile()->addMacro( this ); - - //fprintf(stderr, "chillAST_MacroDefinition::chillAST_MacroDefinition( %s, ", mname); - //if (par) fprintf(stderr, " parent NOT NULL);\n"); - //else fprintf(stderr, " parent NULL);\n"); - isFromSourceFile = true; // default - filename = NULL; -}; - - -chillAST_node* chillAST_MacroDefinition::clone() { - - // TODO ?? cloning a macro makes no sense - return this; -#ifdef CONFUSED - - //fprintf(stderr, "chillAST_MacroDefinition::clone() for %s\n", macroName); - chillAST_MacroDefinition *clo = new chillAST_MacroDefinition( macroName, parent); - for (int i=0; iaddParameter( parameters[i] ); - clo->setBody( body->clone() ); - return clo; -#endif - -} - - -void chillAST_MacroDefinition::setBody( chillAST_node * bod ) { - fprintf(stderr, "%s chillAST_MacroDefinition::setBody( 0x%x )\n", macroName, bod); - body = bod; - fprintf(stderr, "body is:\n"); body->print(0,stderr); fprintf(stderr, "\n\n"); - rhsString = body->stringRep(); - bod->setParent( this ); // well, ... -} - - -void chillAST_MacroDefinition::addParameter( chillAST_VarDecl *p) { - //fprintf(stderr, "%s chillAST_MacroDefinition::addParameter( 0x%x ) total of %d children\n", functionName, p, 1+children.size()); - parameters.push_back(p); - fprintf(stderr, "macro setting %s isAParameter\n", p->varname); - p->isAParameter = true; - p->setParent( this ); - - addVariableToSymbolTable( p ); -} - - -chillAST_VarDecl *chillAST_MacroDefinition::hasParameterNamed( const char *name ) { - int numparams = parameters.size(); - for (int i=0; ivarname)) return parameters[i]; // need to check type? - } - return NULL; -} - - -void chillAST_MacroDefinition::insertChild(int i, chillAST_node* node) { - body->insertChild( i, node ); -} - -void chillAST_MacroDefinition::addChild(chillAST_node* node) { - body->addChild( node ); - node->parent = this; // this, or body?? -} - - -void chillAST_MacroDefinition::dump( int indent, FILE *fp ) { - fprintf(fp, "\n"); - chillindent(indent, fp); - fprintf(fp, "(MacroDefinition %s(", macroName); - for (int i=0; ivarname); - } - fprintf(fp, ")\n"); - body->dump( indent+1, fp); - if (rhsString) fprintf(fp, " (aka %s)"); - fprintf(fp, "\n"); - fflush(fp); -} - - -void chillAST_MacroDefinition::print( int indent, FILE *fp ) { // UHOH TODO - //fprintf(fp, "\n"); // ignore indentation - //fprintf(stderr, "macro has %d parameters\n", numParameters()); - - printPreprocBEFORE(indent, fp); - - fprintf(fp, "#define %s", macroName); - if (0 != numParameters()) { - fprintf(fp, "("); - for (int i=0; ivarname); - } - fprintf(fp, ") "); - } - - if (body) body->print(0, fp); // TODO should force newlines out of multiline macros - fprintf(fp, "\n"); -} - - - - -chillAST_ForStmt::chillAST_ForStmt() { - init = cond = incr = NULL; - body = new chillAST_CompoundStmt(); - - asttype = CHILLAST_NODETYPE_LOOP; // breaking with tradition, this was CHILL_AST_FORSTMT - conditionoperator = IR_COND_UNKNOWN; - parent = NULL; - metacomment = NULL; - symbol_table = NULL; - isFromSourceFile = true; // default - filename = NULL; -} - - -chillAST_ForStmt::chillAST_ForStmt( chillAST_node *ini, chillAST_node *con, chillAST_node *inc, chillAST_node *bod, chillAST_node *par) { - parent = par; - metacomment = NULL; - init = ini; - cond = con; - incr = inc; - body = bod; - init->setParent( this ); - cond->setParent( this ); - incr->setParent( this ); - - //fprintf(stderr, "chillAST_ForStmt::chillAST_ForStmt() bod %p\n", bod); - - if (body) body->setParent( this ); // not sure this should be legal - - asttype = CHILLAST_NODETYPE_LOOP; // breaking with tradition, this was CHILL_AST_FORSTMT - - if (!cond->isBinaryOperator()) { - fprintf(stderr, "ForStmt conditional is of type %s. Expecting a BinaryOperator\n", cond->getTypeString()); - exit(-1); - } - chillAST_BinaryOperator *bo = (chillAST_BinaryOperator *)cond; - char *condstring = bo->op; - if (!strcmp(condstring, "<")) conditionoperator = IR_COND_LT; - else if (!strcmp(condstring, "<=")) conditionoperator = IR_COND_LE; - else if (!strcmp(condstring, ">")) conditionoperator = IR_COND_GT; - else if (!strcmp(condstring, ">=")) conditionoperator = IR_COND_GE; - else { - fprintf(stderr, "ForStmt, illegal/unhandled end condition \"%s\"\n", condstring); - fprintf(stderr, "currently can only handle <, >, <=, >=\n"); - exit(1); - } - isFromSourceFile = true; // default - filename = NULL; -} - - -bool chillAST_ForStmt::lowerBound( int &l ) { // l is an output (passed as reference) - - // above, cond must be a binaryoperator ... ??? - if (conditionoperator == IR_COND_LT || - conditionoperator == IR_COND_LE ) { - - // lower bound is rhs of init - if (!init->isBinaryOperator()) { - fprintf(stderr, "chillAST_ForStmt::lowerBound() init is not a chillAST_BinaryOperator\n"); - exit(-1); - } - - chillAST_BinaryOperator *bo = (chillAST_BinaryOperator *)init; - if (!init->isAssignmentOp()) { - fprintf(stderr, "chillAST_ForStmt::lowerBound() init is not an assignment chillAST_BinaryOperator\n"); - exit(-1); - } - - //fprintf(stderr, "rhs "); bo->rhs->print(0,stderr); fprintf(stderr, " "); - l = bo->rhs->evalAsInt(); // float could be legal I suppose - //fprintf(stderr, " %d\n", l); - return true; - } - else if (conditionoperator == IR_COND_GT || - conditionoperator == IR_COND_GE ) { // decrementing - // lower bound is rhs of cond (not init) - chillAST_BinaryOperator *bo = (chillAST_BinaryOperator *)cond; - l = bo->rhs->evalAsInt(); // float could be legal I suppose - return true; - } - - // some case we don't handle ?? - fprintf(stderr, "chillAST_ForStmt::lowerBound() can't find lower bound of "); - print(0,stderr); - fprintf(stderr, "\n\n"); - return false; // or exit ??? -} - - -bool chillAST_ForStmt::upperBound( int &u ) { // u is an output (passed as reference) - - // above, cond must be a binaryoperator ... ??? - if (conditionoperator == IR_COND_GT || - conditionoperator == IR_COND_GE ) { // decrementing - - // upper bound is rhs of init - if (!init->isBinaryOperator()) { - fprintf(stderr, "chillAST_ForStmt::upperBound() init is not a chillAST_BinaryOperator\n"); - exit(-1); - } - - chillAST_BinaryOperator *bo = (chillAST_BinaryOperator *)init; - if (!init->isAssignmentOp()) { - fprintf(stderr, "chillAST_ForStmt::upperBound() init is not an assignment chillAST_BinaryOperator\n"); - exit(-1); - } - - u = bo->rhs->evalAsInt(); // float could be legal I suppose - return true; - } - else if (conditionoperator == IR_COND_LT || - conditionoperator == IR_COND_LE ) { - //fprintf(stderr, "upper bound is rhs of cond "); - // upper bound is rhs of cond (not init) - chillAST_BinaryOperator *bo = (chillAST_BinaryOperator *)cond; - //bo->rhs->print(0,stderr); - u = bo->rhs->evalAsInt(); // float could be legal I suppose - - if (conditionoperator == IR_COND_LT) u -= 1; - - //fprintf(stderr, " %d\n", u); - return true; - } - - // some case we don't handle ?? - fprintf(stderr, "chillAST_ForStmt::upperBound() can't find upper bound of "); - print(0,stderr); - fprintf(stderr, "\n\n"); - return false; // or exit ??? -} - - - - -void chillAST_ForStmt::printControl( int in, FILE *fp ) { - chillindent(in, fp); - fprintf(fp, "for ("); - init->print(0, fp); - fprintf(fp, "; "); - cond->print(0, fp); - fprintf(fp, "; "); - incr->print(0, fp); - fprintf(fp, ")"); - fflush(fp); -} - - -void chillAST_ForStmt::print( int indent, FILE *fp ) { - printPreprocBEFORE(indent, fp); - //fprintf(fp, "chillAST_ForStmt::print()\n"); - if (metacomment) { - chillindent(indent, fp); - //for(int i=0; igetNumChildren()); - //fprintf(fp, "body child 0 of type %s\n", b->children[0]->getTypeString()); - //fprintf(stderr, "forstmt body type %s\n", Chill_AST_Node_Names[b->asttype] ); - // deal with a tree of compound statements, in an ugly way. leave the ugliness - while (1 == b->getNumChildren() && b->children[0]->isCompoundStmt()) { - b = b->children[0]; - } - - - // this was to sometimes not enclose in a bracket. stupid. always enclose in a bracket. - //if (1 == b->getNumChildren() && b->children[0]->isForStmt()) fprintf(fp, ") {\n" ); - //else if (1 == b->getNumChildren() ) fprintf(fp, ") { ?? \n" ); // to allow for() for( ) to not have open bracket? - //else { - //fprintf(fp, ")\n"); - //chillindent(in, fp); - //fprintf(fp, "{\n" ); - - //fprintf(fp, ")"); - //} - - b->print(indent+1, fp ); - - // I think this can't happen any more. body is always a compound statement - if (b->asttype == CHILLAST_NODETYPE_BINARYOPERATOR) { // a single assignment statement - fprintf(fp, ";\n"); - } - - // always print brackets - - //if ((1 == b->getNumChildren() && b->children[0]->isForStmt()) || - // (1 != b->getNumChildren() )) { - chillindent(indent, fp); - fprintf(fp, "}\n" ); - //} - - printPreprocAFTER(indent, fp); - fflush(fp); // -} - -void chillAST_ForStmt::dump( int indent, FILE *fp ) { - chillindent(indent, fp); - fprintf(fp, "(ForStmt \n"); - - init->dump(indent+1, fp); - cond->dump(indent+1, fp); - incr->dump(indent+1, fp); - body->dump(indent+1, fp); - - chillindent(indent, fp); - fprintf(fp, ")\n"); -} - -chillAST_node *chillAST_ForStmt::constantFold() { - init = init->constantFold(); - cond = cond->constantFold(); - incr = incr->constantFold(); - body = body->constantFold(); - return this; - } - - - chillAST_node *chillAST_ForStmt::clone() { - chillAST_ForStmt *fs = new chillAST_ForStmt( init->clone(), cond->clone(), incr->clone(), body->clone(), parent); - fs->isFromSourceFile = isFromSourceFile; - if (filename) fs->filename = strdup(filename); - return fs; - } - -void chillAST_ForStmt::gatherVarDecls( vector &decls ) { - //fprintf(stderr, "chillAST_ForStmt::gatherVarDecls()\n"); - //fprintf(stderr, "chillAST_ForStmt::gatherVarDecls() before %d\n", decls.size()); - // TODO clear a loop_var_decls variable and then walk it ? - init->gatherVarDecls( decls ); - cond->gatherVarDecls( decls ); - incr->gatherVarDecls( decls ); - body->gatherVarDecls( decls ); - //fprintf(stderr, "after %d\n", decls.size()); -} - -void chillAST_ForStmt::gatherScalarVarDecls( vector &decls ) { - //fprintf(stderr, "chillAST_ForStmt::gatherScalarVarDecls() before %d\n", decls.size()); - init->gatherScalarVarDecls( decls ); - cond->gatherScalarVarDecls( decls ); - incr->gatherScalarVarDecls( decls ); - body->gatherScalarVarDecls( decls ); -} - -void chillAST_ForStmt::gatherArrayVarDecls( vector &decls ) { - //fprintf(stderr, "chillAST_ForStmt::gatherArrayVarDecls() before %d\n", decls.size()); - init->gatherArrayVarDecls( decls ); - cond->gatherArrayVarDecls( decls ); - incr->gatherArrayVarDecls( decls ); - body->gatherArrayVarDecls( decls ); -} - -void chillAST_ForStmt::gatherArrayRefs( std::vector &refs, bool writtento ) { - init->gatherArrayRefs( refs, 0 ); // 0 ?? - cond->gatherArrayRefs( refs, 0 ); // 0 ?? - incr->gatherArrayRefs( refs, 0 ); // 0 ?? - body->gatherArrayRefs( refs, 0 ); // 0 ?? -} - -void chillAST_ForStmt::gatherScalarRefs( std::vector &refs, bool writtento ) { - init->gatherScalarRefs( refs, 0 ); // 0 ?? - cond->gatherScalarRefs( refs, 0 ); // 0 ?? - incr->gatherScalarRefs( refs, 0 ); // 0 ?? - body->gatherScalarRefs( refs, 0 ); // 0 ?? -} - -void chillAST_ForStmt::gatherDeclRefExprs( vector&refs ) { - init->gatherDeclRefExprs( refs ); - cond->gatherDeclRefExprs( refs ); - incr->gatherDeclRefExprs( refs ); - body->gatherDeclRefExprs( refs ); -} - - - -void chillAST_ForStmt::gatherVarUsage( vector &decls ) { - init->gatherVarUsage( decls ); - cond->gatherVarUsage( decls ); - incr->gatherVarUsage( decls ); - body->gatherVarUsage( decls ); -} - -void chillAST_ForStmt::gatherStatements(std::vector &statements ){ - - // for completeness, should do all 4. Maybe someday - //init->gatherStatements( statements ); - //cond->gatherStatements( statements ); - //incr->gatherStatements( statements ); - body->gatherStatements( statements ); -} - - - -void chillAST_ForStmt::addSyncs() { - //fprintf(stderr, "\nchillAST_ForStmt::addSyncs() "); - //fprintf(stderr, "for ("); - //init->print(0, stderr); - //fprintf(stderr, "; "); - //cond->print(0, stderr); - //fprintf(stderr, "; "); - //incr->print(0, stderr); - //fprintf(stderr, ")\n"); - - if (!parent) { - fprintf(stderr, "uhoh, chillAST_ForStmt::addSyncs() ForStmt has no parent!\n"); - fprintf(stderr, "for ("); - init->print(0, stderr); - fprintf(stderr, "; "); - cond->print(0, stderr); - fprintf(stderr, "; "); - incr->print(0, stderr); - fprintf(stderr, ")\n"); - - return; // exit? - } - - if (parent->isCompoundStmt()) { - //fprintf(stderr, "ForStmt parent is CompoundStmt 0x%x\n", parent); - vector chillin = parent->getChildren(); - int numc = chillin.size(); - //fprintf(stderr, "ForStmt parent is CompoundStmt 0x%x with %d children\n", parent, numc); - for (int i=0; igetChild(i)) { - //fprintf(stderr, "forstmt 0x%x is child %d of %d\n", this, i, numc); - chillAST_CudaSyncthreads *ST = new chillAST_CudaSyncthreads(); - parent->insertChild(i+1, ST); // corrupts something ... - //fprintf(stderr, "Create a call to __syncthreads() 2\n"); - //parent->addChild(ST); // wrong, but safer still kills - } - } - - chillin = parent->getChildren(); - int nowc = chillin.size(); - //fprintf(stderr, "old, new number of children = %d %d\n", numc, nowc); - - } - else { - fprintf(stderr, "chillAST_ForStmt::addSyncs() unhandled parent type %s\n", parent->getTypeString()); - exit(-1); - } - - //fprintf(stderr, "leaving addSyncs()\n"); -} - - - - -void chillAST_ForStmt::removeSyncComment() { - //fprintf(stderr, "chillAST_ForStmt::removeSyncComment()\n"); - if (metacomment && strstr(metacomment, "~cuda~") && strstr(metacomment, "preferredIdx: ")) { - char *ptr = strlen( "preferredIdx: " ) + strstr(metacomment, "preferredIdx: "); - *ptr = '\0'; - } -} - - -bool chillAST_ForStmt::findLoopIndexesToReplace(chillAST_SymbolTable *symtab, bool forcesync ) { - fprintf(stderr, "\nchillAST_ForStmt::findLoopIndexesToReplace( force = %d )\n", forcesync); - //if (metacomment) fprintf(stderr, "metacomment '%s'\n", metacomment); - - bool force = forcesync; - bool didasync = false; - if (forcesync) { - //fprintf(stderr, "calling addSyncs() because PREVIOUS ForStmt in a block had preferredIdx\n"); - addSyncs(); - didasync = true; - } - - //fprintf(stderr, "chillAST_ForStmt::findLoopIndexesToReplace()\n"); - if (metacomment && strstr(metacomment, "~cuda~") && strstr(metacomment, "preferredIdx: ")) { - //fprintf(stderr, "metacomment '%s'\n", metacomment); - - char *copy = strdup(metacomment); - char *ptr = strstr(copy, "preferredIdx: "); - char *vname = ptr + strlen( "preferredIdx: " ); - char *space = strstr(vname, " "); // TODO index() - if (space) { - //fprintf(stderr, "vname = '%s'\n", vname); - force = true; - } - - if ((!didasync) && force ) { - //fprintf(stderr, "calling addSyncs() because ForStmt metacomment had preferredIdx '%s'\n", vname); - addSyncs(); - removeSyncComment(); - didasync = true; - } - - if (space) *space = '\0'; // if this is multiple words, grab the first one - //fprintf(stderr, "vname = '%s'\n", vname); - - //fprintf(stderr, "\nfor ("); - //init->print(0, stderr); - //fprintf(stderr, "; "); - //cond->print(0, stderr); - //fprintf(stderr, "; "); - //incr->print(0, stderr); - //fprintf(stderr, ") %s\n", metacomment ); - //fprintf(stderr, "prefer '%s'\n", vname ); - - vector decls; - init->gatherVarLHSUsage( decls ); - //cond->gatherVarUsage( decls ); - //incr->gatherVarUsage( decls ); - //fprintf(stderr, "forstmt has %d vardecls in init, cond, inc\n", decls.size()); - - if ( 1 != decls.size()) { - fprintf(stderr, "uhoh, preferred index in for statement, but multiple variables used\n"); - print(0,stderr); - fprintf(stderr, "\nvariables are:\n"); - for (int i=0; iprint(0,stderr); fprintf(stderr, "\n"); - } - exit(0); - } - chillAST_VarDecl* olddecl = decls[0]; - - // RIGHT NOW, change all the references that this loop wants swapped out - // find vardecl for named preferred index. it has to already exist - fprintf(stderr, "RIGHT NOW, change all the references that this loop wants swapped out \n"); - - chillAST_VarDecl *newguy = findVariableNamed( vname ); // recursive - if (!newguy) { - fprintf(stderr, "there was no variable named %s anywhere I could find\n", vname); - } - - // wrong - this only looks at variables defined in the forstmt, not - // in parents of the forstmt - //int numsym = symtab->size(); - //fprintf(stderr, "%d symbols\n", numsym); - //for (int i=0; ivarname); - // if (!strcmp(vname, (*symtab)[i]->varname)) { - // newguy = (*symtab)[i]; - // } - //} - if (!newguy) { - fprintf(stderr, "chillAST_ForStmt::findLoopIndexesToReplace() there is no defined variable %s\n", vname); - - // make one ?? seems like this should never happen - newguy = new chillAST_VarDecl( olddecl->vartype, vname, ""/*?*/, NULL ); - // insert actual declaration in code location? how? - - // find parent of the ForStmt? - // find parent^n of the ForStmt that is not a Forstmt? - // find parent^n of the Forstmt that is a FunctionDecl? - chillAST_node *contain = findContainingNonLoop(); - if (contain == NULL) { - fprintf(stderr, "nothing but loops all the way up?\n"); - exit(0); - } - fprintf(stderr, "containing non-loop is a %s\n", contain->getTypeString()); - - contain->print(0,stderr); - contain->insertChild( 0, newguy ); // ugly order TODO - contain->addVariableToSymbolTable( newguy ); // adds to first enclosing symbolTable - - if (! symbolTableHasVariableNamed( contain->getSymbolTable(), vname )) { - fprintf(stderr, "container doesn't have a var names %s afterwards???\n", vname); - exit(-1); - } - } - - - // swap out old for new in init, cond, incr, body - if (newguy) { - fprintf(stderr, "\nwill replace %s with %s in init, cond, incr\n", olddecl->varname, newguy->varname); - fprintf(stderr, "was: for ("); - init->print(0, stderr); - fprintf(stderr, "; "); - cond->print(0, stderr); - fprintf(stderr, "; "); - incr->print(0, stderr); - fprintf(stderr, ")\n"); - - - init->replaceVarDecls( olddecl, newguy ); - cond->replaceVarDecls( olddecl, newguy ); - incr->replaceVarDecls( olddecl, newguy ); - - fprintf(stderr, " is: for ("); - init->print(0, stderr); - fprintf(stderr, "; "); - cond->print(0, stderr); - fprintf(stderr, "; "); - incr->print(0, stderr); - fprintf(stderr, ")\n\n"); - - fprintf(stderr,"recursing to ForStmt body of type %s\n", body->getTypeString()); - body->replaceVarDecls( olddecl, newguy ); - - fprintf(stderr, "\nafter recursing to body, this loop is (there should be no %s)\n", olddecl->varname); - print(0, stderr); fprintf(stderr, "\n"); - - } - - //if (!space) // there was only one preferred - //fprintf(stderr, "removing metacomment\n"); - metacomment = NULL; // memleak - - } - - // check for more loops. We may have already swapped variables out in body (right above here) - body->findLoopIndexesToReplace( symtab, false ) ; - - return force; -} - -void chillAST_ForStmt::replaceChild( chillAST_node *old, chillAST_node *newchild ){ - //fprintf(stderr, "chillAST_ForStmt::replaceChild() REALLY CALLING BODY->ReplaceCHILD\n"); - body->replaceChild( old, newchild ); -} - - - -void chillAST_ForStmt::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ - // logic problem if my loop var is olddecl! - - //fprintf(stderr, "chillAST_ForStmt::replaceVarDecls( old %s, new %s )\n", olddecl->varname, newdecl->varname); - - // this is called for inner loops! - init->replaceVarDecls( olddecl, newdecl ); - cond->replaceVarDecls( olddecl, newdecl ); - incr->replaceVarDecls( olddecl, newdecl ); - body->replaceVarDecls( olddecl, newdecl ); -} - - -void chillAST_ForStmt::gatherLoopIndeces( std::vector &indeces ) { - //fprintf(stderr, "chillAST_ForStmt::gatherLoopIndeces()\nloop is:\n"); print(0,stderr); - - vector decls; - init->gatherVarLHSUsage( decls ); - cond->gatherVarLHSUsage( decls ); - incr->gatherVarLHSUsage( decls ); - // note: NOT GOING INTO BODY OF THE LOOP - - int numdecls = decls.size(); - //fprintf(stderr, "gatherLoopIndeces(), %d lhs vardecls for this ForStmt\n", numdecls); - - for (int i=0; ivarname, decls[i] ); - indeces.push_back( decls[i] ); - } - - // Don't forget to keep heading upwards! - if (parent) { - //fprintf(stderr, "loop %p has parent of type %s\n", this, parent->getTypeString()); - parent->gatherLoopIndeces( indeces ); - } - //else fprintf(stderr, "this loop has no parent???\n"); - -} - - -void chillAST_ForStmt::gatherLoopVars( std::vector &loopvars ) { - //fprintf(stderr, "gathering loop vars for loop for ("); - //init->print(0, stderr); - //fprintf(stderr, "; "); - //cond->print(0, stderr); - //fprintf(stderr, "; "); - //incr->print(0, stderr); - //fprintf(stderr, ")\n" ); - - //init->dump(0, stderr); - - - vector decls; - init->gatherVarLHSUsage( decls ); - cond->gatherVarLHSUsage( decls ); - incr->gatherVarLHSUsage( decls ); - // note: NOT GOING INTO BODY OF THE LOOP - - for (int i=0; ivarname )); - -} - - -void chillAST_ForStmt::loseLoopWithLoopVar( char *var ) { - - //fprintf(stderr, "\nchillAST_ForStmt::loseLoopWithLoopVar( %s )\n", var ); - - // now recurse (could do first, I suppose) - // if you DON'T do this first, you may have already replaced yourself with this loop body - // the body will no longer have this forstmt as parent, it will have the forstmt's parent as its parent - //fprintf(stderr, "forstmt 0x%x, recursing loseLoop to body 0x%x of type %s with parent 0x%x of type %s\n", this, body, body->getTypeString(), body->parent, body->parent->getTypeString()); - body->loseLoopWithLoopVar( var ) ; - - - - - // if *I* am a loop to be replaced, tell my parent to replace me with my loop body - - std::vector loopvars; - gatherLoopVars( loopvars ); - - if (loopvars.size() != 1) { - fprintf(stderr, "uhoh, loop has more than a single loop var and trying to loseLoopWithLoopVar()\n"); - print(0,stderr); - fprintf(stderr, "\nvariables are:\n"); - for (int i=0; iprint(0, stderr); - //fprintf(stderr, "; "); - //cond->print(0, stderr); - //fprintf(stderr, "; "); - //incr->print(0, stderr); - //fprintf(stderr, ")\n" ); - - if (!parent) { - fprintf(stderr, "chillAST_ForStmt::loseLoopWithLoopVar() I have no parent!\n"); - exit(-1); - } - - vector decls; - init->gatherVarLHSUsage( decls ); // this can fail if init is outside the loop - cond->gatherVarLHSUsage( decls ); - incr->gatherVarLHSUsage( decls ); - if (decls.size() > 1) { - fprintf(stderr, "chill_ast.cc multiple loop variables confuses me\n"); - exit(-1); - } - chillAST_node *newstmt = body; - - // ACTUALLY, if I am being replaced, and my loop conditional is a min (Ternary), then wrap my loop body in an if statement - if (cond->isBinaryOperator()) { // what else could it be? - chillAST_BinaryOperator *BO = (chillAST_BinaryOperator *) cond; - if (BO->rhs->isTernaryOperator()) { - - chillAST_TernaryOperator *TO = (chillAST_TernaryOperator *)BO->rhs; - chillAST_BinaryOperator *C = (chillAST_BinaryOperator *)TO->condition; - - //fprintf(stderr, "loop condition RHS is ternary\nCondition RHS"); - C->print(); printf("\n"); fflush(stdout); - chillAST_node *l = C->lhs; - if (l->isParenExpr()) l = ((chillAST_ParenExpr *)l)->subexpr; - chillAST_node *r = C->rhs; - if (r->isParenExpr()) r = ((chillAST_ParenExpr *)r)->subexpr; - - //fprintf(stderr, "lhs is %s rhs is %s\n", l->getTypeString(), r->getTypeString()); - - chillAST_node *ifcondrhs = NULL; - if (!(l->isConstant())) ifcondrhs = l; - else if (!(r->isConstant())) ifcondrhs = r; - else { - // should never happen. 2 constants. infinite loop - fprintf(stderr, "chill_ast.cc INIFNITE LOOP?\n"); - this->print(0,stderr); fprintf(stderr, "\n\n"); - exit(-1); - } - - // wrap the loop body in an if - chillAST_DeclRefExpr *DRE = new chillAST_DeclRefExpr( decls[0] ); - chillAST_BinaryOperator *ifcond = new chillAST_BinaryOperator( DRE, "<=", ifcondrhs ); - chillAST_IfStmt *ifstmt = new chillAST_IfStmt( ifcond, body, NULL, NULL ); - - newstmt = ifstmt; - } - } - - //fprintf(stderr, "forstmt 0x%x has parent 0x%x of type %s\n", this, parent, parent->getTypeString()); - //fprintf(stderr, "forstmt will be replaced by\n"); - //newstmt->print(0,stderr); fprintf(stderr, "\n\n"); - - parent->replaceChild( this, newstmt ); - } - - -} - - - - - -chillAST_BinaryOperator::chillAST_BinaryOperator() { - //fprintf(stderr, "chillAST_BinaryOperator::chillAST_BinaryOperator() %p no parent\n", this); - fprintf(stderr, "chillAST_BinaryOperator::chillAST_BinaryOperator() no parent\n"); - lhs = rhs = NULL; - op = NULL; - asttype = CHILLAST_NODETYPE_BINARYOPERATOR; - isFromSourceFile = true; // default - filename = NULL; -} - - -chillAST_BinaryOperator::chillAST_BinaryOperator(chillAST_node *l, const char *oper, chillAST_node *r, chillAST_node *par) { - //fprintf(stderr, "chillAST_BinaryOperator::chillAST_BinaryOperator( l %p %s r %p, parent %p) this %p\n", l, oper, r, par, this); - fprintf(stderr, "chillAST_BinaryOperator::chillAST_BinaryOperator( l %s r )\n", oper); - - //if (l && r ) { - // fprintf(stderr, "("); l->print(0,stderr); fprintf(stderr, ") %s (", oper); r->print(0,stderr); fprintf(stderr, ")\n\n"); - //} - - lhs = l; - rhs = r; - parent = par; - - if (lhs) lhs->setParent( this ); - if (rhs) rhs->setParent( this ); // may only have part of the lhs and rhs when binop is created - op = strdup(oper); - asttype = CHILLAST_NODETYPE_BINARYOPERATOR; - - // if this writes to lhs and lhs type has an 'imwrittento' concept, set that up - if (isAssignmentOp()) { - if (lhs && lhs->isArraySubscriptExpr()) { - ((chillAST_ArraySubscriptExpr*)lhs)->imwrittento = true; - //fprintf(stderr, "chillAST_BinaryOperator, op '=', lhs is an array reference LVALUE\n"); - } - } - if (isAugmentedAssignmentOp()) { // += etc - //fprintf(stderr, "isAugmentedAssignmentOp() "); print(); fflush(stdout); - if (lhs && lhs->isArraySubscriptExpr()) { - //fprintf(stderr, "lhs is also read from "); lhs->print(); fflush(stdout); - ((chillAST_ArraySubscriptExpr*)lhs)->imreadfrom = true; // note will ALSO have imwrittento true - } - } - - isFromSourceFile = true; // default - filename = NULL; -} - - -int chillAST_BinaryOperator::evalAsInt() { - // very limited. allow +-*/ and integer literals ... - if (isAssignmentOp()) return rhs->evalAsInt(); // ?? ignores/loses lhs info - - if (!strcmp("+", op)) { - //fprintf(stderr, "chillAST_BinaryOperator::evalAsInt() %d + %d\n", lhs->evalAsInt(), rhs->evalAsInt()); - return lhs->evalAsInt() + rhs->evalAsInt(); - } - if (!strcmp("-", op)) return lhs->evalAsInt() - rhs->evalAsInt(); - if (!strcmp("*", op)) return lhs->evalAsInt() * rhs->evalAsInt(); - if (!strcmp("/", op)) return lhs->evalAsInt() / rhs->evalAsInt(); - - fprintf(stderr, "chillAST_BinaryOperator::evalAsInt() unhandled op '%s'\n", op); - segfault(); -} - -chillAST_IntegerLiteral *chillAST_BinaryOperator::evalAsIntegerLiteral() { - return new chillAST_IntegerLiteral( evalAsInt() ); // ?? -} - -void chillAST_BinaryOperator::dump( int indent, FILE *fp ) { - chillindent(indent, fp); - fprintf(fp, "(BinaryOperator '%s'\n", op); - - if (lhs) lhs->dump(indent+1, fp); // lhs could be null - else { chillindent(indent+1, fp); fprintf(fp, "(NULL)\n"); } - fflush(fp); - - if (rhs) rhs->dump(indent+1, fp); // rhs could be null - else { chillindent(indent+1, fp); fprintf(fp, "(NULL)\n"); } - fflush(fp); - - chillindent(indent, fp); - fprintf(fp, ")\n"); - fflush(fp); -} - -void chillAST_BinaryOperator::print( int indent, FILE *fp ) { // TODO this needparens logic is wrong - printPreprocBEFORE(indent, fp); - - chillindent( indent, fp ); - bool needparens = false; - if (lhs) { - if (lhs->isImplicitCastExpr()) { - // fprintf(stderr, "\nlhs 0x%x isImplicitCastExpr()\n", lhs); - // fprintf(stderr, "lhs subexpr 0x%x\n", ((chillAST_ImplicitCastExpr*)lhs)->subexpr); - // fprintf(stderr, "lhs subexpr type %s\n", ((chillAST_ImplicitCastExpr*)lhs)->subexpr->getTypeString()); - // - if (((chillAST_ImplicitCastExpr*)lhs)->subexpr->isNotLeaf()) needparens = true; - } - else if (lhs->isNotLeaf()) { - if (isMinusOp() && lhs->isPlusOp()) needparens = false; - else if (isPlusMinusOp() && lhs->isMultDivOp()) needparens = false; - else needparens = true; - } - } - - //fprintf(stderr, "\n\nbinop "); - //lhs->printonly(0,stderr); - //fprintf(stderr," %s ",op); - //rhs->printonly(0,stderr); - //fprintf(stderr,"\n"); - //fprintf(stderr, "op is %s lhs %s rhs %s\n", op, lhs->getTypeString(), rhs->getTypeString()); - //fprintf(stderr, "lhs "); lhs->printonly(0, stderr); fprintf(stderr, " "); - //fprintf(stderr, "lhs needparens = %d\n", needparens); - - - if (needparens) fprintf(fp, "("); - if (lhs) lhs->print( 0, fp ); - else fprintf(fp, "(NULL)"); - if (needparens) fprintf(fp, ")"); - - fprintf( fp, " %s ", op); - - needparens = false; - //fprintf(stderr, "binop rhs is of type %s\n", rhs->getTypeString()); - if (rhs) { - if (rhs->isImplicitCastExpr()) { - if (((chillAST_ImplicitCastExpr*)rhs)->subexpr->isNotLeaf()) needparens = true; - } - //else if (rhs->isNotLeaf()) needparens = true; // too many parens. test too simple - else if (rhs->isNotLeaf()) { - // really need the precedence ordering, and check relative of op and rhs op - if (isMinusOp() ) needparens = true; // safer. perhaps complicated thing on rhs of a minus - else if (isPlusMinusOp() && rhs->isMultDivOp()) needparens = false; - else needparens = true; - } - } - //fprintf(stderr, "rhs "); rhs->printonly(0, stderr); fprintf(stderr, " "); - //fprintf(stderr, "rhs needparens = %d\n\n", needparens); - //if (!needparens) fprintf(stderr, "rhs isNotLeaf() = %d\n", rhs->isNotLeaf()); - - if (needparens) fprintf(fp, "("); - if (rhs) rhs->print( 0, fp ); - else fprintf(fp, "(NULL)"); - if (needparens) fprintf(fp, ")"); - fflush(fp); - printPreprocAFTER(indent, fp); - -} - - -char *chillAST_BinaryOperator::stringRep(int indent ) { - std::string s = string( lhs->stringRep() ) + " " + op + " " + string(lhs->stringRep() ); - return strdup( s.c_str() ); -} - - - -void chillAST_BinaryOperator::printonly( int indent, FILE *fp ) { - - lhs->printonly( indent, fp ); - fprintf( fp, " %s ", op); - rhs->printonly( 0, fp ); - fflush(fp); - - - -} - - -class chillAST_node* chillAST_BinaryOperator::constantFold() { - //fprintf(stderr, "\nchillAST_BinaryOperator::constantFold() "); - //print(0,stderr); fprintf(stderr, "\n"); - - lhs = lhs->constantFold(); - rhs = rhs->constantFold(); - - chillAST_node *returnval = this; - - if (lhs->isConstant() && rhs->isConstant() ) { - //fprintf(stderr, "binop folding constants\n"); print(0,stderr); fprintf(stderr, "\n"); - - if (streq(op, "+") || streq(op, "-") || streq(op, "*")) { - if (lhs->isIntegerLiteral() && rhs->isIntegerLiteral()) { - chillAST_IntegerLiteral *l = (chillAST_IntegerLiteral *)lhs; - chillAST_IntegerLiteral *r = (chillAST_IntegerLiteral *)rhs; - chillAST_IntegerLiteral *I; - - if (streq(op, "+")) I = new chillAST_IntegerLiteral(l->value+r->value, parent); - if (streq(op, "-")) I = new chillAST_IntegerLiteral(l->value-r->value, parent); - if (streq(op, "*")) I = new chillAST_IntegerLiteral(l->value*r->value, parent); - - returnval = I; - //fprintf(stderr, "%d %s %d becomes %d\n", l->value,op, r->value, I->value); - } - else { // at least one is a float - - // usually don't want to do this for floats or doubles - // could probably check for special cases like 0.0/30.0 or X/X or X/1.0 -#ifdef FOLDFLOATS - float lval, rval; - if (lhs->isIntegerLiteral()) { - lval = (float) ((chillAST_IntegerLiteral *)lhs)->value; - } - else { - lval = ((chillAST_FloatingLiteral *)lhs)->value; - } - - if (rhs->isIntegerLiteral()) { - rval = (float) ((chillAST_IntegerLiteral *)rhs)->value; - } - else { - rval = ((chillAST_FloatingLiteral *)rhs)->value; - } - - chillAST_FloatingLiteral *F; - if (streq(op, "+")) F = new chillAST_FloatingLiteral(lval + rval, parent); - if (streq(op, "-")) F = new chillAST_FloatingLiteral(lval - rval, parent); - if (streq(op, "*")) F = new chillAST_FloatingLiteral(lval * rval, parent); - - returnval = F; -#endif - - } - } - //else fprintf(stderr, "can't fold op '%s' yet\n", op); - } - - //fprintf(stderr, "returning "); returnval->print(0,stderr); fprintf(stderr, "\n"); - return returnval; -} - - -class chillAST_node* chillAST_BinaryOperator::clone() { - //fprintf(stderr, "chillAST_BinaryOperator::clone() "); print(); printf("\n"); fflush(stdout); - - chillAST_node* l = lhs->clone(); - chillAST_node* r = rhs->clone(); - chillAST_BinaryOperator *bo = new chillAST_BinaryOperator( l, op, r, parent ); - l->setParent( bo ); - r->setParent( bo ); - bo->isFromSourceFile = isFromSourceFile; - if (filename) bo->filename = strdup(filename); - return bo; -} - -void chillAST_BinaryOperator::gatherArrayRefs( std::vector &refs, bool w ) { - //fprintf(stderr, "chillAST_BinaryOperator::gatherArrayRefs()\n"); - //print(); fflush(stdout); fprintf(stderr, "\n"); - //if (isAugmentedAssignmentOp()) { - // fprintf(stderr, "%s is augmented assignment\n", op); - //} - - //if (isAssignmentOp()) { - // fprintf(stderr, "%s is assignment\n", op); - //} - - //if (isAugmentedAssignmentOp()) { // lhs is ALSO on the RHS, NOT as a write - // if (lhs->isArraySubscriptExpr()) { // probably some case where this fails - // ((chillAST_ArraySubscriptExpr *) lhs)->imreadfrom = true; - // //lhs->&gatherArrayRefs( refs, 0 ); - // } - //} - - //fprintf(stderr, "in chillAST_BinaryOperator::gatherArrayRefs(), %d &arrayrefs before\n", refs.size()); - lhs->gatherArrayRefs( refs, isAssignmentOp() ); - //fprintf(stderr, "in chillAST_BinaryOperator::gatherArrayRefs(), %d &arrayrefs after lhs\n", refs.size()); - rhs->gatherArrayRefs( refs, 0 ); - //fprintf(stderr, "in chillAST_BinaryOperator::gatherArrayRefs(), %d &refs\n", refs.size()); - - //for (int i=0; ibasedecl->varname); - //} - -} - -void chillAST_BinaryOperator::gatherScalarRefs( std::vector &refs, bool writtento ) { - lhs->gatherScalarRefs( refs, isAssignmentOp() ); - rhs->gatherScalarRefs( refs, 0 ); -} - - -void chillAST_BinaryOperator::replaceChild( chillAST_node *old, chillAST_node *newchild ) { - //fprintf(stderr, "\nbinop::replaceChild( old 0x%x, new ) lhs 0x%x rhd 0x%x\n", old, lhs, rhs); - - // will pointers match?? - if (lhs == old) setLHS( newchild ); - else if (rhs == old) setRHS( newchild ); - - // silently ignore? - //else { - // fprintf(stderr, "\nERROR chillAST_BinaryOperator::replaceChild( old 0x%x, new ) lhs 0x%x rhd 0x%x\n", old, lhs, rhs); - // fprintf(stderr, "old is not a child of this BinaryOperator\n"); - // print(); - // dump(); - // exit(-1); - //} -} - - - -void chillAST_BinaryOperator::gatherVarDecls( vector &decls ) { - //fprintf(stderr, "chillAST_BinaryOperator::gatherVarDecls()\n"); - - //fprintf(stderr, "chillAST_BinaryOperator::gatherVarDecls() before %d\n", decls.size()); - //print(0,stderr); fprintf(stderr, "\n"); - //fprintf(stderr, "lhs is %s\n", lhs->getTypeString()); - if (lhs) lhs->gatherVarDecls( decls ); // 'if' to deal with partially formed - if (rhs) rhs->gatherVarDecls( decls ); - //fprintf(stderr, "after %d\n", decls.size()); -} - - -void chillAST_BinaryOperator::gatherScalarVarDecls( vector &decls ) { - //fprintf(stderr, "chillAST_BinaryOperator::gatherScalarVarDecls() before %d\n", decls.size()); - //fprintf(stderr, "lhs is %s\n", lhs->getTypeString()); - lhs->gatherScalarVarDecls( decls ); - rhs->gatherScalarVarDecls( decls ); - //fprintf(stderr, "after %d\n", decls.size()); -} - - -void chillAST_BinaryOperator::gatherArrayVarDecls( vector &decls ) { - //fprintf(stderr, "chillAST_BinaryOperator::gatherArrayVarDecls() before %d\n", decls.size()); - //fprintf(stderr, "lhs is %s\n", lhs->getTypeString()); - lhs->gatherArrayVarDecls( decls ); - rhs->gatherArrayVarDecls( decls ); - //fprintf(stderr, "after %d\n", decls.size()); -} - - - -void chillAST_BinaryOperator::gatherDeclRefExprs( vector&refs ) { - lhs->gatherDeclRefExprs( refs ); - rhs->gatherDeclRefExprs( refs ); -} - - -void chillAST_BinaryOperator::gatherStatements(std::vector &statements ){ - - // what's legit? - if (isAssignmentOp()) { - statements.push_back( this ); - } - -} - - - - -void chillAST_BinaryOperator::gatherVarUsage( vector &decls ) { - lhs->gatherVarUsage( decls ); - rhs->gatherVarUsage( decls ); -} - -void chillAST_BinaryOperator::gatherVarLHSUsage( vector &decls ) { - lhs->gatherVarUsage( decls ); -} - - void chillAST_BinaryOperator::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) { - //if (!strcmp(op, "<=")) { - // fprintf(stderr, "chillAST_BinaryOperator::replaceVarDecls( old %s, new %s)\n", olddecl->varname, newdecl->varname ); - // print(); printf("\n"); fflush(stdout); - // fprintf(stderr, "binaryoperator, lhs is of type %s\n", lhs->getTypeString()); - // fprintf(stderr, "binaryoperator, rhs is of type %s\n", rhs->getTypeString()); - //} - lhs->replaceVarDecls( olddecl, newdecl ); - rhs->replaceVarDecls( olddecl, newdecl ); - //if (!strcmp(op, "<=")) { - // print(); printf("\n\n"); fflush(stdout); - //} - } - - -bool chillAST_BinaryOperator::isSameAs( chillAST_node *other ){ - if (!other->isBinaryOperator()) return false; - chillAST_BinaryOperator *o = (chillAST_BinaryOperator *)other; - if (strcmp(op, o->op)) return false; // different operators - return lhs->isSameAs( o->lhs ) && rhs->isSameAs( o->rhs ); // recurse -} - - - - -chillAST_TernaryOperator::chillAST_TernaryOperator() { - op = strdup("?"); // the only one so far - condition = lhs = rhs = NULL; - asttype = CHILLAST_NODETYPE_TERNARYOPERATOR; - isFromSourceFile = true; // default - filename = NULL; -} - -chillAST_TernaryOperator::chillAST_TernaryOperator(const char *oper, chillAST_node *c, chillAST_node *l, chillAST_node *r, chillAST_node *par) { - - op = strdup(oper); - condition = c; condition->setParent( this ); - lhs = l; lhs->setParent( this ); - rhs = r; rhs->setParent( this ); - asttype = CHILLAST_NODETYPE_TERNARYOPERATOR; - isFromSourceFile = true; // default - filename = NULL; -} - -void chillAST_TernaryOperator::dump( int indent, FILE *fp ) { - chillindent(indent, fp); - fprintf(fp, "(TernaryOperator '%s'\n", op); - condition->dump(indent+1, fp); - lhs->dump(indent+1, fp); - rhs->dump(indent+1, fp); - chillindent(indent, fp); - fprintf(fp, ")\n"); - fflush(fp); -} - -void chillAST_TernaryOperator::print( int indent, FILE *fp ) { - printPreprocBEFORE(indent, fp); - chillindent(indent, fp); - fprintf(fp, "("); - condition->print(0,fp); - fprintf(fp, "%s", op); - lhs->print(0,fp); - fprintf(fp, ":"); - rhs->print(0,fp); - fprintf(fp, ")"); - fflush(fp); -} - -void chillAST_TernaryOperator::replaceChild( chillAST_node *old, chillAST_node *newchild ) { - //fprintf(stderr, "\nbinop::replaceChild( old 0x%x, new ) lhs 0x%x rhd 0x%x\n", old, lhs, rhs); - - // will pointers match?? - if (lhs == old) setLHS( newchild ); - else if (rhs == old) setRHS( newchild ); - else if (condition == old) setCond( newchild ); - - // silently ignore? - //else { - //} -} - - -void chillAST_TernaryOperator::gatherVarDecls( vector &decls ) { - condition->gatherVarDecls( decls ); - lhs->gatherVarDecls( decls ); - rhs->gatherVarDecls( decls ); -} - -void chillAST_TernaryOperator::gatherScalarVarDecls( vector &decls ) { - condition->gatherScalarVarDecls( decls ); - lhs->gatherScalarVarDecls( decls ); - rhs->gatherScalarVarDecls( decls ); -} - - -void chillAST_TernaryOperator::gatherArrayVarDecls( vector &decls ) { - condition->gatherArrayVarDecls( decls ); - lhs->gatherArrayVarDecls( decls ); - rhs->gatherArrayVarDecls( decls ); -} - - - -void chillAST_TernaryOperator::gatherDeclRefExprs( vector&refs ) { - condition->gatherDeclRefExprs( refs ); - lhs->gatherDeclRefExprs( refs ); - rhs->gatherDeclRefExprs( refs ); -} - - - -void chillAST_TernaryOperator::gatherVarUsage( vector &decls ) { - condition->gatherVarUsage( decls ); - lhs->gatherVarUsage( decls ); - rhs->gatherVarUsage( decls ); -} - -void chillAST_TernaryOperator::gatherVarLHSUsage( vector &decls ) { - // this makes no sense for ternary ?? -} - -void chillAST_TernaryOperator::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) { - condition->replaceVarDecls( olddecl, newdecl ); - lhs->replaceVarDecls( olddecl, newdecl ); - rhs->replaceVarDecls( olddecl, newdecl ); -} - -void chillAST_TernaryOperator::printonly( int indent, FILE *fp ) { - fprintf(fp, "("); - condition->printonly(0,fp); - fprintf(fp, "%s", op); - lhs->printonly(0,fp); - fprintf(fp, ":"); - rhs->printonly(0,fp); - fprintf(fp, ")"); - fflush(fp); -} - - -class chillAST_node* chillAST_TernaryOperator::constantFold() { - condition = condition->constantFold(); - lhs = lhs->constantFold(); - rhs = rhs->constantFold(); - - chillAST_node *returnval = this; - - if (condition->isConstant()) { - //fprintf(stderr, "ternop folding constants\n"); - //print(0,stderr); - //fprintf(stderr, "\n"); - - // assume op is "?" - // TODO - /* - - if (streq(op, "+") || streq(op, "-") || streq(op, "*")) { - if (lhs->isIntegerLiteral() && rhs->isIntegerLiteral()) { - chillAST_IntegerLiteral *l = (chillAST_IntegerLiteral *)lhs; - chillAST_IntegerLiteral *r = (chillAST_IntegerLiteral *)rhs; - chillAST_IntegerLiteral *I; - - if (streq(op, "+")) I = new chillAST_IntegerLiteral(l->value+r->value, parent); - if (streq(op, "-")) I = new chillAST_IntegerLiteral(l->value-r->value, parent); - if (streq(op, "*")) I = new chillAST_IntegerLiteral(l->value*r->value, parent); - - returnval = I; - //fprintf(stderr, "%d %s %d becomes %d\n", l->value,op, r->value, I->value); - } - else { // at least one is a float - float lval, rval; - if (lhs->isIntegerLiteral()) { - lval = (float) ((chillAST_IntegerLiteral *)lhs)->value; - } - else { - lval = ((chillAST_FloatingLiteral *)lhs)->value; - } - if (rhs->isIntegerLiteral()) { - rval = (float) ((chillAST_IntegerLiteral *)rhs)->value; - } - else { - rval = ((chillAST_FloatingLiteral *)rhs)->value; - } - - chillAST_FloatingLiteral *F; - if (streq(op, "+")) F = new chillAST_FloatingLiteral(lval + rval, parent); - if (streq(op, "-")) F = new chillAST_FloatingLiteral(lval - rval, parent); - if (streq(op, "*")) F = new chillAST_FloatingLiteral(lval * rval, parent); - - returnval = F; - } - } - else fprintf(stderr, "can't fold op '%s' yet\n", op); - */ - } - - return returnval; -} - -class chillAST_node* chillAST_TernaryOperator::clone() { - chillAST_node* c = condition->clone(); - chillAST_node* l = lhs->clone(); - chillAST_node* r = rhs->clone(); - chillAST_TernaryOperator *to = new chillAST_TernaryOperator( op, l, r, parent ); - c->setParent( to ); - l->setParent( to ); - r->setParent( to ); - to->isFromSourceFile = isFromSourceFile; - filename = NULL; - return to; -} - -void chillAST_TernaryOperator::gatherArrayRefs( std::vector &refs, bool w ) { - condition->gatherArrayRefs( refs, isAssignmentOp() ); - lhs->gatherArrayRefs( refs, isAssignmentOp() ); - rhs->gatherArrayRefs( refs, 0 ); -} - -void chillAST_TernaryOperator::gatherScalarRefs( std::vector &refs, bool writtento ) { - condition->gatherScalarRefs( refs, isAssignmentOp() ); - lhs->gatherScalarRefs( refs, isAssignmentOp() ); - rhs->gatherScalarRefs( refs, 0 ); -} - - - - - - - -chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() { - //fprintf(stderr, "\n%p chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() 0\n", this); - asttype = CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR; - base = index = NULL; - basedecl = NULL; //fprintf(stderr, "setting basedecl NULL for ASE %p\n", this); - imwrittento = false; // ?? - imreadfrom = false; // ?? - parent = NULL; - metacomment = NULL; - //fprintf(stderr, "chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() NEED TO FAKE A LOCATION\n"); - isFromSourceFile = true; // default - filename = NULL; - //fprintf(stderr, "\nASE %p is empty\n", this); -} - - - -chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr( chillAST_node *bas, chillAST_node *indx, chillAST_node *par, void *unique ) { - - //fprintf(stderr, "\nchillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() 1\n"); - //fprintf(stderr, "ASE index %p ", indx); indx->print(0,stderr); fprintf(stderr, "\n"); - asttype = CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR; - bas->setParent( this ); - if (bas->isImplicitCastExpr()) base = ((chillAST_ImplicitCastExpr*)bas)->subexpr; // probably wrong - else base = bas; - if (indx->isImplicitCastExpr()) index = ((chillAST_ImplicitCastExpr*)indx)->subexpr; // probably wrong - else index = indx; - - base->setParent( this ); - index->setParent( this ); - - imwrittento = false; // ?? - imreadfrom = false; // ?? - uniquePtr = (void *) unique; - //fprintf(stderr,"chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() original = 0x%x\n", uniquePtr); - //fprintf(stderr, "chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() 1 calling multibase()\n"); - basedecl = multibase();//fprintf(stderr, "%p ASE 1 basedecl = %p\n",this,basedecl); - //basedecl->print(); printf("\n"); - //basedecl->dump(); printf("\n"); fflush(stdout); - //fprintf(stderr, "basedecl varname %s\n", basedecl->varname); - isFromSourceFile = true; // default - filename = NULL; - - //fprintf(stderr, "\nASE %p parent %p ", this, parent); print(0,stderr); fprintf(stderr, "\n\n"); -} - - - -chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr( chillAST_node *bas, chillAST_node *indx, bool writtento, chillAST_node *par, void *unique ) { - //fprintf(stderr, "\nchillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() 2 parent %p\n", par ); - //fprintf(stderr, "ASE %p index %p ", this, indx); indx->print(0,stderr); fprintf(stderr, "\n"); - - asttype = CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR; - bas->setParent( this ); - if (bas->isImplicitCastExpr()) base = ((chillAST_ImplicitCastExpr*)bas)->subexpr; // probably wrong - else base = bas; - - if (indx->isImplicitCastExpr()) index = ((chillAST_ImplicitCastExpr*)indx)->subexpr; // probably wrong - else index = indx; - - //fprintf(stderr, "setting parent of base %p to %p\n", base, this); - //fprintf(stderr, "setting parent of index %p to %p\n", index, this); - base->setParent( this ); - index->setParent( this ); - - imwrittento = writtento; // ?? - //fprintf(stderr, "ASE %p imwrittento %d\n", this, imwrittento); - imreadfrom = false; // ?? - - uniquePtr = (void *) unique; - //fprintf(stderr,"chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() original = 0x%x\n", uniquePtr); - - basedecl = multibase(); - - //fprintf(stderr, "%p ASE 2 basedecl = %p\n", this, basedecl); - //printf("basedecl is "); fflush(stdout); basedecl->print(); printf("\n"); fflush(stdout); - //basedecl->dump(); printf("\n"); fflush(stdout); - //fprintf(stderr, "basedecl varname %s\n", basedecl->varname); - isFromSourceFile = true; // default - filename = NULL; - - //fprintf(stderr, "chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() 2 DONE\n"); - //print(0,stderr); fprintf(stderr, "\n\n"); - //fprintf(stderr, "\nASE %p parent %p ", this, parent); print(0,stderr); fprintf(stderr, "\n\n"); - } - - - -chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr( chillAST_VarDecl *v, std::vector indeces, chillAST_node *par) { - //fprintf(stderr, "\nchillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() 4\n"); - //fprintf(stderr,"chillAST_ArraySubscriptExpr( chillAST_VarDecl *v, std::vector indeces)\n"); - asttype = CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR; - parent = par; - //if (parent == NULL) { - // fprintf(stderr, "dammit. ASE %p has no parent\n", this); - //} - - - int numindeces = indeces.size(); - for (int i=0; iprint(0,stderr); fprintf(stderr, "\n"); - // printf("["); - // indeces[i]->print(); - // printf("]"); - } - //fflush(stdout); - //fprintf(stderr, "\n"); - - chillAST_DeclRefExpr *DRE = new chillAST_DeclRefExpr( v->vartype, v->varname, v, NULL); - basedecl = v; // ?? - //fprintf(stderr, "%p ASE 3 basedecl = %p ", this, basedecl); - //fprintf(stderr, "of type %s\n", basedecl->getTypeString()); - //basedecl->print(); printf("\n"); - //basedecl->dump(); printf("\n"); fflush(stdout); - //fprintf(stderr, "basedecl varname %s\n", basedecl->varname); - - chillAST_ArraySubscriptExpr *rent = this; // parent for subnodes - - // these are on the top level ASE that we're creating here - base = (chillAST_node *) DRE; - index = indeces[ numindeces-1]; - - base->setParent( this ); - index->setParent(this); - - for (int i=numindeces-2; i>=0; i--) { - - chillAST_ArraySubscriptExpr *ASE = new chillAST_ArraySubscriptExpr( DRE, indeces[i], rent, 0); - rent->base = ASE; // - rent = ASE; - } - - imwrittento = false; - imreadfrom = false; - //fprintf(stderr, "ASE is "); print(); printf("\n\n"); fflush(stdout); - isFromSourceFile = true; // default - filename = NULL; - - //fprintf(stderr, "\nASE %p parent %p ", this, parent); print(0,stderr); fprintf(stderr, "\n\n"); -} - - - -chillAST_node *chillAST_node::getEnclosingStatement( int level ) { // TODO do for subclasses? - - //fprintf(stderr, "chillAST_node::getEnclosingStatement( level %d ) node type %s\n", level, getTypeString()); - //print(); printf("\n"); fflush(stdout); - - // so far, user will ONLY call this directly on an array subscript expression - if (isArraySubscriptExpr()) return parent->getEnclosingStatement( level+1); - - if (level != 0) { - if (isBinaryOperator() || - isUnaryOperator() || - isTernaryOperator() || - isReturnStmt() || - isCallExpr() - ) return this; - - - // things that are not endpoints. recurse through parent - if (isMemberExpr()) return parent->getEnclosingStatement( level+1 ); - if (isImplicitCastExpr()) return parent->getEnclosingStatement( level+1 ); - if (isSizeof()) return parent->getEnclosingStatement( level+1 ); - if (isCStyleCastExpr()) return parent->getEnclosingStatement( level+1 ); - return NULL; - } - - fprintf(stderr, "getEnclosingStatement() level %d type %s, returning NULL\n", level, getTypeString()); - segfault(); - - return NULL; -} - - - -void chillAST_ArraySubscriptExpr::gatherIndeces(std::vector&ind) { - if (base->isArraySubscriptExpr()) ((chillAST_ArraySubscriptExpr *)base)->gatherIndeces( ind ); - ind.push_back( index ); -} - - - -void chillAST_ArraySubscriptExpr::dump( int indent, FILE *fp ) { -// fprintf(stderr, "\n%p chillAST_ArraySubscriptExpr::dump() basedecl %p\n", basedecl); - - char *local; - if (basedecl && basedecl->vartype) { - local = strdup( basedecl->vartype ); - } - else { - fprintf(stderr, "%p chillAST_ArraySubscriptExpr::dump(), no basedecl ???\n",this); - local = strdup(""); - //fprintf(stderr, "base is "); base->dump(); printf("\n"); base->print(); printf("\n"); fflush(stdout); - //print(); printf("\n"); fflush(stdout); - } - - - char *space = rindex(local, ' '); // can't use index because it's a class member! - if (space) *space = '\0'; // turn "float *" into "float" - - chillindent(indent, fp); - //fprintf(fp, "(ArraySubscriptExpr '%s' ", local); - if (basedecl) { - //fprintf(stderr, " chillAST_ArraySubscriptExpr::dump() basedecl is of type %s\n", basedecl->getTypeString()); - fprintf(fp, "(ArraySubscriptExpr (%s) '%s' ", basedecl->varname, local); - } - else fprintf(stderr, " chillAST_ArraySubscriptExpr::dump() has no basedecl\n"); - free(local); - - if (imwrittento) { - if (imreadfrom) fprintf(fp, "lvalue AND rvalue\n"); - else fprintf(fp, "lvalue\n"); - } - else fprintf(fp, "rvalue\n"); - base->dump( indent+1, fp ); - index->dump(indent+1, fp); - - chillindent(indent, fp); - fprintf(fp, ")\n"); - fflush(fp); -} - - - -void chillAST_ArraySubscriptExpr::print( int indent, FILE *fp ) { - base->print( indent, fp ); - fprintf(fp, "["); - index->print(0, fp); - fprintf(fp, "]"); - fflush(fp); -} - -char *chillAST_ArraySubscriptExpr::stringRep(int indent ) { - fprintf(stderr, "chillAST_ArraySubscriptExpr::stringRep\n"); - - char *blurb; - char *b = base->stringRep(0); - char *i = index->stringRep(0); - // combine. shoudl be using strings. much cleaner TODO - std::string s = string(b) + "[" + string(i) + "]"; - fprintf(stderr, "ASE stringrep %s\n", s.c_str()); - return strdup( s.c_str()); - - -} - - -void chillAST_ArraySubscriptExpr::printonly( int indent, FILE *fp ) { - base->printonly( indent, fp ); - fprintf(fp, "["); - index->printonly(0, fp); - fprintf(fp, "]"); - fflush(fp); -} - - -void chillAST_ArraySubscriptExpr::print( int indent, FILE *fp ) const { - base->print( indent, fp ); - fprintf(fp, "["); - index->print(0, fp); - fprintf(fp, "]"); - fflush(fp); -}; - - -chillAST_VarDecl *chillAST_ArraySubscriptExpr::multibase() { - // return the VARDECL of the thing the subscript is an index into - //this should probably be a chillAST_node function instead of having all these ifs - //print(); printf("\n"); fflush(stdout); - //base->print(); printf("\n"); fflush(stdout); - //fprintf(stderr, "chillAST_ArraySubscriptExpr::multibase() base of type %s\n", base->getTypeString()); - - return base->multibase(); - - // this will be used to SET basedecl - //basedecl = NULL; // do this so we don't confuse ourselves looking at uninitialized basedecl - - chillAST_node *b = base; - //fprintf(stderr, "base is of type %s\n", b->getTypeString()); - - if (!b) return NULL; // just in case ?? - - if (base->asttype == CHILLAST_NODETYPE_IMPLICITCASTEXPR) { // bad coding - b = ((chillAST_ImplicitCastExpr*)b)->subexpr; - } - - if (b->asttype == CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR) { // multidimensional array! - // recurse - return ((chillAST_ArraySubscriptExpr *)b)->multibase(); - } - - if (b->asttype == CHILLAST_NODETYPE_DECLREFEXPR) return(((chillAST_DeclRefExpr*)b)->getVarDecl()); - - - if (b->isBinaryOperator()) { - // presumably a dot or pointer ref that resolves to an array - chillAST_BinaryOperator *BO = (chillAST_BinaryOperator *) b; - if ( strcmp(BO->op, ".") ) { - fprintf(stderr, "chillAST_ArraySubscriptExpr::multibase(), UNHANDLED case:\n"); - fprintf(stderr, "base is binary operator, of type %s\n", BO->op); - exit(-1); - } - - chillAST_node *l = BO->lhs; - chillAST_node *r = BO->rhs; - printf("L %s\nR %s\n", l->getTypeString(), r->getTypeString()); - exit(-1); - - return NULL; // TODO do checks? - } - - if (b->isMemberExpr()) { - //c.i[c.count] we want i member of inspector - - chillAST_MemberExpr *ME = (chillAST_MemberExpr *) b; - //fprintf(stderr, "multibase() Member Expression "); ME->print(); printf("\n"); fflush(stdout); - - chillAST_node *n = ME->base; // WRONG want the MEMBER - //fprintf(stderr, "chillAST_ArraySubscriptExpr::multibase() Member Expression base of type %s\n", n->getTypeString()); - //fprintf(stderr, "base is "); ME->base->dump(); - - // NEED to be able to get lowest level recorddecl or typedef from this base - - fprintf(stderr, "chillast.cc, L2315, bailing??\n"); - exit(0); - - if (!n->isDeclRefExpr()) { - fprintf(stderr, "MemberExpr member is not chillAST_DeclRefExpr\n"); - exit(-1); - } - chillAST_DeclRefExpr *DRE = (chillAST_DeclRefExpr *)n; - n = DRE->decl; - //fprintf(stderr, "DRE decl is of type %s\n", n->getTypeString()); - assert( n->isVarDecl() ); - chillAST_VarDecl *vd = (chillAST_VarDecl *) n; - vd->print(); printf("\n"); fflush(stdout); - - chillAST_TypedefDecl *tdd = vd->typedefinition; - chillAST_RecordDecl *rd = vd->vardef; - //fprintf(stderr, "tdd %p rd %p\n", tdd, rd); - - print(); printf("\n"); - dump(); printf("\n"); fflush(stdout); - - assert( tdd != NULL || rd != NULL ); - - chillAST_VarDecl *sub; - if (tdd) sub = tdd->findSubpart( ME->member ); - if (rd) sub = rd->findSubpart( ME->member ); - - //fprintf(stderr, "subpart is "); sub->print(); printf("\n"); fflush(stdout); - - return sub; // what if the sub is an array ?? TODO - } - - - fprintf(stderr, "chillAST_ArraySubscriptExpr::multibase(), UNHANDLED case %s\n", - b->getTypeString()); - print(); printf("\n"); fflush(stdout); - fprintf(stderr, "base is: "); b->print(); printf("\n"); fflush(stdout); - segfault(); -} - - -chillAST_node *chillAST_ArraySubscriptExpr::getIndex(int dim) { - //fprintf(stderr, "chillAST_ArraySubscriptExpr::getIndex( %d )\n", dim); - - chillAST_node *b = base; - - int depth = 0; - std::vector ind; - chillAST_node *curindex = index; - for (;;) { - if (b->asttype == CHILLAST_NODETYPE_IMPLICITCASTEXPR) b = ((chillAST_ImplicitCastExpr*)b)->subexpr; - else if (b->asttype == CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR) { - //fprintf(stderr, "base "); b->print(); fprintf(stderr, "\n"); - //fprintf(stderr, "index "); curindex->print(); fprintf(stderr, "\n"); - ind.push_back(curindex); - curindex = ((chillAST_ArraySubscriptExpr*)b)->index; - b = ((chillAST_ArraySubscriptExpr*)b)->base; - depth++; - } - else { - //fprintf(stderr, "base "); b->print(); fprintf(stderr, "\n"); - //fprintf(stderr, "index "); curindex->print(); fprintf(stderr, "\n"); - //fprintf(stderr, "stopping at base type %s\n", b->getTypeString()); - ind.push_back(curindex); - break; - } - } - //fprintf(stderr, "depth %d\n", depth ); - //for (int i=0; iprint(); fprintf(stderr, "\n"); } - - return ind[ depth - dim ]; - /* - if (dim == 0) return index; // single dimension - fprintf(stderr, "DIM NOT 0\n"); - // multidimension - chillAST_node *b = base; - if (base->asttype == CHILLAST_NODETYPE_IMPLICITCASTEXPR) { // bad coding - b = ((chillAST_ImplicitCastExpr*)b)->subexpr; - } - if (b->asttype == CHILLAST_NODETYPE_IMPLICITCASTEXPR) { // bad coding - b = ((chillAST_ImplicitCastExpr*)b)->subexpr; - } - - b->print(); printf("\n"); fflush(stdout); - if (b->asttype == CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR) { - return ((chillAST_ArraySubscriptExpr *)b)->getIndex(dim-1); - } - - fprintf(stderr, "chillAST_ArraySubscriptExpr::getIndex() failed\n"); - */ - exit(-1); -} - - - - -class chillAST_node* chillAST_ArraySubscriptExpr::constantFold() { - //fprintf(stderr, "chillAST_ArraySubscriptExpr::constantFold()\n"); - base = base->constantFold(); - index = index->constantFold(); - return this; -} - -class chillAST_node* chillAST_ArraySubscriptExpr::clone() { - //fprintf(stderr,"chillAST_ArraySubscriptExpr::clone() old imwrittento %d\n", imwrittento); - //fprintf(stderr, "cloning ASE %p ", this); print(0,stderr); printf(" with parent %p\n", parent); fflush(stdout); - //fprintf(stderr, "base %p base->parent %p index %p index->parent %p\n", base, base->parent, index, index->parent); - - //fprintf(stderr, "old base "); base->print(); printf("\n"); fflush(stdout); - //fprintf(stderr, "old base "); base->dump(); printf("\n"); fflush(stdout); - if (base->isDeclRefExpr()) { - chillAST_VarDecl *vd = (chillAST_VarDecl *)(((chillAST_DeclRefExpr *)base)->decl); - //fprintf(stderr, "old decl "); vd->print(); printf("\n");fflush(stdout); - //fprintf(stderr, "old decl "); vd->dump(); printf("\n");fflush(stdout); - } - chillAST_node *b = base->clone(); - //fprintf(stderr, "new base "); b->print(); printf("\n"); fflush(stdout); - //fprintf(stderr, "new base "); b->dump(); printf("\n"); fflush(stdout); - - chillAST_node *i = index->clone(); - //fprintf(stderr, "new index "); i->print(); printf("\n"); fflush(stdout); - - - //if (!index->parent) { - // fprintf(stderr, "ASE %p SOURCE OF CLONE INDEX %p of type %s HAS NO PARENT\n", this, index, index->getTypeString()); - // fprintf(stderr, "ASE SOURCE IS "); print(0,stderr); fprintf(stderr, "\n\n"); - //} - //fprintf(stderr, "cloning AST %p, after cloning base and index, creating a new ASE\n", this); - chillAST_ArraySubscriptExpr *ASE = new chillAST_ArraySubscriptExpr( b, i, imwrittento, parent, uniquePtr /* ?? */ ); - //fprintf(stderr, "cloned AST will be %p with parent %p and base %p index %p\n", ASE, parent, b, i); - - ASE->imreadfrom = false; // don't know this yet - //ASE->imreadfrom = imreadfrom; // ?? - //if (ASE->imreadfrom) { - // fprintf(stderr, "in chillAST_ArraySubscriptExpr::clone(), imreadfrom is being set. \n"); - // ASE->print(); fflush(stdout); fprintf(stderr, "\n"); - //} - - //fprintf(stderr, "cloned result "); ASE->print(); printf("\n\n\n"); fflush(stdout); - //fprintf(stderr, "ASE clone() this 0x%x clone 0x%x\n", this, ASE); - ASE->isFromSourceFile = isFromSourceFile; - if (filename) ASE->filename = strdup(filename); - return ASE; -} - -void chillAST_ArraySubscriptExpr::gatherArrayRefs( std::vector &refs, bool writtento ) { - //fprintf(stderr, "chillAST_ArraySubscriptExpr::gatherArrayRefs setting imwrittento %d for ", writtento); -//fprintf(stderr, "%s ", base->getTypeString()); -//base->print(); printf("\n"); fflush(stdout); - - //fprintf(stderr, "found an array subscript. &refs 0x%x ", refs); - if (!imwrittento) imwrittento = writtento; // may be both written and not for += - fflush(stdout); - - //fprintf(stderr, "recursing on index "); index->print(0,stderr); fprintf(stderr, "\n"); - index->gatherArrayRefs( refs, 0 ); // recurse first - //fprintf(stderr, "adding this "); print(0,stderr); fprintf(stderr, "\n"); - //fprintf(stderr, "refs[%d] = 0x%x = ", refs.size(), this); print(); fflush(stdout); - refs.push_back( this ); - - //fprintf(stderr, " size now %d\n", refs.size()); - -} - -void chillAST_ArraySubscriptExpr::gatherScalarRefs( std::vector &refs, bool writtento ) { - index->gatherScalarRefs( refs, 0 ); -} - -void chillAST_ArraySubscriptExpr::gatherVarDecls( vector &decls ) { - //fprintf(stderr, "chillAST_ArraySubscriptExpr::gatherVarDecls()\n"); - - base->gatherVarDecls( decls ); - index->gatherVarDecls( decls ); -} - - -void chillAST_ArraySubscriptExpr::gatherScalarVarDecls( vector &decls ) { - //fprintf(stderr, "chillAST_ArraySubscriptExpr::gatherScalarVarDecls()\n"); - //fprintf(stderr, "base %s index %s\n", base->getTypeString(), index->getTypeString()); - base->gatherScalarVarDecls( decls ); - index->gatherScalarVarDecls( decls ); -} - - -void chillAST_ArraySubscriptExpr::gatherArrayVarDecls( vector &decls ) { - //fprintf(stderr, "chillAST_ArraySubscriptExpr::gatherArrayVarDecls()\n"); - //fprintf(stderr, "base %s index %s\n", base->getTypeString(), index->getTypeString()); - base->gatherArrayVarDecls( decls ); - index->gatherArrayVarDecls( decls ); -} - - -void chillAST_ArraySubscriptExpr::gatherDeclRefExprs( vector&refs ) { - base->gatherDeclRefExprs( refs ); - index->gatherDeclRefExprs( refs ); -} - - -void chillAST_ArraySubscriptExpr::gatherVarUsage( vector &decls ) { - base->gatherVarUsage( decls ); - index->gatherVarUsage( decls ); -} - - -void chillAST_ArraySubscriptExpr::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ - base->replaceVarDecls( olddecl, newdecl ); - index->replaceVarDecls( olddecl, newdecl ); -} - - -void chillAST_ArraySubscriptExpr::replaceChild( chillAST_node *old, chillAST_node *newchild ) { - //fprintf(stderr,"chillAST_ArraySubscriptExpr::replaceChild()\n"); - - // arraysubscriptexpression doesn t really have children (should it?) - // try index ??? - if (old == index) { - //fprintf(stderr, "old is index\n"); - index = newchild; - index->parent = this; - return; - } - - // try base ??? unclear if this makes sense TODO - if (old == base) { - //fprintf(stderr, "old is base\n"); - base = newchild; - base->parent = this; - return; - } - - fprintf(stderr, "chillAST_ArraySubscriptExpr::replaceChild() old is not base or index\n"); - print(0,stderr); fprintf(stderr, "\nchild: "); - if (!old) fprintf(stderr, "oldchild NULL!\n"); - old->print(0,stderr); fprintf(stderr, "\nnew: "); - newchild->print(0,stderr); fprintf(stderr, "\n"); - segfault(); // make easier for gdb -}; - - -bool chillAST_ArraySubscriptExpr::operator!=( const chillAST_ArraySubscriptExpr &other) { - bool opposite = *this == other; - return !opposite; -} - - - -bool chillAST_ArraySubscriptExpr::operator==( const chillAST_ArraySubscriptExpr &other) { - //fprintf(stderr, "chillAST_ArraySubscriptExpr::operator==\n"); - //fprintf(stderr, "this->basedecl 0x%x other.basedecl 0x%x\n", this->basedecl, other.basedecl); - //this->basedecl->print(); printf("\n\n"); - //other.basedecl->print(); printf("\n"); fflush(stdout); - - //this->print(); printf(" 0x%x == 0x%x ",this->uniquePtr, other.uniquePtr ); other.print(); printf(" ?? "); fflush(stdout); - //if ( this->uniquePtr == other.uniquePtr) fprintf(stderr, "t\n"); - //else fprintf(stderr, "f\n"); - return this->uniquePtr == other.uniquePtr; -} - - - - - -chillAST_MemberExpr::chillAST_MemberExpr() { - asttype = CHILLAST_NODETYPE_MEMBEREXPR; - base = NULL; - member = NULL; - parent = NULL; - metacomment = NULL; - exptype = CHILL_MEMBER_EXP_DOT; - isFromSourceFile = true; // default - filename = NULL; -} - -chillAST_MemberExpr::chillAST_MemberExpr( chillAST_node *bas, const char *mem, chillAST_node *p, void *unique, CHILL_MEMBER_EXP_TYPE t ) { - asttype = CHILLAST_NODETYPE_MEMBEREXPR; - base = bas; - if (base) base->setParent( this ); - if (mem) member = strdup( mem ); - parent = p; - metacomment = NULL; - uniquePtr = unique; - exptype = t; - isFromSourceFile = true; // default - filename = NULL; - - return; // ignore tests below ?? TODO ?? - - - // base needs to RESOLVE to a decl ref expr but may not BE one - // A.b . c lhs is a binop or memberexpr - - if (bas->isBinaryOperator()) { - //fprintf(stderr, "checking binop to see if it resolved to a declrefexpr\n"); - // cheat for now or just remove the check below - return; - } - - if (! ( bas->isDeclRefExpr() || bas->isArraySubscriptExpr() )) { - fprintf(stderr, "chillAST_MemberExpr::chillAST_MemberExpr(), base is of type %s\n", bas->getTypeString()); - fprintf(stderr, "chillAST_MemberExpr::chillAST_MemberExpr(), base is not DeclRefExpr\n"); - - base->print(); printf(".%s\n", mem); fflush(stdout); - segfault(); - } -} - - -void chillAST_MemberExpr::dump( int indent, FILE *fp ) { - chillindent(indent, fp); - fprintf(fp, "(MemberExpr \n"); - - base->dump( indent+1, fp ); - chillindent(indent+1, fp); - if (exptype == CHILL_MEMBER_EXP_ARROW) fprintf(fp, "->"); - else fprintf(fp, "."); - - fprintf(fp, "%s\n", member); - - chillindent(indent, fp); - fprintf(fp, ")\n"); -} - - -void chillAST_MemberExpr::print( int indent, FILE *fp ) { - if (base) base->print( indent, fp ); - else { - chillindent( indent, fp ); - fprintf(fp, "(NULL)"); - } - if (exptype == CHILL_MEMBER_EXP_ARROW) fprintf(fp, "->"); - else fprintf(fp, "."); - if (member) fprintf(fp, "%s", member); - else fprintf(fp, "(NULL)"); - fflush(fp); -} - - -void chillAST_MemberExpr::printonly( int indent, FILE *fp ) { - base->print( indent, fp ); - if (exptype == CHILL_MEMBER_EXP_ARROW) fprintf(fp, "->"); - else fprintf(fp, "."); - fprintf(fp, "%s", member); - fflush(fp); -} - -char *chillAST_MemberExpr::stringRep( int indent ) { // char pointer to what we'd print - fprintf(stderr, "*chillAST_MemberExpr::stringRep()\n"); - if (base->isDeclRefExpr()) { // - chillAST_VarDecl *vd = (chillAST_VarDecl *) ((chillAST_DeclRefExpr *)base)->decl; - char *leak = (char *)malloc(128); - if (exptype == CHILL_MEMBER_EXP_ARROW) sprintf(leak, "%s->%s", vd->varname, member); - else sprintf(leak, "%s.%s", vd->varname, member); - printstring = leak; - return leak; - } - - - // else - // TODO - return strdup("chillAST_MemberExpr::getStringRep()hadanerror"); -} - - -class chillAST_node* chillAST_MemberExpr::constantFold() { - base = base->constantFold(); - //member = member->constantFold(); - return this; -} - -class chillAST_node* chillAST_MemberExpr::clone() { - chillAST_node *b = base->clone(); - char *m = strdup( member ); // ?? - chillAST_MemberExpr *ME = new chillAST_MemberExpr( b, m, parent, uniquePtr /* ?? */ ); - ME->isFromSourceFile = isFromSourceFile; - if (filename) ME->filename = strdup(filename); - return ME; -} - -void chillAST_MemberExpr::gatherArrayRefs( std::vector &refs, bool writtento ) { - fprintf(stderr, "chillAST_MemberExpr::gatherArrayRefs() "); print(0,stderr); fprintf(stderr, "\n"); - fprintf(stderr, "base of of type %s\n", base->getTypeString()); - base->gatherArrayRefs( refs, writtento ); // - -} - -void chillAST_MemberExpr::gatherScalarRefs( std::vector &refs, bool writtento ) { - base->gatherScalarRefs( refs, writtento ); -} - -void chillAST_MemberExpr::gatherVarDecls( vector &decls ) { - base->gatherVarDecls( decls ); -} - -void chillAST_MemberExpr::gatherScalarVarDecls( vector &decls ) { - base->gatherScalarVarDecls( decls ); -} - - -void chillAST_MemberExpr::gatherArrayVarDecls( vector &decls ) { - base->gatherArrayVarDecls( decls ); -} - - -void chillAST_MemberExpr::gatherDeclRefExprs( vector&refs ) { - base->gatherDeclRefExprs( refs ); -} - - -void chillAST_MemberExpr::gatherVarUsage( vector &decls ) { - base->gatherVarUsage( decls ); -} - - -void chillAST_MemberExpr::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ - base->replaceVarDecls( olddecl, newdecl ); -} - -bool chillAST_MemberExpr::operator!=( const chillAST_MemberExpr &other) { - bool opposite = *this == other; - return !opposite; -} - -bool chillAST_MemberExpr::operator==( const chillAST_MemberExpr &other) { - return this->uniquePtr == other.uniquePtr; -} - - -void chillAST_MemberExpr::replaceChild( chillAST_node *old, chillAST_node *newchild ) { - //printf("\nMemberExpr::replaceChild( )\n"); - //printf("old: "); - //old->print(); - //printf("\nnew: "); - //newchild->print(); - //printf("\n"); fflush(stdout); - - // will pointers match?? - if (base == old) { - //fprintf(stderr, "old matches base of MemberExpr\n"); - base = newchild; - } - else { - base->replaceChild( old, newchild ); - } -} - -chillAST_node *chillAST_MemberExpr::multibase2() { /*fprintf(stderr, "ME MB2\n" );*/ return (chillAST_node *)this; } - -chillAST_VarDecl* chillAST_MemberExpr::getUnderlyingVarDecl() { - fprintf(stderr, "chillAST_MemberExpr:getUnderlyingVarDecl()\n"); - print(); printf("\n"); fflush(stdout); - exit(-1); - // find the member with the correct name - -} - - - - -chillAST_VarDecl *chillAST_MemberExpr::multibase() { - //c.i[c.count] we want i member of c - //fprintf(stderr, "ME MB\n" ); - - //fprintf(stderr, "chillAST_MemberExpr::multibase()\n"); - //print(); printf("\n"); fflush(stdout); - //fprintf(stderr, "MemberExpr base is type %s, member %s\n", base->getTypeString(), member); - - //chillAST_VarDecl *vd = base->getUnderlyingVarDecl(); // this is the only thing that ever calls this ??? - chillAST_VarDecl *vd = base->multibase(); // ?? - - - //fprintf(stderr, "vd "); vd->print(); printf("\n"); fflush(stdout); - - chillAST_RecordDecl *rd = vd->getStructDef(); - if (!rd) { - fprintf(stderr, "chillAST_MemberExpr::multibase() vardecl is not a struct??\n"); - fprintf(stderr, "vd "); vd->print(); printf("\n"); fflush(stdout); - fprintf(stderr, "vd "); vd->dump(); printf("\n"); fflush(stdout); - exit(-1); - } - - // OK, we have the recorddecl that defines the structure - // now find the member with the correct name - chillAST_VarDecl *sub = rd->findSubpart( member ); - //fprintf(stderr, "sub %s:\n", member); - if (!sub) { - fprintf(stderr, "can't find member %s in \n", member); - rd->print(); - } - //sub->print(); printf("\n"); fflush(stdout); - //sub->dump() ; printf("\n"); fflush(stdout); - - return sub; - //find vardecl of member in def of base - - -} - - - - -chillAST_DeclRefExpr::chillAST_DeclRefExpr() { - asttype = CHILLAST_NODETYPE_DECLREFEXPR; - declarationType = strdup("UNKNOWN"); - declarationName = strdup("NONE"); - decl = NULL; - parent = NULL; - metacomment = NULL; - isFromSourceFile = true; // default - filename = NULL; -} - -chillAST_DeclRefExpr::chillAST_DeclRefExpr( const char *varname, chillAST_node *par ) { - asttype = CHILLAST_NODETYPE_DECLREFEXPR; - declarationType = strdup("UNKNOWN"); - declarationName = strdup(varname); - decl = NULL; - parent = par; - isFromSourceFile = true; // default - filename = NULL; -} - -chillAST_DeclRefExpr::chillAST_DeclRefExpr( const char *vartype, const char *varname, chillAST_node *par) { - //fprintf(stderr, "DRE::DRE 0x%x %s %s\n", this, vartype, varname ); - asttype = CHILLAST_NODETYPE_DECLREFEXPR; - declarationType = strdup(vartype); - declarationName = strdup(varname); - decl = NULL; - parent = par; - isFromSourceFile = true; // default - filename = NULL; -} - -chillAST_DeclRefExpr::chillAST_DeclRefExpr( const char *vartype, const char *varname, chillAST_node *d, chillAST_node *par ) { - //fprintf(stderr, "DRE::DRE2 0x%x %s %s 0x%x\n", this, vartype, varname, d ); - asttype = CHILLAST_NODETYPE_DECLREFEXPR; - declarationType = strdup(vartype); - declarationName = strdup(varname); - decl = d; - parent = par; - isFromSourceFile = true; // default - filename = NULL; -} - -chillAST_DeclRefExpr::chillAST_DeclRefExpr( chillAST_VarDecl *vd, chillAST_node *par ){ // variable def - //fprintf(stderr, "DRE::DRE3 (VD) 0x%x %s %s 0x%x\n", this, vd->vartype, vd->varname, vd ); - - asttype = CHILLAST_NODETYPE_DECLREFEXPR; - declarationType = strdup(vd->vartype); - declarationName = strdup(vd->varname); - decl = vd; - parent = par; - isFromSourceFile = true; // default - filename = NULL; -} - - -chillAST_DeclRefExpr::chillAST_DeclRefExpr( chillAST_FunctionDecl *fd, chillAST_node *par ){ // function def - asttype = CHILLAST_NODETYPE_DECLREFEXPR; - declarationType = strdup(fd->returnType); - declarationName = strdup(fd->functionName); - decl = fd; - parent = par; - isFromSourceFile = true; // default - filename = NULL; -} - - - -chillAST_DeclRefExpr *buildDeclRefExpr( chillAST_VarDecl *vd) { - chillAST_DeclRefExpr *dre = new chillAST_DeclRefExpr( vd, NULL ); - -} - -void chillAST_DeclRefExpr::print( int indent, FILE *fp) { - chillindent(indent, fp); - //fprintf(fp, "%s %s", declarationType, declarationName); // this is printing float *A - fprintf(fp, "%s", declarationName); // this is printing A - fflush(fp); -} - - -char *chillAST_DeclRefExpr::stringRep( int indent ) { - return strdup( declarationName ); -} - - -void chillAST_DeclRefExpr::dump( int indent, FILE *fp) { - chillindent(indent, fp); - fprintf(fp, "(DeclRefExpr '%s' ", declarationType); - chillAST_VarDecl *vd = getVarDecl(); - if (vd) { - if (vd->isAParameter) fprintf(fp, "ParmVar "); - else fprintf(fp, "Var "); - } - fprintf(fp, "'%s' ", declarationName); // variable or function name - - if (chillAST_FunctionDecl *fd = getFunctionDecl()) { - // print parameter types for functions - fd->printParameterTypes( fp ); - } - - fprintf(fp, ")\n"); - fflush(fp); -} - -class chillAST_node* chillAST_DeclRefExpr::constantFold() { // can never do anything? - return this; -} - -class chillAST_node* chillAST_DeclRefExpr::clone() { - //fprintf(stderr, "chillAST_DeclRefExpr::clone()\n"); - chillAST_DeclRefExpr *DRE = new chillAST_DeclRefExpr( declarationType, declarationName, decl, parent ); - DRE->isFromSourceFile = isFromSourceFile; - if (filename) DRE->filename = strdup(filename); - return DRE; -} - - -void chillAST_DeclRefExpr::gatherVarDeclsMore( vector &decls ) { - //fprintf(stderr, "chillAST_DeclRefExpr::gatherVarDeclsMore()\n"); - decl->gatherVarDeclsMore( decls ); -} - - -void chillAST_DeclRefExpr::gatherScalarVarDecls( vector &decls ) { - //fprintf(stderr, "chillAST_DeclRefExpr::gatherScalarVarDecls()\n"); - decl->gatherScalarVarDecls(decls); - //fprintf(stderr, "now %d scalar vardecls\n", decls.size()); -} - - -void chillAST_DeclRefExpr::gatherArrayVarDecls( vector &decls ) { - //fprintf(stderr, "chillAST_DeclRefExpr::gatherArrayVarDecls()\n"); - decl->gatherArrayVarDecls(decls); - //fprintf(stderr, "now %d Array vardecls\n", decls.size()); -} - - -void chillAST_DeclRefExpr::gatherDeclRefExprs( vector&refs ) { - refs.push_back(this); -} - -void chillAST_DeclRefExpr::gatherScalarRefs( std::vector &refs, bool writtento ) { - refs.push_back(this); -} - -void chillAST_DeclRefExpr::gatherVarUsage( vector &decls ) { - //fprintf(stderr, "chillAST_DeclRefExpr::gatherVarUsage()\n"); - for (int i=0; ivarname)) { - if (streq(declarationType, decls[i]->vartype)) { - //fprintf(stderr, "decl was already there\n"); - return; - } - } - } - chillAST_VarDecl *vd = getVarDecl(); // null for functiondecl - if (vd) decls.push_back( vd ); - -} - - - - -void chillAST_DeclRefExpr::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ - //fprintf(stderr, "chillAST_DeclRefExpr::replaceVarDecls()\n"); - if (decl == olddecl) { - //fprintf(stderr, "replacing old %s with %s\n", olddecl->varname, newdecl->varname); - //fprintf(stderr, "DRE was "); print(); - decl = newdecl; - declarationType = strdup(newdecl->vartype); - declarationName = strdup(newdecl->varname); - //fprintf(stderr, "\nDRE is "); print(); fprintf(stderr, "\n\n"); - } - else { - if (!strcmp(olddecl->varname, declarationName)) { - //fprintf(stderr, "uhoh, chillAST_DeclRefExpr::replaceVarDecls()\n"); - decl = newdecl; - declarationType = strdup(newdecl->vartype); - declarationName = strdup(newdecl->varname); - } - } -} - -chillAST_VarDecl *chillAST_ImplicitCastExpr::multibase() { - return subexpr->multibase(); -} - - -chillAST_VarDecl *chillAST_DeclRefExpr::multibase() { - // presumably, this is being called because this DRE is the base of an ArraySubscriptExpr - return getVarDecl(); -} - - - - - - - - - -void chillAST_VarDecl::gatherVarDecls( vector &decls ) { - //fprintf(stderr, "chillAST_VarDecl::gatherVarDecls()\n"); - for (int i=0; ivarname, varname)) { - if (streq(decls[i]->vartype, vartype)) { - //fprintf(stderr, "VarDecl (direct) decl was already there\n"); - return; - } - } - } - decls.push_back( this ); -} - - -void chillAST_VarDecl::gatherScalarVarDecls( vector &decls ) { - //fprintf(stderr, "chillAST_VarDecl::gatherScalarVarDecls(), %s numdimensions %d\n", varname, numdimensions); - - if (numdimensions != 0) return; // not a scalar - - for (int i=0; ivarname, varname)) { // wrong. scoping. TODO - if (streq(decls[i]->vartype, vartype)) { - //fprintf(stderr, "VarDecl (direct) decl was already there\n"); - return; - } - } - } - //fprintf(stderr, "adding vardecl for %s to decls\n", varname); - decls.push_back( this ); -} - - -void chillAST_VarDecl::gatherArrayVarDecls( vector &decls ) { - //fprintf(stderr, "chillAST_VarDecl::gatherScalarVarDecls(), %s numdimensions %d\n", varname, numdimensions); - - if (numdimensions == 0) return; // not an array - - for (int i=0; ivarname, varname)) { // wrong. scoping. TODO - if (streq(decls[i]->vartype, vartype)) { - //fprintf(stderr, "VarDecl (direct) decl was already there\n"); - return; - } - } - } - //fprintf(stderr, "adding vardecl for %s to decls\n", varname); - decls.push_back( this ); -} - - - -chillAST_node *chillAST_VarDecl::constantFold() { return this; } - -chillAST_node* chillAST_VarDecl::clone() { - fprintf(stderr, "\nchillAST_VarDecl::clone() cloning vardecl for %s\n", varname); - if (isAParameter) fprintf(stderr, "old vardecl IS a parameter\n"); - //else fprintf(stderr, "old vardecl IS NOT a parameter\n"); - - chillAST_VarDecl *vd = new chillAST_VarDecl( vartype, strdup(varname), arraypart, NULL); // NULL so we don't add the variable AGAIN to the (presumably) function - - vd->typedefinition = typedefinition; - vd->vardef = vardef; // perhaps should not do this TODO - //vd->isStruct = (vardef != NULL); // ?? - - vd->underlyingtype = strdup(underlyingtype); - - vd->arraysizes = NULL; - vd->knownArraySizes = knownArraySizes; - vd->numdimensions = numdimensions; - vd->arraypointerpart = NULL; - - if (arraypart != NULL && NULL!=arraysizes) { // !strcmp(arraypart, "")) { - //fprintf(stderr, "in chillAST_VarDecl::clone(), cloning the array info\n"); - //fprintf(stderr, "numdimensions %d arraysizes 0x%x\n", numdimensions, arraysizes) ; - vd->numdimensions = numdimensions; - - if (arraysizes) { - vd->arraysizes = (int *)malloc( sizeof(int *) * numdimensions ); - for (int i=0; i< numdimensions; i++) { - //fprintf(stderr, "i %d\n", i); - vd->arraysizes[i] = arraysizes[i]; - } - } - } - - if ( arraypointerpart ) { - //fprintf(stderr, "copying arraypointerpart\n"); - vd->arraypointerpart = strdup( arraypointerpart); - } - - vd->isStruct = this->isStruct; - //vd->insideAStruct = this->insideAStruct; - - //if (vd->isStruct) fprintf(stderr, "vardecl::clone() %s is a struct\n", varname); - //else fprintf(stderr, "vardecl::clone() %s is NOT a struct\n", varname); - - - vd->knownArraySizes = this->knownArraySizes; - vd->isFromSourceFile = isFromSourceFile; - if (filename) vd->filename = strdup(filename); - return vd; -} - - -void chillAST_VarDecl::splitarraypart() { - fprintf(stderr, "chillAST_VarDecl::splitarraypart() "); - //fprintf(stderr, "%p ", arraypart); - if (arraypart) fprintf(stderr, "%s", arraypart); - fprintf(stderr, "\n"); - - // split arraypart into (leading??) asterisks and known sizes [1][2][3] - if (!arraypart || // NULL - (arraypart && (*arraypart == '\0'))) { // or empty string - - // parts are both empty string - if (arraypointerpart) free(arraypointerpart); - arraypointerpart = strdup(""); - if (arraysetpart) free(arraysetpart); - arraysetpart = strdup(""); - return; - } - - // arraypart exists and is not empty - int asteriskcount = 0; - int fixedcount = 0; - for ( int i=0; iisFromSourceFile = isFromSourceFile; - if (filename) IL->filename = strdup(filename); - return IL; - -} - -chillAST_FloatingLiteral::chillAST_FloatingLiteral(float val, chillAST_node *par){ - value = val; - precision = 1; - float0double1 = 0; // which is live! - allthedigits = NULL; - asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; - parent = par; - isFromSourceFile = true; // default - filename = NULL; -} - -chillAST_FloatingLiteral::chillAST_FloatingLiteral(double val, chillAST_node *par){ - doublevalue = val; - precision = 2; - float0double1 = 1; // which is live! - allthedigits = NULL; - asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; - parent = par; - isFromSourceFile = true; // default - filename = NULL; -} - -chillAST_FloatingLiteral::chillAST_FloatingLiteral(float val, int precis, chillAST_node *par){ - value = val; - precision = 1; - float0double1 = 0; // which is live! - precision = precis; // - allthedigits = NULL; - asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; - parent = par; - isFromSourceFile = true; // default - filename = NULL; -} - -chillAST_FloatingLiteral::chillAST_FloatingLiteral(double val, int precis, chillAST_node *par){ - doublevalue = val; - float0double1 = 1; // which is live! - precision = precis; // - allthedigits = NULL; - asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; - parent = par; - isFromSourceFile = true; // default - filename = NULL; -} - -chillAST_FloatingLiteral::chillAST_FloatingLiteral(float val, const char *printthis, chillAST_node *par){ - value = val; - float0double1 = 0; // which is live! - precision = 1; - allthedigits = NULL; - if (printthis) allthedigits = strdup( printthis ); - //fprintf(stderr, "\nfloatingliteral allthedigits = '%s'\n", allthedigits); - asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; - parent = par; - isFromSourceFile = true; // default - filename = NULL; -} - -chillAST_FloatingLiteral::chillAST_FloatingLiteral(float val, int precis, const char *printthis, chillAST_node *par){ - value = val; - float0double1 = 0; // which is live! - precision = precis; // but value is a float?? TODO - allthedigits = NULL; - if (printthis) { - //fprintf(stderr, "\nchillAST_FloatingLiteral constructor, printthis "); - //fprintf(stderr, "%p\n", printthis); - allthedigits = strdup( printthis ); - } - //fprintf(stderr, "\nfloatingliteral allthedigits = '%s'\n", allthedigits); - asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; - parent = par; - isFromSourceFile = true; // default - filename = NULL; -} - - -chillAST_FloatingLiteral::chillAST_FloatingLiteral( chillAST_FloatingLiteral *old ) { - //fprintf(stderr, "chillAST_FloatingLiteral::chillAST_FloatingLiteral( old ) allthedigits %p\n", old->allthedigits); - - asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; - value = old->value; - doublevalue = old->doublevalue; - float0double1 = old->float0double1; - allthedigits = NULL; - if (old->allthedigits) allthedigits = strdup(old->allthedigits); - precision = old->precision; - isFromSourceFile = true; // default - filename = NULL; -} - - - -void chillAST_FloatingLiteral::print( int indent, FILE *fp) { - chillindent(indent, fp); - //fprintf(fp, "%f", value); - // attempt to be more like rose output - char output[1024]; // warning, hardcoded - - if (allthedigits != NULL) { - strcpy(output, allthedigits ); // if they have specified 100 digits of pi, give 'em 100 digits - //fprintf(stderr, "floatingliteral allthedigits = '%s'\n", allthedigits); - } - else { - if (float0double1 == 0) sprintf(output, "%f", value); - else sprintf(output, "%f", doublevalue); - - // next part to avoid printing 123.4560000000000000000000000000 - char *dot = index(output, '.'); - if (dot) { - char *end = output + strlen(output); - char *onechar; - char *lastnonzero = dot; - for (onechar = output; onechar < end; onechar ++) { - if (*onechar != '0') lastnonzero = onechar; - } - - if (lastnonzero == dot) - lastnonzero[2] = '\0'; // may be after end of string, but that should be OK - else lastnonzero[1] = '\0'; // may be after end of string, but that should be OK - } - } - if (precision == 1) { - int len = strlen(output); - output[len] = 'f'; // explicit single precision - output[len+1] = '\0'; - } - - fprintf(fp, "%s", output); - fflush(fp); -} - -void chillAST_FloatingLiteral::dump( int indent, FILE *fp) { - chillindent(indent, fp); - // 2x2 cases ??? - if (precision == 1) - fprintf(fp, "(FloatingLiteral 'float' "); - else fprintf(fp, "(FloatingLiteral 'double' "); - - if (float0double1 == 0) fprintf(fp, "%f)\n", value); // %f gives enough digits - else fprintf(fp, "%f)\n", doublevalue); // %f gives enough digits - fflush(fp); -} - - -chillAST_node* chillAST_FloatingLiteral::constantFold() { return this; }; // NOOP - -chillAST_node* chillAST_FloatingLiteral::clone() { - //fprintf(stderr, "chillAST_FloatingLiteral::clone() "); - //fprintf(stderr, "allthedigits %p \n", allthedigits); - chillAST_FloatingLiteral *newone = new chillAST_FloatingLiteral( this ); - - newone->isFromSourceFile = isFromSourceFile; - if (filename) newone->filename = strdup(filename); - //print(); printf(" "); newone->print(); printf("\n"); fflush(stdout); - return newone; -} - -bool chillAST_FloatingLiteral::isSameAs( chillAST_node *other ){ - if (!other->isFloatingLiteral()) return false; - chillAST_FloatingLiteral *o = (chillAST_FloatingLiteral *)other; - // should we care about single vs double precision? - if (float0double1 != o->float0double1) return false; - if (float0double1 == 0) { - return value == o->value; // WARNING, comparing floats with == - } - return doublevalue == o->doublevalue; // WARNING, comparing doubless with == -} - - - - - -chillAST_UnaryOperator::chillAST_UnaryOperator( const char *oper, bool pre, chillAST_node *sub, chillAST_node *par ) { - op = strdup(oper); - prefix = pre; - subexpr = sub; - subexpr->setParent( this ); - asttype = CHILLAST_NODETYPE_UNARYOPERATOR; - parent = par; - isFromSourceFile = true; // default - filename = NULL; -} - -void chillAST_UnaryOperator::gatherArrayRefs( std::vector &refs, bool w ) { - subexpr->gatherArrayRefs( refs, isAssignmentOp()); // -} - - - -void chillAST_UnaryOperator::print( int indent, FILE *fp) { - bool needparens = false; - if (subexpr->isNotLeaf()) needparens = true; // may get more complicated - - chillindent( indent, fp); // will this ever be invoked? - if (prefix) fprintf(fp, "%s", op); - if (needparens) fprintf(fp, "("); - subexpr->print( 0, fp ); - if (needparens) fprintf(fp, ")"); - if (!prefix) fprintf(fp, "%s", op); - fflush(fp); -} - - -void chillAST_UnaryOperator::dump( int indent, FILE *fp) { - chillindent( indent, fp); - fprintf(fp, "(UnaryOperator "); - if (prefix) fprintf(fp, "prefix "); - else fprintf(fp, "postfix "); - fprintf(fp, "%s\n", op); - subexpr->dump(indent+1, fp); - - chillindent( indent, fp); - fprintf(fp, ")\n"); -} - - -void chillAST_UnaryOperator::gatherVarLHSUsage( vector &decls ) { - if ((!strcmp("++", op)) || (!strcmp("--", op))) { - subexpr->gatherVarUsage( decls ); // do all unary modify the subexpr? (no, - ) - } -} - - - -chillAST_node* chillAST_UnaryOperator::constantFold() { - //fprintf(stderr, "chillAST_UnaryOperator::constantFold() "); - //print(); fprintf(stderr, "\n"); - - subexpr = subexpr->constantFold(); - chillAST_node *returnval = this; - if (subexpr->isConstant()) { - //fprintf(stderr, "unary op folding constants\n"); - //print(0,stderr); fprintf(stderr, "\n"); - - if (streq(op, "-")) { - if (subexpr->isIntegerLiteral()) { - int intval = ((chillAST_IntegerLiteral*)subexpr)->value; - chillAST_IntegerLiteral *I = new chillAST_IntegerLiteral( -intval, parent); - returnval = I; - //fprintf(stderr, "integer -%d becomes %d\n", intval, I->value); - } - else { - chillAST_FloatingLiteral *FL = (chillAST_FloatingLiteral*)subexpr; - chillAST_FloatingLiteral *F = new chillAST_FloatingLiteral( FL ); // clone - F->parent = FL->parent; - - F->value = -F->value; - F->doublevalue = -F->doublevalue; - - F->print(); fprintf(stderr, "\n"); - - returnval = F; - } - } - else fprintf(stderr, "can't fold op '%s' yet\n", op); - } - return returnval; -} - - -class chillAST_node* chillAST_UnaryOperator::clone() { - chillAST_UnaryOperator *UO = new chillAST_UnaryOperator( op, prefix, subexpr->clone(), parent ); - UO->isFromSourceFile = isFromSourceFile; - if (filename) UO->filename = strdup(filename); - return UO; -} - - -void chillAST_UnaryOperator::gatherVarDecls( vector &decls ) { - subexpr->gatherVarDecls( decls ); -} - - -void chillAST_UnaryOperator::gatherScalarVarDecls( vector &decls ) { - subexpr->gatherScalarVarDecls( decls ); -} - - -void chillAST_UnaryOperator::gatherArrayVarDecls( vector &decls ) { - subexpr->gatherArrayVarDecls( decls ); -} - - -void chillAST_UnaryOperator::gatherDeclRefExprs( vector&refs ) { - subexpr->gatherDeclRefExprs( refs ); -} - - -void chillAST_UnaryOperator::gatherVarUsage( vector &decls ) { - subexpr->gatherVarUsage( decls ); -} - - void chillAST_UnaryOperator::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) { - subexpr->replaceVarDecls( olddecl, newdecl ); - } - - -int chillAST_UnaryOperator::evalAsInt() { - if (!strcmp("+", op)) return subexpr->evalAsInt(); - if (!strcmp("-", op)) return -subexpr->evalAsInt(); - if (!strcmp("++", op)) return 1 + subexpr->evalAsInt(); - if (!strcmp("--", op)) return subexpr->evalAsInt() - 1; - - fprintf(stderr, "chillAST_UnaryOperator::evalAsInt() unhandled op '%s'\n", op); - segfault(); - -} - -bool chillAST_UnaryOperator::isSameAs( chillAST_node *other ){ - if (!other->isUnaryOperator()) return false; - chillAST_UnaryOperator *o = (chillAST_UnaryOperator *)other; - if (strcmp(op, o->op)) return false; // different operators - return subexpr->isSameAs( o->subexpr ); // recurse -} - - -chillAST_ImplicitCastExpr::chillAST_ImplicitCastExpr( chillAST_node *sub, chillAST_node *par ) { - subexpr = sub; - subexpr->setParent( this ); - asttype = CHILLAST_NODETYPE_IMPLICITCASTEXPR; - parent = par; - //fprintf(stderr, "ImplicitCastExpr 0x%x has subexpr 0x%x", this, subexpr); - //fprintf(stderr, " of type %s\n", subexpr->getTypeString()); - isFromSourceFile = true; // default - filename = NULL; -} - -void chillAST_ImplicitCastExpr::print( int indent, FILE *fp) { - // No need to print anything, simply forward to the sub expression. - subexpr->print( indent, fp ); - fflush(fp); -}; - -void chillAST_ImplicitCastExpr::printonly( int indent, FILE *fp) { - // No need to print anything, simply forward to the sub expression. - subexpr->printonly( indent, fp ); - fflush(fp); -}; - -void chillAST_ImplicitCastExpr::replaceChild( chillAST_node *old, chillAST_node *newchild ){ - if (subexpr == old) { // should be the case for this to get called - subexpr = newchild; - subexpr->setParent( this ); - //old->parent = NULL; - return; - } - - fprintf(stderr, "chillAST_ImplicitCastExpr::replaceChild() called with bad 'old'\n"); - exit(-1); // ?? -} - -class chillAST_node* chillAST_ImplicitCastExpr::constantFold() { - chillAST_node *child = subexpr->constantFold(); - child->setParent( parent ) ; // remove myself !! probably a bad idea. TODO - return child; -} - - -class chillAST_node* chillAST_ImplicitCastExpr::clone() { - chillAST_ImplicitCastExpr *ICE = new chillAST_ImplicitCastExpr( subexpr->clone(), parent); - ICE->isFromSourceFile = isFromSourceFile; - if (filename) ICE->filename = strdup(filename); - return ICE; -} - - -void chillAST_ImplicitCastExpr::gatherArrayRefs( std::vector &refs, bool w ) { - subexpr->gatherArrayRefs( refs, w ); -} - -void chillAST_ImplicitCastExpr::gatherScalarRefs( std::vector &refs, bool writtento ) { - subexpr->gatherScalarRefs( refs, writtento ); -} - -void chillAST_ImplicitCastExpr::gatherVarDecls( vector &decls ) { - subexpr->gatherVarDecls( decls ); -} - - -void chillAST_ImplicitCastExpr::gatherScalarVarDecls( vector &decls ) { - subexpr->gatherScalarVarDecls( decls ); -} - - -void chillAST_ImplicitCastExpr::gatherArrayVarDecls( vector &decls ) { - subexpr->gatherArrayVarDecls( decls ); -} - - -void chillAST_ImplicitCastExpr::gatherDeclRefExprs( vector&refs ) { - subexpr->gatherDeclRefExprs( refs ); -} - - -void chillAST_ImplicitCastExpr::gatherVarUsage( vector &decls ) { - subexpr->gatherVarUsage( decls ); -} - - - -chillAST_CStyleCastExpr::chillAST_CStyleCastExpr( const char *to, chillAST_node *sub, chillAST_node *par ) { - - //fprintf(stderr, "chillAST_CStyleCastExpr::chillAST_CStyleCastExpr( %s, ...)\n", to); - towhat = strdup(to); - subexpr = sub; - if (subexpr) subexpr->setParent( this ); - asttype = CHILLAST_NODETYPE_CSTYLECASTEXPR; - parent = par; - //fprintf(stderr, "chillAST_CStyleCastExpr (%s) sub 0x%x\n", towhat, sub ); - isFromSourceFile = true; // default - filename = NULL; -} - -void chillAST_CStyleCastExpr::replaceChild( chillAST_node *old, chillAST_node *newchild ){ - if (subexpr == old) { // should be the case for this to get called - subexpr = newchild; - subexpr->setParent( this ); - //old->parent = NULL; - return; - } - - fprintf(stderr, "chillAST_CStyleCastExpr::replaceChild() called with bad 'old'\n"); - exit(-1); // ?? -} - - void chillAST_CStyleCastExpr::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) { - subexpr->replaceVarDecls( olddecl, newdecl); - } - -void chillAST_CStyleCastExpr::print( int indent, FILE *fp) { - //fprintf(stderr, "CStyleCastExpr::print()\n"); - chillindent(indent, fp); - - // special cases? should probably walk the AST and change the literal itself - if ( !strcmp("float", towhat) && subexpr->isIntegerLiteral()) { // (float) 3 => 3.0f - subexpr->print( 0, fp ); fprintf(fp, ".0f"); - } - else if ( !strcmp("double", towhat) && subexpr->isIntegerLiteral()) { // (double) 3 => 3.0 - subexpr->print( 0, fp ); fprintf(fp, ".0"); - } - else if ( !strcmp("float", towhat) && subexpr->isFloatingLiteral()) { // (float) 3.0 => 3.0f - subexpr->print( 0, fp ); fprintf(fp, "f"); - } - else { // general case - fprintf(fp, "((%s) ", towhat); - //fprintf(fp, "\ntowhat '%s'\n", towhat ); - - if (subexpr->isVarDecl()) fprintf(fp, "%s", ((chillAST_VarDecl *)subexpr)->varname); - else subexpr->print( indent, fp ); - //fprintf(fp, "subexpr '%s' ", subexpr->getTypeString()); - fprintf(fp, ")"); - } - fflush(fp); -}; - - -void chillAST_CStyleCastExpr::dump( int indent, FILE *fp) { - chillindent(indent, fp); - fprintf(fp, "(CStyleCastExpr (%s) \n", towhat); - subexpr->dump( indent+1, fp ); - chillindent(indent, fp); - fprintf(fp, ")\n"); - fflush(fp); -} - -class chillAST_node* chillAST_CStyleCastExpr::constantFold() { - subexpr = subexpr->constantFold(); - return this; -} - - -class chillAST_node* chillAST_CStyleCastExpr::clone() { - chillAST_CStyleCastExpr *CSCE = new chillAST_CStyleCastExpr( towhat, subexpr->clone(), parent ); - CSCE->isFromSourceFile = isFromSourceFile; - if (filename) CSCE->filename = strdup(filename); - return CSCE; -} - -void chillAST_CStyleCastExpr::gatherArrayRefs( std::vector &refs, bool w ) { - subexpr->gatherArrayRefs( refs, w ); -} - -void chillAST_CStyleCastExpr::gatherScalarRefs( std::vector &refs, bool writtento ) { - subexpr->gatherScalarRefs( refs, writtento ); -} - - -void chillAST_CStyleCastExpr::gatherVarDecls( vector &decls ) { - subexpr->gatherVarDecls( decls ); -} - - -void chillAST_CStyleCastExpr::gatherScalarVarDecls( vector &decls ) { - subexpr->gatherScalarVarDecls( decls ); -} - - -void chillAST_CStyleCastExpr::gatherArrayVarDecls( vector &decls ) { - subexpr->gatherArrayVarDecls( decls ); -} - - -void chillAST_CStyleCastExpr::gatherDeclRefExprs( vector&refs ) { - subexpr->gatherDeclRefExprs( refs ); -} - - -void chillAST_CStyleCastExpr::gatherVarUsage( vector &decls ) { - subexpr->gatherVarUsage( decls ); -} - - - - -chillAST_CStyleAddressOf::chillAST_CStyleAddressOf( chillAST_node *sub, chillAST_node *par ) { - subexpr = sub; - subexpr->setParent( this ); - asttype = CHILLAST_NODETYPE_CSTYLEADDRESSOF; - parent = par; - //fprintf(stderr, "chillAST_CStyleCastExpr (%s) sub 0x%x\n", towhat, sub ); - isFromSourceFile = true; // default - filename = NULL; -} - -void chillAST_CStyleAddressOf::print( int indent, FILE *fp) { - //fprintf(stderr, "CStyleAddressOf::print()\n"); - chillindent(indent, fp); - fprintf(fp, "(&"); - subexpr->print( 0, fp ); - fprintf(fp, ")"); - fflush(fp); -}; - -void chillAST_CStyleAddressOf::dump( int indent, FILE *fp) { - chillindent(indent, fp); - fprintf(fp, "(CStyleAddressOf \n"); - subexpr->print( indent+1, fp ); - chillindent(indent, fp); - fprintf(fp, ")\n"); - fflush(fp); -} - -class chillAST_node* chillAST_CStyleAddressOf::constantFold() { - subexpr = subexpr->constantFold(); - return this; -} - -class chillAST_node* chillAST_CStyleAddressOf::clone() { - chillAST_CStyleAddressOf *CSAO = new chillAST_CStyleAddressOf( subexpr->clone(), parent ); - CSAO->isFromSourceFile = isFromSourceFile; - if (filename) CSAO->filename = strdup(filename); - return CSAO; -} - -void chillAST_CStyleAddressOf::gatherArrayRefs( std::vector &refs, bool w ) { - subexpr->gatherArrayRefs( refs, w ); -} - -void chillAST_CStyleAddressOf::gatherScalarRefs( std::vector &refs, bool writtento ) { - subexpr->gatherScalarRefs( refs, writtento ); -} - -void chillAST_CStyleAddressOf::gatherVarDecls( vector &decls ) { - subexpr->gatherVarDecls( decls ); -} - -void chillAST_CStyleAddressOf::gatherScalarVarDecls( vector &decls ) { - subexpr->gatherScalarVarDecls( decls ); -} - - -void chillAST_CStyleAddressOf::gatherArrayVarDecls( vector &decls ) { - subexpr->gatherArrayVarDecls( decls ); -} - - -void chillAST_CStyleAddressOf::gatherDeclRefExprs( vector&refs ) { - subexpr->gatherDeclRefExprs( refs ); -} - - -void chillAST_CStyleAddressOf::gatherVarUsage( vector &decls ) { - subexpr->gatherVarUsage( decls ); -} - - - - -chillAST_Malloc::chillAST_Malloc(chillAST_node *size, chillAST_node *p) { - thing = NULL; - sizeexpr = size; // probably a multiply like sizeof(int) * 1024 - asttype = CHILLAST_NODETYPE_MALLOC; - parent = p; - isFromSourceFile = true; // default - filename = NULL; -}; - -chillAST_Malloc::chillAST_Malloc(char *thething, chillAST_node *numthings, chillAST_node *p) { - thing = strdup(thething); // "int" or "float" or "struct widget" - sizeexpr = numthings; - asttype = CHILLAST_NODETYPE_MALLOC; - parent = p; - isFromSourceFile = true; // default - filename = NULL; -}; - -chillAST_node* chillAST_Malloc::constantFold() { - sizeexpr->constantFold(); -} - -chillAST_node* chillAST_Malloc::clone() { - chillAST_Malloc *M = new chillAST_Malloc( thing, sizeexpr, parent); // the general version - M->isFromSourceFile = isFromSourceFile; - if (filename) M->filename = strdup(filename); - return M; -}; - -void chillAST_Malloc::gatherArrayRefs( std::vector &refs, bool writtento ) { - sizeexpr->gatherArrayRefs( refs, writtento ); -}; - - -void chillAST_Malloc::gatherScalarRefs( std::vector &refs, bool writtento ) { - sizeexpr->gatherScalarRefs( refs, writtento ); -}; - -void chillAST_Malloc::gatherVarDecls( vector &decls ) { - sizeexpr->gatherVarDecls(decls); -}; - -void chillAST_Malloc::gatherScalarVarDecls( vector &decls ){ - sizeexpr->gatherScalarVarDecls(decls); -}; - -void chillAST_Malloc::gatherArrayVarDecls ( vector &decls ) { - sizeexpr->gatherArrayVarDecls(decls); -}; - -void chillAST_Malloc::gatherVarUsage( vector &decls ){ - sizeexpr->gatherVarUsage(decls); -}; - - - -void chillAST_Malloc::print( int indent, FILE *fp ) { - chillindent(indent, fp); - fprintf(fp, "malloc("); - - if (thing) { - fprintf(fp, " sizeof(%s) * ", thing ); - } - sizeexpr->print(0,fp); - fprintf(fp, ")"); - fflush(fp); -}; - - -void chillAST_Malloc::dump( int indent, FILE *fp ) { - chillindent(indent, fp); - fprintf(fp, "(Malloc \n"); - sizeexpr->dump( indent+1, fp ); - chillindent(indent, fp); - fprintf(fp, ")\n"); - fflush(fp); -}; - - - -chillAST_CudaMalloc::chillAST_CudaMalloc(chillAST_node *devmemptr, chillAST_node *size, chillAST_node *p) { - devPtr = devmemptr; - sizeinbytes = size; // probably a multiply like sizeof(int) * 1024 - asttype = CHILLAST_NODETYPE_CUDAMALLOC; - parent = p; - isFromSourceFile = true; // default - filename = NULL; -}; - -void chillAST_CudaMalloc::print( int indent, FILE *fp ) { - chillindent(indent, fp); - fprintf(fp, "cudaMalloc("); - devPtr->print( 0, fp ); - fprintf(fp, ","); - sizeinbytes->print( 0, fp ); - fprintf(fp, ")"); - fflush(fp); -}; - -void chillAST_CudaMalloc::dump( int indent, FILE *fp ) { - chillindent(indent, fp); - fprintf(fp, "(CudaMalloc \n"); - devPtr->dump( indent+1, fp ); - fprintf(fp, "\n"); - sizeinbytes->dump( indent+1, fp ); - fprintf(fp, ")\n"); - fflush(fp); -}; - -class chillAST_node* chillAST_CudaMalloc::constantFold() { - devPtr = devPtr->constantFold(); - return this; -} - -class chillAST_node* chillAST_CudaMalloc::clone() { - chillAST_CudaMalloc *CM = new chillAST_CudaMalloc( devPtr->clone(), sizeinbytes->clone(), parent ); - CM->isFromSourceFile = isFromSourceFile; - if (filename) CM->filename = strdup(filename); - return CM; -} - -void chillAST_CudaMalloc::gatherArrayRefs( std::vector &refs, bool w ) { - devPtr->gatherArrayRefs( refs, false ); - sizeinbytes->gatherArrayRefs( refs, false ); -} - -void chillAST_CudaMalloc::gatherScalarRefs( std::vector &refs, bool writtento ) { - devPtr->gatherScalarRefs( refs, false ); - sizeinbytes->gatherScalarRefs( refs, false ); -} - -void chillAST_CudaMalloc::gatherVarDecls( vector &decls ) { - devPtr->gatherVarDecls( decls ); - sizeinbytes->gatherVarDecls( decls ); -} - - -void chillAST_CudaMalloc::gatherScalarVarDecls( vector &decls ) { - devPtr->gatherScalarVarDecls( decls ); - sizeinbytes->gatherScalarVarDecls( decls ); -} - - - -void chillAST_CudaMalloc::gatherArrayVarDecls( vector &decls ) { - devPtr->gatherArrayVarDecls( decls ); - sizeinbytes->gatherArrayVarDecls( decls ); -} - - - -void chillAST_CudaMalloc::gatherVarUsage( vector &decls ) { - devPtr->gatherVarUsage( decls ); - sizeinbytes->gatherVarUsage( decls ); -} - - - -chillAST_CudaFree::chillAST_CudaFree(chillAST_VarDecl *var, chillAST_node *p) { - variable = var; - parent = p; - asttype = CHILLAST_NODETYPE_CUDAFREE; - isFromSourceFile = true; // default - filename = NULL; -}; - -void chillAST_CudaFree::print( int indent, FILE *fp ) { - chillindent(indent, fp); - fprintf(fp, "cudaFree(%s)", variable->varname); - fflush(fp); -}; - -void chillAST_CudaFree::dump( int indent, FILE *fp ) { - chillindent(indent, fp); - fprintf(fp, "(CudaFree %s )\n", variable->varname); - fflush(fp); -}; - -class chillAST_node* chillAST_CudaFree::constantFold() { - return this; -} - -class chillAST_node* chillAST_CudaFree::clone() { - chillAST_CudaFree *CF = new chillAST_CudaFree( variable, parent ); - CF->isFromSourceFile = isFromSourceFile; - if (filename) CF->filename = strdup(filename); - return CF; -} - -void chillAST_CudaFree::gatherArrayRefs( std::vector &refs, bool w ) {} -void chillAST_CudaFree::gatherScalarRefs( std::vector &refs, bool writtento ) {} - -void chillAST_CudaFree::gatherVarDecls( vector &decls ) { - variable->gatherVarDecls( decls ); -} - - -void chillAST_CudaFree::gatherScalarVarDecls( vector &decls ) { - variable->gatherScalarVarDecls( decls ); -} - - -void chillAST_CudaFree::gatherArrayVarDecls( vector &decls ) { - variable->gatherArrayVarDecls( decls ); -} - - - -void chillAST_CudaFree::gatherVarUsage( vector &decls ) { - variable->gatherVarUsage( decls ); -} - - - - - - - - - -chillAST_CudaMemcpy::chillAST_CudaMemcpy(chillAST_VarDecl *d, chillAST_VarDecl *s, chillAST_node *siz, char *kind, chillAST_node *par) { - dest = d; - src = s; - //fprintf(stderr, "chillAST_CudaMemcpy::chillAST_CudaMemcpy( dest %s, src %s, ...)\n", d->varname, s->varname ); - size = siz; - cudaMemcpyKind = kind; - asttype = CHILLAST_NODETYPE_CUDAMEMCPY; - isFromSourceFile = true; // default - filename = NULL; - parent = par; -}; - -void chillAST_CudaMemcpy::print( int indent, FILE *fp ) { - chillindent(indent, fp); - fprintf(fp, "cudaMemcpy(%s,%s,", dest->varname, src->varname); - //dest->print( 0, fp ); - //fprintf(fp, ","); - // src->print( 0, fp ); just want the src NAME, not name and array info - //fprintf(fp, ","); - size->print( 0, fp ); - fprintf(fp, ",%s)", cudaMemcpyKind); - fflush(fp); -}; - -void chillAST_CudaMemcpy::dump( int indent, FILE *fp ) { - chillindent(indent, fp); - fprintf(fp, "(CudaMemcpy \n"); - dest->dump( indent+1, fp ); - src->dump( indent+1, fp ); - size->dump( indent+1, fp ); - chillindent(indent+1, fp); - fprintf(fp, ",%s\n", cudaMemcpyKind); - fflush(fp); -}; - -class chillAST_node* chillAST_CudaMemcpy::constantFold() { - dest = (chillAST_VarDecl *)dest->constantFold(); - src = (chillAST_VarDecl *)src->constantFold(); - size = size->constantFold(); - return this; -} - -class chillAST_node* chillAST_CudaMemcpy::clone() { - chillAST_CudaMemcpy *CMCPY = new chillAST_CudaMemcpy((chillAST_VarDecl *)(dest->clone()),(chillAST_VarDecl *)(src->clone()), size->clone(), strdup(cudaMemcpyKind), parent ); - CMCPY->isFromSourceFile = isFromSourceFile; - if (filename) CMCPY->filename = strdup(filename); - return CMCPY; -} - -void chillAST_CudaMemcpy::gatherArrayRefs( std::vector &refs, bool w ) { - dest->gatherArrayRefs( refs, false ); - src ->gatherArrayRefs( refs, false ); - size->gatherArrayRefs( refs, false ); -} - -void chillAST_CudaMemcpy::gatherScalarRefs( std::vector &refs, bool writtento ) { - dest->gatherScalarRefs( refs, false ); - src ->gatherScalarRefs( refs, false ); - size->gatherScalarRefs( refs, false ); -} - -void chillAST_CudaMemcpy::gatherVarDecls( vector &decls ) { - dest->gatherVarDecls( decls ); - src ->gatherVarDecls( decls ); - size->gatherVarDecls( decls ); -} - - -void chillAST_CudaMemcpy::gatherScalarVarDecls( vector &decls ) { - dest->gatherScalarVarDecls( decls ); - src ->gatherScalarVarDecls( decls ); - size->gatherScalarVarDecls( decls ); -} - - -void chillAST_CudaMemcpy::gatherArrayVarDecls( vector &decls ) { - dest->gatherArrayVarDecls( decls ); - src ->gatherArrayVarDecls( decls ); - size->gatherArrayVarDecls( decls ); -} - - -void chillAST_CudaMemcpy::gatherVarUsage( vector &decls ) { - dest->gatherVarUsage( decls ); - src ->gatherVarUsage( decls ); - size->gatherVarUsage( decls ); -} - - - -chillAST_CudaSyncthreads::chillAST_CudaSyncthreads( chillAST_node *par) { - asttype = CHILLAST_NODETYPE_CUDASYNCTHREADS; - parent = par; - isFromSourceFile = true; // default - filename = NULL; -} - - void chillAST_CudaSyncthreads::print( int indent, FILE *fp ) { - chillindent(indent, fp); - fprintf(fp, "__syncthreads()"); - fflush(fp); - } - - void chillAST_CudaSyncthreads::dump( int indent, FILE *fp ) { - chillindent(indent, fp); - fprintf(fp, "(syncthreads)\n"); - fflush(fp); - } - - - - - - - - - - -chillAST_ReturnStmt::chillAST_ReturnStmt( chillAST_node *retval, chillAST_node *par ) { - asttype = CHILLAST_NODETYPE_RETURNSTMT; - returnvalue = retval; - if (returnvalue) returnvalue->setParent( this ); - parent = par; - isFromSourceFile = true; // default - filename = NULL; -} - - -void chillAST_ReturnStmt::print( int indent, FILE *fp) { - printPreprocBEFORE(indent, fp); - chillindent(indent, fp); - if (returnvalue != NULL) { - fprintf(fp, "return("); - returnvalue->print( 0, fp ); - fprintf(fp, ")" ); // parent will add ";\n" ?? - } - else { - fprintf(fp, "return"); - } - fflush(fp); -} - - -void chillAST_ReturnStmt::dump( int indent, FILE *fp) { - chillindent(indent, fp); - fprintf(fp, "(ReturnStmt"); - if (returnvalue) { - fprintf(fp, "\n"); - returnvalue->dump(indent+1,fp); - chillindent(indent, fp); - } - fprintf(fp, ")\n"); -} - - -class chillAST_node* chillAST_ReturnStmt::constantFold() { - if (returnvalue) returnvalue = returnvalue->constantFold(); - return this; -} - - - -class chillAST_node* chillAST_ReturnStmt::clone() { - chillAST_node *val = NULL; - if ( returnvalue ) val = returnvalue->clone(); - chillAST_ReturnStmt *RS = new chillAST_ReturnStmt( val, parent ); - RS->isFromSourceFile = isFromSourceFile; - if (filename) RS->filename = strdup(filename); - return RS; -} - - -void chillAST_ReturnStmt::gatherVarDecls( vector &decls ) { - if (returnvalue) returnvalue->gatherVarDecls( decls ); -} - - -void chillAST_ReturnStmt::gatherScalarVarDecls( vector &decls ) { - if (returnvalue) returnvalue->gatherScalarVarDecls( decls ); -} - - -void chillAST_ReturnStmt::gatherArrayVarDecls( vector &decls ) { - if (returnvalue) returnvalue->gatherArrayVarDecls( decls ); -} - - - -void chillAST_ReturnStmt::gatherDeclRefExprs( vector&refs ) { - if (returnvalue) returnvalue->gatherDeclRefExprs( refs ); -} - - - -void chillAST_ReturnStmt::gatherVarUsage( vector &decls ) { - if (returnvalue) returnvalue->gatherVarUsage( decls ); -} - - - - -chillAST_CallExpr::chillAST_CallExpr(chillAST_node *c, chillAST_node *par) { //, int numofargs, chillAST_node **theargs ) { - - //fprintf(stderr, "chillAST_CallExpr::chillAST_CallExpr callee type %s\n", c->getTypeString()); - asttype = CHILLAST_NODETYPE_CALLEXPR; - callee = c; - //callee->setParent( this ); // ?? - numargs = 0; - parent = par; - grid = block = NULL; - isFromSourceFile = true; // default - filename = NULL; -} - - -void chillAST_CallExpr::addArg( chillAST_node *a ) { - args.push_back( a ); - a->setParent( this ); - numargs += 1; -} - - -void chillAST_CallExpr::print( int indent, FILE *fp) { - printPreprocBEFORE(indent, fp); - chillindent(indent, fp); - chillAST_FunctionDecl *FD = NULL; - chillAST_MacroDefinition *MD = NULL; - - if (callee->isDeclRefExpr()) { - chillAST_DeclRefExpr *DRE = (chillAST_DeclRefExpr *) callee; - //fprintf(stderr, "DRE decl is 0x%x\n", DRE->decl); - if (!DRE->decl) { - // a macro? - fprintf(fp, "%s ", DRE->declarationName); - return; // ?? - } - - //fprintf(stderr, "DRE decl of type %s\n", DRE->decl->getTypeString()); - if ( (DRE->decl)->isFunctionDecl()) FD = (chillAST_FunctionDecl *)DRE->decl; - else { - fprintf(stderr, "chillAST_CallExpr::print() DRE decl of type %s\n", DRE->decl->getTypeString()); - exit(-1); - } - } - else if (callee->isFunctionDecl()) FD = (chillAST_FunctionDecl *) callee; - else if (callee->isMacroDefinition()) { - MD = (chillAST_MacroDefinition *) callee; - fprintf(fp, "%s(", MD->macroName); - } - else { - fprintf(stderr, "\nchillAST_CallExpr::print() callee of unhandled type %s\n", callee->getTypeString()); - callee->dump(); - exit(-1); - } - - if (FD) { - fprintf(fp, "%s", FD->functionName ); fflush(fp); - if (grid && block) { - fprintf(fp, "<<<%s,%s>>>(", grid->varname, block->varname); // a - } - else fprintf(fp, "("); - } - - - //callee->print( indent, fp); - for (int i=0; iprint(0, fp); - } - fprintf(fp, ")"); //a - fflush(fp); -} - -void chillAST_CallExpr::dump( int indent, FILE *fp) { - chillindent(indent, fp); - fprintf(fp, "(CallExpr "); - //fprintf(stderr, "callee type %s\n", callee->getTypeString()); - chillAST_FunctionDecl *fd = NULL; - if (callee->isDeclRefExpr()) { // always? - chillAST_DeclRefExpr *dre = (chillAST_DeclRefExpr *)callee; - fd = dre->getFunctionDecl(); // if NULL, we've got a Vardecl instead - if (fd) { - //fd->print(); - fprintf(fp, "%s\n", fd->returnType); - } - - callee->dump(indent+1, fp); - if (fd) { - int numparams = fd->parameters.size(); - for (int i=0; iparameters[i]->dump(indent+1, fp); - } - } - chillindent(indent, fp); - fprintf(fp, ")\n"); -} - -void chillAST_CallExpr::gatherArrayRefs( std::vector &refs, bool writtento ) { - for (int i=0; igatherArrayRefs( refs, writtento ); - } -} -void chillAST_CallExpr::gatherScalarRefs( std::vector &refs, bool writtento ) { - for (int i=0; igatherScalarRefs( refs, writtento ); - } -} - - -void chillAST_CallExpr::gatherVarDecls( vector &decls ) { - for (int i=0; igatherVarDecls( decls ); - } -} - - -void chillAST_CallExpr::gatherScalarVarDecls( vector &decls ) { - for (int i=0; igatherScalarVarDecls( decls ); - } -} - - -void chillAST_CallExpr::gatherArrayVarDecls( vector &decls ) { - for (int i=0; igatherArrayVarDecls( decls ); - } -} - - -void chillAST_CallExpr::gatherDeclRefExprs( vector&refs ) { - for (int i=0; igatherDeclRefExprs( refs ); - } -} - -void chillAST_CallExpr::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ - for (int i=0; ireplaceVarDecls( olddecl, newdecl ); -} - -void chillAST_CallExpr::gatherVarUsage( vector &decls ) { - for (int i=0; igatherVarUsage( decls ); - } -} - - -chillAST_node* chillAST_CallExpr::constantFold() { - numargs = args.size(); // wrong place for this - for (int i=0; iconstantFold(); - } - return this; -} - -chillAST_node* chillAST_CallExpr::clone() { - //fprintf(stderr, "chillAST_CallExpr::clone()\n"); - //print(0, stderr); fprintf(stderr, "\n"); - - chillAST_CallExpr *CE = new chillAST_CallExpr( callee->clone(), NULL ); - for (int i=0; iaddArg( args[i]->clone() ); - CE->isFromSourceFile = isFromSourceFile; - if (filename) CE->filename = strdup(filename); - return CE; -} - - - - -chillAST_VarDecl::chillAST_VarDecl() { - //fprintf(stderr, "0chillAST_VarDecl::chillAST_VarDecl() %p\n", this); - fprintf(stderr, "0chillAST_VarDecl::chillAST_VarDecl()\n"); - vartype = underlyingtype = varname = arraypart = arraypointerpart = arraysetpart = NULL; - typedefinition = NULL; - - //fprintf(stderr, "setting underlying type NULL\n" ); - init = NULL; - numdimensions=0; arraysizes = NULL; - asttype = CHILLAST_NODETYPE_VARDECL; // - parent = NULL; - metacomment = NULL; - - vardef = NULL; - isStruct = false; - - //insideAStruct = false; - isAParameter = false; - byreference = false; - isABuiltin = false; - isRestrict = isDevice = isShared = false; // fprintf(stderr, "RDS = false\n"); - knownArraySizes = false; - isFromSourceFile = true; // default - filename = NULL; -}; - - - -chillAST_VarDecl::chillAST_VarDecl( const char *t, const char *n, const char *a, chillAST_node *par) { - //fprintf(stderr, "1chillAST_VarDecl::chillAST_VarDecl( type %s, name %s, arraypart %s, parent %p) %p\n", t, n, a, par, this); - fprintf(stderr, "1chillAST_VarDecl::chillAST_VarDecl( type %s, name %s, arraypart %s)\n", t, n, a); - vartype = strdup(t); - typedefinition = NULL; - - underlyingtype = parseUnderlyingType( vartype ); - //fprintf(stderr, "setting underlying type %s from %s\n", underlyingtype, vartype ); - varname = strdup(n); - arraypointerpart = arraysetpart = NULL; - if (a) arraypart = strdup(a); - else arraypart = strdup(""); - splitarraypart(); - - init = NULL; - numdimensions=0; arraysizes = NULL; - uniquePtr = NULL; - asttype = CHILLAST_NODETYPE_VARDECL; - parent = par; - - - - knownArraySizes = false; - //fprintf(stderr, "arraypart len %d\n", strlen(a)); - for (int i=0; iaddVariableToSymbolTable( this ); // should percolate up until something has a symbol table - - } - isFromSourceFile = true; // default - filename = NULL; -}; - - - -chillAST_VarDecl::chillAST_VarDecl( chillAST_RecordDecl *astruct, const char *nam, const char *array, chillAST_node *par) { - // define a variable whose type is a struct! - - fprintf(stderr, "3chillAST_VarDecl::chillAST_VarDecl( %s %p struct ", nam, this ); - const char *type = astruct->getName(); - fprintf (stderr, "%s, name %s, arraypart %s parent ) %p\n", type, nam, array, this); // , par); - - vartype = strdup(type); - - // these always go together ?? - vardef = astruct;// pointer to the thing that says what is inside the struct - isStruct = true; // ?? wrong if it's a union ?? TODO - - //insideAStruct = false; - //fprintf(stderr, "setting vardef of %s to %p\n", nam, vardef); - - underlyingtype = parseUnderlyingType( vartype ); - //fprintf(stderr, "setting underlying type %s from %s\n", underlyingtype, vartype ); - varname = strdup(nam); - arraypart = strdup(array); - arraypointerpart = arraysetpart = NULL; - splitarraypart(); - - init = NULL; - numdimensions=0; arraysizes = NULL; - uniquePtr = NULL; - asttype = CHILLAST_NODETYPE_VARDECL; - parent = par; - - knownArraySizes = false; - //fprintf(stderr, "arraypart len %d\n", strlen(a)); - for (int i=0; iaddVariableToSymbolTable( this ); // should percolate up until something has a symbol table - - isFromSourceFile = true; // default - filename = NULL; - -}; - - - - - -chillAST_VarDecl::chillAST_VarDecl( chillAST_TypedefDecl *tdd, const char *n, const char *a, chillAST_node *par) { - fprintf(stderr, "4chillAST_VarDecl::chillAST_VarDecl( %s typedef ", n); - const char *type = tdd->getStructName(); - //fprintf (stderr, "%s, name %s, arraypart %s parent ) %p\n", type, n, a,this); // , par); - typedefinition = tdd; - vartype = strdup(type); - underlyingtype = parseUnderlyingType( vartype ); - //fprintf(stderr, "setting underlying type %s from %s\n", underlyingtype, vartype ); - varname = strdup(n); - arraypart = strdup(a); - arraypointerpart = arraysetpart = NULL; - splitarraypart(); - - init = NULL; - numdimensions=0; arraysizes = NULL; - uniquePtr = NULL; - asttype = CHILLAST_NODETYPE_VARDECL; - parent = par; - - knownArraySizes = false; - //fprintf(stderr, "arraypart len %d\n", strlen(a)); - for (int i=0; iisAStruct(); - - //insideAStruct = false; - - vardef = NULL; - - - isAParameter = false; - byreference = false; - isABuiltin = false; - isRestrict = isDevice = isShared = false; // //fprintf(stderr, "RDS = false\n"); - if (parent) parent->addVariableToSymbolTable( this ); // should percolate up until something has a symbol table - isFromSourceFile = true; // default - filename = NULL; -}; - - - - - -chillAST_VarDecl::chillAST_VarDecl( const char *t, const char *n, const char *a, void *ptr, chillAST_node *par) { - fprintf(stderr, "2chillAST_VarDecl::chillAST_VarDecl( type %s, name %s, arraypart '%s' ) %p\n", t, n, a, this); - //fprintf(stderr, "2chillAST_VarDecl::chillAST_VarDecl( type %s, name %s, arraypart %s, ptr 0x%x, parent 0x%x )\n", t, n, a, ptr, par); - - - vartype = strdup(t); - typedefinition = NULL; - underlyingtype = parseUnderlyingType( vartype ); - //fprintf(stderr, "setting underlying type %s from %s\n", underlyingtype, vartype ); - varname = strdup(n); - - vardef = NULL; // not a struct - isStruct = false; - isAParameter = false; - - if (a) arraypart = strdup(a); - else arraypart = strdup(""); // should catch this earlier - arraypointerpart = arraysetpart = NULL; - splitarraypart(); - - init = NULL; - numdimensions=0; arraysizes = NULL; - uniquePtr = ptr; - asttype = CHILLAST_NODETYPE_VARDECL; - parent = par; - knownArraySizes = false; - - if (par) par->addChild(this); // ?? - - //fprintf(stderr, "name arraypart len %d\n", strlen(a)); - //fprintf(stderr, "arraypart '%s'\n", arraypart); - for (int i=0; iaddVariableToSymbolTable( this ); // should percolate up until something has a symbol table - - - isFromSourceFile = true; // default - filename = NULL; - - fprintf(stderr, "2chillAST_VarDecl::chillAST_VarDecl LEAVING\n"); - //parent->print(); fprintf(stderr, "\n\n"); - - -}; - - -void chillAST_VarDecl::print( int indent, FILE *fp ) { - //fprintf(fp, "chillAST_VarDecl::print()\n"); - - printPreprocBEFORE(indent, fp); - - //fprintf(fp, "VarDecl vartype '%s' varname %s ", vartype, varname); - //if (isAStruct()) fprintf(fp, "isAStruct()\n"); - //else fprintf(fp, "NOT A Struct\n"); - - // fprintf(fp, "\n"); fflush(fp); dump(0,fp); fflush(fp); // debug - - chillindent(indent, fp); - //fprintf(fp, "vardecl->print vartype '%s'\n", vartype); - if (isDevice) fprintf(fp, "__device__ "); - if (isShared) fprintf(fp, "__shared__ "); - - //if (isAStruct()) fprintf(fp, "/* isAStruct() */ "); - //else fprintf(fp, "/* NOT A Struct() */ "); - //if (vardef) fprintf(fp, "/* vardef */ "); - //else fprintf(fp, "/* NOT vardef */ "); - - - //fprintf(stderr, "chillAST_VarDecl::print() %s\n", varname ); - //if (isParmVarDecl()) fprintf(stderr, "%s is a parameter\n", varname); - //if (isAStruct()) fprintf(stderr, "%s is a struct\n", varname); - //else fprintf(stderr, "%s is NOT a struct\n", varname); - //if (!parent) fprintf(stderr, "VARDECL HAS NO PARENT\n"); - //else fprintf(stderr, "parent of %s is type %s\n", varname, parent->getTypeString()); - - // this logic is probably wrong (what about pointer to struct? ) - - //fprintf(stderr, "checking for unnamed only used here\n"); - - if ((!isAParameter) && isAStruct() && vardef) { // an unnamed struct used only here ?? - - //fprintf(fp, "i%s sAStruct() && vardef ?? vardecl of type UNNAMED ONLY USED HERE \n", varname ); - // print the internals of the struct and then the name - vardef->printStructure( 0, fp ); - fprintf(fp, "%s", varname ); - - return; - } - - //fprintf(fp, "ugly logic\n"); - // ugly logic TODO - - if (typedefinition && typedefinition->isAStruct()) fprintf(fp, "struct "); - - if (isAParameter) { - //fprintf(fp, "%s isaparameter\n", varname); - //if (isAStruct()) fprintf(fp, "struct "); - //fprintf(fp, "(param) nd %d", numdimensions ); - //dump(); - if (numdimensions > 0) { - if (knownArraySizes) { // just [12][34][56] - fprintf(fp, "%s ", vartype); - if (byreference) fprintf(fp, "&"); - fprintf(fp, "%s", varname); - for (int n=0; n< (numdimensions); n++) fprintf(fp, "[%d]", arraysizes[n]); - } - else { // some unknown array part float *a; or float **a; or float (*)a[1234] - - //fprintf(fp, "\nsome unknown\n"); - //fprintf(fp, "arraypointerpart '%s'\n", arraypointerpart); - //fprintf(fp, "arraysetpart '%s'\n", arraysetpart); - - if (numdimensions == 1) { - //fprintf(fp, "\nnd1, vartype %s\n", vartype); - - // TODO this if means I have probably made a mistake somewhere - if (!index(vartype, '*')) fprintf(fp, "%s *%s", vartype, varname ); // float *x - else fprintf(fp, "%s%s", vartype, varname); // float *a; - - - } - else { // more than one dimension - - if ( !strcmp("", arraysetpart) ) { // no known dimensions float ***a; - fprintf(fp, "%s %s%s", vartype, arraypointerpart, varname); - } - else if ( !strcmp("", arraypointerpart)) { // ALL known float a[2][7]; - fprintf(fp, "%s %s", vartype, varname); - for (int n=0; n< numdimensions; n++) fprintf(fp, "[%d]", arraysizes[n]); - } - else { // float (*)a[1234] - // this seems really wrong - // float (*)a[1234] - fprintf(fp, "%s (", vartype); - for (int n=0; n< (numdimensions-1); n++) fprintf(fp, "*"); - fprintf(fp, "%s)", varname); - fprintf(fp, "[%d]", arraysizes[numdimensions-1]); - } - - } - } - } // if numdimensions > 0 - else { // parameter float x - fprintf(fp, "%s ", vartype); - if (byreference) fprintf(fp, "&"); - fprintf(fp, "%s", varname); - } - } // end parameter - - else { // NOT A PARAMETER - //fprintf(fp, "NOT A PARAM ... vartype '%s'\n", vartype); - //if (isArray()) fprintf(stderr, "an array, numdimensions %d\n", numdimensions); - //fprintf(stderr, "arraysizes %p\n", arraysizes); - - - - //if (isArray() && arraysizes == NULL) { - // // we just know the number of dimensions but no sizes - // // int ***something - // fprintf(fp, "%s ", vartype); // "int " - // for (int i=0; igetStructDef(); - return NULL; -} - - - - - -chillAST_CompoundStmt::chillAST_CompoundStmt() { - //fprintf(stderr, "chillAST_CompoundStmt::chillAST_CompoundStmt() %p\n", this); - asttype = CHILLAST_NODETYPE_COMPOUNDSTMT; - parent = NULL; - symbol_table = new chillAST_SymbolTable; - typedef_table = NULL; - isFromSourceFile = true; // default - filename = NULL; -}; - - -void chillAST_CompoundStmt::print( int indent, FILE *fp ) { - printPreprocBEFORE(indent, fp); - int numchildren = children.size(); - //fprintf(stderr, "NUMCHILDREN %d\n", numchildren); sleep(1); - for (int i=0; iprint(indent, fp); - if (children[i]->asttype != CHILLAST_NODETYPE_FORSTMT - && children[i]->asttype != CHILLAST_NODETYPE_IFSTMT - && children[i]->asttype != CHILLAST_NODETYPE_COMPOUNDSTMT - //&& children[i]->asttype != CHILLAST_NODETYPE_VARDECL // vardecl does its own ";\n" - ) - { - fprintf(fp, ";\n"); // probably wrong - } - } - fflush(fp); -} - -void chillAST_CompoundStmt::replaceChild( chillAST_node *old, chillAST_node *newchild ){ - //fprintf(stderr, "chillAST_CompoundStmt::replaceChild( old %s, new %s)\n", old->getTypeString(), newchild->getTypeString() ); - vector dupe = children; - int numdupe = dupe.size(); - int any = 0; - - for (int i=0; igetTypeString()); - //} - - - if (dupe[i] == old) { - //fprintf(stderr, "replacing child %d of %d\n", i, numdupe); - //fprintf(stderr, "was \n"); print(); - children[i] = newchild; - newchild->setParent( this ); - //fprintf(stderr, "is \n"); print(); fprintf(stderr, "\n\n"); - // old->parent = NULL; - any = 1; - } - } - - if (!any) { - fprintf(stderr, "chillAST_CompoundStmt::replaceChild(), could not find old\n"); - exit(-1); - } -} - - -void chillAST_CompoundStmt::loseLoopWithLoopVar( char *var ) { - //fprintf(stderr, "chillAST_CompoundStmt::loseLoopWithLoopVar( %s )\n", var); - - //fprintf(stderr, "CompoundStmt 0x%x has parent 0x%x ", this, this->parent); - //fprintf(stderr, "%s\n", parent->getTypeString()); - - - //fprintf(stderr, "CompoundStmt node has %d children\n", children.size()); - //fprintf(stderr, "before doing a damned thing, \n"); - //print(); - //dump(); fflush(stdout); - //fprintf(stderr, "\n\n"); - -#ifdef DAMNED - for (int j=0; jasttype); - fprintf(stderr, "%s ", children[j]->getTypeString()); - if (children[j]->isForStmt()) { - chillAST_ForStmt *FS = ((chillAST_ForStmt *) children[j]); - fprintf(stderr, "for ("); - FS->init->print(0, stderr); - fprintf(stderr, "; "); - FS->cond->print(0, stderr); - fprintf(stderr, "; "); - FS->incr->print(0, stderr); - fprintf(stderr, ") with %d statements in body 0x%x\n", FS->body->getNumChildren(), FS->body ); - } - else fprintf(stderr, "\n"); - } -#endif - - - vector dupe = children; // simple enough? - for (int i=0; igetTypeString()); - // if (children[j]->isForStmt()) { - // chillAST_ForStmt *FS = ((chillAST_ForStmt *) children[j]); - // fprintf(stderr, "for ("); - // FS->init->print(0, stderr); - // fprintf(stderr, "; "); - // FS->cond->print(0, stderr); - // fprintf(stderr, "; "); - // FS->incr->print(0, stderr); - // fprintf(stderr, ") with %d statements in body 0x%x\n", FS->body->getNumChildren(), FS->body ); - //} - //else fprintf(stderr, "\n"); - //} - - //fprintf(stderr, "CompoundStmt 0x%x recursing to child %d/%d\n", this, i, dupe.size()); - dupe[i]->loseLoopWithLoopVar( var ); - } - //fprintf(stderr, "CompoundStmt node 0x%x done recursing\n", this ); -} - - - -void chillAST_CompoundStmt::dump( int indent, FILE *fp ) { - chillindent(indent, fp); - fprintf(fp, "(CompoundStmt \n" ); - int numchildren = children.size(); - - //for (int i=0; igetTypeString(), children[i]); - //} - //fprintf(fp, "\n"); - - for (int i=0; idump(indent+1, fp); - fprintf(fp, "\n"); // ??? - fflush(fp); - } - chillindent(indent, fp); - fprintf(fp, ")\n"); -}; - - - -chillAST_node* chillAST_CompoundStmt::constantFold(){ - //fprintf(stderr, "chillAST_CompoundStmt::constantFold()\n"); - for (int i=0; iconstantFold(); - return this; -} - - -chillAST_node* chillAST_CompoundStmt::clone(){ - chillAST_CompoundStmt *cs = new chillAST_CompoundStmt(); - for (int i=0; iaddChild( children[i]->clone() ); - cs->setParent( parent ); - cs->isFromSourceFile = isFromSourceFile; - if (filename) cs->filename = strdup(filename); - return cs; -} - - -void chillAST_CompoundStmt::gatherVarDecls( vector &decls ) { - //fprintf(stderr, "chillAST_CompoundStmt::gatherVarDecls()\n"); - for (int i=0; igatherVarDecls( decls ); -} - - -void chillAST_CompoundStmt::gatherScalarVarDecls( vector &decls ) { - for (int i=0; igatherScalarVarDecls( decls ); -} - - -void chillAST_CompoundStmt::gatherArrayVarDecls( vector &decls ) { - for (int i=0; igatherArrayVarDecls( decls ); -} - - -void chillAST_CompoundStmt::gatherDeclRefExprs( vector&refs ) { - for (int i=0; igatherDeclRefExprs( refs ); -} - - -void chillAST_CompoundStmt::gatherVarUsage( vector &decls ) { - for (int i=0; igatherVarUsage( decls ); -} - - -void chillAST_CompoundStmt::gatherArrayRefs( std::vector &refs, bool writtento ) { - for (int i=0; igatherArrayRefs( refs, 0); -} - -void chillAST_CompoundStmt::gatherScalarRefs( std::vector &refs, bool writtento ) { - for (int i=0; igatherScalarRefs( refs, 0); -} - -void chillAST_CompoundStmt::gatherStatements(std::vector &statements ){ - for (int i=0; igatherStatements( statements ); -} - - - -void chillAST_CompoundStmt::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ - for (int i=0; ireplaceVarDecls( olddecl, newdecl ); -} - - -bool chillAST_CompoundStmt::findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync ) { - - // see how many elements we currently have - int sofar = children.size(); - - // make big enough to add a sync after each statement. wasteful. TODO - // this prevents inserts happening at the forstmt::addSync() from causing a - // reallocation, which screwsup the loop below here - children.reserve( 2 * sofar ); - //fprintf(stderr, "sofar %d reserved %d\n", sofar, 2*sofar); - - bool force = false; - for (int i=0; i sofar ) { - //fprintf(stderr, "HEY! CompoundStmt::findLoopIndexesToReplace() noticed that children increased from %d to %d\n", sofar, children.size()); - sofar = children.size(); - } - - //fprintf(stderr, "compound child %d of type %s force %d\n", i, children[i]->getTypeString(), force ); - bool thisforces = children[i]->findLoopIndexesToReplace( symtab, force ); - force = force || thisforces; // once set, always - } - - return false; - -/* - vector childrencopy; - for (int i=0; igetTypeString() ); - origtypes[i] = strdup( children[i]->getTypeString() ); - fprintf(stderr, "ORIGINAL compound child %d of type %s\n", i, children[i]->getTypeString() ); - } - - for (int i=0; igetTypeString(), force ); - force = force || childrencopy[i]->findLoopIndexesToReplace( symtab, force ); // once set, always - } - - fprintf(stderr, "\n"); - for (int i=0; igetTypeString() ); - } - - return false; -*/ -} - - - - - -chillAST_ParenExpr::chillAST_ParenExpr( chillAST_node *sub, chillAST_node *par ){ - subexpr = sub; - subexpr->setParent( this ); - asttype = CHILLAST_NODETYPE_PARENEXPR; - parent = par; - isFromSourceFile = true; // default - filename = NULL; -} - -void chillAST_ParenExpr::print( int indent, FILE *fp ) { - //fprintf(stderr, "chillAST_ParenExpr::print()\n"); - chillindent(indent, fp); // hard to believe this will ever do anything - fprintf(fp, "(" ); - subexpr->print( 0, fp ); - fprintf(fp, ")" ); - fflush(fp); -} - -void chillAST_ParenExpr::dump( int indent, FILE *fp ) { - chillindent(indent, fp); - fprintf(fp, "(ParenExpr \n"); - subexpr->dump( indent+1, fp ); - chillindent(indent, fp); - fprintf(fp, ")\n"); -} - - -void chillAST_ParenExpr::gatherArrayRefs( std::vector &refs, bool writtento ) { - subexpr->gatherArrayRefs( refs, writtento ); -} - -void chillAST_ParenExpr::gatherScalarRefs( std::vector &refs, bool writtento ) { - subexpr->gatherScalarRefs( refs, writtento ); -} - - - -chillAST_node* chillAST_ParenExpr::constantFold() { - subexpr = subexpr->constantFold(); - return this; -} - - -chillAST_node* chillAST_ParenExpr::clone() { - chillAST_ParenExpr *PE = new chillAST_ParenExpr( subexpr->clone(), NULL ); - PE->isFromSourceFile = isFromSourceFile; - if (filename) PE->filename = strdup(filename); - return PE; -} - -void chillAST_ParenExpr::gatherVarDecls( vector &decls ) { - subexpr->gatherVarDecls( decls ); -} - - -void chillAST_ParenExpr::gatherScalarVarDecls( vector &decls ) { - subexpr->gatherScalarVarDecls( decls ); -} - - -void chillAST_ParenExpr::gatherArrayVarDecls( vector &decls ) { - subexpr->gatherArrayVarDecls( decls ); -} - - -void chillAST_ParenExpr::gatherDeclRefExprs( vector&refs ) { - subexpr->gatherDeclRefExprs( refs ); -} - -void chillAST_ParenExpr::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ - subexpr->replaceVarDecls( olddecl, newdecl ); -} - -void chillAST_ParenExpr::gatherVarUsage( vector &decls ) { - subexpr->gatherVarUsage( decls ); -} - - - -chillAST_Sizeof::chillAST_Sizeof( char *athing, chillAST_node *par ){ - thing = strdup( athing ); // memory leak - parent = par; - isFromSourceFile = true; // default - filename = NULL; -} - -void chillAST_Sizeof::print( int indent, FILE *fp ) { - //fprintf(stderr, "chillAST_Sizeof::print()\n"); - chillindent(indent, fp); // hard to believe this will ever do anything - fprintf(fp, "sizeof(" ); - fprintf(fp, "%s)", thing ); - fflush(fp); -} - - -void chillAST_Sizeof::dump( int indent, FILE *fp ) { - chillindent(indent, fp); - fprintf(fp, "(Sizeof %s )\n", thing); -} - -void chillAST_Sizeof::gatherArrayRefs( std::vector &refs, bool writtento ) {} -void chillAST_Sizeof::gatherScalarRefs( std::vector &refs, bool writtento ) {} - -chillAST_node* chillAST_Sizeof::constantFold() { - return this; -} - -chillAST_node* chillAST_Sizeof::clone() { - chillAST_Sizeof *SO = new chillAST_Sizeof( thing, NULL ); - SO->isFromSourceFile = isFromSourceFile; - if (filename) SO->filename = strdup(filename); - return SO; -} - -void chillAST_Sizeof::gatherVarDecls( vector &decls ) { // TODO -} - - -void chillAST_Sizeof::gatherScalarVarDecls( vector &decls ) { // TODO -} - - -void chillAST_Sizeof::gatherArrayVarDecls( vector &decls ) { // TODO -} - - -void chillAST_Sizeof::gatherDeclRefExprs( vector&refs ) { - // TODO -} - - -void chillAST_Sizeof::gatherVarUsage( vector &decls ) { -} - - -void insertNewDeclAtLocationOfOldIfNeeded( chillAST_VarDecl *newdecl, chillAST_VarDecl *olddecl) { - //fprintf(stderr, "insertNewDeclAtLocationOfOldIfNeeded( new 0x%x old 0x%x\n", newdecl, olddecl ); - - if (newdecl == NULL || olddecl == NULL) { - fprintf(stderr, "chill_ast.cc insertNewDeclAtLocationOfOldIfNeeded() NULL decl\n"); - exit(-1); - } - - if (newdecl == olddecl) return; - - newdecl->vartype = strdup(olddecl->vartype); - - chillAST_node *newparent = newdecl->parent; - chillAST_node *oldparent = olddecl->parent; - //fprintf(stderr, "newparent 0x%x oldparent 0x%x\n", newparent, oldparent ); - if (newparent == oldparent) return; - - if (newparent != NULL) - //fprintf(stderr, "chill_ast.cc insertNewDeclAtLocationOfOldIfNeeded() new decl already has parent?? probably wrong\n"); - newdecl->parent = oldparent; // will be true soon - - // find actual location of old decl and insert new one there - //fprintf(stderr, "oldparent is of type %s\n", oldparent->getTypeString()); // better be compoundstmt ?? - vector children = oldparent->getChildren(); - - int numchildren = children.size(); - //fprintf(stderr, "oldparent has %d children\n", numchildren); - - if (numchildren == 0) { - fprintf(stderr, "chill_ast.cc insertNewDeclAtLocationOfOldIfNeeded() impossible number of oldparent children (%d)\n", numchildren); - exit(-1); - } - - bool newalreadythere = false; - int index = -1; - //fprintf(stderr, "olddecl is 0x%x\n", olddecl); - //fprintf(stderr, "I know of %d variables\n", numchildren); - for (int i=0; igetChild(i); - //fprintf(stderr, "child %d @ 0x%x is of type %s\n", i, child, child->getTypeString()); - if (children[i] == olddecl) { - index = i; - //fprintf(stderr, "found old decl at index %d\n", index); - } - if (children[i] == newdecl) { - newalreadythere = true; - //fprintf(stderr, "new already there @ index %d\n", i); - } - } - if (index == -1) { - fprintf(stderr, "chill_ast.cc insertNewDeclAtLocationOfOldIfNeeded() can't find old decl for %s\n", olddecl->varname); - exit(-1); - } - - if (!newalreadythere) oldparent->insertChild( index, newdecl ); - -} - - -void gatherVarDecls( vector &code, vector &decls) { - //fprintf(stderr, "gatherVarDecls()\n"); - - int numcode = code.size(); - //fprintf(stderr, "%d top level statements\n", numcode); - for (int i=0; igatherVarDecls( decls ); - } - -} - - -void gatherVarUsage( vector &code, vector &decls) { - //fprintf(stderr, "gatherVarUsage()\n"); - - int numcode = code.size(); - //fprintf(stderr, "%d top level statements\n", numcode); - for (int i=0; igatherVarUsage( decls ); - } - -} - - - - -chillAST_IfStmt::chillAST_IfStmt() { - cond = thenpart = elsepart = NULL; - asttype = CHILLAST_NODETYPE_IFSTMT; - isFromSourceFile = true; // default - filename = NULL; -} - -chillAST_IfStmt::chillAST_IfStmt(chillAST_node *c, chillAST_node *t, chillAST_node *e, chillAST_node *p){ - cond = c; - if (cond) cond->setParent( this ); - thenpart = t; - if (thenpart) thenpart->setParent( this ); - elsepart = e; - if (elsepart) elsepart->setParent( this ); - parent = p; - asttype = CHILLAST_NODETYPE_IFSTMT; - isFromSourceFile = true; // default - filename = NULL; -} - -void chillAST_IfStmt::gatherVarDecls( vector &decls ) { - if (cond) cond->gatherVarDecls( decls ); - if (thenpart) thenpart->gatherVarDecls( decls ); - if (elsepart) elsepart->gatherVarDecls( decls ); -} - - -void chillAST_IfStmt::gatherScalarVarDecls( vector &decls ) { - if (cond) cond->gatherScalarVarDecls( decls ); - if (thenpart) thenpart->gatherScalarVarDecls( decls ); - if (elsepart) elsepart->gatherScalarVarDecls( decls ); -} - - -void chillAST_IfStmt::gatherArrayVarDecls( vector &decls ) { - if (cond) cond->gatherArrayVarDecls( decls ); - if (thenpart) thenpart->gatherArrayVarDecls( decls ); - if (elsepart) elsepart->gatherArrayVarDecls( decls ); -} - - -void chillAST_IfStmt::gatherDeclRefExprs( vector&refs ) { - if (cond) cond->gatherDeclRefExprs( refs ); - if (thenpart) thenpart->gatherDeclRefExprs( refs ); - if (elsepart) elsepart->gatherDeclRefExprs( refs ); -} - - -void chillAST_IfStmt::gatherVarUsage( vector &decls ) { - if (cond) cond->gatherVarUsage( decls ); - if (thenpart) thenpart->gatherVarUsage( decls ); - if (elsepart) elsepart->gatherVarUsage( decls ); -} - - -void chillAST_IfStmt::gatherArrayRefs( std::vector &refs, bool writtento ) { - cond->gatherArrayRefs( refs, 0 ); // 0 ?? - thenpart->gatherArrayRefs( refs, 0 ); // 0 ?? - if (elsepart) elsepart->gatherArrayRefs( refs, 0 ); // 0 ?? -} - -void chillAST_IfStmt::gatherScalarRefs( std::vector &refs, bool writtento ) { - cond->gatherScalarRefs( refs, 0 ); // 0 ?? - thenpart->gatherScalarRefs( refs, 0 ); // 0 ?? - if (elsepart) elsepart->gatherScalarRefs( refs, 0 ); // 0 ?? -} - - -chillAST_node *chillAST_IfStmt::constantFold() { - if (cond) cond = cond->constantFold(); - if (thenpart) thenpart = thenpart->constantFold(); - if (elsepart) elsepart = elsepart->constantFold(); - return this; -} - -void chillAST_IfStmt::gatherStatements(std::vector &statements ){ - - //print(); printf("\n"); fflush(stdout); - thenpart->gatherStatements( statements ); - //fprintf(stderr, "ifstmt, after then, %d statements\n", statements.size()); - if (elsepart){ - //fprintf(stderr, "there is an elsepart of type %s\n", elsepart->getTypeString()); - elsepart->gatherStatements( statements ); - } - //fprintf(stderr, "ifstmt, after else, %d statements\n", statements.size()); -} - - - -chillAST_node *chillAST_IfStmt::clone() { - chillAST_node *c, *t, *e; - c = t = e = NULL; - if (cond) c = cond->clone(); // has to be one, right? - if (thenpart) t = thenpart->clone(); - if (elsepart) e = elsepart->clone(); - - chillAST_IfStmt *IS = new chillAST_IfStmt( c, t, e, parent); - IS->isFromSourceFile = isFromSourceFile; - if (filename) IS->filename = strdup(filename); - return IS; -} - - - -void chillAST_IfStmt::dump( int indent, FILE *fp ) { - chillindent(indent, fp); - fprintf(fp, "(if "); - fprintf(fp, "\n"); - - cond->dump(indent+1, fp); - fprintf(fp, "\n"); - - thenpart->dump(indent+1, fp); - fprintf(fp, "\n"); - - if (elsepart) { - elsepart->dump(indent+1, fp); - fprintf(fp, "\n"); - } - chillindent(indent, fp); - fprintf(fp, ")\n"); -} - - - -void chillAST_IfStmt::print(int indent, FILE *fp ) { - printPreprocBEFORE(indent, fp); - chillindent(indent, fp); - fprintf(fp, "if ("); - if (cond) cond->print(0, fp); - else fprintf(fp, "(NULL cond)"); - - bool needbracket = true; - if (thenpart) { - if (thenpart->isBinaryOperator()) needbracket = false; - if (thenpart->isCompoundStmt()) { // almost always true - chillAST_CompoundStmt *CS = (chillAST_CompoundStmt*) thenpart; - if (CS->children.size() == 1 && CS->children[0]->isBinaryOperator()) needbracket = false; - } - - if(needbracket) fprintf(fp, ") {\n"); - else fprintf(fp, ")\n"); - - thenpart->print(indent+1, fp); // end of line - - if(needbracket) { - //fprintf(fp, "\n"); - chillindent(indent, fp); - fprintf(fp, "}\n"); - } - } - else fprintf(fp, "(NULL thenpart)"); - - - needbracket = true; - if (elsepart) { - if (elsepart->isBinaryOperator()) needbracket = false; - if (elsepart->isCompoundStmt()) { // almost always true - chillAST_CompoundStmt *CS = (chillAST_CompoundStmt*) elsepart; - - if (CS->children.size() == 1 && CS->children[0]->isBinaryOperator()) needbracket = false; - - } - - fprintf(fp, "\n"); - chillindent(indent, fp); - - if (needbracket) fprintf(fp, "else {\n"); - else fprintf(fp, "else\n"); - - elsepart->print(indent+1, fp); - - if(needbracket) { - fprintf(fp, "\n"); - chillindent(indent, fp); - fprintf(fp, "}\n"); - } - } - //else fprintf(fp, "else { /* NOTHING */ }"); -} - - - -bool chillAST_IfStmt::findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync ) { - thenpart->findLoopIndexesToReplace( symtab ); - elsepart->findLoopIndexesToReplace( symtab ); - return false; // ?? -} - - - -chillAST_node *lessthanmacro( chillAST_node *left, chillAST_node *right) { - - chillAST_ParenExpr *lp1 = new chillAST_ParenExpr( left ); - chillAST_ParenExpr *rp1 = new chillAST_ParenExpr( right ); - chillAST_BinaryOperator *cond = new chillAST_BinaryOperator( lp1, "<", rp1 ); - - chillAST_ParenExpr *lp2 = new chillAST_ParenExpr( left ); - chillAST_ParenExpr *rp2 = new chillAST_ParenExpr( right ); - - chillAST_TernaryOperator *t = new chillAST_TernaryOperator("?", cond, lp2, rp2); - - return t; -} - - - - -// look for function declaration with a given name, in the tree with root "node" -void findFunctionDeclRecursive( chillAST_node *node, const char *procname, vector& funcs ) -{ - //fprintf(stderr, "findmanually() CHILL AST node of type %s\n", node->getTypeString()); - - if (node->isFunctionDecl()) { - char *name = ((chillAST_FunctionDecl *) node)->functionName; // compare name with desired name - //fprintf(stderr, "node name 0x%x ", name); - //fprintf(stderr, "%s procname ", name); - //fprintf(stderr, "0x%x ", procname); - //fprintf(stderr, "%s\n", procname); - if (!strcmp( name, procname)) { - //fprintf(stderr, "found procedure %s\n", procname ); - funcs.push_back( (chillAST_FunctionDecl*) node ); // this is it - // quit recursing. probably not correct in some horrible case - return; - } - //else fprintf(stderr, "this is not the function we're looking for\n"); - } - - - // this is where the children can be used effectively. - // we don't really care what kind of node we're at. We just check the node itself - // and then its children is needed. - - int numc = node->children.size(); - fprintf(stderr, "(top)node has %d children\n", numc); - - for (int i=0; iisSourceFile()) { - fprintf(stderr, "node of type %s is recursing to child %d of type %s\n", node->getTypeString(), i, node->children[i]->getTypeString()); - if (node->children[i]->isFunctionDecl()) { - chillAST_FunctionDecl *fd = (chillAST_FunctionDecl*) node->children[i]; - fprintf(stderr, "child %d is functiondecl %s\n", i, fd->functionName); - } - } - findFunctionDeclRecursive( node->children[i], procname, funcs ); - - } - return; -} - - -chillAST_FunctionDecl *findFunctionDecl( chillAST_node *node, const char *procname) -{ - vector functions; - findFunctionDeclRecursive( node, procname, functions ); - - if ( functions.size() == 0 ) { - fprintf(stderr, "could not find function named '%s'\n", procname); - exit(-1); - } - - if ( functions.size() > 1 ) { - fprintf(stderr, "oddly, found %d functions named '%s'\n", functions.size(), procname); - fprintf(stderr, "I am unsure what to do\n"); - - for (int f = 0; f < functions.size(); f++) { - fprintf(stderr, "function %d %p %s\n", f, functions[f], functions[f]->functionName); - } - exit(-1); - } - - //fprintf(stderr, "found the procedure named %s\n", procname); - return functions[0]; -} - - -chillAST_SymbolTable *addSymbolToTable( chillAST_SymbolTable *st, chillAST_VarDecl *vd ) // definition -{ - chillAST_SymbolTable *s = st; - if (!s) s = new chillAST_SymbolTable; - - int tablesize = s->size(); - - for (int i=0; ivarname, vd->varname); - if (!strcmp( (*s)[i]->varname, vd->varname)) { - //fprintf(stderr, "symbol with the same name was already there\n"); - return s; // already there - } - } - - //fprintf(stderr, "adding %s %s to a symbol table that didn't already have it\n", vd->vartype, vd->varname); - - //printf("before:\n"); - //printSymbolTable( s ); fflush(stdout); - - s->push_back(vd); // add it - - //printf("after:\n"); - //printSymbolTable( s ); fflush(stdout); - return s; -} - - -chillAST_TypedefTable *addTypedefToTable( chillAST_TypedefTable *tdt, chillAST_TypedefDecl *td ) -{ - - chillAST_TypedefTable *t = tdt; - if (!t) t = new chillAST_TypedefTable; - - int tablesize = t->size(); - - for (int i=0; ipush_back(td); // add it - return t; -} - - -chillAST_NoOp::chillAST_NoOp( chillAST_node *p ) { - parent = p; - isFromSourceFile = true; // default - filename = NULL; -}; // so we have SOMETHING for NoOp in the cc file ??? - - -chillAST_Preprocessing::chillAST_Preprocessing() { - position = CHILL_PREPROCESSING_POSITIONUNKNOWN; - pptype = CHILL_PREPROCESSING_TYPEUNKNOWN; - blurb = strdup(""); // never use null. ignore the leak ?? -} - - - chillAST_Preprocessing::chillAST_Preprocessing(CHILL_PREPROCESSING_POSITION pos, - CHILL_PREPROCESSING_TYPE t, - char *text ) - { - position = pos; - pptype = t; - blurb = strdup( text ); - } - -void chillAST_Preprocessing::print( int indent, FILE *fp ) { // probably very wrong - if (position == CHILL_PREPROCESSING_LINEAFTER ) { - fprintf(fp, "\n"); - chillindent(indent, fp); - } - if (position == CHILL_PREPROCESSING_LINEBEFORE) { // ??? - //fprintf(fp, "\n"); - chillindent(indent, fp); - } - - fprintf(fp, "%s", blurb); - - if (position == CHILL_PREPROCESSING_TOTHERIGHT) { - fprintf(fp, "\n"); - } - - - if (position == CHILL_PREPROCESSING_LINEBEFORE) { - //fprintf(fp, "\n"); // comment seems to have \n at the end already - //chillindent(indent, fp); - } - - - //if (pptype != CHILL_PREPROCESSING_IMMEDIATELYBEFORE && pptype != CHILL_PREPROCESSING_UNKNOWN) fprint(fp, "\n"); - - } diff --git a/src/ir_clang.cc b/src/ir_clang.cc index 16deff3..0c56cf0 100755 --- a/src/ir_clang.cc +++ b/src/ir_clang.cc @@ -43,7 +43,7 @@ History: #include #include -#include "chill_ast.hh" +#include "chillAST.h" // TODO move to ir_clang.hh // fwd declarations @@ -833,7 +833,7 @@ chillAST_node * ConvertDeclStmt( DeclStmt *clangDS, chillAST_node *p ) { // TODO if (V->hasInit()) { - fprintf(stderr, " ConvertDeclStmt() UNHANDLED initialization\n"); + CHILL_ERROR(" ConvertDeclStmt() UNHANDLED initialization\n"); exit(-1); } } @@ -886,13 +886,12 @@ chillAST_node * ConvertFunctionDecl( FunctionDecl *D, chillAST_node *p ) { int numparams = D->getNumParams(); - //fprintf(stderr, "\nand %d parameters\n", numparams); + CHILL_DEBUG_PRINT( " %d parameters\n", numparams); for (int i=0; igetParamDecl(i); // the ith parameter (CLANG) ParmVarDecl *pvd = D->getParamDecl(i); QualType T = pvd->getOriginalType(); - fprintf(stderr, "OTYPE %s\n", T.getAsString().c_str()); + CHILL_DEBUG_PRINT("OTYPE %s\n", T.getAsString().c_str()); chillAST_VarDecl *chillPVD = (chillAST_VarDecl *)ConvertVarDecl( clangvardecl, chillFD ) ; //chillPVD->print(); fflush(stdout); @@ -901,14 +900,14 @@ chillAST_node * ConvertFunctionDecl( FunctionDecl *D, chillAST_node *p ) { VariableDeclarations.push_back(chillPVD); chillFD->addParameter(chillPVD); - fprintf(stderr, "chillAST ParmVarDecl for %s from chill location 0x%x\n",chillPVD->varname, clangvardecl); + CHILL_DEBUG_PRINT("chillAST ParmVarDecl for %s from chill location 0x%x\n",chillPVD->varname, clangvardecl); } // for each parameter //fprintf(stderr, ")\n{\n"); // beginning of function body //if (D->isExternC()) { chillFD->setExtern(); fprintf(stderr, "%s is extern\n", FuncName.c_str()); }; - if (D->getBuiltinID()) { chillFD->setExtern(); fprintf(stderr, "%s is builtin (extern)\n", FuncName.c_str()); }; + if (D->getBuiltinID()) { chillFD->setExtern(); CHILL_DEBUG_PRINT("%s is builtin (extern)\n", FuncName.c_str()); }; Stmt *clangbody = D->getBody(); if (clangbody) { // may just be fwd decl or external, without an actual body @@ -1670,12 +1669,14 @@ IR_Ref *IR_chillArrayRef::clone() const { // ---------------------------------------------------------------------------- // Class: IR_chillLoop // ---------------------------------------------------------------------------- -IR_chillLoop::IR_chillLoop(const IR_Code *ir, clang::ForStmt *tf) { fprintf(stderr, "IR_chillLoop::IR_chillLoop() you lose\n"); exit(-1); }; +IR_chillLoop::IR_chillLoop(const IR_Code *ir, clang::ForStmt *tf) { CHILL_ERROR("IR_chillLoop::IR_chillLoop() you lose\n"); exit(-1); }; -IR_chillLoop::IR_chillLoop(const IR_Code *ir, chillAST_ForStmt *achillforstmt) { - fprintf(stderr, "IR_xxxxLoop::IR_xxxxLoop()\n"); - fprintf(stderr, "loop is:\n"); - achillforstmt->print(); +IR_chillLoop::IR_chillLoop(const IR_Code *ir, chillAST_ForStmt *achillforstmt) { + CHILL_DEBUG_BEGIN + fprintf(stderr, "IR_xxxxLoop::IR_xxxxLoop()\n"); + fprintf(stderr, "loop is:\n"); + achillforstmt->print(); + CHILL_DEBUG_END ir_ = ir; chillforstmt = achillforstmt; @@ -1684,7 +1685,7 @@ IR_chillLoop::IR_chillLoop(const IR_Code *ir, chillAST_ForStmt *achillforstmt) { chillAST_BinaryOperator *cond = (chillAST_BinaryOperator *)chillforstmt->getCond(); // check to be sure (assert) if (!init->isAssignmentOp() || !cond->isComparisonOp() ) { - fprintf(stderr, "ir_clang.cc, malformed loop init or cond:\n"); + CHILL_ERROR("malformed loop init or cond:\n"); achillforstmt->print(); exit(-1); } @@ -1738,21 +1739,21 @@ IR_chillLoop::IR_chillLoop(const IR_Code *ir, chillAST_ForStmt *achillforstmt) { else beets = true; if (beets) { - fprintf(stderr, "malformed loop increment (or more likely unhandled case)\n"); - inc->print(); - exit(-1); + CHILL_ERROR("malformed loop increment (or more likely unhandled case)\n"); + inc->print(); + exit(-1); } } // binary operator - else { - fprintf(stderr, "IR_chillLoop constructor, unhandled loop increment\n"); - inc->print(); - exit(-1); + else { + CHILL_ERROR("IR_chillLoop constructor, unhandled loop increment\n"); + inc->print(); + exit(-1); } //inc->print(0, stderr);fprintf(stderr, "\n"); chillAST_DeclRefExpr *dre = (chillAST_DeclRefExpr *)init->getLHS(); if (!dre->isDeclRefExpr()) { - fprintf(stderr, "malformed loop init.\n"); + CHILL_DEBUG_PRINT("malformed loop init.\n"); init->print(); } @@ -1767,22 +1768,22 @@ IR_chillLoop::IR_chillLoop(const IR_Code *ir, chillAST_ForStmt *achillforstmt) { chillbody = achillforstmt->getBody(); - fprintf(stderr, "IR_xxxxLoop::IR_xxxxLoop() DONE\n"); + CHILL_DEBUG_PRINT("IR_xxxxLoop::IR_xxxxLoop() DONE\n"); } omega::CG_outputRepr *IR_chillLoop::lower_bound() const { - fprintf(stderr, "IR_xxxxLoop::lower_bound()\n"); + CHILL_DEBUG_PRINT("IR_xxxxLoop::lower_bound()\n"); return new omega::CG_chillRepr(chilllowerbound); } omega::CG_outputRepr *IR_chillLoop::upper_bound() const { - fprintf(stderr, "IR_xxxxLoop::upper_bound()\n"); + CHILL_DEBUG_PRINT("IR_xxxxLoop::upper_bound()\n"); return new omega::CG_chillRepr(chillupperbound); } IR_Block *IR_chillLoop::body() const { - fprintf(stderr, "IR_xxxxLoop::body()\n"); + CHILL_DEBUG_PRINT("IR_xxxxLoop::body()\n"); //assert(isa(tf_->getBody())); //fprintf(stderr, "returning a clangBLOCK corresponding to the body of the loop\n"); //fprintf(stderr, "body type %s\n", chillbody->getTypeString()); @@ -1790,25 +1791,26 @@ IR_Block *IR_chillLoop::body() const { } IR_Control *IR_chillLoop::clone() const { - fprintf(stderr, "IR_xxxxLoop::clone()\n"); + CHILL_DEBUG_PRINT("IR_xxxxLoop::clone()\n"); //chillforstmt->print(); fflush(stdout); return new IR_chillLoop(ir_, chillforstmt); } IR_CONDITION_TYPE IR_chillLoop::stop_cond() const { chillAST_BinaryOperator *loopcondition = (chillAST_BinaryOperator*) chillupperbound; - fprintf(stderr, "IR_xxxxLoop::stop_cond()\n"); + CHILL_DEBUG_PRINT("IR_xxxxLoop::stop_cond()\n"); return conditionoperator; } IR_Block *IR_chillLoop::convert() { // convert the loop to a block - fprintf(stderr, "IR_xxxxLoop::convert() maybe \n"); + CHILL_DEBUG_PRINT("IR_xxxxLoop::convert() maybe \n"); return new IR_chillBlock( ir_, chillbody ); // ?? return NULL; } void IR_chillLoop::dump() const { - fprintf(stderr, "TODO: IR_chillLoop::dump()\n"); exit(-1); + CHILL_ERROR("TODO: IR_chillLoop::dump()\n"); + exit(-1); } @@ -1816,8 +1818,8 @@ void IR_chillLoop::dump() const { // Class: IR_chillBlock // ---------------------------------------------------------------------------- omega::CG_outputRepr *IR_chillBlock::original() const { - fprintf(stderr, "IR_xxxxBlock::original() TODO \n"); - exit(-1); + CHILL_ERROR("IR_xxxxBlock::original() TODO \n"); + exit(-1); return NULL; } @@ -1851,7 +1853,7 @@ omega::CG_outputRepr *IR_chillBlock::extract() const { } IR_Control *IR_chillBlock::clone() const { - fprintf(stderr, "IR_xxxxBlock::clone()\n"); + CHILL_DEBUG_PRINT("IR_xxxxBlock::clone()\n"); //fprintf(stderr, "IR_xxxxBlock::clone() %d statements\n", statements.size()); return new IR_chillBlock( this ); // shallow copy ? } @@ -1945,15 +1947,12 @@ IR_clangCode_Global_Init *IR_clangCode_Global_Init::pinstance = 0; IR_clangCode_Global_Init *IR_clangCode_Global_Init::Instance(char **argv) { - fprintf(stderr, "in IR_clangCode_Global_Init::Instance(), "); - if (pinstance == 0) { - //fprintf(stderr, "\n\n*** making the one and only instance ***\n\n\n"); + if (pinstance == 0) { // this is the only way to create an IR_clangCode_Global_Init pinstance = new IR_clangCode_Global_Init; pinstance->ClangCompiler = new aClangCompiler( argv[1] ); } - //fprintf(stderr, "leaving IR_clangCode_Global_Init::Instance()\n"); return pinstance; } @@ -2053,7 +2052,7 @@ aClangCompiler::aClangCompiler( char *filename ) { NULLASTConsumer TheConsumer; // must pass a consumer in to ParseAST(). This one does nothing //fprintf(stderr, "ready? Parse.\n"); - fprintf(stderr, "actually parsing file %s using clang\n", filename); + CHILL_DEBUG_PRINT("actually parsing file %s using clang\n", filename); ParseAST( Clang->getPreprocessor(), &TheConsumer, Clang->getASTContext()); @@ -2062,7 +2061,7 @@ aClangCompiler::aClangCompiler( char *filename ) { // TUD->dump(); // print it out // create another AST, very similar to the clang AST but not written by idiots - fprintf(stderr, "converting entire clang AST into chill AST (ir_clang.cc)\n"); + CHILL_DEBUG_PRINT("converting entire clang AST into chill AST (ir_clang.cc)\n"); chillAST_node * wholefile = ConvertTranslationUnit( TUD, filename); fflush(stdout); @@ -2136,17 +2135,17 @@ chillAST_FunctionDecl* aClangCompiler::findprocedurebyname( char *procname ) { //fprintf(stderr, "procs has %d members\n", procs.size()); if ( procs.size() == 0 ) { - fprintf(stderr, "could not find function named '%s' in AST from file %s\n", procname, SourceFileName); + CHILL_ERROR("could not find function named '%s' in AST from file %s\n", procname, SourceFileName); exit(-1); } if ( procs.size() > 1 ) { - fprintf(stderr, "oddly, found %d functions named '%s' in AST from file %s\n", procs.size(), procname, SourceFileName); - fprintf(stderr, "I am unsure what to do\n"); + CHILL_ERROR("oddly, found %d functions named '%s' in AST from file %s\n", procs.size(), procname, SourceFileName); + CHILL_ERROR("I am unsure what to do\n"); exit(-1); } - fprintf(stderr, "found the procedure named %s\n", procname); + CHILL_DEBUG_PRINT("found the procedure named %s\n", procname); return (chillAST_FunctionDecl *)procs[0]; } @@ -2226,7 +2225,7 @@ IR_clangCode_Global_Init::~IR_clangCode_Global_Init() // ---------------------------------------------------------------------------- IR_clangCode::IR_clangCode(const char *fname, const char *proc_name): IR_Code() { - fprintf(stderr, "\nIR_xxxxCode::IR_xxxxCode()\n\n"); + CHILL_DEBUG_PRINT("IR_xxxxCode::IR_xxxxCode()\n"); //fprintf(stderr, "IR_clangCode::IR_clangCode( filename %s, procedure %s )\n", filename, proc_name); filename = strdup(fname); // filename is internal to IR_clangCode @@ -2260,15 +2259,14 @@ IR_clangCode::IR_clangCode(const char *fname, const char *proc_name): IR_Code() pInstance->setCurrentFunction( localFD ); chillAST_node *b = localFD->getBody(); // we do this just because it will get done next - fprintf(stderr, "in IR_xxxxCode::IR_xxxxCode(), new CG_xxxxBuilder\n"); - fprintf(stderr, "ir_clang.cc calling new CG_chillBuilder() umwut?\n"); + CHILL_DEBUG_PRINT("calling new CG_chillBuilder() umwut?\n"); ocg_ = new omega::CG_chillBuilder(); // ocg == omega code gen chillfunc = localFD; } - fprintf(stderr, "IR_xxxxCode::IR_xxxxCode() returning after reading source file and finding function\n\n"); + CHILL_DEBUG_PRINT("returning after reading source file and finding function\n\n"); //chillfunc->dump( 0, stderr); @@ -2277,7 +2275,7 @@ IR_clangCode::IR_clangCode(const char *fname, const char *proc_name): IR_Code() IR_clangCode::~IR_clangCode() { //func_->print(llvm::outs(), 4); // printing as part of the destructor !! - fprintf(stderr, "IR_xxxxCode::~IR_xxxxCode()\noutput happening as part of the destructor !!\n"); + CHILL_DEBUG_PRINT("\n\toutput happening as part of the destructor !!\n"); //chillfunc->dump(); //chillfunc->print(); @@ -2578,7 +2576,7 @@ std::vector IR_clangCode::FindArrayRef(const omega::CG_outputRepr std::vector IR_clangCode::FindOneLevelControlStructure(const IR_Block *block) const { - fprintf(stderr, "IR_xxxxCode::FindOneLevelControlStructure()\n"); + CHILL_DEBUG_PRINT("IR_xxxxCode::FindOneLevelControlStructure()\n"); const IR_chillBlock *CB = (const IR_chillBlock *) block; //fprintf(stderr, "block 0x%x\n", block); @@ -2588,14 +2586,14 @@ std::vector IR_clangCode::FindOneLevelControlStructure(const IR_Bl //fprintf(stderr, "blockast 0x%x\n", blockast); if (blockast == NULL) { int numstmts = CB->statements.size(); - fprintf(stderr, "%d statements\n", numstmts); + CHILL_DEBUG_PRINT("%d statements\n", numstmts); if (numstmts == 0) return controls; else if (numstmts == 1) blockast = CB->statements[0]; // a single statement else { - fprintf(stderr, "IR_xxxBlock is dumb, with multiple ways to hold statements\n"); + CHILL_ERROR( "IR_xxxBlock is dumb, with multiple ways to hold statements\n"); exit(-1); // TODO FIX } } @@ -2615,11 +2613,14 @@ std::vector IR_clangCode::FindOneLevelControlStructure(const IR_Bl std::vector children; - if (blockast->asttype == CHILLAST_NODETYPE_FORSTMT) { fflush(stdout); - fprintf(stderr, "found a top level For statement (Loop)\n"); - fprintf(stderr, "For Stmt (loop) is:\n"); - blockast->print(); - fprintf(stderr, "pushing the loop at TOP\n"); + if (blockast->asttype == CHILLAST_NODETYPE_FORSTMT) { + CHILL_DEBUG_BEGIN + fflush(stdout); + fprintf(stderr, "found a top level For statement (Loop)\n"); + fprintf(stderr, "For Stmt (loop) is:\n"); + blockast->print(); + fprintf(stderr, "pushing the loop at TOP\n"); + CHILL_DEBUG_END controls.push_back( new IR_chillLoop( this, (chillAST_ForStmt *)blockast)); } @@ -2663,16 +2664,16 @@ std::vector IR_clangCode::FindOneLevelControlStructure(const IR_Bl CHILL_ASTNODE_TYPE typ = children[i]->asttype; if (typ == CHILLAST_NODETYPE_LOOP) { if (numchildren == 1) { - fprintf(stderr, "found a For statement (Loop)\n"); + CHILL_DEBUG_PRINT("found a For statement (Loop)\n"); } else { - fprintf(stderr, "found a For statement (Loop) at %d within a Basic Block\n", i); + CHILL_DEBUG_PRINT("found a For statement (Loop) at %d within a Basic Block\n", i); } //children[i]->print(); printf("\n"); fflush(stdout); ns = basicblock->numstatements(); if (ns) { - fprintf(stderr, "pushing a run of statements %d to %d as a block\n", i-ns, i-1); + CHILL_DEBUG_PRINT("pushing a run of statements %d to %d as a block\n", i-ns, i-1); controls.push_back( basicblock ); basicblock = new IR_chillBlock(this); // start a new one } @@ -2704,17 +2705,17 @@ std::vector IR_clangCode::FindOneLevelControlStructure(const IR_Bl } else { - fprintf(stderr, "IR_clangCode::FindOneLevelControlStructure(), block is a %s???\n", blockast->getTypeString()); + CHILL_ERROR("IR_clangCode::FindOneLevelControlStructure(), block is a %s???\n", blockast->getTypeString()); exit(-1); } - fprintf(stderr, "returning vector of %d controls\n", controls.size() ); + CHILL_DEBUG_PRINT("returning vector of %d controls\n", controls.size() ); return controls; } IR_Block *IR_clangCode::MergeNeighboringControlStructures(const std::vector &controls) const { - fprintf(stderr, "IR_xxxxCode::MergeNeighboringControlStructures %d controls\n", controls.size()); + CHILL_DEBUG_PRINT("IR_xxxxCode::MergeNeighboringControlStructures %d controls\n", controls.size()); if (controls.size() == 0) return NULL; @@ -2726,7 +2727,7 @@ IR_Block *IR_clangCode::MergeNeighboringControlStructures(const std::vectortype()) { case IR_CONTROL_LOOP: { - fprintf(stderr, "control %d is IR_CONTROL_LOOP\n", i); + CHILL_DEBUG_PRINT("control %d is IR_CONTROL_LOOP\n", i); chillAST_ForStmt *loop = static_cast(controls[i])->chillforstmt; if (parent == NULL) { parent = loop->parent; @@ -2739,7 +2740,7 @@ IR_Block *IR_clangCode::MergeNeighboringControlStructures(const std::vector(controls[i]); std::vector blockstmts = CB->statements; if (statements.size() != 0) { @@ -2758,8 +2759,7 @@ IR_Block *IR_clangCode::MergeNeighboringControlStructures(const std::vectorchillAST) CBlock->addStatement(CBlock->chillAST); // if this is a block, add theblock's statements? else { // should never happen - fprintf(stderr, "WARNING: ir_clang.cc IR_clangCode::MergeNeighboringControlStructures"); - fprintf(stderr, " empty IR_CONTROL_BLOCK \n"); + CHILL_DEBUG_PRINT("WARNING: empty IR_CONTROL_BLOCK \n"); } } break; @@ -2923,9 +2923,8 @@ void IR_clangCode::ReplaceCode(IR_Control *old, omega::CG_outputRepr *repr) { } break; case IR_CONTROL_BLOCK: - fprintf(stderr, "old is IR_CONTROL_BLOCK\n"); - fprintf(stderr, "IR_clangCode::ReplaceCode() stubbed out\n"); - exit(-1); + CHILL_ERROR("old is IR_CONTROL_BLOCK\n"); + exit(-1); //tf_old = static_cast(old)->getStmtList()[0]; break; default: @@ -2935,17 +2934,18 @@ void IR_clangCode::ReplaceCode(IR_Control *old, omega::CG_outputRepr *repr) { fflush(stdout); //fprintf(stderr, "\nafter inserting %d statements into the Clang IR,", numnew); - fprintf(stderr, "\nnew parent2 is\n\n{\n"); - std::vector newparentcode = par->getChildren(); - for (int i=0; iprint(); printf(";\n"); fflush(stdout); - } - + CHILL_DEBUG_BEGIN + fprintf(stderr, "new parent2 is\n\n{\n"); + std::vector newparentcode = par->getChildren(); + for (int i=0; iprint(); printf(";\n"); fflush(stdout); + } + fprintf(stderr, "}\n"); + CHILL_DEBUG_END - fprintf(stderr, "}\n"); } @@ -3045,14 +3045,14 @@ IR_OPERATION_TYPE IR_clangCode::QueryExpOperation(const omega::CG_outputRepr *re if (!strcmp(opstring, "/")) return IR_OP_DIVIDE; if (!strcmp(opstring, "=")) return IR_OP_ASSIGNMENT; - fprintf(stderr, "ir_clang.cc IR_clangCode::QueryExpOperation() UNHANDLED Binary(or Unary)Operator op type (%s)\n", opstring); + CHILL_ERROR("UNHANDLED Binary(or Unary)Operator op type (%s)\n", opstring); exit(-1); } else if (node->isDeclRefExpr() ) return IR_OP_VARIABLE; // ?? //else if (node->is ) return something; else { - fprintf(stderr, "IR_clangCode::QueryExpOperation() UNHANDLED NODE TYPE %s\n", node->getTypeString()); - exit(-1); + CHILL_ERROR("IR_clangCode::QueryExpOperation() UNHANDLED NODE TYPE %s\n", node->getTypeString()); + exit(-1); } /* CLANG @@ -3123,7 +3123,7 @@ std::vector IR_clangCode::QueryExpOperand(const omega::C v.push_back(new omega::CG_chillRepr( bop->rhs )); } else { - fprintf(stderr, "ir_clang.cc IR_clangCode::QueryExpOperand() Binary Operator UNHANDLED op (%s)\n", op); + CHILL_ERROR("Binary Operator UNHANDLED op (%s)\n", op); exit(-1); } } // BinaryOperator @@ -3135,13 +3135,13 @@ std::vector IR_clangCode::QueryExpOperand(const omega::C v.push_back( new omega::CG_chillRepr( uop->subexpr )); } else { - fprintf(stderr, "ir_clang.cc IR_clangCode::QueryExpOperand() Unary Operator UNHANDLED op (%s)\n", op); + CHILL_ERROR("ir_clang.cc IR_clangCode::QueryExpOperand() Unary Operator UNHANDLED op (%s)\n", op); exit(-1); } } // unaryoperator else { - fprintf(stderr, "ir_clang.cc IR_clangCode::QueryExpOperand() UNHANDLED node type %s\n", e->getTypeString()); - exit(-1); + CHILL_ERROR("UNHANDLED node type %s\n", e->getTypeString()); + exit(-1); } diff --git a/src/irtools.cc b/src/irtools.cc index 16c4f7c..d8d234f 100644 --- a/src/irtools.cc +++ b/src/irtools.cc @@ -13,6 +13,7 @@ #include #include +#include #include "irtools.hh" #include "omegatools.hh" #include "chill_error.hh" @@ -26,18 +27,18 @@ std::vector build_ir_tree(IR_Control *control, ir_tree_node *parent) { std::vector result; - fprintf(stderr, "irtools.cc, build_ir_tree( control, parent) building a CHILL IR tree \n"); + CHILL_DEBUG_PRINT("building a CHILL IR tree \n"); switch (control->type()) { case IR_CONTROL_BLOCK: { - fprintf(stderr, "irtools.cc L31 case IR_CONTROL_BLOCK\n"); + CHILL_DEBUG_PRINT("case IR_CONTROL_BLOCK\n"); IR_Block *IRCB = static_cast(control); std::vector controls = control->ir_->FindOneLevelControlStructure(IRCB); - fprintf(stderr, "irtools.cc BACK FROM FindOneLevelControlStructure() %d controls\n", controls.size()); + CHILL_DEBUG_PRINT( "BACK FROM FindOneLevelControlStructure() %d controls\n", controls.size()); if (controls.size() == 0) { - fprintf(stderr, "controls.size() == 0\n"); + CHILL_DEBUG_PRINT("controls.size() == 0\n"); ir_tree_node *node = new ir_tree_node; node->content = control; @@ -46,19 +47,19 @@ std::vector build_ir_tree(IR_Control *control, result.push_back(node); } else { - fprintf(stderr, "controls.size() == %d (NONZERO)\n", controls.size()); + CHILL_DEBUG_PRINT("controls.size() == %d (NONZERO)\n", controls.size()); delete control; for (int i = 0; i < controls.size(); i++) switch (controls[i]->type()) { case IR_CONTROL_BLOCK: { - fprintf(stderr, "controls[%d] is IR_CONTROL_BLOCK\n", i); + CHILL_DEBUG_PRINT("controls[%d] is IR_CONTROL_BLOCK\n", i); std::vector t = build_ir_tree(controls[i], parent); result.insert(result.end(), t.begin(), t.end()); break; } case IR_CONTROL_LOOP: { - fprintf(stderr, "controls[%d] is IR_CONTROL_LOOP\n", i); + CHILL_DEBUG_PRINT("controls[%d] is IR_CONTROL_LOOP\n", i); ir_tree_node *node = new ir_tree_node; node->content = controls[i]; node->parent = parent; @@ -68,7 +69,7 @@ std::vector build_ir_tree(IR_Control *control, break; } case IR_CONTROL_IF: { - fprintf(stderr, "controls[%d] is IR_CONTROL_IF\n", i); + CHILL_DEBUG_PRINT("controls[%d] is IR_CONTROL_IF\n", i); static int unique_if_identifier = 0; IR_If* theif = static_cast(controls[i]); @@ -85,7 +86,7 @@ std::vector build_ir_tree(IR_Control *control, block = theif->else_body(); if (block != NULL) { - fprintf(stderr, "IF_CONTROL has an else\n"); + CHILL_DEBUG_PRINT("IF_CONTROL has an else\n"); ir_tree_node *node = new ir_tree_node; node->content = controls[i]->clone(); node->parent = parent; @@ -108,16 +109,16 @@ std::vector build_ir_tree(IR_Control *control, break; } case IR_CONTROL_LOOP: { - fprintf(stderr, "case IR_CONTROL_LOOP\n"); + CHILL_DEBUG_PRINT("case IR_CONTROL_LOOP\n"); ir_tree_node *node = new ir_tree_node; node->content = control; node->parent = parent; - fprintf(stderr, "recursing. build_ir_tree() of CONTROL_LOOP creating children L122\n"); + CHILL_DEBUG_PRINT("recursing. build_ir_tree() of CONTROL_LOOP creating children L122\n"); node->children = build_ir_tree( static_cast(control)->body(), node); node->payload = -1; result.push_back(node); - fprintf(stderr, "recursing. build_ir_tree() of CONTROL_LOOP creating children DONE\n"); + CHILL_DEBUG_PRINT("recursing. build_ir_tree() of CONTROL_LOOP creating children DONE\n"); break; } default: @@ -129,7 +130,7 @@ std::vector build_ir_tree(IR_Control *control, break; } - fprintf(stderr, "build_ir_tree() vector result has %ld parts\n", result.size()); + CHILL_DEBUG_PRINT("build_ir_tree() vector result has %ld parts\n", result.size()); return result; } @@ -138,18 +139,18 @@ std::vector build_ir_tree(IR_Control *control, // lexical order in the source code. std::vector extract_ir_stmts(const std::vector &ir_tree) { - fprintf(stderr, "extract_ir_stmts() ir_tree.size() %d\n", ir_tree.size()); + CHILL_DEBUG_PRINT("extract_ir_stmts() ir_tree.size() %d\n", ir_tree.size()); std::vector result; for (int i = 0; i < ir_tree.size(); i++) switch (ir_tree[i]->content->type()) { case IR_CONTROL_BLOCK: - fprintf(stderr, "IR_CONTROL_BLOCK\n"); + CHILL_DEBUG_PRINT("IR_CONTROL_BLOCK\n"); result.push_back(ir_tree[i]); break; case IR_CONTROL_LOOP: { - fprintf(stderr, "IR_CONTROL_LOOP( recursing )\n"); + CHILL_DEBUG_PRINT("IR_CONTROL_LOOP( recursing )\n"); // clear loop payload from previous unsuccessful initialization process ir_tree[i]->payload = -1; @@ -159,7 +160,7 @@ std::vector extract_ir_stmts(const std::vector & break; } case IR_CONTROL_IF: { - fprintf(stderr, "IR_CONTROL_IF( recursing )\n"); + CHILL_DEBUG_PRINT("IR_CONTROL_IF( recursing )\n"); std::vector t = extract_ir_stmts(ir_tree[i]->children); result.insert(result.end(), t.begin(), t.end()); break; @@ -176,7 +177,7 @@ std::string chill_ir_control_type_string( IR_CONTROL_TYPE type ) { case IR_CONTROL_BLOCK: return std::string( "IR_CONTROL_BLOCK"); case IR_CONTROL_LOOP: return std::string( "IR_CONTROL_LOOP" ); case IR_CONTROL_IF: return std::string( "IR_CONTROL_IF" ); - case IR_CONTROL_WHILE: return std::string( "IR_CONTROL_WHLIE"); break; + case IR_CONTROL_WHILE: return std::string( "IR_CONTROL_WHLIE"); default: return std::string( "UNKNOWN_IR_NODE_TYPE" ); } } @@ -282,15 +283,15 @@ test_data_dependences(IR_Code *ir, int nestLevelj, std::map > &uninterpreted_symbols, std::map > &uninterpreted_symbols_stringrepr) { + CHILL_DEBUG_BEGIN + fprintf(stderr, "\nirtools.cc test_data_dependences() %d freevars\n", freevar.size()); + fprintf(stderr, "\nrepr1 %p ", repr1); repr1->dump(); fflush(stdout); + fprintf(stderr, "\nrepr2 %p ", repr2); repr2->dump(); fflush(stdout); - fprintf(stderr, "\nirtools.cc test_data_dependences() %d freevars\n", freevar.size()); - fprintf(stderr, "\nrepr1 %p ", repr1); repr1->dump(); fflush(stdout); - fprintf(stderr, "\nrepr2 %p ", repr2); repr2->dump(); fflush(stdout); - - for (int i=0; iprint(); fflush(stdout); - helper = new Relation(IS2); fprintf(stderr, "IS2 "); helper->print(); fflush(stdout); - + for (int i=0; iprint(); fflush(stdout); + helper = new Relation(IS2); fprintf(stderr, "IS2 "); helper->print(); fflush(stdout); + CHILL_DEBUG_END //for (int i=0; ibase_name()); @@ -301,23 +302,25 @@ test_data_dependences(IR_Code *ir, std::pair, std::vector > result; if (repr1 == repr2) { - fprintf(stderr, "repr1 == repr2\nrepr1->dump()\n"); - repr1->dump(); + CHILL_DEBUG_BEGIN + fprintf(stderr, "repr1 == repr2\nrepr1->dump()\n"); + repr1->dump(); + CHILL_DEBUG_END fflush(stdout); std::vector access = ir->FindArrayRef(repr1); - fprintf(stderr, "access of size %d\n", access.size()); + CHILL_DEBUG_PRINT("access of size %d\n", access.size()); for (int i = 0; i < access.size(); i++) { IR_ArrayRef *a = access[i]; if (a->is_write()) { - fprintf(stderr, "WRITE array access %d = %s\n", i, a->name().c_str()); + CHILL_DEBUG_PRINT("WRITE array access %d = %s\n", i, a->name().c_str()); } else { - fprintf(stderr, " array access %d = %s\n", i, a->name().c_str()); + CHILL_DEBUG_PRINT(" array access %d = %s\n", i, a->name().c_str()); } } - fprintf(stderr, "that was the list\n\n"); + CHILL_DEBUG_PRINT("that was the list\n\n"); // Manu:: variables/structures added to identify dependence vectors related to reduction operation tempResultMap trMap; @@ -335,9 +338,9 @@ test_data_dependences(IR_Code *ir, // Manu -- changes for identifying possible reduction operation // The below loop nest is used to classify array references into different statements - fprintf(stderr, "\nbefore mapRefstoStatements()\n"); + CHILL_DEBUG_PRINT("\nbefore mapRefstoStatements()\n"); mapRefstoStatements(ir,access,ref2Stmt,rMap,tnrStmts,nrStmts); - fprintf(stderr, "after mapRefstoStatements()\n\n"); + CHILL_DEBUG_PRINT("after mapRefstoStatements()\n\n"); //------------------------------------------------------------- omega::coef_t lbound[3], ubound[3]; // for each kind of dependence. We can potentially have reduction only if all @@ -368,10 +371,11 @@ test_data_dependences(IR_Code *ir, else fprintf(stderr, "%d b->is_NOT_write()\n", j); if (*sym_a == *sym_b && (a->is_write() || b->is_write())) { - fprintf(stderr, "\nirtools.cc ij %d %d SYMBOL A == SYMBOL B and one is a write\n", i, j); Relation r = arrays2relation(ir, freevar, a, IS1, b, IS2,uninterpreted_symbols,uninterpreted_symbols_stringrepr); - helper = new Relation(r); fprintf(stderr, "r "); helper->print(); fflush(stdout); - + CHILL_DEBUG_BEGIN + fprintf(stderr, "\nirtools.cc ij %d %d SYMBOL A == SYMBOL B and one is a write\n", i, j); + Relation *helper = new Relation(r); fprintf(stderr, "r "); helper->print(); fflush(stdout); + CHILL_DEBUG_END fprintf(stderr, "1\n"); std::pair, diff --git a/src/loop.cc b/src/loop.cc deleted file mode 100644 index 5f863f2..0000000 --- a/src/loop.cc +++ /dev/null @@ -1,4435 +0,0 @@ -/***************************************************************************** - Copyright (C) 2008 University of Southern California - Copyright (C) 2009-2010 University of Utah - All Rights Reserved. - - Purpose: - Core loop transformation functionality. - - Notes: - "level" (starting from 1) means loop level and it corresponds to "dim" - (starting from 0) in transformed iteration space [c_1,l_1,c_2,l_2,...., - c_n,l_n,c_(n+1)], e.g., l_2 is loop level 2 in generated code, dim 3 - in transformed iteration space, and variable 4 in Omega relation. - All c's are constant numbers only and they will not show up as actual loops. - Formula: - dim = 2*level - 1 - var = dim + 1 - - History: - 10/2005 Created by Chun Chen. - 09/2009 Expand tile functionality, -chun - 10/2009 Initialize unfusible loop nest without bailing out, -chun -*****************************************************************************/ - -#include -#include -#include -#include -#include -#include // Mark. Bad idea. TODO -#include -#include -#include -#include "loop.hh" -#include "omegatools.hh" -#include "irtools.hh" -#include "chill_error.hh" -#include -#include - -// TODO -#define _DEBUG_ true - - - -using namespace omega; - -const std::string Loop::tmp_loop_var_name_prefix = std::string("chill_t"); // Manu:: In fortran, first character of a variable name must be a letter, so this change -const std::string Loop::overflow_var_name_prefix = std::string("over"); - -void echocontroltype( const IR_Control *control ) { - switch(control->type()) { - case IR_CONTROL_BLOCK: { - fprintf(stderr, "IR_CONTROL_BLOCK\n"); - break; - } - case IR_CONTROL_LOOP: { - fprintf(stderr, "IR_CONTROL_LOOP\n"); - break; - } - case IR_CONTROL_IF: { - fprintf(stderr, "IR_CONTROL_IF\n"); - break; - } - default: - fprintf(stderr, "just a bunch of statements?\n"); - - } // switch -} - -omega::Relation Loop::getNewIS(int stmt_num) const { - - omega::Relation result; - - if (stmt[stmt_num].xform.is_null()) { - omega::Relation known = omega::Extend_Set(omega::copy(this->known), - stmt[stmt_num].IS.n_set() - this->known.n_set()); - result = omega::Intersection(omega::copy(stmt[stmt_num].IS), known); - } else { - omega::Relation known = omega::Extend_Set(omega::copy(this->known), - stmt[stmt_num].xform.n_out() - this->known.n_set()); - result = omega::Intersection( - omega::Range( - omega::Restrict_Domain( - omega::copy(stmt[stmt_num].xform), - omega::copy(stmt[stmt_num].IS))), known); - } - - result.simplify(2, 4); - - return result; -} - - - -void Loop::reduce(int stmt_num, - std::vector &level, - int param, - std::string func_name, - std::vector &seq_levels, - std::vector cudaized_levels, - int bound_level) { - - // illegal instruction?? fprintf(stderr, " Loop::reduce( stmt %d, param %d, func_name (encrypted)...)\n", stmt, param); // , func_name.c_str()); - - //std::cout << "Reducing stmt# " << stmt_num << " at level " << level << "\n"; - //ir->printStmt(stmt[stmt_num].code); - - if (stmt[stmt_num].reduction != 1) { - std::cout << "loop.cc Cannot reduce this statement\n"; - return; - } - fprintf(stderr, "loop.cc CAN reduce this statment?\n"); - - /*for (int i = 0; i < level.size(); i++) - if (stmt[stmt_num].loop_level[level[i] - 1].segreducible != true) { - std::cout << "Cannot reduce this statement\n"; - return; - } - for (int i = 0; i < seq_levels.size(); i++) - if (stmt[stmt_num].loop_level[seq_levels[i] - 1].segreducible != true) { - std::cout << "Cannot reduce this statement\n"; - return; - } - */ - // std::pair to_insert(level, func_name); - // reduced_statements.insert(std::pair >(stmt_num, to_insert )); - // invalidate saved codegen computation - delete last_compute_cgr_; - last_compute_cgr_ = NULL; - delete last_compute_cg_; - last_compute_cg_ = NULL; - fprintf(stderr, "set last_compute_cg_ = NULL;\n"); - - omega::CG_outputBuilder *ocg = ir->builder(); - - omega::CG_outputRepr *funCallRepr; - std::vector arg_repr_list; - apply_xform(stmt_num); - std::vector access = ir->FindArrayRef(stmt[stmt_num].code); - std::set names; - for (int i = 0; i < access.size(); i++) { - std::vector access2; - for (int j = 0; j < access[i]->n_dim(); j++) { - std::vector access3 = ir->FindArrayRef( - access[i]->index(j)); - access2.insert(access2.end(), access3.begin(), access3.end()); - } - if (access2.size() == 0) { - if (names.find(access[i]->name()) == names.end()) { - arg_repr_list.push_back( - ocg->CreateAddressOf(access[i]->convert())); - names.insert(access[i]->name()); - if (access[i]->is_write()) - reduced_write_refs.insert(access[i]->name()); - } - } else { - if (names.find(access[i]->name()) == names.end()) { - arg_repr_list.push_back(ocg->CreateAddressOf(ocg->CreateArrayRefExpression(ocg->CreateIdent(access[i]->name()), - ocg->CreateInt(0)))); - names.insert(access[i]->name()); - if (access[i]->is_write()) - reduced_write_refs.insert(access[i]->name()); - } - } - } - - for (int i = 0; i < seq_levels.size(); i++) - arg_repr_list.push_back( - ocg->CreateIdent( - stmt[stmt_num].IS.set_var(seq_levels[i])->name())); - - if (bound_level != -1) { - - omega::Relation new_IS = copy(stmt[stmt_num].IS); - new_IS.copy_names(stmt[stmt_num].IS); - new_IS.setup_names(); - new_IS.simplify(); - int dim = bound_level; - //omega::Relation r = getNewIS(stmt_num); - for (int j = dim + 1; j <= new_IS.n_set(); j++) - new_IS = omega::Project(new_IS, new_IS.set_var(j)); - - new_IS.simplify(2, 4); - - omega::Relation bound_ = get_loop_bound(copy(new_IS), dim - 1); - omega::Variable_ID v = bound_.set_var(dim); - std::vector ubList; - for (omega::GEQ_Iterator e( - const_cast(bound_).single_conjunct()->GEQs()); - e; e++) { - if ((*e).get_coef(v) < 0) { - // && (*e).is_const_except_for_global(v)) - omega::CG_outputRepr *UPPERBOUND = - omega::output_upper_bound_repr(ir->builder(), *e, v, - bound_, - std::vector< - std::pair >( - bound_.n_set(), - std::make_pair( - static_cast(NULL), - 0)), uninterpreted_symbols[stmt_num]); - if (UPPERBOUND != NULL) - ubList.push_back(UPPERBOUND); - - } - - } - - omega::CG_outputRepr * ubRepr; - if (ubList.size() > 1) { - - ubRepr = ir->builder()->CreateInvoke("min", ubList); - arg_repr_list.push_back(ubRepr); - } else if (ubList.size() == 1) - arg_repr_list.push_back(ubList[0]); - } - - funCallRepr = ocg->CreateInvoke(func_name, arg_repr_list); - stmt[stmt_num].code = funCallRepr; - for (int i = 0; i < level.size(); i++) { - //stmt[*i].code = outputStatement(ocg, stmt[*i].code, 0, mapping, known, std::vector(mapping.n_out(), NULL)); - std::vector loop_vars; - loop_vars.push_back(stmt[stmt_num].IS.set_var(level[i])->name()); - - std::vector subs; - subs.push_back(ocg->CreateInt(0)); - - stmt[stmt_num].code = ocg->CreateSubstitutedStmt(0, stmt[stmt_num].code, - loop_vars, subs); - - } - - omega::Relation new_IS = copy(stmt[stmt_num].IS); - new_IS.copy_names(stmt[stmt_num].IS); - new_IS.setup_names(); - new_IS.simplify(); - int old_size = new_IS.n_set(); - - omega::Relation R = omega::copy(stmt[stmt_num].IS); - R.copy_names(stmt[stmt_num].IS); - R.setup_names(); - - for (int i = level.size() - 1; i >= 0; i--) { - int j; - - for (j = 0; j < cudaized_levels.size(); j++) { - if (cudaized_levels[j] == level[i]) - break; - - } - - if (j == cudaized_levels.size()) { - R = omega::Project(R, level[i], omega::Input_Var); - R.simplify(); - - } - // - - } - - omega::F_And *f_Root = R.and_with_and(); - for (int i = level.size() - 1; i >= 0; i--) { - int j; - - for (j = 0; j < cudaized_levels.size(); j++) { - if (cudaized_levels[j] == level[i]) - break; - - } - - if (j == cudaized_levels.size()) { - - omega::EQ_Handle h = f_Root->add_EQ(); - - h.update_coef(R.set_var(level[i]), 1); - h.update_const(-1); - } - // - - } - - R.simplify(); - stmt[stmt_num].IS = R; -} - - - - - - -//----------------------------------------------------------------------------- -// Class Loop -//----------------------------------------------------------------------------- -// --begin Anand: Added from CHiLL 0.2 - -bool Loop::isInitialized() const { - return stmt.size() != 0 && !stmt[0].xform.is_null(); -} - -//--end Anand: added from CHiLL 0.2 - -bool Loop::init_loop(std::vector &ir_tree, - std::vector &ir_stmt) { - - fprintf(stderr, "\n Loop::init_loop()\n"); - - fprintf(stderr, "extract_ir_stmts()\n"); - fprintf(stderr, "ir_tree has %d statements\n", ir_tree.size()); - - ir_stmt = extract_ir_stmts(ir_tree); - - fprintf(stderr,"nesting level stmt size = %d\n", (int)ir_stmt.size()); - stmt_nesting_level_.resize(ir_stmt.size()); - - std::vector stmt_nesting_level(ir_stmt.size()); - - fprintf(stderr, "%d statements?\n", (int)ir_stmt.size()); - - // find out how deeply nested each statement is. (how can these be different?) - for (int i = 0; i < ir_stmt.size(); i++) { - fprintf(stderr, "i %d\n", i); - ir_stmt[i]->payload = i; - int t = 0; - ir_tree_node *itn = ir_stmt[i]; - while (itn->parent != NULL) { - itn = itn->parent; - if (itn->content->type() == IR_CONTROL_LOOP) - t++; - } - stmt_nesting_level_[i] = t; - stmt_nesting_level[i] = t; - fprintf(stderr, "stmt_nesting_level[%d] = %d\n", i, t); - } - - if (actual_code.size() == 0) - actual_code = std::vector(ir_stmt.size()); - - stmt = std::vector(ir_stmt.size()); - fprintf(stderr, "in init_loop, made %d stmts\n", (int)ir_stmt.size()); - - uninterpreted_symbols = std::vector > >(ir_stmt.size()); - uninterpreted_symbols_stringrepr = std::vector > >(ir_stmt.size()); - - int n_dim = -1; - int max_loc; - //std::vector index; - for (int i = 0; i < ir_stmt.size(); i++) { - int max_nesting_level = -1; - int loc; - - // find the max nesting level and remember the statement that was at that level - for (int j = 0; j < ir_stmt.size(); j++) { - if (stmt_nesting_level[j] > max_nesting_level) { - max_nesting_level = stmt_nesting_level[j]; - loc = j; - } - } - - fprintf(stderr, "max nesting level %d at location %d\n", max_nesting_level, loc); - - // most deeply nested statement acting as a reference point - if (n_dim == -1) { - fprintf(stderr, "loop.cc L356 n_dim now max_nesting_level %d\n", max_nesting_level); - n_dim = max_nesting_level; - max_loc = loc; - - index = std::vector(n_dim); - - ir_tree_node *itn = ir_stmt[loc]; - fprintf(stderr, "itn = stmt[%d]\n", loc); - int cur_dim = n_dim - 1; - while (itn->parent != NULL) { - fprintf(stderr, "parent\n"); - - itn = itn->parent; - if (itn->content->type() == IR_CONTROL_LOOP) { - fprintf(stderr, "IR_CONTROL_LOOP cur_dim %d\n", cur_dim); - IR_Loop *IRL = static_cast(itn->content); - index[cur_dim] = IRL->index()->name(); - fprintf(stderr, "index[%d] = '%s'\n", cur_dim, index[cur_dim].c_str()); - itn->payload = cur_dim--; - } - } - } - - fprintf(stderr, "align loops by names,\n"); - // align loops by names, temporary solution - ir_tree_node *itn = ir_stmt[loc]; // defined outside loops?? - int depth = stmt_nesting_level_[loc] - 1; - - for (int t = depth; t >= 0; t--) { - int y = t; - itn = ir_stmt[loc]; - - while ((itn->parent != NULL) && (y >= 0)) { - itn = itn->parent; - if (itn->content->type() == IR_CONTROL_LOOP) - y--; - } - - if (itn->content->type() == IR_CONTROL_LOOP && itn->payload == -1) { - CG_outputBuilder *ocg = ir->builder(); - - itn->payload = depth - t; - - CG_outputRepr *code = - static_cast(ir_stmt[loc]->content)->extract(); - - std::vector index_expr; - std::vector old_index; - CG_outputRepr *repl = ocg->CreateIdent(index[itn->payload]); - index_expr.push_back(repl); - old_index.push_back( - static_cast(itn->content)->index()->name()); - code = ocg->CreateSubstitutedStmt(0, code, old_index, - index_expr); - - replace.insert(std::pair(loc, code)); - //stmt[loc].code = code; - - } - } - - fprintf(stderr, "\nset relation variable names ****\n"); - // set relation variable names - - // this finds the loop variables for loops enclosing this statement and puts - // them in an Omega Relation (just their names, which could fail) - - fprintf(stderr, "Relation r(%d)\n", n_dim); - Relation r(n_dim); - F_And *f_root = r.add_and(); - itn = ir_stmt[loc]; - int temp_depth = depth; - while (itn->parent != NULL) { - - itn = itn->parent; - if (itn->content->type() == IR_CONTROL_LOOP) { - fprintf(stderr, "it's a loop. temp_depth %d\n", temp_depth); - fprintf(stderr, "r.name_set_var( %d, %s )\n", itn->payload + 1, index[temp_depth].c_str()); - r.name_set_var(itn->payload + 1, index[temp_depth]); - - temp_depth--; - } - //static_cast(itn->content)->index()->name()); - } - fprintf(stderr, "Relation r "); r.print(); fflush(stdout); - //fprintf(stderr, "f_root "); f_root->print(stderr); fprintf(stderr, "\n"); - - /*while (itn->parent != NULL) { - itn = itn->parent; - if (itn->content->type() == IR_CONTROL_LOOP) - r.name_set_var(itn->payload+1, static_cast(itn->content)->index()->name()); - }*/ - - - - - fprintf(stderr, "extract information from loop/if structures\n"); - // extract information from loop/if structures - std::vector processed(n_dim, false); - std::vector vars_to_be_reversed; - - std::vector insp_lb; - std::vector insp_ub; - - itn = ir_stmt[loc]; - while (itn->parent != NULL) { // keep heading upward - itn = itn->parent; - - switch (itn->content->type()) { - case IR_CONTROL_LOOP: { - fprintf(stderr, "loop.cc l 462 IR_CONTROL_LOOP\n"); - IR_Loop *lp = static_cast(itn->content); - Variable_ID v = r.set_var(itn->payload + 1); - int c; - - try { - c = lp->step_size(); - //fprintf(stderr, "step size %d\n", c); - if (c > 0) { - CG_outputRepr *lb = lp->lower_bound(); - fprintf(stderr, "loop.cc, got the lower bound. it is:\n"); - lb->dump(); printf("\n"); fflush(stdout); - - exp2formula(ir, r, f_root, freevar, lb, v, 's', - IR_COND_GE, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); - - CG_outputRepr *ub = lp->upper_bound(); - //fprintf(stderr, "loop.cc, got the upper bound. it is:\n"); - //ub->dump(); printf("\n"); fflush(stdout); - - - - IR_CONDITION_TYPE cond = lp->stop_cond(); - if (cond == IR_COND_LT || cond == IR_COND_LE) - exp2formula(ir, r, f_root, freevar, ub, v, 's', - cond, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); - else - throw ir_error("loop condition not supported"); - - - if ((ir->QueryExpOperation(lp->lower_bound()) - == IR_OP_ARRAY_VARIABLE) - && (ir->QueryExpOperation(lp->lower_bound()) - == ir->QueryExpOperation( - lp->upper_bound()))) { - - fprintf(stderr, "loop.cc lower and upper are both IR_OP_ARRAY_VARIABLE?\n"); - - std::vector v = - ir->QueryExpOperand(lp->lower_bound()); - IR_ArrayRef *ref = - static_cast(ir->Repr2Ref( - v[0])); - std::string s0 = ref->name(); - std::vector v2 = - ir->QueryExpOperand(lp->upper_bound()); - IR_ArrayRef *ref2 = - static_cast(ir->Repr2Ref( - v2[0])); - std::string s1 = ref2->name(); - - if (s0 == s1) { - insp_lb.push_back(s0); - insp_ub.push_back(s1); - - } - - } - - - } else if (c < 0) { - CG_outputBuilder *ocg = ir->builder(); - CG_outputRepr *lb = lp->lower_bound(); - lb = ocg->CreateMinus(NULL, lb); - exp2formula(ir, r, f_root, freevar, lb, v, 's', - IR_COND_GE, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); - CG_outputRepr *ub = lp->upper_bound(); - ub = ocg->CreateMinus(NULL, ub); - IR_CONDITION_TYPE cond = lp->stop_cond(); - if (cond == IR_COND_GE) - exp2formula(ir, r, f_root, freevar, ub, v, 's', - IR_COND_LE, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); - else if (cond == IR_COND_GT) - exp2formula(ir, r, f_root, freevar, ub, v, 's', - IR_COND_LT, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); - else - throw ir_error("loop condition not supported"); - - vars_to_be_reversed.push_back(lp->index()->name()); - } else - throw ir_error("loop step size zero"); - } catch (const ir_error &e) { - actual_code[loc] = - static_cast(ir_stmt[loc]->content)->extract(); - for (int i = 0; i < itn->children.size(); i++) - delete itn->children[i]; - itn->children = std::vector(); - itn->content = itn->content->convert(); - return false; - } - - // check for loop increment or decrement that is not 1 - //fprintf(stderr, "abs(c)\n"); - if (abs(c) != 1) { - F_Exists *f_exists = f_root->add_exists(); - Variable_ID e = f_exists->declare(); - F_And *f_and = f_exists->add_and(); - Stride_Handle h = f_and->add_stride(abs(c)); - if (c > 0) - h.update_coef(e, 1); - else - h.update_coef(e, -1); - h.update_coef(v, -1); - CG_outputRepr *lb = lp->lower_bound(); - exp2formula(ir, r, f_and, freevar, lb, e, 's', IR_COND_EQ, - true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); - } - - processed[itn->payload] = true; - break; - } - - - case IR_CONTROL_IF: { - fprintf(stderr, "IR_CONTROL_IF\n"); - IR_If *theif = static_cast(itn->content); - - CG_outputRepr *cond = - static_cast(itn->content)->condition(); - - try { - if (itn->payload % 2 == 1) - exp2constraint(ir, r, f_root, freevar, cond, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); - else { - F_Not *f_not = f_root->add_not(); - F_And *f_and = f_not->add_and(); - exp2constraint(ir, r, f_and, freevar, cond, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); - } - } catch (const ir_error &e) { - std::vector *t; - if (itn->parent == NULL) - t = &ir_tree; - else - t = &(itn->parent->children); - int id = itn->payload; - int i = t->size() - 1; - while (i >= 0) { - if ((*t)[i] == itn) { - for (int j = 0; j < itn->children.size(); j++) - delete itn->children[j]; - itn->children = std::vector(); - itn->content = itn->content->convert(); - } else if ((*t)[i]->payload >> 1 == id >> 1) { - delete (*t)[i]; - t->erase(t->begin() + i); - } - i--; - } - return false; - } - - break; - } - default: - //fprintf(stderr, "default?\n"); - for (int i = 0; i < itn->children.size(); i++) - delete itn->children[i]; - itn->children = std::vector(); - itn->content = itn->content->convert(); - return false; - } - } - - - //fprintf(stderr, "add information for missing loops n_dim(%d)\n", n_dim); - // add information for missing loops - for (int j = 0; j < n_dim; j++) - if (!processed[j]) { - ir_tree_node *itn = ir_stmt[max_loc]; - while (itn->parent != NULL) { - itn = itn->parent; - if (itn->content->type() == IR_CONTROL_LOOP - && itn->payload == j) - break; - } - - Variable_ID v = r.set_var(j + 1); - if (loc < max_loc) { - - CG_outputBuilder *ocg = ir->builder(); - - CG_outputRepr *lb = - static_cast(itn->content)->lower_bound(); - - exp2formula(ir, r, f_root, freevar, lb, v, 's', IR_COND_EQ, - false,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); - - /* if (ir->QueryExpOperation( - static_cast(itn->content)->lower_bound()) - == IR_OP_VARIABLE) { - IR_ScalarRef *ref = - static_cast(ir->Repr2Ref( - static_cast(itn->content)->lower_bound())); - std::string name_ = ref->name(); - - for (int i = 0; i < index.size(); i++) - if (index[i] == name_) { - exp2formula(ir, r, f_root, freevar, lb, v, 's', - IR_COND_GE, false); - - CG_outputRepr *ub = - static_cast(itn->content)->upper_bound(); - IR_CONDITION_TYPE cond = - static_cast(itn->content)->stop_cond(); - if (cond == IR_COND_LT || cond == IR_COND_LE) - exp2formula(ir, r, f_root, freevar, ub, v, - 's', cond, false); - - - - } - - } - */ - - } else { // loc > max_loc - - CG_outputBuilder *ocg = ir->builder(); - CG_outputRepr *ub = - static_cast(itn->content)->upper_bound(); - - exp2formula(ir, r, f_root, freevar, ub, v, 's', IR_COND_EQ, - false,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); - /*if (ir->QueryExpOperation( - static_cast(itn->content)->upper_bound()) - == IR_OP_VARIABLE) { - IR_ScalarRef *ref = - static_cast(ir->Repr2Ref( - static_cast(itn->content)->upper_bound())); - std::string name_ = ref->name(); - - for (int i = 0; i < index.size(); i++) - if (index[i] == name_) { - - CG_outputRepr *lb = - static_cast(itn->content)->lower_bound(); - - exp2formula(ir, r, f_root, freevar, lb, v, 's', - IR_COND_GE, false); - - CG_outputRepr *ub = - static_cast(itn->content)->upper_bound(); - IR_CONDITION_TYPE cond = - static_cast(itn->content)->stop_cond(); - if (cond == IR_COND_LT || cond == IR_COND_LE) - exp2formula(ir, r, f_root, freevar, ub, v, - 's', cond, false); - - - } - } - */ - } - } - - r.setup_names(); - r.simplify(); - - // THIS IS MISSING IN PROTONU's - for (int j = 0; j < insp_lb.size(); j++) { - - std::string lb = insp_lb[j] + "_"; - std::string ub = lb + "_"; - - Global_Var_ID u, l; - bool found_ub = false; - bool found_lb = false; - for (DNF_Iterator di(copy(r).query_DNF()); di; di++) - for (Constraint_Iterator ci = (*di)->constraints(); ci; ci++) - - for (Constr_Vars_Iter cvi(*ci); cvi; cvi++) { - Variable_ID v = cvi.curr_var(); - if (v->kind() == Global_Var) - if (v->get_global_var()->arity() > 0) { - - std::string name = - v->get_global_var()->base_name(); - if (name == lb) { - l = v->get_global_var(); - found_lb = true; - } else if (name == ub) { - u = v->get_global_var(); - found_ub = true; - } - } - - } - - if (found_lb && found_ub) { - Relation known_(copy(r).n_set()); - known_.copy_names(copy(r)); - known_.setup_names(); - Variable_ID index_lb = known_.get_local(l, Input_Tuple); - Variable_ID index_ub = known_.get_local(u, Input_Tuple); - F_And *fr = known_.add_and(); - GEQ_Handle g = fr->add_GEQ(); - g.update_coef(index_ub, 1); - g.update_coef(index_lb, -1); - g.update_const(-1); - addKnown(known_); - - } - - } - - - fprintf(stderr, "loop.cc L441 insert the statement\n"); - // insert the statement - CG_outputBuilder *ocg = ir->builder(); - std::vector reverse_expr; - for (int j = 1; j <= vars_to_be_reversed.size(); j++) { - CG_outputRepr *repl = ocg->CreateIdent(vars_to_be_reversed[j]); - repl = ocg->CreateMinus(NULL, repl); - reverse_expr.push_back(repl); - } - fprintf(stderr, "loop.cc before extract\n"); - CG_outputRepr *code = - static_cast(ir_stmt[loc]->content)->extract(); - fprintf(stderr, "code = ocg->CreateSubstitutedStmt(...)\n"); - ((CG_chillRepr *)code)->Dump(); fflush(stdout); - - code = ocg->CreateSubstitutedStmt(0, code, vars_to_be_reversed, - reverse_expr); - fprintf(stderr, "stmt\n"); - ((CG_chillRepr *)code)->Dump(); fflush(stdout); - - stmt[loc].code = code; - stmt[loc].IS = r; - - //Anand: Add Information on uninterpreted function constraints to - //Known relation - - fprintf(stderr, "loop.cc stmt[%d].loop_level has size n_dim %d\n", loc, n_dim); - - stmt[loc].loop_level = std::vector(n_dim); - stmt[loc].ir_stmt_node = ir_stmt[loc]; - stmt[loc].has_inspector = false; - fprintf(stderr, "for int i < n_dim(%d)\n", n_dim); - for (int ii = 0; ii < n_dim; ii++) { - stmt[loc].loop_level[ii].type = LoopLevelOriginal; - stmt[loc].loop_level[ii].payload = ii; - stmt[loc].loop_level[ii].parallel_level = 0; - } - fprintf(stderr, "whew\n"); - - stmt_nesting_level[loc] = -1; - } - dump(); - fprintf(stderr, " loop.cc Loop::init_loop() END\n\n"); - - return true; -} - - - -Loop::Loop(const IR_Control *control) { - - fprintf(stderr, "\nLoop::Loop(const IR_Control *control)\n"); - fprintf(stderr, "control type is %d ", control->type()); - echocontroltype(control); - - last_compute_cgr_ = NULL; - last_compute_cg_ = NULL; - fprintf(stderr, "2set last_compute_cg_ = NULL; \n"); - - ir = const_cast(control->ir_); // point to the CHILL IR that this loop came from - if (ir == 0) { - fprintf(stderr, "ir gotten from control = 0x%x\n", (long)ir); - fprintf(stderr, "loop.cc GONNA DIE SOON *******************************\n\n"); - } - - init_code = NULL; - cleanup_code = NULL; - tmp_loop_var_name_counter = 1; - overflow_var_name_counter = 1; - known = Relation::True(0); - - fprintf(stderr, "in Loop::Loop, calling build_ir_tree()\n"); - fprintf(stderr, "\nloop.cc, Loop::Loop() about to clone control\n"); - ir_tree = build_ir_tree(control->clone(), NULL); - //fprintf(stderr,"in Loop::Loop. ir_tree has %ld parts\n", ir_tree.size()); - - // std::vector ir_stmt; - //fprintf(stderr, "loop.cc after build_ir_tree() %ld statements\n", stmt.size()); - - int count = 0; - //fprintf(stderr, "before init_loops, %d freevar\n", freevar.size()); - //fprintf(stderr, "count %d\n", count++); - //fprintf(stderr, "loop.cc before init_loop, %ld statements\n", stmt.size()); - while (!init_loop(ir_tree, ir_stmt)) { - //fprintf(stderr, "count %d\n", count++); - } - fprintf(stderr, "after init_loop, %d freevar\n", (int)freevar.size()); - - - fprintf(stderr, "loop.cc after init_loop, %d statements\n", (int)stmt.size()); - for (int i = 0; i < stmt.size(); i++) { - std::map::iterator it = replace.find(i); - - if (it != replace.end()) - stmt[i].code = it->second; - else - stmt[i].code = stmt[i].code; - } - - if (stmt.size() != 0) - dep = DependenceGraph(stmt[0].IS.n_set()); - else - dep = DependenceGraph(0); - // init the dependence graph - for (int i = 0; i < stmt.size(); i++) - dep.insert(); - - fprintf(stderr, "this really REALLY needs some comments\n"); - // this really REALLY needs some comments - for (int i = 0; i < stmt.size(); i++) { - fprintf(stderr, "i %d\n", i); - stmt[i].reduction = 0; // Manu -- initialization - for (int j = i; j < stmt.size(); j++) { - fprintf(stderr, "j %d\n", j); - std::pair, - std::vector > dv = test_data_dependences( - ir, - stmt[i].code, - stmt[i].IS, - stmt[j].code, - stmt[j].IS, - freevar, - index, - stmt_nesting_level_[i], - stmt_nesting_level_[j], - uninterpreted_symbols[ i ], - uninterpreted_symbols_stringrepr[ i ]); - - fprintf(stderr, "dv.first.size() %d\n", (int)dv.first.size()); - for (int k = 0; k < dv.first.size(); k++) { - fprintf(stderr, "k1 %d\n", k); - if (is_dependence_valid(ir_stmt[i], ir_stmt[j], dv.first[k], - true)) - dep.connect(i, j, dv.first[k]); - else { - dep.connect(j, i, dv.first[k].reverse()); - } - - } - - for (int k = 0; k < dv.second.size(); k++) { - fprintf(stderr, "k2 %d\n", k); - if (is_dependence_valid(ir_stmt[j], ir_stmt[i], dv.second[k], - false)) - dep.connect(j, i, dv.second[k]); - else { - dep.connect(i, j, dv.second[k].reverse()); - } - } - } - } - - fprintf(stderr, "\n\n*** LOTS OF REDUCTIONS ***\n\n"); - - // TODO: Reduction check - // Manu:: Initial implementation / algorithm - std::set reducCand = std::set(); - std::vector canReduce = std::vector(); - fprintf(stderr, "\ni range %d\n", stmt.size()); - for (int i = 0; i < stmt.size(); i++) { - fprintf(stderr, "i %d\n", i); - if (!dep.hasEdge(i, i)) { - continue; - } - fprintf(stderr, "dep.hasEdge(%d, %d)\n", i, i); - - // for each statement check if it has all the three dependences (RAW, WAR, WAW) - // If there is such a statement, it is a reduction candidate. Mark all reduction candidates. - std::vector tdv = dep.getEdge(i, i); - fprintf(stderr, "tdv size %d\n", tdv.size()); - for (int j = 0; j < tdv.size(); j++) { - fprintf(stderr, "ij %d %d\n", i, j); - if (tdv[j].is_reduction_cand) { - fprintf(stderr, "reducCand.insert( %d )\n", i); - reducCand.insert(i); - } - } - } - - fprintf(stderr, "loop.cc reducCand.size() %d\n", reducCand.size()); - bool reduc; - std::set::iterator it; - int counter = 0; - for (it = reducCand.begin(); it != reducCand.end(); it++) { - fprintf(stderr, "counter %d\n", counter); - reduc = true; - for (int j = 0; j < stmt.size(); j++) { - fprintf(stderr, "j %d\n", j); - if ((*it != j) - && (stmt_nesting_level_[*it] < stmt_nesting_level_[j])) { - if (dep.hasEdge(*it, j) || dep.hasEdge(j, *it)) { - fprintf(stderr, "counter %d j %d reduc = false\n", counter, j); - reduc = false; - break; - } - } - counter += 1; - } - - if (reduc) { - fprintf(stderr, "canReduce.push_back()\n"); - canReduce.push_back(*it); - stmt[*it].reduction = 2; // First, assume that reduction is possible with some processing - } - } - - - // If reduction is possible without processing, update the value of the reduction variable to 1 - fprintf(stderr, "loop.cc canReduce.size() %d\n", canReduce.size()); - for (int i = 0; i < canReduce.size(); i++) { - // Here, assuming that stmtType returns 1 when there is a single statement within stmt[i] - if (stmtType(ir, stmt[canReduce[i]].code) == 1) { - stmt[canReduce[i]].reduction = 1; - IR_OPERATION_TYPE opType; - opType = getReductionOperator(ir, stmt[canReduce[i]].code); - stmt[canReduce[i]].reductionOp = opType; - } - } - - // printing out stuff for debugging - - if (DEP_DEBUG) { - std::cout << "STATEMENTS THAT CAN BE REDUCED: \n"; - for (int i = 0; i < canReduce.size(); i++) { - std::cout << "------- " << canReduce[i] << " ------- " - << stmt[canReduce[i]].reduction << "\n"; - ir->printStmt(stmt[canReduce[i]].code); // Manu - if (stmt[canReduce[i]].reductionOp == IR_OP_PLUS) - std::cout << "Reduction type:: + \n"; - else if (stmt[canReduce[i]].reductionOp == IR_OP_MINUS) - std::cout << "Reduction type:: - \n"; - else if (stmt[canReduce[i]].reductionOp == IR_OP_MULTIPLY) - std::cout << "Reduction type:: * \n"; - else if (stmt[canReduce[i]].reductionOp == IR_OP_DIVIDE) - std::cout << "Reduction type:: / \n"; - else - std::cout << "Unknown reduction type\n"; - } - } - // cleanup the IR tree - - fprintf(stderr, "init dumb transformation relations\n"); - - // init dumb transformation relations e.g. [i, j] -> [ 0, i, 0, j, 0] - for (int i = 0; i < stmt.size(); i++) { - int n = stmt[i].IS.n_set(); - stmt[i].xform = Relation(n, 2 * n + 1); - F_And *f_root = stmt[i].xform.add_and(); - - for (int j = 1; j <= n; j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(stmt[i].xform.output_var(2 * j), 1); - h.update_coef(stmt[i].xform.input_var(j), -1); - } - - for (int j = 1; j <= 2 * n + 1; j += 2) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(stmt[i].xform.output_var(j), 1); - } - stmt[i].xform.simplify(); - } - //fprintf(stderr, "done with dumb\n"); - - if (stmt.size() != 0) - num_dep_dim = stmt[0].IS.n_set(); - else - num_dep_dim = 0; - // debug - /*for (int i = 0; i < stmt.size(); i++) { - std::cout << i << ": "; - //stmt[i].xform.print(); - stmt[i].IS.print(); - std::cout << std::endl; - - }*/ - //end debug - fprintf(stderr, " at bottom of Loop::Loop, printCode\n"); - printCode(); // this dies TODO figure out why -} - -Loop::~Loop() { - - delete last_compute_cgr_; - delete last_compute_cg_; - - for (int i = 0; i < stmt.size(); i++) - if (stmt[i].code != NULL) { - stmt[i].code->clear(); - delete stmt[i].code; - } - - for (int i = 0; i < ir_tree.size(); i++) - delete ir_tree[i]; - - if (init_code != NULL) { - init_code->clear(); - delete init_code; - } - if (cleanup_code != NULL) { - cleanup_code->clear(); - delete cleanup_code; - } -} - - - - -int Loop::get_dep_dim_of(int stmt_num, int level) const { - if (stmt_num < 0 || stmt_num >= stmt.size()) - throw std::invalid_argument("invaid statement " + to_string(stmt_num)); - - if (level < 1 || level > stmt[stmt_num].loop_level.size()) - return -1; - - int trip_count = 0; - while (true) { - switch (stmt[stmt_num].loop_level[level - 1].type) { - case LoopLevelOriginal: - return stmt[stmt_num].loop_level[level - 1].payload; - case LoopLevelTile: - level = stmt[stmt_num].loop_level[level - 1].payload; - if (level < 1) - return -1; - if (level > stmt[stmt_num].loop_level.size()) - throw loop_error("incorrect loop level information for statement " - + to_string(stmt_num)); - break; - default: - throw loop_error( - "unknown loop level information for statement " - + to_string(stmt_num)); - } - trip_count++; - if (trip_count >= stmt[stmt_num].loop_level.size()) - throw loop_error( - "incorrect loop level information for statement " - + to_string(stmt_num)); - } -} - -int Loop::get_last_dep_dim_before(int stmt_num, int level) const { - if (stmt_num < 0 || stmt_num >= stmt.size()) - throw std::invalid_argument("invaid statement " + to_string(stmt_num)); - - if (level < 1) - return -1; - if (level > stmt[stmt_num].loop_level.size()) - level = stmt[stmt_num].loop_level.size() + 1; - - for (int i = level - 1; i >= 1; i--) - if (stmt[stmt_num].loop_level[i - 1].type == LoopLevelOriginal) - return stmt[stmt_num].loop_level[i - 1].payload; - - return -1; -} - -void Loop::print_internal_loop_structure() const { - for (int i = 0; i < stmt.size(); i++) { - std::vector lex = getLexicalOrder(i); - std::cout << "s" << i + 1 << ": "; - for (int j = 0; j < stmt[i].loop_level.size(); j++) { - if (2 * j < lex.size()) - std::cout << lex[2 * j]; - switch (stmt[i].loop_level[j].type) { - case LoopLevelOriginal: - std::cout << "(dim:" << stmt[i].loop_level[j].payload << ")"; - break; - case LoopLevelTile: - std::cout << "(tile:" << stmt[i].loop_level[j].payload << ")"; - break; - default: - std::cout << "(unknown)"; - } - std::cout << ' '; - } - for (int j = 2 * stmt[i].loop_level.size(); j < lex.size(); j += 2) { - std::cout << lex[j]; - if (j != lex.size() - 1) - std::cout << ' '; - } - std::cout << std::endl; - } -} - -void Loop::debugRelations() const { - const int m = stmt.size(); - { - std::vector IS(m); - std::vector xforms(m); - - for (int i = 0; i < m; i++) { - IS[i] = stmt[i].IS; - xforms[i] = stmt[i].xform; // const stucks - } - - printf("\nxforms:\n"); - for (int i = 0; i < m; i++) { xforms[i].print(); printf("\n"); } - printf("\nIS:\n"); - for (int i = 0; i < m; i++) { IS[i].print(); printf("\n"); } - fflush(stdout); - } -} - - -CG_outputRepr *Loop::getCode(int effort) const { - fprintf(stderr,"\nloop.cc Loop::getCode( effort %d )\n", effort ); - - const int m = stmt.size(); - if (m == 0) - return NULL; - const int n = stmt[0].xform.n_out(); - - if (last_compute_cg_ == NULL) { - fprintf(stderr, "Loop::getCode() last_compute_cg_ == NULL\n"); - - std::vector IS(m); - std::vector xforms(m); - for (int i = 0; i < m; i++) { - IS[i] = stmt[i].IS; - xforms[i] = stmt[i].xform; - } - - debugRelations(); - - - Relation known = Extend_Set(copy(this->known), n - this->known.n_set()); - printf("\nknown:\n"); known.print(); printf("\n\n"); fflush(stdout); - - last_compute_cg_ = new CodeGen(xforms, IS, known); - delete last_compute_cgr_; - last_compute_cgr_ = NULL; - } - else { - fprintf(stderr, "Loop::getCode() last_compute_cg_ NOT NULL\n"); - } - - - if (last_compute_cgr_ == NULL || last_compute_effort_ != effort) { - delete last_compute_cgr_; - last_compute_cgr_ = last_compute_cg_->buildAST(effort); - last_compute_effort_ = effort; - } - - std::vector stmts(m); - fprintf(stderr, "%d stmts\n", m); - for (int i = 0; i < m; i++) - stmts[i] = stmt[i].code; - CG_outputBuilder *ocg = ir->builder(); - - fprintf(stderr, "calling last_compute_cgr_->printRepr()\n"); - CG_outputRepr *repr = last_compute_cgr_->printRepr(ocg, stmts, - uninterpreted_symbols); - - if (init_code != NULL) - repr = ocg->StmtListAppend(init_code->clone(), repr); - if (cleanup_code != NULL) - repr = ocg->StmtListAppend(repr, cleanup_code->clone()); - - fprintf(stderr,"\nloop.cc Loop::getCode( effort %d ) DONE\n", effort ); - return repr; -} - - - - -void Loop::printCode(int effort) const { - fprintf(stderr,"\nloop.cc Loop::printCode( effort %d )\n", effort ); - const int m = stmt.size(); - if (m == 0) - return; - const int n = stmt[0].xform.n_out(); - - if (last_compute_cg_ == NULL) { - fprintf(stderr, "Loop::printCode(), last_compute_cg_ == NULL\n"); - std::vector IS(m); - std::vector xforms(m); - for (int i = 0; i < m; i++) { - IS[i] = stmt[i].IS; - xforms[i] = stmt[i].xform; - } - Relation known = Extend_Set(copy(this->known), n - this->known.n_set()); - - last_compute_cg_ = new CodeGen(xforms, IS, known); - delete last_compute_cgr_; - last_compute_cgr_ = NULL; - } - else fprintf(stderr, "Loop::printCode(), last_compute_cg_ NOT NULL\n"); - - if (last_compute_cgr_ == NULL || last_compute_effort_ != effort) { - delete last_compute_cgr_; - last_compute_cgr_ = last_compute_cg_->buildAST(effort); - last_compute_effort_ = effort; - } - - std::string repr = last_compute_cgr_->printString( - uninterpreted_symbols_stringrepr); - fprintf(stderr, "leaving Loop::printCode()\n"); - std::cout << repr << std::endl; -} - -void Loop::printIterationSpace() const { - for (int i = 0; i < stmt.size(); i++) { - std::cout << "s" << i << ": "; - Relation r = getNewIS(i); - for (int j = 1; j <= r.n_inp(); j++) - r.name_input_var(j, CodeGen::loop_var_name_prefix + to_string(j)); - r.setup_names(); - r.print(); - } -} - -void Loop::printDependenceGraph() const { - if (dep.edgeCount() == 0) - std::cout << "no dependence exists" << std::endl; - else { - std::cout << "dependence graph:" << std::endl; - std::cout << dep; - } -} - -std::vector Loop::getNewIS() const { - const int m = stmt.size(); - - std::vector new_IS(m); - for (int i = 0; i < m; i++) - new_IS[i] = getNewIS(i); - - return new_IS; -} - -// pragmas are tied to loops only ??? -void Loop::pragma(int stmt_num, int level, const std::string &pragmaText) { - // check sanity of parameters - if(stmt_num < 0) - throw std::invalid_argument("invalid statement " + to_string(stmt_num)); - - CG_outputBuilder *ocg = ir->builder(); - CG_outputRepr *code = stmt[stmt_num].code; - ocg->CreatePragmaAttribute(code, level, pragmaText); -} - - -/* - void Loop::prefetch(int stmt_num, int level, const std::string &arrName, const std::string &indexName, int offset, int hint) { - // check sanity of parameters - if(stmt_num < 0) - throw std::invalid_argument("invalid statement " + to_string(stmt_num)); - - CG_outputBuilder *ocg = ir->builder(); - CG_outputRepr *code = stmt[stmt_num].code; - ocg->CreatePrefetchAttribute(code, level, arrName, indexName, int offset, hint); - } -*/ - -void Loop::prefetch(int stmt_num, int level, const std::string &arrName, int hint) { - // check sanity of parameters - if(stmt_num < 0) - throw std::invalid_argument("invalid statement " + to_string(stmt_num)); - - CG_outputBuilder *ocg = ir->builder(); - CG_outputRepr *code = stmt[stmt_num].code; - ocg->CreatePrefetchAttribute(code, level, arrName, hint); -} - -std::vector Loop::getLexicalOrder(int stmt_num) const { - assert(stmt_num < stmt.size()); - - const int n = stmt[stmt_num].xform.n_out(); - std::vector lex(n, 0); - - for (int i = 0; i < n; i += 2) - lex[i] = get_const(stmt[stmt_num].xform, i, Output_Var); - - return lex; -} - -// find the sub loop nest specified by stmt_num and level, -// only iteration space satisfiable statements returned. -std::set Loop::getSubLoopNest(int stmt_num, int level) const { - assert(stmt_num >= 0 && stmt_num < stmt.size()); - assert(level > 0 && level <= stmt[stmt_num].loop_level.size()); - - std::set working; - for (int i = 0; i < stmt.size(); i++) - if (const_cast(this)->stmt[i].IS.is_upper_bound_satisfiable() - && stmt[i].loop_level.size() >= level) - working.insert(i); - - for (int i = 1; i <= level; i++) { - int a = getLexicalOrder(stmt_num, i); - for (std::set::iterator j = working.begin(); j != working.end();) { - int b = getLexicalOrder(*j, i); - if (b != a) - working.erase(j++); - else - ++j; - } - } - - return working; -} - -int Loop::getLexicalOrder(int stmt_num, int level) const { - assert(stmt_num >= 0 && stmt_num < stmt.size()); - assert(level > 0 && level <= stmt[stmt_num].loop_level.size()+1); - - Relation &r = const_cast(this)->stmt[stmt_num].xform; - for (EQ_Iterator e(r.single_conjunct()->EQs()); e; e++) - if (abs((*e).get_coef(r.output_var(2 * level - 1))) == 1) { - bool is_const = true; - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) - if (cvi.curr_var() != r.output_var(2 * level - 1)) { - is_const = false; - break; - } - if (is_const) { - int t = static_cast((*e).get_const()); - return (*e).get_coef(r.output_var(2 * level - 1)) > 0 ? -t : t; - } - } - - throw loop_error( - "can't find lexical order for statement " + to_string(stmt_num) - + "'s loop level " + to_string(level)); -} - -std::set Loop::getStatements(const std::vector &lex, int dim) const { - const int m = stmt.size(); - - std::set same_loops; - for (int i = 0; i < m; i++) { - if (dim < 0) - same_loops.insert(i); - else { - std::vector a_lex = getLexicalOrder(i); - int j; - for (j = 0; j <= dim; j += 2) - if (lex[j] != a_lex[j]) - break; - if (j > dim) - same_loops.insert(i); - } - - } - - return same_loops; -} - -void Loop::shiftLexicalOrder(const std::vector &lex, int dim, int amount) { - const int m = stmt.size(); - - if (amount == 0) - return; - - for (int i = 0; i < m; i++) { - std::vector lex2 = getLexicalOrder(i); - - bool need_shift = true; - - for (int j = 0; j < dim; j++) - if (lex2[j] != lex[j]) { - need_shift = false; - break; - } - - if (!need_shift) - continue; - - if (amount > 0) { - if (lex2[dim] < lex[dim]) - continue; - } else if (amount < 0) { - if (lex2[dim] > lex[dim]) - continue; - } - - assign_const(stmt[i].xform, dim, lex2[dim] + amount); - } -} - -std::vector > Loop::sort_by_same_loops(std::set active, - int level) { - - std::set not_nested_at_this_level; - std::map > sorted_by_loop; - std::map > sorted_by_lex_order; - std::vector > to_return; - bool lex_order_already_set = false; - for (std::set::iterator it = active.begin(); it != active.end(); - it++) { - - if (stmt[*it].ir_stmt_node == NULL) - lex_order_already_set = true; - } - - if (lex_order_already_set) { - - for (std::set::iterator it = active.begin(); it != active.end(); - it++) { - std::map >::iterator it2 = - sorted_by_lex_order.find( - get_const(stmt[*it].xform, 2 * (level - 1), - Output_Var)); - - if (it2 != sorted_by_lex_order.end()) - it2->second.insert(*it); - else { - - std::set to_insert; - - to_insert.insert(*it); - - sorted_by_lex_order.insert( - std::pair >( - get_const(stmt[*it].xform, 2 * (level - 1), - Output_Var), to_insert)); - - } - - } - - for (std::map >::iterator it2 = - sorted_by_lex_order.begin(); it2 != sorted_by_lex_order.end(); - it2++) - to_return.push_back(it2->second); - - } else { - - for (std::set::iterator it = active.begin(); it != active.end(); - it++) { - - ir_tree_node* itn = stmt[*it].ir_stmt_node; - itn = itn->parent; - //while (itn->content->type() != IR_CONTROL_LOOP && itn != NULL) - // itn = itn->parent; - - while ((itn != NULL) && (itn->payload != level - 1)) { - itn = itn->parent; - while (itn != NULL && itn->content->type() != IR_CONTROL_LOOP ) - itn = itn->parent; - } - - if (itn == NULL) - not_nested_at_this_level.insert(*it); - else { - std::map >::iterator it2 = - sorted_by_loop.find(itn); - - if (it2 != sorted_by_loop.end()) - it2->second.insert(*it); - else { - std::set to_insert; - - to_insert.insert(*it); - - sorted_by_loop.insert( - std::pair >(itn, - to_insert)); - - } - - } - - } - if (not_nested_at_this_level.size() > 0) { - for (std::set::iterator it = not_nested_at_this_level.begin(); - it != not_nested_at_this_level.end(); it++) { - std::set temp; - temp.insert(*it); - to_return.push_back(temp); - - } - } - for (std::map >::iterator it2 = - sorted_by_loop.begin(); it2 != sorted_by_loop.end(); it2++) - to_return.push_back(it2->second); - } - return to_return; -} - -void update_successors(int n, - int node_num[], - int cant_fuse_with[], - Graph, bool> &g, - std::list &work_list, - std::list &type_list, - std::vector types) { - - std::set disconnect; - for (Graph, bool>::EdgeList::iterator i = - g.vertex[n].second.begin(); i != g.vertex[n].second.end(); i++) { - int m = i->first; - - if (node_num[m] != -1) - throw loop_error("Graph input for fusion has cycles not a DAG!!"); - - std::vector check_ = g.getEdge(n, m); - - bool has_bad_edge_path = false; - for (int i = 0; i < check_.size(); i++) - if (!check_[i]) { - has_bad_edge_path = true; - break; - } - if (!types[m]) { - cant_fuse_with[m] = std::max(cant_fuse_with[m], cant_fuse_with[n]); - } else { - if (has_bad_edge_path) - cant_fuse_with[m] = std::max(cant_fuse_with[m], node_num[n]); - else - cant_fuse_with[m] = std::max(cant_fuse_with[m], cant_fuse_with[n]); - } - disconnect.insert(m); - } - - - for (std::set::iterator i = disconnect.begin(); i != disconnect.end(); - i++) { - g.disconnect(n, *i); - - bool no_incoming_edges = true; - for (int j = 0; j < g.vertex.size(); j++) - if (j != *i) - if (g.hasEdge(j, *i)) { - no_incoming_edges = false; - break; - } - - if (no_incoming_edges) { - work_list.push_back(*i); - type_list.push_back(types[*i]); - } - } -} - - - -int Loop::getMinLexValue(std::set stmts, int level) { - - int min; - - std::set::iterator it = stmts.begin(); - min = getLexicalOrder(*it, level); - - for (; it != stmts.end(); it++) { - int curr = getLexicalOrder(*it, level); - if (curr < min) - min = curr; - } - - return min; -} - - - - -Graph, bool> Loop::construct_induced_graph_at_level( - std::vector > s, DependenceGraph dep, int dep_dim) { - Graph, bool> g; - - for (int i = 0; i < s.size(); i++) - g.insert(s[i]); - - for (int i = 0; i < s.size(); i++) { - - for (int j = i + 1; j < s.size(); j++) { - bool has_true_edge_i_to_j = false; - bool has_true_edge_j_to_i = false; - bool is_connected_i_to_j = false; - bool is_connected_j_to_i = false; - for (std::set::iterator ii = s[i].begin(); ii != s[i].end(); - ii++) { - - for (std::set::iterator jj = s[j].begin(); - jj != s[j].end(); jj++) { - - std::vector dvs = dep.getEdge(*ii, *jj); - for (int k = 0; k < dvs.size(); k++) - if (dvs[k].is_control_dependence() - || (dvs[k].is_data_dependence() - && dvs[k].has_been_carried_at(dep_dim))) { - - if (dvs[k].is_data_dependence() - && dvs[k].has_negative_been_carried_at( - dep_dim)) { - //g.connect(i, j, false); - is_connected_i_to_j = true; - break; - } else { - //g.connect(i, j, true); - - has_true_edge_i_to_j = true; - //break - } - } - - //if (is_connected) - - // break; - // if (has_true_edge_i_to_j && !is_connected_i_to_j) - // g.connect(i, j, true); - dvs = dep.getEdge(*jj, *ii); - for (int k = 0; k < dvs.size(); k++) - if (dvs[k].is_control_dependence() - || (dvs[k].is_data_dependence() - && dvs[k].has_been_carried_at(dep_dim))) { - - if (is_connected_i_to_j || has_true_edge_i_to_j) - throw loop_error( - "Graph input for fusion has cycles not a DAG!!"); - - if (dvs[k].is_data_dependence() - && dvs[k].has_negative_been_carried_at( - dep_dim)) { - //g.connect(i, j, false); - is_connected_j_to_i = true; - break; - } else { - //g.connect(i, j, true); - - has_true_edge_j_to_i = true; - //break; - } - } - - // if (is_connected) - //break; - // if (is_connected) - //break; - } - - //if (is_connected) - // break; - } - - - if (is_connected_i_to_j) - g.connect(i, j, false); - else if (has_true_edge_i_to_j) - g.connect(i, j, true); - - if (is_connected_j_to_i) - g.connect(j, i, false); - else if (has_true_edge_j_to_i) - g.connect(j, i, true); - - } - } - return g; -} - - - -std::vector > Loop::typed_fusion(Graph, bool> g, - std::vector &types) { - - bool roots[g.vertex.size()]; - - for (int i = 0; i < g.vertex.size(); i++) - roots[i] = true; - - for (int i = 0; i < g.vertex.size(); i++) - for (int j = i + 1; j < g.vertex.size(); j++) { - - if (g.hasEdge(i, j)) - roots[j] = false; - - if (g.hasEdge(j, i)) - roots[i] = false; - - } - - std::list work_list; - std::list type_list; - int cant_fuse_with[g.vertex.size()]; - int fused = 0; - int lastfused = 0; - int lastnum = 0; - std::vector > s; - //Each Fused set's representative node - - int node_to_fused_nodes[g.vertex.size()]; - int node_num[g.vertex.size()]; - int next[g.vertex.size()]; - - for (int i = 0; i < g.vertex.size(); i++) { - if (roots[i] == true) { - work_list.push_back(i); - type_list.push_back(types[i]); - } - cant_fuse_with[i] = 0; - node_to_fused_nodes[i] = 0; - node_num[i] = -1; - next[i] = 0; - } - - - // topological sort according to chun's permute algorithm - // std::vector > s = g.topoSort(); - std::vector > s2 = g.topoSort(); - if (work_list.empty() || (s2.size() != g.vertex.size())) { - - std::cout << s2.size() << "\t" << g.vertex.size() << std::endl; - throw loop_error("Input for fusion not a DAG!!"); - - - } - int fused_nodes_counter = 0; - while (!work_list.empty()) { - int n = work_list.front(); - bool type = type_list.front(); - //int n_ = g.vertex[n].first; - work_list.pop_front(); - type_list.pop_front(); - int node; - /*if (cant_fuse_with[n] == 0) - node = 0; - else - node = cant_fuse_with[n]; - */ - int p; - if (type) { - //if ((fused_nodes_counter != 0) && (node != fused_nodes_counter)) { - if (cant_fuse_with[n] == 0) - p = fused; - else - p = next[cant_fuse_with[n]]; - - if (p != 0) { - int rep_node = node_to_fused_nodes[p]; - node_num[n] = node_num[rep_node]; - - try { - update_successors(n, node_num, cant_fuse_with, g, work_list, - type_list, types); - } catch (const loop_error &e) { - - throw loop_error( - "statements cannot be fused together due to negative dependence"); - - } - for (std::set::iterator it = g.vertex[n].first.begin(); - it != g.vertex[n].first.end(); it++) - s[node_num[n] - 1].insert(*it); - } else { - //std::set new_node; - //new_node.insert(n_); - s.push_back(g.vertex[n].first); - lastnum = lastnum + 1; - node_num[n] = lastnum; - node_to_fused_nodes[node_num[n]] = n; - - if (lastfused == 0) { - fused = lastnum; - lastfused = fused; - } else { - next[lastfused] = lastnum; - lastfused = lastnum; - - } - - try { - update_successors(n, node_num, cant_fuse_with, g, work_list, - type_list, types); - } catch (const loop_error &e) { - - throw loop_error( - "statements cannot be fused together due to negative dependence"); - - } - fused_nodes_counter++; - } - - } else { - s.push_back(g.vertex[n].first); - lastnum = lastnum + 1; - node_num[n] = lastnum; - node_to_fused_nodes[node_num[n]] = n; - - try { - update_successors(n, node_num, cant_fuse_with, g, work_list, - type_list, types); - } catch (const loop_error &e) { - - throw loop_error( - "statements cannot be fused together due to negative dependence"); - - } - //fused_nodes_counter++; - - } - - } - - return s; -} - - - - -void Loop::setLexicalOrder(int dim, const std::set &active, - int starting_order, std::vector > idxNames) { - fprintf(stderr, "Loop::setLexicalOrder() %d idxNames active size %d starting_order %d\n", idxNames.size(), active.size(), starting_order); - if (active.size() == 0) - return; - - for (int i=0; i< idxNames.size(); i++) { - std::vector what = idxNames[i]; - for (int j=0; j lex; - int ref_stmt_num; - for (std::set::iterator i = active.begin(); i != active.end(); i++) { - if ((*i) < 0 || (*i) >= stmt.size()) - throw std::invalid_argument( - "invalid statement number " + to_string(*i)); - if (dim >= stmt[*i].xform.n_out()) - throw std::invalid_argument( - "invalid constant loop level to set lexicographical order"); - if (i == active.begin()) { - lex = getLexicalOrder(*i); - ref_stmt_num = *i; - } else { - std::vector lex2 = getLexicalOrder(*i); - for (int j = 0; j < dim; j += 2) - if (lex[j] != lex2[j]) - throw std::invalid_argument( - "statements are not in the same sub loop nest"); - } - } - - // separate statements by current loop level types - int level = (dim + 2) / 2; - std::map, std::set > active_by_level_type; - std::set active_by_no_level; - for (std::set::iterator i = active.begin(); i != active.end(); i++) { - if (level > stmt[*i].loop_level.size()) - active_by_no_level.insert(*i); - else - active_by_level_type[std::make_pair( - stmt[*i].loop_level[level - 1].type, - stmt[*i].loop_level[level - 1].payload)].insert(*i); - } - - // further separate statements due to control dependences - std::vector > active_by_level_type_splitted; - for (std::map, std::set >::iterator i = - active_by_level_type.begin(); i != active_by_level_type.end(); i++) - active_by_level_type_splitted.push_back(i->second); - for (std::set::iterator i = active_by_no_level.begin(); - i != active_by_no_level.end(); i++) - for (int j = active_by_level_type_splitted.size() - 1; j >= 0; j--) { - std::set controlled, not_controlled; - for (std::set::iterator k = - active_by_level_type_splitted[j].begin(); - k != active_by_level_type_splitted[j].end(); k++) { - std::vector dvs = dep.getEdge(*i, *k); - bool is_controlled = false; - for (int kk = 0; kk < dvs.size(); kk++) - if (dvs[kk].type = DEP_CONTROL) { - is_controlled = true; - break; - } - if (is_controlled) - controlled.insert(*k); - else - not_controlled.insert(*k); - } - if (controlled.size() != 0 && not_controlled.size() != 0) { - active_by_level_type_splitted.erase( - active_by_level_type_splitted.begin() + j); - active_by_level_type_splitted.push_back(controlled); - active_by_level_type_splitted.push_back(not_controlled); - } - } - - // set lexical order separating loops with different loop types first - if (active_by_level_type_splitted.size() + active_by_no_level.size() > 1) { - int dep_dim = get_last_dep_dim_before(ref_stmt_num, level) + 1; - - Graph, Empty> g; - for (std::vector >::iterator i = - active_by_level_type_splitted.begin(); - i != active_by_level_type_splitted.end(); i++) - g.insert(*i); - for (std::set::iterator i = active_by_no_level.begin(); - i != active_by_no_level.end(); i++) { - std::set t; - t.insert(*i); - g.insert(t); - } - for (int i = 0; i < g.vertex.size(); i++) - for (int j = i + 1; j < g.vertex.size(); j++) { - bool connected = false; - for (std::set::iterator ii = g.vertex[i].first.begin(); - ii != g.vertex[i].first.end(); ii++) { - for (std::set::iterator jj = g.vertex[j].first.begin(); - jj != g.vertex[j].first.end(); jj++) { - std::vector dvs = dep.getEdge(*ii, - *jj); - for (int k = 0; k < dvs.size(); k++) - if (dvs[k].is_control_dependence() - || (dvs[k].is_data_dependence() - && !dvs[k].has_been_carried_before( - dep_dim))) { - g.connect(i, j); - connected = true; - break; - } - if (connected) - break; - } - if (connected) - break; - } - connected = false; - for (std::set::iterator ii = g.vertex[i].first.begin(); - ii != g.vertex[i].first.end(); ii++) { - for (std::set::iterator jj = g.vertex[j].first.begin(); - jj != g.vertex[j].first.end(); jj++) { - std::vector dvs = dep.getEdge(*jj, - *ii); - // find the sub loop nest specified by stmt_num and level, - // only iteration space satisfiable statements returned. - for (int k = 0; k < dvs.size(); k++) - if (dvs[k].is_control_dependence() - || (dvs[k].is_data_dependence() - && !dvs[k].has_been_carried_before( - dep_dim))) { - g.connect(j, i); - connected = true; - break; - } - if (connected) - break; - } - if (connected) - break; - } - } - - std::vector > s = g.topoSort(); - if (s.size() != g.vertex.size()) - throw loop_error( - "cannot separate statements with different loop types at loop level " - + to_string(level)); - - // assign lexical order - int order = starting_order; - for (int i = 0; i < s.size(); i++) { - std::set &cur_scc = g.vertex[*(s[i].begin())].first; - int sz = cur_scc.size(); - if (sz == 1) { - int cur_stmt = *(cur_scc.begin()); - assign_const(stmt[cur_stmt].xform, dim, order); - for (int j = dim + 2; j < stmt[cur_stmt].xform.n_out(); j += 2) - assign_const(stmt[cur_stmt].xform, j, 0); - order++; - } else { // recurse ! - fprintf(stderr, "Loop:setLexicalOrder() recursing\n"); - setLexicalOrder(dim, cur_scc, order, idxNames); - order += sz; - } - } - } - else { // set lexical order separating single iteration statements and loops - - std::set true_singles; - std::set nonsingles; - std::map > fake_singles; - std::set fake_singles_; - - // sort out statements that do not require loops - for (std::set::iterator i = active.begin(); i != active.end(); - i++) { - Relation cur_IS = getNewIS(*i); - if (is_single_iteration(cur_IS, dim + 1)) { - bool is_all_single = true; - for (int j = dim + 3; j < stmt[*i].xform.n_out(); j += 2) - if (!is_single_iteration(cur_IS, j)) { - is_all_single = false; - break; - } - if (is_all_single) - true_singles.insert(*i); - else { - fake_singles_.insert(*i); - try { - fake_singles[get_const(cur_IS, dim + 1, Set_Var)].insert( - *i); - } catch (const std::exception &e) { - fake_singles[posInfinity].insert(*i); - } - } - } else - nonsingles.insert(*i); - } - - - // split nonsingles forcibly according to negative dependences present (loop unfusible) - int dep_dim = get_dep_dim_of(ref_stmt_num, level); - - if (dim < stmt[ref_stmt_num].xform.n_out() - 1) { - - bool dummy_level_found = false; - - std::vector > s; - - s = sort_by_same_loops(active, level); - bool further_levels_exist = false; - - if (!idxNames.empty()) - if (level <= idxNames[ref_stmt_num].size()) - if (idxNames[ref_stmt_num][level - 1].length() == 0) { - // && s.size() == 1) { - int order1 = 0; - dummy_level_found = true; - - for (int i = level; i < idxNames[ref_stmt_num].size(); - i++) - if (idxNames[ref_stmt_num][i].length() > 0) - further_levels_exist = true; - - } - - //if (!dummy_level_found) { - - if (s.size() > 1) { - - std::vector types; - for (int i = 0; i < s.size(); i++) - types.push_back(true); - - Graph, bool> g = construct_induced_graph_at_level( - s, dep, dep_dim); - s = typed_fusion(g, types); - } - int order = starting_order; - for (int i = 0; i < s.size(); i++) { - - for (std::set::iterator it = s[i].begin(); - it != s[i].end(); it++) { - assign_const(stmt[*it].xform, dim, order); - stmt[*it].xform.simplify(); - } - - if ((dim + 2) <= (stmt[ref_stmt_num].xform.n_out() - 1)) { // recurse ! - fprintf(stderr, "Loop:setLexicalOrder() recursing\n"); - setLexicalOrder(dim + 2, s[i], order, idxNames); - } - - order++; - } - //} - /* else { - - int order1 = 0; - int order = 0; - for (std::set::iterator i = active.begin(); - i != active.end(); i++) { - if (!further_levels_exist) - assign_const(stmt[*i].xform, dim, order1++); - else - assign_const(stmt[*i].xform, dim, order1); - - } - - if ((dim + 2) <= (stmt[ref_stmt_num].xform.n_out() - 1) && further_levels_exist) - setLexicalOrder(dim + 2, active, order, idxNames); - } - */ - } else { - int dummy_order = 0; - for (std::set::iterator i = active.begin(); i != active.end(); - i++) { - assign_const(stmt[*i].xform, dim, dummy_order++); - stmt[*i].xform.simplify(); - } - } - /*for (int i = 0; i < g2.vertex.size(); i++) - for (int j = i+1; j < g2.vertex.size(); j++) { - std::vector dvs = dep.getEdge(g2.vertex[i].first, g2.vertex[j].first); - for (int k = 0; k < dvs.size(); k++) - if (dvs[k].is_control_dependence() || - (dvs[k].is_data_dependence() && dvs[k].has_negative_been_carried_at(dep_dim))) { - g2.connect(i, j); - break; - } - dvs = dep.getEdge(g2.vertex[j].first, g2.vertex[i].first); - for (int k = 0; k < dvs.size(); k++) - if (dvs[k].is_control_dependence() || - (dvs[k].is_data_dependence() && dvs[k].has_negative_been_carried_at(dep_dim))) { - g2.connect(j, i); - break; - } - } - - std::vector > s2 = g2.packed_topoSort(); - - std::vector > splitted_nonsingles; - for (int i = 0; i < s2.size(); i++) { - std::set cur_scc; - for (std::set::iterator j = s2[i].begin(); j != s2[i].end(); j++) - cur_scc.insert(g2.vertex[*j].first); - splitted_nonsingles.push_back(cur_scc); - } - */ - //convert to dependence graph for grouped statements - //dep_dim = get_last_dep_dim_before(ref_stmt_num, level) + 1; - /*int order = 0; - for (std::set::iterator j = active.begin(); j != active.end(); - j++) { - std::set continuous; - std::cout<< active.size()< 0) { - std::vector > s = typed_fusion(continuous, dep, - dep_dim); - - for (int i = 0; i < s.size(); i++) { - for (std::set::iterator l = s[i].begin(); - l != s[i].end(); l++) { - assign_const(stmt[*l].xform, dim + 2, order); - setLexicalOrder(dim + 2, s[i]); - } - order++; - } - } - - if (j != active.end()) { - assign_const(stmt[*j].xform, dim + 2, order); - - for (int k = dim + 4; k < stmt[*j].xform.n_out(); k += 2) - assign_const(stmt[*j].xform, k, 0); - order++; - } - - if( j == active.end()) - break; - } - */ - - - // assign lexical order - /*int order = starting_order; - for (int i = 0; i < s.size(); i++) { - // translate each SCC into original statements - std::set cur_scc; - for (std::set::iterator j = s[i].begin(); j != s[i].end(); j++) - copy(s[i].begin(), s[i].end(), - inserter(cur_scc, cur_scc.begin())); - - // now assign the constant - for (std::set::iterator j = cur_scc.begin(); - j != cur_scc.end(); j++) - assign_const(stmt[*j].xform, dim, order); - - if (cur_scc.size() > 1) - setLexicalOrder(dim + 2, cur_scc); - else if (cur_scc.size() == 1) { - int cur_stmt = *(cur_scc.begin()); - for (int j = dim + 2; j < stmt[cur_stmt].xform.n_out(); j += 2) - assign_const(stmt[cur_stmt].xform, j, 0); - } - - if (cur_scc.size() > 0) - order++; - } - */ - } - - fprintf(stderr, "LEAVING Loop::setLexicalOrder() %d idxNames\n", idxNames.size()); - for (int i=0; i< idxNames.size(); i++) { - std::vector what = idxNames[i]; - for (int j=0; j active; - for (int i = 0; i < stmt.size(); i++) - active.insert(i); - apply_xform(active); -} - -void Loop::apply_xform(int stmt_num) { - fprintf(stderr, "apply_xform( %d )\n", stmt_num); - std::set active; - active.insert(stmt_num); - apply_xform(active); -} - -void Loop::apply_xform(std::set &active) { - fflush(stdout); - fprintf(stderr, "loop.cc apply_xform( set )\n"); - - int max_n = 0; - - omega::CG_outputBuilder *ocg = ir->builder(); - for (std::set::iterator i = active.begin(); i != active.end(); i++) { - int n = stmt[*i].loop_level.size(); - if (n > max_n) - max_n = n; - - std::vector lex = getLexicalOrder(*i); - - omega::Relation mapping(2 * n + 1, n); - omega::F_And *f_root = mapping.add_and(); - for (int j = 1; j <= n; j++) { - omega::EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(j), 1); - h.update_coef(mapping.input_var(2 * j), -1); - } - mapping = omega::Composition(mapping, stmt[*i].xform); - mapping.simplify(); - - // match omega input/output variables to variable names in the code - for (int j = 1; j <= stmt[*i].IS.n_set(); j++) - mapping.name_input_var(j, stmt[*i].IS.set_var(j)->name()); - for (int j = 1; j <= n; j++) - mapping.name_output_var(j, - tmp_loop_var_name_prefix - + omega::to_string( - tmp_loop_var_name_counter + j - 1)); - mapping.setup_names(); - mapping.print(); // "{[I] -> [_t1] : I = _t1 } - fflush(stdout); - - omega::Relation known = Extend_Set(copy(this->known), - mapping.n_out() - this->known.n_set()); - //stmt[*i].code = outputStatement(ocg, stmt[*i].code, 0, mapping, known, std::vector(mapping.n_out(), NULL)); - - omega::CG_outputBuilder *ocgr = ir->builder(); - - - //this is probably CG_chillBuilder; - - omega::CG_stringBuilder *ocgs = new omega::CG_stringBuilder; - if (uninterpreted_symbols[*i].size() == 0) { - - - std::set globals; - - for (omega::DNF_Iterator di(stmt[*i].IS.query_DNF()); di; di++) { - - for (omega::Constraint_Iterator e(*di); e; e++) { - for (omega::Constr_Vars_Iter cvi(*e); cvi; cvi++) { - omega::Variable_ID v = cvi.curr_var(); - if (v->kind() == omega::Global_Var - && v->get_global_var()->arity() > 0 - && globals.find(v->name()) == globals.end()) { - omega::Global_Var_ID g = v->get_global_var(); - globals.insert(v->name()); - std::vector reprs; - std::vector reprs2; - - for (int l = 1; l <= g->arity(); l++) { - omega::CG_outputRepr *temp = ocgr->CreateIdent( - stmt[*i].IS.set_var(l)->name()); - omega::CG_outputRepr *temp2 = ocgs->CreateIdent( - stmt[*i].IS.set_var(l)->name()); - - reprs.push_back(temp); - reprs2.push_back(temp2); - } - uninterpreted_symbols[*i].insert( - std::pair >( - v->get_global_var()->base_name(), - reprs)); - uninterpreted_symbols_stringrepr[*i].insert( - std::pair >( - v->get_global_var()->base_name(), - reprs2)); - } - } - } - } - } - - std::vector loop_vars; - for (int j = 1; j <= stmt[*i].IS.n_set(); j++) { - loop_vars.push_back(stmt[*i].IS.set_var(j)->name()); - } - for (int j = 0; j subs = output_substitutions(ocg, - Inverse(copy(mapping)), - std::vector >( - mapping.n_out(), - std::make_pair( - static_cast(NULL), 0)), - uninterpreted_symbols[*i]); - - std::vector subs2; - for (int l = 0; l < subs.size(); l++) - subs2.push_back(subs[l]->clone()); - - fprintf(stderr, "%d uninterpreted symbols\n", (int)uninterpreted_symbols.size()); - for (int j = 0; j >::iterator it = - uninterpreted_symbols[*i].begin(); - it != uninterpreted_symbols[*i].end(); it++) { - fprintf(stderr, "\ncount %d\n", count); - - std::vector reprs_ = it->second; - fprintf(stderr, "%d reprs_\n", (int)reprs_.size()); - - std::vector reprs_2; - for (int k = 0; k < reprs_.size(); k++) { - fprintf(stderr, "k %d\n", k); - std::vector subs; - for (int l = 0; l < subs2.size(); l++) { - fprintf(stderr, "l %d\n", l); - subs.push_back(subs2[l]->clone()); - } - - fprintf(stderr, "clone\n"); - CG_outputRepr *c = reprs_[k]->clone(); - c->dump(); fflush(stdout); - - fprintf(stderr, "createsub\n"); - CG_outputRepr *s = ocgr->CreateSubstitutedStmt(0, c, - loop_vars, subs, true); - - fprintf(stderr, "push back\n"); - reprs_2.push_back( s ); - - } - - it->second = reprs_2; - count++; - fprintf(stderr, "bottom\n"); - } - - std::vector subs3 = output_substitutions( - ocgs, Inverse(copy(mapping)), - std::vector >( - mapping.n_out(), - std::make_pair( - static_cast(NULL), 0)), - uninterpreted_symbols_stringrepr[*i]); - - for (std::map >::iterator it = - uninterpreted_symbols_stringrepr[*i].begin(); - it != uninterpreted_symbols_stringrepr[*i].end(); it++) { - - std::vector reprs_ = it->second; - std::vector reprs_2; - for (int k = 0; k < reprs_.size(); k++) { - std::vector subs; - /* for (int l = 0; l < subs3.size(); l++) - subs.push_back(subs3[l]->clone()); - reprs_2.push_back( - ocgs->CreateSubstitutedStmt(0, reprs_[k]->clone(), - loop_vars, subs)); - */ - reprs_2.push_back(subs3[k]->clone()); - } - - it->second = reprs_2; - - } - - - fprintf(stderr, "loop.cc stmt[*i].code =\n"); - //stmt[*i].code->dump(); - //fprintf(stderr, "\n"); - stmt[*i].code = ocg->CreateSubstitutedStmt(0, stmt[*i].code, loop_vars, - subs); - //fprintf(stderr, "loop.cc substituted code =\n"); - //stmt[*i].code->dump(); - //fprintf(stderr, "\n"); - - stmt[*i].IS = omega::Range(Restrict_Domain(mapping, stmt[*i].IS)); - stmt[*i].IS.simplify(); - - // replace original transformation relation with straight 1-1 mapping - //fprintf(stderr, "replace original transformation relation with straight 1-1 mapping\n"); - mapping = Relation(n, 2 * n + 1); - f_root = mapping.add_and(); - for (int j = 1; j <= n; j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(2 * j), 1); - h.update_coef(mapping.input_var(j), -1); - } - for (int j = 1; j <= 2 * n + 1; j += 2) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(j), 1); - h.update_const(-lex[j - 1]); - } - stmt[*i].xform = mapping; - - //fprintf(stderr, "\ncode is: \n"); - //stmt[*i].code->dump(); - //fprintf(stderr, "\n\n"); - - } - - tmp_loop_var_name_counter += max_n; - fflush(stdout); - fprintf(stderr, "loop.cc LEAVING apply_xform( set )\n\n"); - //for (std::set::iterator i = active.begin(); i != active.end(); i++) { - // fprintf(stderr, "\nloop.cc stmt[i].code =\n"); - // stmt[*i].code->dump(); - // fprintf(stderr, "\n\n"); - //} - -} - - - - -void Loop::addKnown(const Relation &cond) { - - // invalidate saved codegen computation - delete last_compute_cgr_; - last_compute_cgr_ = NULL; - delete last_compute_cg_; - last_compute_cg_ = NULL; - fprintf(stderr, "Loop::addKnown(), SETTING last_compute_cg_ = NULL\n"); - - int n1 = this->known.n_set(); - - Relation r = copy(cond); - int n2 = r.n_set(); - - if (n1 < n2) - this->known = Extend_Set(this->known, n2 - n1); - else if (n1 > n2) - r = Extend_Set(r, n1 - n2); - - this->known = Intersection(this->known, r); -} - -void Loop::removeDependence(int stmt_num_from, int stmt_num_to) { - // check for sanity of parameters - if (stmt_num_from >= stmt.size()) - throw std::invalid_argument( - "invalid statement number " + to_string(stmt_num_from)); - if (stmt_num_to >= stmt.size()) - throw std::invalid_argument( - "invalid statement number " + to_string(stmt_num_to)); - - dep.disconnect(stmt_num_from, stmt_num_to); -} - -void Loop::dump() const { - for (int i = 0; i < stmt.size(); i++) { - std::vector lex = getLexicalOrder(i); - std::cout << "s" << i + 1 << ": "; - for (int j = 0; j < stmt[i].loop_level.size(); j++) { - if (2 * j < lex.size()) - std::cout << lex[2 * j]; - switch (stmt[i].loop_level[j].type) { - case LoopLevelOriginal: - std::cout << "(dim:" << stmt[i].loop_level[j].payload << ")"; - break; - case LoopLevelTile: - std::cout << "(tile:" << stmt[i].loop_level[j].payload << ")"; - break; - default: - std::cout << "(unknown)"; - } - std::cout << ' '; - } - for (int j = 2 * stmt[i].loop_level.size(); j < lex.size(); j += 2) { - std::cout << lex[j]; - if (j != lex.size() - 1) - std::cout << ' '; - } - std::cout << std::endl; - } -} - -bool Loop::nonsingular(const std::vector > &T) { - if (stmt.size() == 0) - return true; - - // check for sanity of parameters - for (int i = 0; i < stmt.size(); i++) { - if (stmt[i].loop_level.size() != num_dep_dim) - throw std::invalid_argument( - "nonsingular loop transformations must be applied to original perfect loop nest"); - for (int j = 0; j < stmt[i].loop_level.size(); j++) - if (stmt[i].loop_level[j].type != LoopLevelOriginal) - throw std::invalid_argument( - "nonsingular loop transformations must be applied to original perfect loop nest"); - } - if (T.size() != num_dep_dim) - throw std::invalid_argument("invalid transformation matrix"); - for (int i = 0; i < stmt.size(); i++) - if (T[i].size() != num_dep_dim + 1 && T[i].size() != num_dep_dim) - throw std::invalid_argument("invalid transformation matrix"); - // invalidate saved codegen computation - delete last_compute_cgr_; - last_compute_cgr_ = NULL; - delete last_compute_cg_; - last_compute_cg_ = NULL; - fprintf(stderr, "Loop::nonsingular(), SETTING last_compute_cg_ = NULL\n"); - - // build relation from matrix - Relation mapping(2 * num_dep_dim + 1, 2 * num_dep_dim + 1); - F_And *f_root = mapping.add_and(); - for (int i = 0; i < num_dep_dim; i++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(2 * (i + 1)), -1); - for (int j = 0; j < num_dep_dim; j++) - if (T[i][j] != 0) - h.update_coef(mapping.input_var(2 * (j + 1)), T[i][j]); - if (T[i].size() == num_dep_dim + 1) - h.update_const(T[i][num_dep_dim]); - } - for (int i = 1; i <= 2 * num_dep_dim + 1; i += 2) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(i), -1); - h.update_coef(mapping.input_var(i), 1); - } - - // update transformation relations - for (int i = 0; i < stmt.size(); i++) - stmt[i].xform = Composition(copy(mapping), stmt[i].xform); - - // update dependence graph - for (int i = 0; i < dep.vertex.size(); i++) - for (DependenceGraph::EdgeList::iterator j = - dep.vertex[i].second.begin(); j != dep.vertex[i].second.end(); - j++) { - std::vector dvs = j->second; - for (int k = 0; k < dvs.size(); k++) { - DependenceVector &dv = dvs[k]; - switch (dv.type) { - case DEP_W2R: - case DEP_R2W: - case DEP_W2W: - case DEP_R2R: { - std::vector lbounds(num_dep_dim), ubounds( - num_dep_dim); - for (int p = 0; p < num_dep_dim; p++) { - coef_t lb = 0; - coef_t ub = 0; - for (int q = 0; q < num_dep_dim; q++) { - if (T[p][q] > 0) { - if (lb == -posInfinity - || dv.lbounds[q] == -posInfinity) - lb = -posInfinity; - else - lb += T[p][q] * dv.lbounds[q]; - if (ub == posInfinity - || dv.ubounds[q] == posInfinity) - ub = posInfinity; - else - ub += T[p][q] * dv.ubounds[q]; - } else if (T[p][q] < 0) { - if (lb == -posInfinity - || dv.ubounds[q] == posInfinity) - lb = -posInfinity; - else - lb += T[p][q] * dv.ubounds[q]; - if (ub == posInfinity - || dv.lbounds[q] == -posInfinity) - ub = posInfinity; - else - ub += T[p][q] * dv.lbounds[q]; - } - } - if (T[p].size() == num_dep_dim + 1) { - if (lb != -posInfinity) - lb += T[p][num_dep_dim]; - if (ub != posInfinity) - ub += T[p][num_dep_dim]; - } - lbounds[p] = lb; - ubounds[p] = ub; - } - dv.lbounds = lbounds; - dv.ubounds = ubounds; - - break; - } - default: - ; - } - } - j->second = dvs; - } - - // set constant loop values - std::set active; - for (int i = 0; i < stmt.size(); i++) - active.insert(i); - setLexicalOrder(0, active); - - return true; -} - - -bool Loop::is_dependence_valid_based_on_lex_order(int i, int j, - const DependenceVector &dv, bool before) { - std::vector lex_i = getLexicalOrder(i); - std::vector lex_j = getLexicalOrder(j); - int last_dim; - if (!dv.is_scalar_dependence) { - for (last_dim = 0; - last_dim < lex_i.size() && (lex_i[last_dim] == lex_j[last_dim]); - last_dim++) - ; - last_dim = last_dim / 2; - if (last_dim == 0) - return true; - - for (int i = 0; i < last_dim; i++) { - if (dv.lbounds[i] > 0) - return true; - else if (dv.lbounds[i] < 0) - return false; - } - } - if (before) - return true; - - return false; - -} - -// Manu:: reduction operation - -void Loop::scalar_expand(int stmt_num, const std::vector &levels, - std::string arrName, int memory_type, int padding_alignment, - int assign_then_accumulate, int padding_stride) { - - //std::cout << "In scalar_expand function: " << stmt_num << ", " << arrName << "\n"; - //std::cout.flush(); - - //fprintf(stderr, "\n%d statements\n", stmt.size()); - //for (int i=0; iDump(); - //} - //fprintf(stderr, "\n"); - - // check for sanity of parameters - bool found_non_constant_size_dimension = false; - - if (stmt_num < 0 || stmt_num >= stmt.size()) - throw std::invalid_argument( - "invalid statement number " + to_string(stmt_num)); - //Anand: adding check for privatized levels - //if (arrName != "RHS") - // throw std::invalid_argument( - // "invalid 3rd argument: only 'RHS' supported " + arrName); - for (int i = 0; i < levels.size(); i++) { - if (levels[i] <= 0 || levels[i] > stmt[stmt_num].loop_level.size()) - throw std::invalid_argument( - "1invalid loop level " + to_string(levels[i])); - - if (i > 0) { - if (levels[i] < levels[i - 1]) - throw std::invalid_argument( - "loop levels must be in ascending order"); - } - } - //end --adding check for privatized levels - - delete last_compute_cgr_; - last_compute_cgr_ = NULL; - delete last_compute_cg_; - last_compute_cg_ = NULL; - fprintf(stderr, "Loop::scalar_expand(), SETTING last_compute_cg_ = NULL\n"); - - fprintf(stderr, "\nloop.cc finding array accesses in stmt %d of the code\n",stmt_num ); - std::vector access = ir->FindArrayRef(stmt[stmt_num].code); - fprintf(stderr, "loop.cc L2726 %d access\n", access.size()); - - IR_ArraySymbol *sym = NULL; - fprintf(stderr, "arrName %s\n", arrName.c_str()); - if (arrName == "RHS") { - fprintf(stderr, "sym RHS\n"); - sym = access[0]->symbol(); - } - else { - fprintf(stderr, "looking for array %s in access\n", arrName.c_str()); - for (int k = 0; k < access.size(); k++) { // BUH - - //fprintf(stderr, "access[%d] = %s ", k, access[k]->getTypeString()); access[k]->print(0,stderr); fprintf(stderr, "\n"); - - std::string name = access[k]->symbol()->name(); - //fprintf(stderr, "comparing %s to %s\n", name.c_str(), arrName.c_str()); - - if (access[k]->symbol()->name() == arrName) { - fprintf(stderr, "found it sym access[ k=%d ]\n", k); - sym = access[k]->symbol(); - } - } - } - if (!sym) fprintf(stderr, "DIDN'T FIND IT\n"); - fprintf(stderr, "sym %p\n", sym); - - // collect array references by name - std::vector lex = getLexicalOrder(stmt_num); - int dim = 2 * levels[levels.size() - 1] - 1; - std::set same_loop = getStatements(lex, dim - 1); - - //Anand: shifting this down - // assign_const(stmt[newStmt_num].xform, 2*level+1, 1); - - // std::cout << " before temp array name \n "; - // create a temporary variable - IR_Symbol *tmp_sym; - - // get the loop upperbound, that would be the size of the temp array. - omega::coef_t lb[levels.size()], ub[levels.size()], size[levels.size()]; - - //Anand Adding apply xform so that tiled loop bounds are reflected - fprintf(stderr, "Adding apply xform so that tiled loop bounds are reflected\n"); - apply_xform(same_loop); - fprintf(stderr, "loop.cc, back from apply_xform()\n"); - - //Anand commenting out the folowing 4 lines - /* copy(stmt[stmt_num].IS).query_variable_bounds( - copy(stmt[stmt_num].IS).set_var(level), lb, ub); - std::cout << "Upper Bound = " << ub << "\n"; - std::cout << "lower Bound = " << lb << "\n"; - */ - // testing testing -- Manu //////////////////////////////////////////////// - /* - // int n_dim = sym->n_dim(); - // std::cout << "------- n_dim ----------- " << n_dim << "\n"; - std::pair result = find_simplest_stride(stmt[stmt_num].IS, stmt[stmt_num].IS.set_var(level)); - omega::coef_t index_stride; - if (result.second != NULL) { - index_stride = abs(result.first.get_coef(result.second))/gcd(abs(result.first.get_coef(result.second)), abs(result.first.get_coef(stmt[stmt_num].IS.set_var(level)))); - std::cout << "simplest_stride :: " << index_stride << ", " << result.first.get_coef(result.second) << ", " << result.first.get_coef(stmt[stmt_num].IS.set_var(level))<< "\n"; - } - Relation bound; - // bound = get_loop_bound(stmt[stmt_num].IS, level); - bound = SimpleHull(stmt[stmt_num].IS,true, true); - bound.print(); - - bound = copy(stmt[stmt_num].IS); - for (int i = 1; i < level; i++) { - bound = Project(bound, i, Set_Var); - std::cout << "-------------------------------\n"; - bound.print(); - } - - bound.simplify(); - bound.print(); - // bound = get_loop_bound(bound, level); - - copy(bound).query_variable_bounds(copy(bound).set_var(level), lb, ub); - std::cout << "Upper Bound = " << ub << "\n"; - std::cout << "lower Bound = " << lb << "\n"; - - result = find_simplest_stride(bound, bound.set_var(level)); - if (result.second != NULL) - index_stride = abs(result.first.get_coef(result.second))/gcd(abs(result.first.get_coef(result.second)), abs(result.first.get_coef(bound.set_var(level)))); - else - index_stride = 1; - std::cout << "simplest_stride 11:: " << index_stride << "\n"; - */ - //////////////////////////////////////////////////////////////////////////////// - ///////////////////////////// copied datacopy code here ///////////////////////////////////////////// - - //std::cout << "In scalar_expand function 2: " << stmt_num << ", " << arrName << "\n"; - //std::cout.flush(); - - //fprintf(stderr, "\n%d statements\n", stmt.size()); - //for (int i=0; iDump(); - //} - //fprintf(stderr, "\n"); - - - - int n_dim = levels.size(); - Relation copy_is = copy(stmt[stmt_num].IS); - // extract temporary array information - CG_outputBuilder *ocg1 = ir->builder(); - std::vector index_lb(n_dim); // initialized to NULL - std::vector index_stride(n_dim); - std::vector is_index_eq(n_dim, false); - std::vector > index_sz(0); - Relation reduced_copy_is = copy(copy_is); - std::vector size_repr; - std::vector size_int; - Relation xform = copy(stmt[stmt_num].xform); - for (int i = 0; i < n_dim; i++) { - - dim = 2 * levels[i] - 1; - //Anand: Commenting out the lines below: not required - // if (i != 0) - // reduced_copy_is = Project(reduced_copy_is, level - 1 + i, Set_Var); - Relation bound = get_loop_bound(copy(reduced_copy_is), levels[i] - 1); - - // extract stride - std::pair result = find_simplest_stride(bound, - bound.set_var(levels[i])); - if (result.second != NULL) - index_stride[i] = abs(result.first.get_coef(result.second)) - / gcd(abs(result.first.get_coef(result.second)), - abs( - result.first.get_coef( - bound.set_var(levels[i])))); - else - index_stride[i] = 1; - // std::cout << "simplest_stride 11:: " << index_stride[i] << "\n"; - - // check if this array index requires loop - Conjunct *c = bound.query_DNF()->single_conjunct(); - for (EQ_Iterator ei(c->EQs()); ei; ei++) { - if ((*ei).has_wildcards()) - continue; - - int coef = (*ei).get_coef(bound.set_var(levels[i])); - if (coef != 0) { - int sign = 1; - if (coef < 0) { - coef = -coef; - sign = -1; - } - - CG_outputRepr *op = NULL; - for (Constr_Vars_Iter ci(*ei); ci; ci++) { - switch ((*ci).var->kind()) { - case Input_Var: { - if ((*ci).var != bound.set_var(levels[i])) - if ((*ci).coef * sign == 1) - op = ocg1->CreateMinus(op, - ocg1->CreateIdent((*ci).var->name())); - else if ((*ci).coef * sign == -1) - op = ocg1->CreatePlus(op, - ocg1->CreateIdent((*ci).var->name())); - else if ((*ci).coef * sign > 1) { - op = ocg1->CreateMinus(op, - ocg1->CreateTimes( - ocg1->CreateInt( - abs((*ci).coef)), - ocg1->CreateIdent( - (*ci).var->name()))); - } - else - // (*ci).coef*sign < -1 - op = ocg1->CreatePlus(op, - ocg1->CreateTimes( - ocg1->CreateInt( - abs((*ci).coef)), - ocg1->CreateIdent( - (*ci).var->name()))); - break; - } - case Global_Var: { - Global_Var_ID g = (*ci).var->get_global_var(); - if ((*ci).coef * sign == 1) - op = ocg1->CreateMinus(op, - ocg1->CreateIdent(g->base_name())); - else if ((*ci).coef * sign == -1) - op = ocg1->CreatePlus(op, - ocg1->CreateIdent(g->base_name())); - else if ((*ci).coef * sign > 1) - op = ocg1->CreateMinus(op, - ocg1->CreateTimes( - ocg1->CreateInt(abs((*ci).coef)), - ocg1->CreateIdent(g->base_name()))); - else - // (*ci).coef*sign < -1 - op = ocg1->CreatePlus(op, - ocg1->CreateTimes( - ocg1->CreateInt(abs((*ci).coef)), - ocg1->CreateIdent(g->base_name()))); - break; - } - default: - throw loop_error("unsupported array index expression"); - } - } - if ((*ei).get_const() != 0) - op = ocg1->CreatePlus(op, - ocg1->CreateInt(-sign * ((*ei).get_const()))); - if (coef != 1) - op = ocg1->CreateIntegerFloor(op, ocg1->CreateInt(coef)); - - index_lb[i] = op; - is_index_eq[i] = true; - break; - } - } - if (is_index_eq[i]) - continue; - - // separate lower and upper bounds - std::vector lb_list, ub_list; - std::set excluded_floor_vars; - excluded_floor_vars.insert(bound.set_var(levels[i])); - for (GEQ_Iterator gi(c->GEQs()); gi; gi++) { - int coef = (*gi).get_coef(bound.set_var(levels[i])); - if (coef != 0 && (*gi).has_wildcards()) { - bool clean_bound = true; - GEQ_Handle h; - for (Constr_Vars_Iter cvi(*gi, true); gi; gi++) - if (!find_floor_definition(bound, (*cvi).var, - excluded_floor_vars).first) { - clean_bound = false; - break; - } - else - h= find_floor_definition(bound, (*cvi).var, - excluded_floor_vars).second; - - if (!clean_bound) - continue; - else{ - if (coef > 0) - lb_list.push_back(h); - else if (coef < 0) - ub_list.push_back(h); - continue; - } - - } - - if (coef > 0) - lb_list.push_back(*gi); - else if (coef < 0) - ub_list.push_back(*gi); - } - if (lb_list.size() == 0 || ub_list.size() == 0) - throw loop_error("failed to calcuate array footprint size"); - - // build lower bound representation - std::vector lb_repr_list; - /* for (int j = 0; j < lb_list.size(); j++){ - if(this->known.n_set() == 0) - lb_repr_list.push_back(output_lower_bound_repr(ocg1, lb_list[j], bound.set_var(level-1+i+1), result.first, result.second, bound, Relation::True(bound.n_set()), std::vector >(bound.n_set(), std::make_pair(static_cast(NULL), 0)))); - else - lb_repr_list.push_back(output_lower_bound_repr(ocg1, lb_list[j], bound.set_var(level-1+i+1), result.first, result.second, bound, this->known, std::vector >(bound.n_set(), std::make_pair(static_cast(NULL), 0)))); - - } - */ - if (lb_repr_list.size() > 1) - index_lb[i] = ocg1->CreateInvoke("max", lb_repr_list); - else if (lb_repr_list.size() == 1) - index_lb[i] = lb_repr_list[0]; - - // build temporary array size representation - { - Relation cal(copy_is.n_set(), 1); - F_And *f_root = cal.add_and(); - for (int j = 0; j < ub_list.size(); j++) - for (int k = 0; k < lb_list.size(); k++) { - GEQ_Handle h = f_root->add_GEQ(); - - for (Constr_Vars_Iter ci(ub_list[j]); ci; ci++) { - switch ((*ci).var->kind()) { - case Input_Var: { - int pos = (*ci).var->get_position(); - h.update_coef(cal.input_var(pos), (*ci).coef); - break; - } - case Global_Var: { - Global_Var_ID g = (*ci).var->get_global_var(); - Variable_ID v; - if (g->arity() == 0) - v = cal.get_local(g); - else - v = cal.get_local(g, (*ci).var->function_of()); - h.update_coef(v, (*ci).coef); - break; - } - default: - throw loop_error( - "cannot calculate temporay array size statically"); - } - } - h.update_const(ub_list[j].get_const()); - - for (Constr_Vars_Iter ci(lb_list[k]); ci; ci++) { - switch ((*ci).var->kind()) { - case Input_Var: { - int pos = (*ci).var->get_position(); - h.update_coef(cal.input_var(pos), (*ci).coef); - break; - } - case Global_Var: { - Global_Var_ID g = (*ci).var->get_global_var(); - Variable_ID v; - if (g->arity() == 0) - v = cal.get_local(g); - else - v = cal.get_local(g, (*ci).var->function_of()); - h.update_coef(v, (*ci).coef); - break; - } - default: - throw loop_error( - "cannot calculate temporay array size statically"); - } - } - h.update_const(lb_list[k].get_const()); - - h.update_const(1); - h.update_coef(cal.output_var(1), -1); - } - - cal = Restrict_Domain(cal, copy(copy_is)); - for (int j = 1; j <= cal.n_inp(); j++) { - cal = Project(cal, j, Input_Var); - } - cal.simplify(); - - // pad temporary array size - // TODO: for variable array size, create padding formula - //int padding_stride = 0; - Conjunct *c = cal.query_DNF()->single_conjunct(); - bool is_index_bound_const = false; - if (padding_stride != 0 && i == n_dim - 1) { - //size = (size + index_stride[i] - 1) / index_stride[i]; - size_repr.push_back(ocg1->CreateInt(padding_stride)); - } else { - for (GEQ_Iterator gi(c->GEQs()); gi && !is_index_bound_const; - gi++) - if ((*gi).is_const(cal.output_var(1))) { - coef_t size = (*gi).get_const() - / (-(*gi).get_coef(cal.output_var(1))); - - if (padding_alignment > 1 && i == n_dim - 1) { // align to boundary for data packing - int residue = size % padding_alignment; - if (residue) - size = size + padding_alignment - residue; - } - - index_sz.push_back( - std::make_pair(i, ocg1->CreateInt(size))); - is_index_bound_const = true; - size_int.push_back(size); - size_repr.push_back(ocg1->CreateInt(size)); - - // std::cout << "============================== size :: " - // << size << "\n"; - - } - - if (!is_index_bound_const) { - - found_non_constant_size_dimension = true; - Conjunct *c = bound.query_DNF()->single_conjunct(); - for (GEQ_Iterator gi(c->GEQs()); - gi && !is_index_bound_const; gi++) { - int coef = (*gi).get_coef(bound.set_var(levels[i])); - if (coef < 0) { - - size_repr.push_back( - ocg1->CreatePlus( - output_upper_bound_repr(ocg1, *gi, - bound.set_var(levels[i]), - bound, - std::vector< - std::pair< - CG_outputRepr *, - int> >( - bound.n_set(), - std::make_pair( - static_cast(NULL), - 0)), - uninterpreted_symbols[stmt_num]), - ocg1->CreateInt(1))); - - /*CG_outputRepr *op = NULL; - for (Constr_Vars_Iter ci(*gi); ci; ci++) { - if ((*ci).var != cal.output_var(1)) { - switch ((*ci).var->kind()) { - case Global_Var: { - Global_Var_ID g = - (*ci).var->get_global_var(); - if ((*ci).coef == 1) - op = ocg1->CreatePlus(op, - ocg1->CreateIdent( - g->base_name())); - else if ((*ci).coef == -1) - op = ocg1->CreateMinus(op, - ocg1->CreateIdent( - g->base_name())); - else if ((*ci).coef > 1) - op = - ocg1->CreatePlus(op, - ocg1->CreateTimes( - ocg1->CreateInt( - (*ci).coef), - ocg1->CreateIdent( - g->base_name()))); - else - // (*ci).coef < -1 - op = - ocg1->CreateMinus(op, - ocg1->CreateTimes( - ocg1->CreateInt( - -(*ci).coef), - ocg1->CreateIdent( - g->base_name()))); - break; - } - default: - throw loop_error( - "failed to generate array index bound code"); - } - } - } - int c = (*gi).get_const(); - if (c > 0) - op = ocg1->CreatePlus(op, ocg1->CreateInt(c)); - else if (c < 0) - op = ocg1->CreateMinus(op, ocg1->CreateInt(-c)); - */ - /* if (padding_stride != 0) { - if (i == fastest_changing_dimension) { - coef_t g = gcd(index_stride[i], static_cast(padding_stride)); - coef_t t1 = index_stride[i] / g; - if (t1 != 1) - op = ocg->CreateIntegerFloor(ocg->CreatePlus(op, ocg->CreateInt(t1-1)), ocg->CreateInt(t1)); - coef_t t2 = padding_stride / g; - if (t2 != 1) - op = ocg->CreateTimes(op, ocg->CreateInt(t2)); - } - else if (index_stride[i] != 1) { - op = ocg->CreateIntegerFloor(ocg->CreatePlus(op, ocg->CreateInt(index_stride[i]-1)), ocg->CreateInt(index_stride[i])); - } - } - */ - //index_sz.push_back(std::make_pair(i, op)); - //break; - } - } - } - } - } - //size[i] = ub[i]; - - } - ///////////////////////////////////////////////////////////////////////////////////////////////////// - // - - //Anand: Creating IS of new statement - - //for(int l = dim; l < stmt[stmt_num].xform.n_out(); l+=2) - //std::cout << "In scalar_expand function 3: " << stmt_num << ", " << arrName << "\n"; - //std::cout.flush(); - - //fprintf(stderr, "\n%d statements\n", stmt.size()); - //for (int i=0; iDump(); - //} - //fprintf(stderr, "\n"); - - - shiftLexicalOrder(lex, dim + 1, 1); - Statement s = stmt[stmt_num]; - s.ir_stmt_node = NULL; - int newStmt_num = stmt.size(); - - fprintf(stderr, "loop.cc L3249 adding stmt %d\n", stmt.size()); - stmt.push_back(s); - - fprintf(stderr, "uninterpreted_symbols.push_back() newStmt_num %d\n", newStmt_num); - uninterpreted_symbols.push_back(uninterpreted_symbols[stmt_num]); - uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[stmt_num]); - stmt[newStmt_num].code = stmt[stmt_num].code->clone(); - stmt[newStmt_num].IS = copy(stmt[stmt_num].IS); - stmt[newStmt_num].xform = xform; - stmt[newStmt_num].reduction = stmt[stmt_num].reduction; - stmt[newStmt_num].reductionOp = stmt[stmt_num].reductionOp; - - - //fprintf(stderr, "\nafter clone, %d statements\n", stmt.size()); - //for (int i=0; iDump(); - //} - //fprintf(stderr, "\n"); - - - - //assign_const(stmt[newStmt_num].xform, stmt[stmt_num].xform.n_out(), 1);//Anand: change from 2*level + 1 to stmt[stmt_num].xform.size() - //Anand-End creating IS of new statement - - CG_outputRepr * tmpArrSz; - CG_outputBuilder *ocg = ir->builder(); - - //for(int k =0; k < levels.size(); k++ ) - // size_repr.push_back(ocg->CreateInt(size[k]));//Anand: copying apply_xform functionality to prevent IS modification - //due to side effects with uninterpreted function symbols and failures in omega - - //int n = stmt[stmt_num].loop_level.size(); - - /*Relation mapping(2 * n + 1, n); - F_And *f_root = mapping.add_and(); - for (int j = 1; j <= n; j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(j), 1); - h.update_coef(mapping.input_var(2 * j), -1); - } - mapping = Composition(mapping, copy(stmt[stmt_num].xform)); - mapping.simplify(); - - // match omega input/output variables to variable names in the code - for (int j = 1; j <= stmt[stmt_num].IS.n_set(); j++) - mapping.name_input_var(j, stmt[stmt_num].IS.set_var(j)->name()); - for (int j = 1; j <= n; j++) - mapping.name_output_var(j, - tmp_loop_var_name_prefix - + to_string(tmp_loop_var_name_counter + j - 1)); - mapping.setup_names(); - - Relation size_ = omega::Range(Restrict_Domain(mapping, copy(stmt[stmt_num].IS))); - size_.simplify(); - */ - - //Anand -commenting out tmp sym creation as symbol may have more than one dimension - //tmp_sym = ir->CreateArraySymbol(tmpArrSz, sym); - std::vector lhs_index; - CG_outputRepr *arr_ref_repr; - arr_ref_repr = ocg->CreateIdent( - stmt[stmt_num].IS.set_var(levels[levels.size() - 1])->name()); - - CG_outputRepr *total_size = size_repr[0]; - fprintf(stderr, "total_size = "); total_size->dump(); fflush(stdout); - - for (int i = 1; i < size_repr.size(); i++) { - fprintf(stderr, "total_size now "); total_size->dump(); fflush(stdout); fprintf(stderr, " times something\n\n"); - - total_size = ocg->CreateTimes(total_size->clone(), - size_repr[i]->clone()); - - } - - // COMMENT NEEDED - //fprintf(stderr, "\nloop.cc COMMENT NEEDED\n"); - for (int k = levels.size() - 2; k >= 0; k--) { - CG_outputRepr *temp_repr =ocg->CreateIdent(stmt[stmt_num].IS.set_var(levels[k])->name()); - for (int l = k + 1; l < levels.size(); l++) { - //fprintf(stderr, "\nloop.cc CREATETIMES\n"); - temp_repr = ocg->CreateTimes(temp_repr->clone(), - size_repr[l]->clone()); - } - - //fprintf(stderr, "\nloop.cc CREATEPLUS\n"); - arr_ref_repr = ocg->CreatePlus(arr_ref_repr->clone(), - temp_repr->clone()); - } - - - //fprintf(stderr, "loop.cc, about to die\n"); - std::vector to_push; - to_push.push_back(total_size); - - if (!found_non_constant_size_dimension) { - fprintf(stderr, "constant size dimension\n"); - tmp_sym = ir->CreateArraySymbol(sym, to_push, memory_type); - } - else { - fprintf(stderr, "NON constant size dimension?\n"); - //tmp_sym = ir->CreatePointerSymbol(sym, to_push); - tmp_sym = ir->CreatePointerSymbol(sym, to_push); - - static_cast(tmp_sym)->set_size(0, total_size); // ?? - ptr_variables.push_back(static_cast(tmp_sym)); - fprintf(stderr, "ptr_variables now has %d entries\n", ptr_variables.size()); - } - - // add tmp_sym to Loop symtables ?? - - - // std::cout << " temp array name == " << tmp_sym->name().c_str() << "\n"; - - // get loop index variable at the given "level" - // Relation R = omega::Range(Restrict_Domain(copy(stmt[stmt_num].xform), copy(stmt[stmt_num].IS))); - // stmt[stmt_num].IS.print(); - //stmt[stmt_num].IS. - // std::cout << stmt[stmt_num].IS.n_set() << std::endl; - // std::string v = stmt[stmt_num].IS.set_var(level)->name(); - // std::cout << "loop index variable is '" << v.c_str() << "'\n"; - - // create a reference for the temporary array - fprintf(stderr, "create a reference for the temporary array\n"); - //std::cout << "In scalar_expand function 4: " << stmt_num << ", " << arrName << "\n"; - //std::cout.flush(); - - //fprintf(stderr, "\n%d statements\n", stmt.size()); - //for (int i=0; iDump(); - //} - //fprintf(stderr, "\n"); - - - - std::vector to_push2; - to_push2.push_back(arr_ref_repr); // can have only one entry - - //lhs_index[0] = ocg->CreateIdent(v); - - - IR_ArrayRef *tmp_array_ref; - IR_PointerArrayRef * tmp_ptr_array_ref; // was IR_PointerArrayref - - if (!found_non_constant_size_dimension) { - fprintf(stderr, "constant size\n"); - - tmp_array_ref = ir->CreateArrayRef( - static_cast(tmp_sym), to_push2); - } - else { - fprintf(stderr, "NON constant size\n"); - tmp_ptr_array_ref = ir->CreatePointerArrayRef( - static_cast(tmp_sym), to_push2); - // TODO static_cast(tmp_sym), to_push2); - } - fflush(stdout); - - //fprintf(stderr, "\n%d statements\n", stmt.size()); - //for (int i=0; iDump(); - //} - //fprintf(stderr, "\n"); - - - //std::string stemp; - //stemp = tmp_array_ref->name(); - //std::cout << "Created array reference --> " << stemp.c_str() << "\n"; - - // get the RHS expression - fprintf(stderr, "get the RHS expression arrName %s\n", arrName.c_str()); - - CG_outputRepr *rhs; - if (arrName == "RHS") { - rhs = ir->GetRHSExpression(stmt[stmt_num].code); - - std::vector symbols = ir->FindArrayRef(rhs); - } - std::set sym_names; - - //for (int i = 0; i < symbols.size(); i++) - // sym_names.insert(symbols[i]->symbol()->name()); - - fflush(stdout); - - //fprintf(stderr, "\nbefore if (arrName == RHS)\n%d statements\n", stmt.size()); // problem is after here - //for (int i=0; iDump(); - //} - //fprintf(stderr, "\n"); - - if (arrName == "RHS") { - - std::vector symbols = ir->FindArrayRef(rhs); - - for (int i = 0; i < symbols.size(); i++) - sym_names.insert(symbols[i]->symbol()->name()); - } - else { - - fprintf(stderr, "finding array refs in stmt_num %d\n", stmt_num); - //fprintf(stderr, "\n%d statements\n", stmt.size()); - //for (int i=0; iDump(); - //} - //fprintf(stderr, "\n"); - - std::vector refs = ir->FindArrayRef(stmt[stmt_num].code); - fprintf(stderr, "\n%d refs\n", refs.size()); - - - bool found = false; - - for (int j = 0; j < refs.size(); j++) { - CG_outputRepr* to_replace; - - fprintf(stderr, "j %d build new assignment statement with temporary array\n",j); - // build new assignment statement with temporary array - if (!found_non_constant_size_dimension) { - to_replace = tmp_array_ref->convert(); - } else { - to_replace = tmp_ptr_array_ref->convert(); - } - //fprintf(stderr, "to_replace %p\n", to_replace); - //CG_chillRepr *CR = (CG_chillRepr *) to_replace; - //CR->Dump(); - - if (refs[j]->name() == arrName) { - fflush(stdout); - fprintf(stderr, "loop.cc L353\n"); // problem is after here - //fprintf(stderr, "\n%d statements\n", stmt.size()); - //for (int i=0; iDump(); - //} - //fprintf(stderr, "\n"); - - - sym_names.insert(refs[j]->symbol()->name()); - - if (!found) { - if (!found_non_constant_size_dimension) { - fprintf(stderr, "constant size2\n"); - omega::CG_outputRepr * t = tmp_array_ref->convert(); - omega::CG_outputRepr * r = refs[j]->convert()->clone(); - //CR = (CG_chillRepr *) t; - //CR->Dump(); - //CR = (CG_chillRepr *) r; - //CR->Dump(); - - //fprintf(stderr, "lhs t %p lhs r %p\n", t, r); - stmt[newStmt_num].code = - ir->builder()->CreateAssignment(0, - t, // tmp_array_ref->convert(), - r); // refs[j]->convert()->clone() - } - else { - fprintf(stderr, "NON constant size2\n"); - omega::CG_outputRepr * t = tmp_ptr_array_ref->convert(); // this fails - omega::CG_outputRepr * r = refs[j]->convert()->clone(); - - //omega::CG_chillRepr *CR = (omega::CG_chillRepr *) t; - //CR->Dump(); - //CR = (omega::CG_chillRepr *) r; - //CR->Dump(); - - //fprintf(stderr, "lhs t %p lhs r %p\n", t, r); - stmt[newStmt_num].code = - ir->builder()->CreateAssignment(0, - t, // tmp_ptr_array_ref->convert(), - r ); // refs[j]->convert()->clone()); - } - found = true; - - } - - // refs[j] has no parent? - fprintf(stderr, "replacing refs[%d]\n", j ); - ir->ReplaceExpression(refs[j], to_replace); - } - - } - - } - //ToDo need to update the dependence graph - //Anand adding dependence graph update - fprintf(stderr, "adding dependence graph update\n"); // problem is before here - //fprintf(stderr, "\n%d statements\n", stmt.size()); - //for (int i=0; iDump(); - //} - //fprintf(stderr, "\n"); - - dep.insert(); - - //Anand:Copying Dependence checks from datacopy code, might need to be a separate function/module - // in the future - - /*for (int i = 0; i < newStmt_num; i++) { - std::vector > D; - - for (DependenceGraph::EdgeList::iterator j = - dep.vertex[i].second.begin(); j != dep.vertex[i].second.end(); - ) { - if (same_loop.find(i) != same_loop.end() - && same_loop.find(j->first) == same_loop.end()) { - std::vector dvs1, dvs2; - for (int k = 0; k < j->second.size(); k++) { - DependenceVector dv = j->second[k]; - if (dv.sym != NULL - && sym_names.find(dv.sym->name()) != sym_names.end() - && (dv.type == DEP_R2R || dv.type == DEP_R2W)) - dvs1.push_back(dv); - else - dvs2.push_back(dv); - } - j->second = dvs2; - if (dvs1.size() > 0) - dep.connect(newStmt_num, j->first, dvs1); - } else if (same_loop.find(i) == same_loop.end() - && same_loop.find(j->first) != same_loop.end()) { - std::vector dvs1, dvs2; - for (int k = 0; k < j->second.size(); k++) { - DependenceVector dv = j->second[k]; - if (dv.sym != NULL - && sym_names.find(dv.sym->name()) != sym_names.end() - && (dv.type == DEP_R2R || dv.type == DEP_W2R)) - dvs1.push_back(dv); - else - dvs2.push_back(dv); - } - j->second = dvs2; - if (dvs1.size() > 0) - D.push_back(dvs1); - } - - if (j->second.size() == 0) - dep.vertex[i].second.erase(j++); - else - j++; - } - - for (int j = 0; j < D.size(); j++) - dep.connect(i, newStmt_num, D[j]); - } - */ - //Anand--end dependence check - if (arrName == "RHS") { - - // build new assignment statement with temporary array - if (!found_non_constant_size_dimension) { - if (assign_then_accumulate) { - stmt[newStmt_num].code = ir->builder()->CreateAssignment(0, - tmp_array_ref->convert(), rhs); - fprintf(stderr, "ir->ReplaceRHSExpression( stmt_ num %d )\n", stmt_num); - ir->ReplaceRHSExpression(stmt[stmt_num].code, tmp_array_ref); - } else { - CG_outputRepr *temp = tmp_array_ref->convert()->clone(); - if (ir->QueryExpOperation(stmt[stmt_num].code) - != IR_OP_PLUS_ASSIGNMENT) - throw ir_error( - "Statement is not a += accumulation statement"); - - fprintf(stderr, "replacing in a +=\n"); - stmt[newStmt_num].code = ir->builder()->CreatePlusAssignment(0, - temp->clone(), rhs); - - CG_outputRepr * lhs = ir->GetLHSExpression(stmt[stmt_num].code); - - CG_outputRepr *assignment = ir->builder()->CreateAssignment(0, - lhs, temp->clone()); - Statement init_ = stmt[newStmt_num]; // copy ?? - init_.ir_stmt_node = NULL; - - init_.code = stmt[newStmt_num].code->clone(); - init_.IS = copy(stmt[newStmt_num].IS); - init_.xform = copy(stmt[newStmt_num].xform); - init_.has_inspector = false; // ?? - - Relation mapping(init_.IS.n_set(), init_.IS.n_set()); - - F_And *f_root = mapping.add_and(); - - for (int i = 1; i <= mapping.n_inp(); i++) { - EQ_Handle h = f_root->add_EQ(); - //if (i < levels[0]) { - if (i <= levels[levels.size() - 1]) { - h.update_coef(mapping.input_var(i), 1); - h.update_coef(mapping.output_var(i), -1); - } else { - h.update_const(-1); - h.update_coef(mapping.output_var(i), 1); - } - - /*else { - int j; - for (j = 0; j < levels.size(); j++) - if (i == levels[j]) - break; - - if (j == levels.size()) { - - h.update_coef(mapping.output_var(i), 1); - h.update_const(-1); - - } else { - - - h.update_coef(mapping.input_var(i), 1); - h.update_coef(mapping.output_var(i), -1); - - - } - */ - //} - } - - mapping.simplify(); - // match omega input/output variables to variable names in the code - for (int j = 1; j <= init_.IS.n_set(); j++) - mapping.name_output_var(j, init_.IS.set_var(j)->name()); - for (int j = 1; j <= init_.IS.n_set(); j++) - mapping.name_input_var(j, init_.IS.set_var(j)->name()); - - mapping.setup_names(); - - init_.IS = omega::Range( - omega::Restrict_Domain(mapping, init_.IS)); - std::vector lex = getLexicalOrder(newStmt_num); - int dim = 2 * levels[0] - 1; - //init_.IS.print(); - // init_.xform.print(); - //stmt[newStmt_num].xform.print(); - // shiftLexicalOrder(lex, dim + 1, 1); - shiftLexicalOrder(lex, dim + 1, 1); - init_.reduction = stmt[newStmt_num].reduction; - init_.reductionOp = stmt[newStmt_num].reductionOp; - - init_.code = ir->builder()->CreateAssignment(0, temp->clone(), - ir->builder()->CreateInt(0)); - - fprintf(stderr, "loop.cc L3693 adding stmt %d\n", stmt.size()); - stmt.push_back(init_); - - uninterpreted_symbols.push_back(uninterpreted_symbols[newStmt_num]); - uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[newStmt_num]); - stmt[stmt_num].code = assignment; - } - } else { - if (assign_then_accumulate) { - stmt[newStmt_num].code = ir->builder()->CreateAssignment(0, - tmp_ptr_array_ref->convert(), rhs); - ir->ReplaceRHSExpression(stmt[stmt_num].code, - tmp_ptr_array_ref); - } else { - CG_outputRepr *temp = tmp_ptr_array_ref->convert()->clone(); - if (ir->QueryExpOperation(stmt[stmt_num].code) - != IR_OP_PLUS_ASSIGNMENT) - throw ir_error( - "Statement is not a += accumulation statement"); - stmt[newStmt_num].code = ir->builder()->CreatePlusAssignment(0, - temp->clone(), rhs); - - CG_outputRepr * lhs = ir->GetLHSExpression(stmt[stmt_num].code); - - CG_outputRepr *assignment = ir->builder()->CreateAssignment(0, - lhs, temp->clone()); - - stmt[stmt_num].code = assignment; - } - // call function to replace rhs with temporary array - } - } - - //std::cout << "End of scalar_expand function!! \n"; - - // if(arrName == "RHS"){ - DependenceVector dv; - std::vector E; - dv.lbounds = std::vector(4); - dv.ubounds = std::vector(4); - dv.type = DEP_W2R; - - for (int k = 0; k < 4; k++) { - dv.lbounds[k] = 0; - dv.ubounds[k] = 0; - - } - - //std::vector array_refs = ir->FindArrayRef(stmt[newStmt_num].code); - dv.sym = tmp_sym->clone(); - - E.push_back(dv); - - dep.connect(newStmt_num, stmt_num, E); - // } - -} - - - - -std::pair createCSRstyleISandXFORM(CG_outputBuilder *ocg, - std::vector &outer_loop_bounds, std::string index_name, - std::map &zero_loop_bounds, - std::map > &uninterpreted_symbols, - std::map > &uninterpreted_symbols_string, - Loop *this_loop) { - - Relation IS(outer_loop_bounds.size() + 1 + zero_loop_bounds.size()); - Relation XFORM(outer_loop_bounds.size() + 1 + zero_loop_bounds.size(), - 2 * (outer_loop_bounds.size() + 1 + zero_loop_bounds.size()) + 1); - - F_And * f_r_ = IS.add_and(); - F_And * f_root = XFORM.add_and(); - - if (outer_loop_bounds.size() > 0) { - for (int it = 0; it < IS.n_set(); it++) { - IS.name_set_var(it + 1, - const_cast(outer_loop_bounds[0]).set_var(it + 1)->name()); - XFORM.name_input_var(it + 1, - const_cast(outer_loop_bounds[0]).set_var(it + 1)->name()); - - } - } else if (zero_loop_bounds.size() > 0) { - for (int it = 0; it < IS.n_set(); it++) { - IS.name_set_var(it + 1, - const_cast(zero_loop_bounds.begin()->second).set_var( - it + 1)->name()); - XFORM.name_input_var(it + 1, - const_cast(zero_loop_bounds.begin()->second).set_var( - it + 1)->name()); - - } - - } - - for (int i = 0; i < outer_loop_bounds.size(); i++) - IS = replace_set_var_as_another_set_var(IS, outer_loop_bounds[i], i + 1, - i + 1); - - int count = 1; - for (std::map::iterator i = zero_loop_bounds.begin(); - i != zero_loop_bounds.end(); i++, count++) - IS = replace_set_var_as_another_set_var(IS, i->second, - outer_loop_bounds.size() + 1 + count, i->first); - - if (outer_loop_bounds.size() > 0) { - Free_Var_Decl *lb = new Free_Var_Decl(index_name + "_", 1); // index_ - Variable_ID csr_lb = IS.get_local(lb, Input_Tuple); - - Free_Var_Decl *ub = new Free_Var_Decl(index_name + "__", 1); // index__ - Variable_ID csr_ub = IS.get_local(ub, Input_Tuple); - - //lower bound - - F_And * f_r = IS.and_with_and(); - GEQ_Handle lower_bound = f_r->add_GEQ(); - lower_bound.update_coef(csr_lb, -1); - lower_bound.update_coef(IS.set_var(outer_loop_bounds.size() + 1), 1); - - //upper bound - - GEQ_Handle upper_bound = f_r->add_GEQ(); - upper_bound.update_coef(csr_ub, 1); - upper_bound.update_coef(IS.set_var(outer_loop_bounds.size() + 1), -1); - upper_bound.update_const(-1); - - omega::CG_stringBuilder *ocgs = new CG_stringBuilder; - - std::vector reprs; - std::vector reprs2; - - std::vector reprs3; - std::vector reprs4; - - reprs.push_back( - ocg->CreateIdent(IS.set_var(outer_loop_bounds.size())->name())); - reprs2.push_back( - ocgs->CreateIdent( - IS.set_var(outer_loop_bounds.size())->name())); - uninterpreted_symbols.insert( - std::pair >( - index_name + "_", reprs)); - uninterpreted_symbols_string.insert( - std::pair >( - index_name + "_", reprs2)); - - std::string arg = "(" + IS.set_var(outer_loop_bounds.size())->name() - + ")"; - std::vector< std::string > argvec; - argvec.push_back( arg ); - - CG_outputRepr *repr = ocg->CreateArrayRefExpression(index_name, - ocg->CreateIdent(IS.set_var(outer_loop_bounds.size())->name())); - - //fprintf(stderr, "( VECTOR _)\n"); - //fprintf(stderr, "loop.cc calling CreateDefineMacro( %s, argvec, repr)\n", (index_name + "_").c_str()); - this_loop->ir->CreateDefineMacro(index_name + "_", argvec, repr); - - Relation known_(copy(IS).n_set()); - known_.copy_names(copy(IS)); - known_.setup_names(); - Variable_ID index_lb = known_.get_local(lb, Input_Tuple); - Variable_ID index_ub = known_.get_local(ub, Input_Tuple); - F_And *fr = known_.add_and(); - GEQ_Handle g = fr->add_GEQ(); - g.update_coef(index_ub, 1); - g.update_coef(index_lb, -1); - g.update_const(-1); - this_loop->addKnown(known_); - - reprs3.push_back( - - ocg->CreateIdent(IS.set_var(outer_loop_bounds.size())->name())); - reprs4.push_back( - - ocgs->CreateIdent(IS.set_var(outer_loop_bounds.size())->name())); - - CG_outputRepr *repr2 = ocg->CreateArrayRefExpression(index_name, - ocg->CreatePlus( - ocg->CreateIdent( - IS.set_var(outer_loop_bounds.size())->name()), - ocg->CreateInt(1))); - - //fprintf(stderr, "( VECTOR __)\n"); - //fprintf(stderr, "loop.cc calling CreateDefineMacro( %s, argvec, repr)\n", (index_name + "__").c_str()); - - this_loop->ir->CreateDefineMacro(index_name + "__", argvec, repr2); - - uninterpreted_symbols.insert( - std::pair >( - index_name + "__", reprs3)); - uninterpreted_symbols_string.insert( - std::pair >( - index_name + "__", reprs4)); - } else { - Free_Var_Decl *ub = new Free_Var_Decl(index_name); - Variable_ID csr_ub = IS.get_local(ub); - F_And * f_r = IS.and_with_and(); - GEQ_Handle upper_bound = f_r->add_GEQ(); - upper_bound.update_coef(csr_ub, 1); - upper_bound.update_coef(IS.set_var(outer_loop_bounds.size() + 1), -1); - upper_bound.update_const(-1); - - GEQ_Handle lower_bound = f_r->add_GEQ(); - lower_bound.update_coef(IS.set_var(outer_loop_bounds.size() + 1), 1); - - } - - for (int j = 1; j <= XFORM.n_inp(); j++) { - omega::EQ_Handle h = f_root->add_EQ(); - h.update_coef(XFORM.output_var(2 * j), 1); - h.update_coef(XFORM.input_var(j), -1); - } - - for (int j = 1; j <= XFORM.n_out(); j += 2) { - omega::EQ_Handle h = f_root->add_EQ(); - h.update_coef(XFORM.output_var(j), 1); - } - - if (_DEBUG_) { - IS.print(); - XFORM.print(); - - } - - return std::pair(IS, XFORM); - -} - -std::pair construct_reduced_IS_And_XFORM(IR_Code *ir, - const Relation &is, const Relation &xform, const std::vector loops, - std::vector &lex_order, Relation &known, - std::map > &uninterpreted_symbols) { - - Relation IS(loops.size()); - Relation XFORM(loops.size(), 2 * loops.size() + 1); - int count_ = 1; - std::map pos_mapping; - - int n = is.n_set(); - Relation is_and_known = Intersection(copy(is), - Extend_Set(copy(known), n - known.n_set())); - - for (int it = 0; it < loops.size(); it++, count_++) { - IS.name_set_var(count_, - const_cast(is).set_var(loops[it])->name()); - XFORM.name_input_var(count_, - const_cast(xform).input_var(loops[it])->name()); - XFORM.name_output_var(2 * count_, - const_cast(xform).output_var((loops[it]) * 2)->name()); - XFORM.name_output_var(2 * count_ - 1, - const_cast(xform).output_var((loops[it]) * 2 - 1)->name()); - pos_mapping.insert(std::pair(count_, loops[it])); - } - - XFORM.name_output_var(2 * loops.size() + 1, - const_cast(xform).output_var(is.n_set() * 2 + 1)->name()); - - F_And * f_r = IS.add_and(); - for (std::map::iterator it = pos_mapping.begin(); - it != pos_mapping.end(); it++) - IS = replace_set_var_as_another_set_var(IS, is_and_known, it->first, - it->second); - /* - for (std::map >::iterator it2 = - uninterpreted_symbols.begin(); - it2 != uninterpreted_symbols.end(); it2++) { - std::vector reprs_ = it2->second; - //std::vector reprs_2; - - for (int k = 0; k < reprs_.size(); k++) { - std::vector refs = ir->FindScalarRef(reprs_[k]); - bool exception_found = false; - for (int m = 0; m < refs.size(); m++){ - - if (refs[m]->name() - == const_cast(is).set_var(it->second)->name()) - try { - ir->ReplaceExpression(refs[m], - ir->builder()->CreateIdent( - IS.set_var(it->first)->name())); - } catch (ir_error &e) { - - reprs_[k] = ir->builder()->CreateIdent( - IS.set_var(it->first)->name()); - exception_found = true; - } - if(exception_found) - break; - } - - } - it2->second = reprs_; - } - - } - */ - if (_DEBUG_) { - std::cout << "relation debug" << std::endl; - IS.print(); - } - - F_And *f_root = XFORM.add_and(); - - count_ = 1; - - for (int j = 1; j <= loops.size(); j++) { - omega::EQ_Handle h = f_root->add_EQ(); - h.update_coef(XFORM.output_var(2 * j), 1); - h.update_coef(XFORM.input_var(j), -1); - } - for (int j = 0; j < loops.size(); j++, count_++) { - omega::EQ_Handle h = f_root->add_EQ(); - h.update_coef(XFORM.output_var(count_ * 2 - 1), 1); - h.update_const(-lex_order[count_ * 2 - 2]); - } - - omega::EQ_Handle h = f_root->add_EQ(); - h.update_coef(XFORM.output_var((loops.size()) * 2 + 1), 1); - h.update_const(-lex_order[xform.n_out() - 1]); - - if (_DEBUG_) { - std::cout << "relation debug" << std::endl; - IS.print(); - XFORM.print(); - } - - return std::pair(IS, XFORM); - -} - -std::set inspect_repr_for_scalars(IR_Code *ir, - CG_outputRepr * repr, std::set ignore) { - - std::vector refs = ir->FindScalarRef(repr); - std::set loop_vars; - - for (int i = 0; i < refs.size(); i++) - if (ignore.find(refs[i]->name()) == ignore.end()) - loop_vars.insert(refs[i]->name()); - - return loop_vars; - -} - -std::set inspect_loop_bounds(IR_Code *ir, const Relation &R, - int pos, - std::map > &uninterpreted_symbols) { - - if (!R.is_set()) - throw loop_error("Input R has to be a set not a relation!"); - - std::set vars; - - std::vector refs; - Variable_ID v = const_cast(R).set_var(pos); - for (DNF_Iterator di(const_cast(R).query_DNF()); di; di++) { - for (GEQ_Iterator gi = (*di)->GEQs(); gi; gi++) { - if ((*gi).get_coef(v) != 0 && (*gi).is_const_except_for_global(v)) { - for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { - Variable_ID v = cvi.curr_var(); - switch (v->kind()) { - - case Global_Var: { - Global_Var_ID g = v->get_global_var(); - Variable_ID v2; - if (g->arity() > 0) { - - std::string s = g->base_name(); - std::copy( - uninterpreted_symbols.find(s)->second.begin(), - uninterpreted_symbols.find(s)->second.end(), - back_inserter(refs)); - - } - - break; - } - default: - break; - } - } - - } - } - } - - for (int i = 0; i < refs.size(); i++) { - std::vector refs_ = ir->FindScalarRef(refs[i]); - - for (int j = 0; j < refs_.size(); j++) - vars.insert(refs_[j]->name()); - - } - return vars; -} - -CG_outputRepr * create_counting_loop_body(IR_Code *ir, const Relation &R, - int pos, CG_outputRepr * count, - std::map > &uninterpreted_symbols) { - - if (!R.is_set()) - throw loop_error("Input R has to be a set not a relation!"); - - CG_outputRepr *ub, *lb; - ub = NULL; - lb = NULL; - std::vector refs; - Variable_ID v = const_cast(R).set_var(pos); - for (DNF_Iterator di(const_cast(R).query_DNF()); di; di++) { - for (GEQ_Iterator gi = (*di)->GEQs(); gi; gi++) { - if ((*gi).get_coef(v) != 0 && (*gi).is_const_except_for_global(v)) { - bool same_ge_1 = false; - bool same_ge_2 = false; - for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { - Variable_ID v = cvi.curr_var(); - switch (v->kind()) { - - case Global_Var: { - Global_Var_ID g = v->get_global_var(); - Variable_ID v2; - if (g->arity() > 0) { - - std::string s = g->base_name(); - - if ((*gi).get_coef(v) > 0) { - if (ub != NULL) - throw ir_error( - "bound expression too complex!"); - - ub = ir->builder()->CreateInvoke(s, - uninterpreted_symbols.find(s)->second); - //ub = ir->builder()->CreateMinus(ub->clone(), ir->builder()->CreateInt(-(*gi).get_const())); - same_ge_1 = true; - - } else { - if (lb != NULL) - throw ir_error( - "bound expression too complex!"); - lb = ir->builder()->CreateInvoke(s, - uninterpreted_symbols.find(s)->second); - same_ge_2 = true; - - } - } - - break; - } - default: - break; - } - } - - if (same_ge_1 && same_ge_2) - lb = ir->builder()->CreatePlus(lb->clone(), - ir->builder()->CreateInt(-(*gi).get_const())); - else if (same_ge_1) - ub = ir->builder()->CreatePlus(ub->clone(), - ir->builder()->CreateInt(-(*gi).get_const())); - else if (same_ge_2) - lb = ir->builder()->CreatePlus(lb->clone(), - ir->builder()->CreateInt(-(*gi).get_const())); - } - } - - } - - return ir->builder()->CreatePlusAssignment(0, count, - ir->builder()->CreatePlus( - ir->builder()->CreateMinus(ub->clone(), lb->clone()), - ir->builder()->CreateInt(1))); -} - - - -std::map > recurse_on_exp_for_arrays( - IR_Code * ir, CG_outputRepr * exp) { - - std::map > arr_index_to_ref; - switch (ir->QueryExpOperation(exp)) { - - case IR_OP_ARRAY_VARIABLE: { - IR_ArrayRef *ref = dynamic_cast(ir->Repr2Ref(exp)); - IR_PointerArrayRef *ref_ = - dynamic_cast(ir->Repr2Ref(exp)); - if (ref == NULL && ref_ == NULL) - throw loop_error("Array symbol unidentifiable!"); - - if (ref != NULL) { - std::vector s0; - - for (int i = 0; i < ref->n_dim(); i++) { - CG_outputRepr * index = ref->index(i); - std::map > a0 = - recurse_on_exp_for_arrays(ir, index); - std::vector s; - for (std::map >::iterator j = - a0.begin(); j != a0.end(); j++) { - if (j->second.size() != 1 && (j->second)[0] != "") - throw loop_error( - "indirect array references not allowed in guard!"); - s.push_back(j->first); - } - std::copy(s.begin(), s.end(), back_inserter(s0)); - } - arr_index_to_ref.insert( - std::pair >( - ref->name(), s0)); - } else { - std::vector s0; - for (int i = 0; i < ref_->n_dim(); i++) { - CG_outputRepr * index = ref_->index(i); - std::map > a0 = - recurse_on_exp_for_arrays(ir, index); - std::vector s; - for (std::map >::iterator j = - a0.begin(); j != a0.end(); j++) { - if (j->second.size() != 1 && (j->second)[0] != "") - throw loop_error( - "indirect array references not allowed in guard!"); - s.push_back(j->first); - } - std::copy(s.begin(), s.end(), back_inserter(s0)); - } - arr_index_to_ref.insert( - std::pair >( - ref_->name(), s0)); - } - break; - } - case IR_OP_PLUS: - case IR_OP_MINUS: - case IR_OP_MULTIPLY: - case IR_OP_DIVIDE: { - std::vector v = ir->QueryExpOperand(exp); - std::map > a0 = - recurse_on_exp_for_arrays(ir, v[0]); - std::map > a1 = - recurse_on_exp_for_arrays(ir, v[1]); - arr_index_to_ref.insert(a0.begin(), a0.end()); - arr_index_to_ref.insert(a1.begin(), a1.end()); - break; - - } - case IR_OP_POSITIVE: - case IR_OP_NEGATIVE: { - std::vector v = ir->QueryExpOperand(exp); - std::map > a0 = - recurse_on_exp_for_arrays(ir, v[0]); - - arr_index_to_ref.insert(a0.begin(), a0.end()); - break; - - } - case IR_OP_VARIABLE: { - std::vector v = ir->QueryExpOperand(exp); - IR_ScalarRef *ref = static_cast(ir->Repr2Ref(v[0])); - - std::string s = ref->name(); - std::vector to_insert; - to_insert.push_back(""); - arr_index_to_ref.insert( - std::pair >(s, - to_insert)); - break; - } - case IR_OP_CONSTANT: - break; - - default: { - std::vector v = ir->QueryExpOperand(exp); - - for (int i = 0; i < v.size(); i++) { - std::map > a0 = - recurse_on_exp_for_arrays(ir, v[i]); - - arr_index_to_ref.insert(a0.begin(), a0.end()); - } - - break; - } - } - return arr_index_to_ref; -} - - - -std::vector find_guards(IR_Code *ir, IR_Control *code) { - fprintf(stderr, "find_guards()\n"); - std::vector guards; - switch (code->type()) { - case IR_CONTROL_IF: { - fprintf(stderr, "find_guards() it's an if\n"); - CG_outputRepr *cond = dynamic_cast(code)->condition(); - - std::vector then_body; - std::vector else_body; - IR_Block *ORTB = dynamic_cast(code)->then_body(); - if (ORTB != NULL) { - fprintf(stderr, "recursing on then\n"); - then_body = find_guards(ir, ORTB); - //dynamic_cast(code)->then_body()); - } - if (dynamic_cast(code)->else_body() != NULL) { - fprintf(stderr, "recursing on then\n"); - else_body = find_guards(ir, - dynamic_cast(code)->else_body()); - } - - guards.push_back(cond); - if (then_body.size() > 0) - std::copy(then_body.begin(), then_body.end(), - back_inserter(guards)); - if (else_body.size() > 0) - std::copy(else_body.begin(), else_body.end(), - back_inserter(guards)); - break; - } - case IR_CONTROL_BLOCK: { - fprintf(stderr, "find_guards() it's a control block\n"); - IR_Block* IRCB = dynamic_cast(code); - fprintf(stderr, "find_guards() calling ir->FindOneLevelControlStructure(IRCB);\n"); - std::vector stmts = ir->FindOneLevelControlStructure(IRCB); - - for (int i = 0; i < stmts.size(); i++) { - std::vector stmt_repr = find_guards(ir, stmts[i]); - std::copy(stmt_repr.begin(), stmt_repr.end(), - back_inserter(guards)); - } - break; - } - case IR_CONTROL_LOOP: { - fprintf(stderr, "find_guards() it's a control loop\n"); - std::vector body = find_guards(ir, - dynamic_cast(code)->body()); - if (body.size() > 0) - std::copy(body.begin(), body.end(), back_inserter(guards)); - break; - } // loop - } // switch - return guards; -} - -bool sort_helper(std::pair > i, - std::pair > j) { - int c1 = 0; - int c2 = 0; - for (int k = 0; k < i.second.size(); k++) - if (i.second[k] != "") - c1++; - - for (int k = 0; k < j.second.size(); k++) - if (j.second[k] != "") - c2++; - return (c1 < c2); - -} - -bool sort_helper_2(std::pair i, std::pair j) { - - return (i.second < j.second); - -} - -std::vector construct_iteration_order( - std::map > & input) { - std::vector arrays; - std::vector scalars; - std::vector > > input_aid; - - for (std::map >::iterator j = - input.begin(); j != input.end(); j++) - input_aid.push_back( - std::pair >(j->first, - j->second)); - - std::sort(input_aid.begin(), input_aid.end(), sort_helper); - - for (int j = 0; j < input_aid[input_aid.size() - 1].second.size(); j++) - if (input_aid[input_aid.size() - 1].second[j] != "") { - arrays.push_back(input_aid[input_aid.size() - 1].second[j]); - - } - - if (arrays.size() > 0) { - for (int i = input_aid.size() - 2; i >= 0; i--) { - - int max_count = 0; - for (int j = 0; j < input_aid[i].second.size(); j++) - if (input_aid[i].second[j] != "") { - max_count++; - } - if (max_count > 0) { - for (int j = 0; j < max_count; j++) { - std::string s = input_aid[i].second[j]; - bool found = false; - for (int k = 0; k < max_count; k++) - if (s == arrays[k]) - found = true; - if (!found) - throw loop_error("guard condition not solvable"); - } - } else { - bool found = false; - for (int k = 0; k < arrays.size(); k++) - if (arrays[k] == input_aid[i].first) - found = true; - if (!found) - arrays.push_back(input_aid[i].first); - } - } - } else { - - for (int i = input_aid.size() - 1; i >= 0; i--) { - arrays.push_back(input_aid[i].first); - } - } - return arrays; -} - - - diff --git a/src/loop_basic.cc b/src/loop_basic.cc deleted file mode 100644 index a058598..0000000 --- a/src/loop_basic.cc +++ /dev/null @@ -1,1839 +0,0 @@ -/* - * loop_basic.cc - * - * Created on: Nov 12, 2012 - * Author: anand - */ - -#include "loop.hh" -#include "chill_error.hh" -#include -#include "omegatools.hh" -#include - -#include - -using namespace omega; - -void Loop::permute(const std::vector &pi) { - std::set active; - for (int i = 0; i < stmt.size(); i++) - active.insert(i); - - permute(active, pi); -} - -void Loop::original() { - std::set active; - for (int i = 0; i < stmt.size(); i++) - active.insert(i); - setLexicalOrder(0, active); - //apply_xform(); -} -void Loop::permute(int stmt_num, int level, const std::vector &pi) { - // check for sanity of parameters - int starting_order; - if (stmt_num < 0 || stmt_num >= stmt.size()) - throw std::invalid_argument( - "invalid statement number " + to_string(stmt_num)); - std::set active; - if (level < 0 || level > stmt[stmt_num].loop_level.size()) - throw std::invalid_argument("3invalid loop level " + to_string(level)); - else if (level == 0) { - for (int i = 0; i < stmt.size(); i++) - active.insert(i); - level = 1; - starting_order = 0; - } else { - std::vector lex = getLexicalOrder(stmt_num); - active = getStatements(lex, 2 * level - 2); - starting_order = lex[2 * level - 2]; - lex[2 * level - 2]++; - shiftLexicalOrder(lex, 2 * level - 2, active.size() - 1); - } - std::vector pi_inverse(pi.size(), 0); - for (int i = 0; i < pi.size(); i++) { - if (pi[i] >= level + pi.size() || pi[i] < level - || pi_inverse[pi[i] - level] != 0) - throw std::invalid_argument("invalid permuation"); - pi_inverse[pi[i] - level] = level + i; - } - for (std::set::iterator i = active.begin(); i != active.end(); i++) - if (level + pi.size() - 1 > stmt[*i].loop_level.size()) - throw std::invalid_argument( - "invalid permutation for statement " + to_string(*i)); - - // invalidate saved codegen computation - delete last_compute_cgr_; - last_compute_cgr_ = NULL; - delete last_compute_cg_; - last_compute_cg_ = NULL; - - // Update transformation relations - for (std::set::iterator i = active.begin(); i != active.end(); i++) { - int n = stmt[*i].xform.n_out(); - Relation mapping(n, n); - F_And *f_root = mapping.add_and(); - for (int j = 1; j <= 2 * level - 2; j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(j), 1); - h.update_coef(mapping.input_var(j), -1); - } - for (int j = level; j <= level + pi.size() - 1; j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(2 * j), 1); - h.update_coef(mapping.input_var(2 * pi[j - level]), -1); - } - for (int j = level; j <= level + pi.size() - 1; j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(2 * j - 1), 1); - h.update_coef(mapping.input_var(2 * j - 1), -1); - } - for (int j = 2 * (level + pi.size() - 1) + 1; j <= n; j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(j), 1); - h.update_coef(mapping.input_var(j), -1); - } - stmt[*i].xform = Composition(mapping, stmt[*i].xform); - stmt[*i].xform.simplify(); - } - - // get the permuation for dependence vectors - std::vector t; - for (int i = 0; i < pi.size(); i++) - if (stmt[stmt_num].loop_level[pi[i] - 1].type == LoopLevelOriginal) - t.push_back(stmt[stmt_num].loop_level[pi[i] - 1].payload); - int max_dep_dim = -1; - int min_dep_dim = dep.num_dim(); - for (int i = 0; i < t.size(); i++) { - if (t[i] > max_dep_dim) - max_dep_dim = t[i]; - if (t[i] < min_dep_dim) - min_dep_dim = t[i]; - } - if (min_dep_dim > max_dep_dim) - return; - if (max_dep_dim - min_dep_dim + 1 != t.size()) - throw loop_error("cannot update the dependence graph after permuation"); - std::vector dep_pi(dep.num_dim()); - for (int i = 0; i < min_dep_dim; i++) - dep_pi[i] = i; - for (int i = min_dep_dim; i <= max_dep_dim; i++) - dep_pi[i] = t[i - min_dep_dim]; - for (int i = max_dep_dim + 1; i < dep.num_dim(); i++) - dep_pi[i] = i; - - dep.permute(dep_pi, active); - - // update the dependence graph - DependenceGraph g(dep.num_dim()); - for (int i = 0; i < dep.vertex.size(); i++) - g.insert(); - for (int i = 0; i < dep.vertex.size(); i++) - for (DependenceGraph::EdgeList::iterator j = - dep.vertex[i].second.begin(); j != dep.vertex[i].second.end(); - j++) { - if ((active.find(i) != active.end() - && active.find(j->first) != active.end())) { - std::vector dv = j->second; - for (int k = 0; k < dv.size(); k++) { - switch (dv[k].type) { - case DEP_W2R: - case DEP_R2W: - case DEP_W2W: - case DEP_R2R: { - std::vector lbounds(dep.num_dim()); - std::vector ubounds(dep.num_dim()); - for (int d = 0; d < dep.num_dim(); d++) { - lbounds[d] = dv[k].lbounds[dep_pi[d]]; - ubounds[d] = dv[k].ubounds[dep_pi[d]]; - } - dv[k].lbounds = lbounds; - dv[k].ubounds = ubounds; - break; - } - case DEP_CONTROL: { - break; - } - default: - throw loop_error("unknown dependence type"); - } - } - g.connect(i, j->first, dv); - } else if (active.find(i) == active.end() - && active.find(j->first) == active.end()) { - std::vector dv = j->second; - g.connect(i, j->first, dv); - } else { - std::vector dv = j->second; - for (int k = 0; k < dv.size(); k++) - switch (dv[k].type) { - case DEP_W2R: - case DEP_R2W: - case DEP_W2W: - case DEP_R2R: { - for (int d = 0; d < dep.num_dim(); d++) - if (dep_pi[d] != d) { - dv[k].lbounds[d] = -posInfinity; - dv[k].ubounds[d] = posInfinity; - } - break; - } - case DEP_CONTROL: - break; - default: - throw loop_error("unknown dependence type"); - } - g.connect(i, j->first, dv); - } - } - dep = g; - - // update loop level information - for (std::set::iterator i = active.begin(); i != active.end(); i++) { - int cur_dep_dim = min_dep_dim; - std::vector new_loop_level(stmt[*i].loop_level.size()); - for (int j = 1; j <= stmt[*i].loop_level.size(); j++) - if (j >= level && j < level + pi.size()) { - switch (stmt[*i].loop_level[pi_inverse[j - level] - 1].type) { - case LoopLevelOriginal: - new_loop_level[j - 1].type = LoopLevelOriginal; - new_loop_level[j - 1].payload = cur_dep_dim++; - new_loop_level[j - 1].parallel_level = - stmt[*i].loop_level[pi_inverse[j - level] - 1].parallel_level; - break; - case LoopLevelTile: { - new_loop_level[j - 1].type = LoopLevelTile; - int ref_level = stmt[*i].loop_level[pi_inverse[j - level] - - 1].payload; - if (ref_level >= level && ref_level < level + pi.size()) - new_loop_level[j - 1].payload = pi_inverse[ref_level - - level]; - else - new_loop_level[j - 1].payload = ref_level; - new_loop_level[j - 1].parallel_level = stmt[*i].loop_level[j - - 1].parallel_level; - break; - } - default: - throw loop_error( - "unknown loop level information for statement " - + to_string(*i)); - } - } else { - switch (stmt[*i].loop_level[j - 1].type) { - case LoopLevelOriginal: - new_loop_level[j - 1].type = LoopLevelOriginal; - new_loop_level[j - 1].payload = - stmt[*i].loop_level[j - 1].payload; - new_loop_level[j - 1].parallel_level = stmt[*i].loop_level[j - - 1].parallel_level; - break; - case LoopLevelTile: { - new_loop_level[j - 1].type = LoopLevelTile; - int ref_level = stmt[*i].loop_level[j - 1].payload; - if (ref_level >= level && ref_level < level + pi.size()) - new_loop_level[j - 1].payload = pi_inverse[ref_level - - level]; - else - new_loop_level[j - 1].payload = ref_level; - new_loop_level[j - 1].parallel_level = stmt[*i].loop_level[j - - 1].parallel_level; - break; - } - default: - throw loop_error( - "unknown loop level information for statement " - + to_string(*i)); - } - } - stmt[*i].loop_level = new_loop_level; - } - - setLexicalOrder(2 * level - 2, active, starting_order); -} -void Loop::permute(const std::set &active, const std::vector &pi) { - if (active.size() == 0 || pi.size() == 0) - return; - - // check for sanity of parameters - int level = pi[0]; - for (int i = 1; i < pi.size(); i++) - if (pi[i] < level) - level = pi[i]; - if (level < 1) - throw std::invalid_argument("invalid permuation"); - std::vector reverse_pi(pi.size(), 0); - for (int i = 0; i < pi.size(); i++) - if (pi[i] >= level + pi.size()) - throw std::invalid_argument("invalid permutation"); - else - reverse_pi[pi[i] - level] = i + level; - for (int i = 0; i < reverse_pi.size(); i++) - if (reverse_pi[i] == 0) - throw std::invalid_argument("invalid permuation"); - int ref_stmt_num; - std::vector lex; - for (std::set::iterator i = active.begin(); i != active.end(); i++) { - if (*i < 0 || *i >= stmt.size()) - throw std::invalid_argument("invalid statement " + to_string(*i)); - if (i == active.begin()) { - ref_stmt_num = *i; - lex = getLexicalOrder(*i); - } else { - if (level + pi.size() - 1 > stmt[*i].loop_level.size()) - throw std::invalid_argument("invalid permuation"); - std::vector lex2 = getLexicalOrder(*i); - for (int j = 0; j < 2 * level - 3; j += 2) - if (lex[j] != lex2[j]) - throw std::invalid_argument( - "statements to permute must be in the same subloop"); - for (int j = 0; j < pi.size(); j++) - if (!(stmt[*i].loop_level[level + j - 1].type - == stmt[ref_stmt_num].loop_level[level + j - 1].type - && stmt[*i].loop_level[level + j - 1].payload - == stmt[ref_stmt_num].loop_level[level + j - 1].payload)) - throw std::invalid_argument( - "permuted loops must have the same loop level types"); - } - } - // invalidate saved codegen computation - delete last_compute_cgr_; - last_compute_cgr_ = NULL; - delete last_compute_cg_; - last_compute_cg_ = NULL; - - // Update transformation relations - for (std::set::iterator i = active.begin(); i != active.end(); i++) { - int n = stmt[*i].xform.n_out(); - Relation mapping(n, n); - F_And *f_root = mapping.add_and(); - for (int j = 1; j <= n; j += 2) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(j), 1); - h.update_coef(mapping.input_var(j), -1); - } - for (int j = 0; j < pi.size(); j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(2 * (level + j)), 1); - h.update_coef(mapping.input_var(2 * pi[j]), -1); - } - for (int j = 1; j < level; j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(2 * j), 1); - h.update_coef(mapping.input_var(2 * j), -1); - } - for (int j = level + pi.size(); j <= stmt[*i].loop_level.size(); j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(2 * j), 1); - h.update_coef(mapping.input_var(2 * j), -1); - } - - stmt[*i].xform = Composition(mapping, stmt[*i].xform); - stmt[*i].xform.simplify(); - } - - // get the permuation for dependence vectors - std::vector t; - for (int i = 0; i < pi.size(); i++) - if (stmt[ref_stmt_num].loop_level[pi[i] - 1].type == LoopLevelOriginal) - t.push_back(stmt[ref_stmt_num].loop_level[pi[i] - 1].payload); - int max_dep_dim = -1; - int min_dep_dim = num_dep_dim; - for (int i = 0; i < t.size(); i++) { - if (t[i] > max_dep_dim) - max_dep_dim = t[i]; - if (t[i] < min_dep_dim) - min_dep_dim = t[i]; - } - if (min_dep_dim > max_dep_dim) - return; - if (max_dep_dim - min_dep_dim + 1 != t.size()) - throw loop_error("cannot update the dependence graph after permuation"); - std::vector dep_pi(num_dep_dim); - for (int i = 0; i < min_dep_dim; i++) - dep_pi[i] = i; - for (int i = min_dep_dim; i <= max_dep_dim; i++) - dep_pi[i] = t[i - min_dep_dim]; - for (int i = max_dep_dim + 1; i < num_dep_dim; i++) - dep_pi[i] = i; - - dep.permute(dep_pi, active); - - // update the dependence graph - DependenceGraph g(dep.num_dim()); - for (int i = 0; i < dep.vertex.size(); i++) - g.insert(); - for (int i = 0; i < dep.vertex.size(); i++) - for (DependenceGraph::EdgeList::iterator j = - dep.vertex[i].second.begin(); j != dep.vertex[i].second.end(); - j++) { // - if ((active.find(i) != active.end() - && active.find(j->first) != active.end())) { - std::vector dv = j->second; - for (int k = 0; k < dv.size(); k++) { - switch (dv[k].type) { - case DEP_W2R: - case DEP_R2W: - case DEP_W2W: - case DEP_R2R: { - std::vector lbounds(num_dep_dim); - std::vector ubounds(num_dep_dim); - for (int d = 0; d < num_dep_dim; d++) { - lbounds[d] = dv[k].lbounds[dep_pi[d]]; - ubounds[d] = dv[k].ubounds[dep_pi[d]]; - } - dv[k].lbounds = lbounds; - dv[k].ubounds = ubounds; - break; - } - case DEP_CONTROL: { - break; - } - default: - throw loop_error("unknown dependence type"); - } - } - g.connect(i, j->first, dv); - } else if (active.find(i) == active.end() - && active.find(j->first) == active.end()) { - std::vector dv = j->second; - g.connect(i, j->first, dv); - } else { - std::vector dv = j->second; - for (int k = 0; k < dv.size(); k++) - switch (dv[k].type) { - case DEP_W2R: - case DEP_R2W: - case DEP_W2W: - case DEP_R2R: { - for (int d = 0; d < num_dep_dim; d++) - if (dep_pi[d] != d) { - dv[k].lbounds[d] = -posInfinity; - dv[k].ubounds[d] = posInfinity; - } - break; - } - case DEP_CONTROL: - break; - default: - throw loop_error("unknown dependence type"); - } - g.connect(i, j->first, dv); - } - } - dep = g; - - // update loop level information - for (std::set::iterator i = active.begin(); i != active.end(); i++) { - int cur_dep_dim = min_dep_dim; - std::vector new_loop_level(stmt[*i].loop_level.size()); - for (int j = 1; j <= stmt[*i].loop_level.size(); j++) - if (j >= level && j < level + pi.size()) { - switch (stmt[*i].loop_level[reverse_pi[j - level] - 1].type) { - case LoopLevelOriginal: - new_loop_level[j - 1].type = LoopLevelOriginal; - new_loop_level[j - 1].payload = cur_dep_dim++; - new_loop_level[j - 1].parallel_level = - stmt[*i].loop_level[reverse_pi[j - level] - 1].parallel_level; - break; - case LoopLevelTile: { - new_loop_level[j - 1].type = LoopLevelTile; - int ref_level = stmt[*i].loop_level[reverse_pi[j - level]-1].payload; - if (ref_level >= level && ref_level < level + pi.size()) - new_loop_level[j - 1].payload = reverse_pi[ref_level - - level]; - else - new_loop_level[j - 1].payload = ref_level; - new_loop_level[j - 1].parallel_level = - stmt[*i].loop_level[reverse_pi[j - level] - 1].parallel_level; - break; - } - default: - throw loop_error( - "unknown loop level information for statement " - + to_string(*i)); - } - } else { - switch (stmt[*i].loop_level[j - 1].type) { - case LoopLevelOriginal: - new_loop_level[j - 1].type = LoopLevelOriginal; - new_loop_level[j - 1].payload = - stmt[*i].loop_level[j - 1].payload; - new_loop_level[j - 1].parallel_level = stmt[*i].loop_level[j - - 1].parallel_level; - break; - case LoopLevelTile: { - new_loop_level[j - 1].type = LoopLevelTile; - int ref_level = stmt[*i].loop_level[j - 1].payload; - if (ref_level >= level && ref_level < level + pi.size()) - new_loop_level[j - 1].payload = reverse_pi[ref_level - - level]; - else - new_loop_level[j - 1].payload = ref_level; - new_loop_level[j - 1].parallel_level = stmt[*i].loop_level[j - - 1].parallel_level; - break; - } - default: - throw loop_error( - "unknown loop level information for statement " - + to_string(*i)); - } - } - stmt[*i].loop_level = new_loop_level; - } - - setLexicalOrder(2 * level - 2, active); -} - - -void Loop::set_array_size(std::string name, int size ){ - array_dims.insert(std::pair(name, size)); -} - - -std::set Loop::split(int stmt_num, int level, const Relation &cond) { - // check for sanity of parameters - if (stmt_num < 0 || stmt_num >= stmt.size()) - throw std::invalid_argument("invalid statement " + to_string(stmt_num)); - if (level <= 0 || level > stmt[stmt_num].loop_level.size()) - throw std::invalid_argument("4invalid loop level " + to_string(level)); - - std::set result; - int dim = 2 * level - 1; - std::vector lex = getLexicalOrder(stmt_num); - std::set same_loop = getStatements(lex, dim - 1); - - Relation cond2 = copy(cond); - cond2.simplify(); - cond2 = EQs_to_GEQs(cond2); - Conjunct *c = cond2.single_conjunct(); - int cur_lex = lex[dim - 1]; - - for (GEQ_Iterator gi(c->GEQs()); gi; gi++) { - int max_level = (*gi).max_tuple_pos(); - Relation single_cond(max_level); - single_cond.and_with_GEQ(*gi); - - // TODO: should decide where to place newly created statements with - // complementary split condition from dependence graph. - bool place_after; - if (max_level == 0) - place_after = true; - else if ((*gi).get_coef(cond2.set_var(max_level)) < 0) - place_after = true; - else - place_after = false; - - bool temp_place_after; // = place_after; - bool assigned = false; - int part1_to_part2; - int part2_to_part1; - // original statements with split condition, - // new statements with complement of split condition - int old_num_stmt = stmt.size(); - std::map what_stmt_num; - apply_xform(same_loop); - for (std::set::iterator i = same_loop.begin(); - i != same_loop.end(); i++) { - int n = stmt[*i].IS.n_set(); - Relation part1, part2; - if (max_level > n) { - part1 = copy(stmt[*i].IS); - part2 = Relation::False(0); - } else { - part1 = Intersection(copy(stmt[*i].IS), - Extend_Set(copy(single_cond), n - max_level)); - part2 = Intersection(copy(stmt[*i].IS), - Extend_Set(Complement(copy(single_cond)), - n - max_level)); - } - - //split dependence check - - if (max_level > level) { - - DNF_Iterator di1(stmt[*i].IS.query_DNF()); - DNF_Iterator di2(part1.query_DNF()); - for (; di1 && di2; di1++, di2++) { - //printf("In next conjunct,\n"); - EQ_Iterator ei1 = (*di1)->EQs(); - EQ_Iterator ei2 = (*di2)->EQs(); - for (; ei1 && ei2; ei1++, ei2++) { - //printf(" In next equality constraint,\n"); - Constr_Vars_Iter cvi1(*ei1); - Constr_Vars_Iter cvi2(*ei2); - int dimension = (*cvi1).var->get_position(); - int same = 0; - bool identical = false; - if (identical = !strcmp((*cvi1).var->char_name(), - (*cvi2).var->char_name())) { - - for (; cvi1 && cvi2; cvi1++, cvi2++) { - - if (((*cvi1).coef != (*cvi2).coef - || (*ei1).get_const() - != (*ei2).get_const()) - || (strcmp((*cvi1).var->char_name(), - (*cvi2).var->char_name()))) { - - same++; - } - } - } - if ((same != 0) || !identical) { - - dimension = dimension - 1; - - while (stmt[*i].loop_level[dimension].type - == LoopLevelTile) - dimension = - stmt[*i].loop_level[dimension].payload; - - dimension = stmt[*i].loop_level[dimension].payload; - - for (int i = 0; i < stmt.size(); i++) { - std::vector > D; - for (DependenceGraph::EdgeList::iterator j = - dep.vertex[i].second.begin(); - j != dep.vertex[i].second.end(); j++) { - for (int k = 0; k < j->second.size(); k++) { - DependenceVector dv = j->second[k]; - if (dv.type != DEP_CONTROL) - if (dv.hasNegative(dimension) - && !dv.quasi) - throw loop_error( - "loop error: Split is illegal, dependence violation!"); - - } - } - } - - } - - GEQ_Iterator gi1 = (*di1)->GEQs(); - GEQ_Iterator gi2 = (*di2)->GEQs(); - - for (; gi1 && gi2; gi++, gi2++) { - - Constr_Vars_Iter cvi1(*gi1); - Constr_Vars_Iter cvi2(*gi2); - int dimension = (*cvi1).var->get_position(); - int same = 0; - bool identical = false; - if (identical = !strcmp((*cvi1).var->char_name(), - (*cvi2).var->char_name())) { - - for (; cvi1 && cvi2; cvi1++, cvi2++) { - - if (((*cvi1).coef != (*cvi2).coef - || (*gi1).get_const() - != (*gi2).get_const()) - || (strcmp((*cvi1).var->char_name(), - (*cvi2).var->char_name()))) { - - same++; - } - } - } - if ((same != 0) || !identical) { - dimension = dimension - 1; - - while (stmt[*i].loop_level[dimension].type - == LoopLevelTile) - stmt[*i].loop_level[dimension].payload; - - dimension = - stmt[*i].loop_level[dimension].payload; - - for (int i = 0; i < stmt.size(); i++) { - std::vector > D; - for (DependenceGraph::EdgeList::iterator j = - dep.vertex[i].second.begin(); - j != dep.vertex[i].second.end(); - j++) { - for (int k = 0; k < j->second.size(); - k++) { - DependenceVector dv = j->second[k]; - if (dv.type != DEP_CONTROL) - if (dv.hasNegative(dimension) - && !dv.quasi) - - throw loop_error( - "loop error: Split is illegal, dependence violation!"); - - } - } - } - - } - - } - - } - - } - - DNF_Iterator di3(stmt[*i].IS.query_DNF()); - DNF_Iterator di4(part2.query_DNF()); // - for (; di3 && di4; di3++, di4++) { - EQ_Iterator ei1 = (*di3)->EQs(); - EQ_Iterator ei2 = (*di4)->EQs(); - for (; ei1 && ei2; ei1++, ei2++) { - Constr_Vars_Iter cvi1(*ei1); - Constr_Vars_Iter cvi2(*ei2); - int dimension = (*cvi1).var->get_position(); - int same = 0; - bool identical = false; - if (identical = !strcmp((*cvi1).var->char_name(), - (*cvi2).var->char_name())) { - - for (; cvi1 && cvi2; cvi1++, cvi2++) { - - if (((*cvi1).coef != (*cvi2).coef - || (*ei1).get_const() - != (*ei2).get_const()) - || (strcmp((*cvi1).var->char_name(), - (*cvi2).var->char_name()))) { - - same++; - } - } - } - if ((same != 0) || !identical) { - dimension = dimension - 1; - - while (stmt[*i].loop_level[dimension].type - == LoopLevelTile) - stmt[*i].loop_level[dimension].payload; - - dimension = stmt[*i].loop_level[dimension].payload; - - for (int i = 0; i < stmt.size(); i++) { - std::vector > D; - for (DependenceGraph::EdgeList::iterator j = - dep.vertex[i].second.begin(); - j != dep.vertex[i].second.end(); j++) { - for (int k = 0; k < j->second.size(); k++) { - DependenceVector dv = j->second[k]; - if (dv.type != DEP_CONTROL) - if (dv.hasNegative(dimension) - && !dv.quasi) - - throw loop_error( - "loop error: Split is illegal, dependence violation!"); - - } - } - } - - } - - } - GEQ_Iterator gi1 = (*di3)->GEQs(); - GEQ_Iterator gi2 = (*di4)->GEQs(); - - for (; gi1 && gi2; gi++, gi2++) { - Constr_Vars_Iter cvi1(*gi1); - Constr_Vars_Iter cvi2(*gi2); - int dimension = (*cvi1).var->get_position(); - int same = 0; - bool identical = false; - if (identical = !strcmp((*cvi1).var->char_name(), - (*cvi2).var->char_name())) { - - for (; cvi1 && cvi2; cvi1++, cvi2++) { - - if (((*cvi1).coef != (*cvi2).coef - || (*gi1).get_const() - != (*gi2).get_const()) - || (strcmp((*cvi1).var->char_name(), - (*cvi2).var->char_name()))) { - - same++; - } - } - } - if ((same != 0) || !identical) { - dimension = dimension - 1; - - while (stmt[*i].loop_level[dimension].type // - == LoopLevelTile) - stmt[*i].loop_level[dimension].payload; - - dimension = stmt[*i].loop_level[dimension].payload; - - for (int i = 0; i < stmt.size(); i++) { - std::vector > D; - for (DependenceGraph::EdgeList::iterator j = - dep.vertex[i].second.begin(); - j != dep.vertex[i].second.end(); j++) { - for (int k = 0; k < j->second.size(); k++) { - DependenceVector dv = j->second[k]; - if (dv.type != DEP_CONTROL) - if (dv.hasNegative(dimension) - && !dv.quasi) - - throw loop_error( - "loop error: Split is illegal, dependence violation!"); - - } - } - } - - } - - } - - } - - } - - stmt[*i].IS = part1; - - int n1 = part2.n_set(); - int m = this->known.n_set(); - Relation test; - if(m > n1) - test = Intersection(copy(this->known), - Extend_Set(copy(part2), m - part2.n_set())); - else - test = Intersection(copy(part2), - Extend_Set(copy(this->known), n1 - this->known.n_set())); - - if (test.is_upper_bound_satisfiable()) { - Statement new_stmt; - new_stmt.code = stmt[*i].code->clone(); - new_stmt.IS = part2; - new_stmt.xform = copy(stmt[*i].xform); - new_stmt.ir_stmt_node = NULL; - new_stmt.loop_level = stmt[*i].loop_level; - - new_stmt.has_inspector = stmt[*i].has_inspector; - new_stmt.reduction = stmt[*i].reduction; - new_stmt.reductionOp = stmt[*i].reductionOp; - - stmt_nesting_level_.push_back(stmt_nesting_level_[*i]); - - - if (place_after) - assign_const(new_stmt.xform, dim - 1, cur_lex + 1); - else - assign_const(new_stmt.xform, dim - 1, cur_lex - 1); - - fprintf(stderr, "loop_basic.cc L828 adding stmt %d\n", stmt.size()); - stmt.push_back(new_stmt); - - uninterpreted_symbols.push_back(uninterpreted_symbols[stmt_num]); - uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[stmt_num]); - dep.insert(); - what_stmt_num[*i] = stmt.size() - 1; - if (*i == stmt_num) - result.insert(stmt.size() - 1); - } - - } - // make adjacent lexical number available for new statements - if (place_after) { - lex[dim - 1] = cur_lex + 1; - shiftLexicalOrder(lex, dim - 1, 1); - } else { - lex[dim - 1] = cur_lex - 1; - shiftLexicalOrder(lex, dim - 1, -1); - } - // update dependence graph - int dep_dim = get_dep_dim_of(stmt_num, level); - for (int i = 0; i < old_num_stmt; i++) { - std::vector > > D; - - for (DependenceGraph::EdgeList::iterator j = - dep.vertex[i].second.begin(); - j != dep.vertex[i].second.end(); j++) { - if (same_loop.find(i) != same_loop.end()) { - if (same_loop.find(j->first) != same_loop.end()) { - if (what_stmt_num.find(i) != what_stmt_num.end() - && what_stmt_num.find(j->first) - != what_stmt_num.end()) - dep.connect(what_stmt_num[i], - what_stmt_num[j->first], j->second); - if (place_after - && what_stmt_num.find(j->first) - != what_stmt_num.end()) { - std::vector dvs; - for (int k = 0; k < j->second.size(); k++) { - DependenceVector dv = j->second[k]; - if (dv.is_data_dependence() && dep_dim != -1) { - dv.lbounds[dep_dim] = -posInfinity; - dv.ubounds[dep_dim] = posInfinity; - } - dvs.push_back(dv); - } - if (dvs.size() > 0) - D.push_back( - std::make_pair(what_stmt_num[j->first], - dvs)); - } else if (!place_after - && what_stmt_num.find(i) - != what_stmt_num.end()) { - std::vector dvs; - for (int k = 0; k < j->second.size(); k++) { - DependenceVector dv = j->second[k]; - if (dv.is_data_dependence() && dep_dim != -1) { - dv.lbounds[dep_dim] = -posInfinity; - dv.ubounds[dep_dim] = posInfinity; - } - dvs.push_back(dv); - } - if (dvs.size() > 0) - dep.connect(what_stmt_num[i], j->first, dvs); - - } - } else { - if (what_stmt_num.find(i) != what_stmt_num.end()) - dep.connect(what_stmt_num[i], j->first, j->second); - } - } else if (same_loop.find(j->first) != same_loop.end()) { - if (what_stmt_num.find(j->first) != what_stmt_num.end()) - D.push_back( - std::make_pair(what_stmt_num[j->first], - j->second)); - } - } - - for (int j = 0; j < D.size(); j++) - dep.connect(i, D[j].first, D[j].second); - } - - } - - return result; -} - -void Loop::skew(const std::set &stmt_nums, int level, - const std::vector &skew_amount) { - if (stmt_nums.size() == 0) - return; - - // check for sanity of parameters - int ref_stmt_num = *(stmt_nums.begin()); - for (std::set::const_iterator i = stmt_nums.begin(); - i != stmt_nums.end(); i++) { - if (*i < 0 || *i >= stmt.size()) - throw std::invalid_argument( - "invalid statement number " + to_string(*i)); - if (level < 1 || level > stmt[*i].loop_level.size()) - throw std::invalid_argument( - "5invalid loop level " + to_string(level)); - for (int j = stmt[*i].loop_level.size(); j < skew_amount.size(); j++) - if (skew_amount[j] != 0) - throw std::invalid_argument("invalid skewing formula"); - } - - // invalidate saved codegen computation - delete last_compute_cgr_; - last_compute_cgr_ = NULL; - delete last_compute_cg_; - last_compute_cg_ = NULL; - - // set trasformation relations - for (std::set::const_iterator i = stmt_nums.begin(); - i != stmt_nums.end(); i++) { - int n = stmt[*i].xform.n_out(); - Relation r(n, n); - F_And *f_root = r.add_and(); - for (int j = 1; j <= n; j++) - if (j != 2 * level) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(r.input_var(j), 1); - h.update_coef(r.output_var(j), -1); - } - EQ_Handle h = f_root->add_EQ(); - h.update_coef(r.output_var(2 * level), -1); - for (int j = 0; j < skew_amount.size(); j++) - if (skew_amount[j] != 0) - h.update_coef(r.input_var(2 * (j + 1)), skew_amount[j]); - - stmt[*i].xform = Composition(r, stmt[*i].xform); - stmt[*i].xform.simplify(); - } - - // update dependence graph - if (stmt[ref_stmt_num].loop_level[level - 1].type == LoopLevelOriginal) { - int dep_dim = stmt[ref_stmt_num].loop_level[level - 1].payload; - for (std::set::const_iterator i = stmt_nums.begin(); - i != stmt_nums.end(); i++) - for (DependenceGraph::EdgeList::iterator j = - dep.vertex[*i].second.begin(); - j != dep.vertex[*i].second.end(); j++) - if (stmt_nums.find(j->first) != stmt_nums.end()) { - // dependence between skewed statements - std::vector dvs = j->second; - for (int k = 0; k < dvs.size(); k++) { - DependenceVector &dv = dvs[k]; - if (dv.is_data_dependence()) { - coef_t lb = 0; - coef_t ub = 0; - for (int kk = 0; kk < skew_amount.size(); kk++) { - int cur_dep_dim = get_dep_dim_of(*i, kk + 1); - if (skew_amount[kk] > 0) { - if (lb != -posInfinity - && stmt[*i].loop_level[kk].type == LoopLevelOriginal - && dv.lbounds[cur_dep_dim] != -posInfinity) - lb += skew_amount[kk] * dv.lbounds[cur_dep_dim]; - else { - if (cur_dep_dim != -1 - && !(dv.lbounds[cur_dep_dim] == 0 - && dv.ubounds[cur_dep_dim]== 0)) - lb = -posInfinity; - } - if (ub != posInfinity - && stmt[*i].loop_level[kk].type == LoopLevelOriginal - && dv.ubounds[cur_dep_dim] != posInfinity) - ub += skew_amount[kk] * dv.ubounds[cur_dep_dim]; - else { - if (cur_dep_dim != -1 - && !(dv.lbounds[cur_dep_dim] == 0 - && dv.ubounds[cur_dep_dim] == 0)) - ub = posInfinity; - } - } else if (skew_amount[kk] < 0) { - if (lb != -posInfinity - && stmt[*i].loop_level[kk].type == LoopLevelOriginal - && dv.ubounds[cur_dep_dim] != posInfinity) - lb += skew_amount[kk] * dv.ubounds[cur_dep_dim]; - else { - if (cur_dep_dim != -1 - && !(dv.lbounds[cur_dep_dim] == 0 - && dv.ubounds[cur_dep_dim] == 0)) - lb = -posInfinity; - } - if (ub != posInfinity - && stmt[*i].loop_level[kk].type == LoopLevelOriginal - && dv.lbounds[cur_dep_dim] != -posInfinity) - ub += skew_amount[kk] * dv.lbounds[cur_dep_dim]; - else { - if (cur_dep_dim != -1 - && !(dv.lbounds[cur_dep_dim] == 0 - && dv.ubounds[cur_dep_dim] == 0)) - ub = posInfinity; - } - } - } - dv.lbounds[dep_dim] = lb; - dv.ubounds[dep_dim] = ub; - if ((dv.isCarried(dep_dim) && dv.hasPositive(dep_dim)) - && dv.quasi) - dv.quasi = false; - - if ((dv.isCarried(dep_dim) && dv.hasNegative(dep_dim)) - && !dv.quasi) - throw loop_error( - "loop error: Skewing is illegal, dependence violation!"); - dv.lbounds[dep_dim] = lb; - dv.ubounds[dep_dim] = ub; - if ((dv.isCarried(dep_dim) - && dv.hasPositive(dep_dim)) && dv.quasi) - dv.quasi = false; - - if ((dv.isCarried(dep_dim) - && dv.hasNegative(dep_dim)) && !dv.quasi) - throw loop_error( - "loop error: Skewing is illegal, dependence violation!"); - } - } - j->second = dvs; - } else { - // dependence from skewed statement to unskewed statement becomes jumbled, - // put distance value at skewed dimension to unknown - std::vector dvs = j->second; - for (int k = 0; k < dvs.size(); k++) { - DependenceVector &dv = dvs[k]; - if (dv.is_data_dependence()) { - dv.lbounds[dep_dim] = -posInfinity; - dv.ubounds[dep_dim] = posInfinity; - } - } - j->second = dvs; - } - for (int i = 0; i < dep.vertex.size(); i++) - if (stmt_nums.find(i) == stmt_nums.end()) - for (DependenceGraph::EdgeList::iterator j = - dep.vertex[i].second.begin(); - j != dep.vertex[i].second.end(); j++) - if (stmt_nums.find(j->first) != stmt_nums.end()) { - // dependence from unskewed statement to skewed statement becomes jumbled, - // put distance value at skewed dimension to unknown - std::vector dvs = j->second; - for (int k = 0; k < dvs.size(); k++) { - DependenceVector &dv = dvs[k]; - if (dv.is_data_dependence()) { - dv.lbounds[dep_dim] = -posInfinity; - dv.ubounds[dep_dim] = posInfinity; - } - } - j->second = dvs; - } - } -} - - -void Loop::shift(const std::set &stmt_nums, int level, int shift_amount) { - if (stmt_nums.size() == 0) - return; - - // check for sanity of parameters - int ref_stmt_num = *(stmt_nums.begin()); - for (std::set::const_iterator i = stmt_nums.begin(); - i != stmt_nums.end(); i++) { - if (*i < 0 || *i >= stmt.size()) - throw std::invalid_argument( - "invalid statement number " + to_string(*i)); - if (level < 1 || level > stmt[*i].loop_level.size()) - throw std::invalid_argument( - "6invalid loop level " + to_string(level)); - } - - // do nothing - if (shift_amount == 0) - return; - - // invalidate saved codegen computation - delete last_compute_cgr_; - last_compute_cgr_ = NULL; - delete last_compute_cg_; - last_compute_cg_ = NULL; - - // set trasformation relations - for (std::set::const_iterator i = stmt_nums.begin(); - i != stmt_nums.end(); i++) { - int n = stmt[*i].xform.n_out(); - - Relation r(n, n); - F_And *f_root = r.add_and(); - for (int j = 1; j <= n; j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(r.input_var(j), 1); - h.update_coef(r.output_var(j), -1); - if (j == 2 * level) - h.update_const(shift_amount); - } - - stmt[*i].xform = Composition(r, stmt[*i].xform); - stmt[*i].xform.simplify(); - } - - // update dependence graph - if (stmt[ref_stmt_num].loop_level[level - 1].type == LoopLevelOriginal) { - int dep_dim = stmt[ref_stmt_num].loop_level[level - 1].payload; - for (std::set::const_iterator i = stmt_nums.begin(); - i != stmt_nums.end(); i++) - for (DependenceGraph::EdgeList::iterator j = - dep.vertex[*i].second.begin(); - j != dep.vertex[*i].second.end(); j++) - if (stmt_nums.find(j->first) == stmt_nums.end()) { - // dependence from shifted statement to unshifted statement - std::vector dvs = j->second; - for (int k = 0; k < dvs.size(); k++) { - DependenceVector &dv = dvs[k]; - if (dv.is_data_dependence()) { - if (dv.lbounds[dep_dim] != -posInfinity) - dv.lbounds[dep_dim] -= shift_amount; - if (dv.ubounds[dep_dim] != posInfinity) - dv.ubounds[dep_dim] -= shift_amount; - } - } - j->second = dvs; - } - for (int i = 0; i < dep.vertex.size(); i++) - if (stmt_nums.find(i) == stmt_nums.end()) - for (DependenceGraph::EdgeList::iterator j = - dep.vertex[i].second.begin(); - j != dep.vertex[i].second.end(); j++) - if (stmt_nums.find(j->first) != stmt_nums.end()) { - // dependence from unshifted statement to shifted statement - std::vector dvs = j->second; - for (int k = 0; k < dvs.size(); k++) { - DependenceVector &dv = dvs[k]; - if (dv.is_data_dependence()) { - if (dv.lbounds[dep_dim] != -posInfinity) - dv.lbounds[dep_dim] += shift_amount; - if (dv.ubounds[dep_dim] != posInfinity) - dv.ubounds[dep_dim] += shift_amount; - } - } - j->second = dvs; - } - } -} - -void Loop::scale(const std::set &stmt_nums, int level, int scale_amount) { - std::vector skew_amount(level, 0); - skew_amount[level - 1] = scale_amount; - skew(stmt_nums, level, skew_amount); -} - -void Loop::reverse(const std::set &stmt_nums, int level) { - scale(stmt_nums, level, -1); -} - -void Loop::fuse(const std::set &stmt_nums, int level) { - if (stmt_nums.size() == 0 || stmt_nums.size() == 1) - return; - - // invalidate saved codegen computation - delete last_compute_cgr_; - last_compute_cgr_ = NULL; - delete last_compute_cg_; - last_compute_cg_ = NULL; - - int dim = 2 * level - 1; - // check for sanity of parameters - std::vector ref_lex; - int ref_stmt_num; - apply_xform(); - for (std::set::const_iterator i = stmt_nums.begin(); - i != stmt_nums.end(); i++) { - if (*i < 0 || *i >= stmt.size()) { - fprintf(stderr, "statement number %d should be in [0, %d)\n", *i, stmt.size()); - throw std::invalid_argument( - "FUSE invalid statement number " + to_string(*i)); - } - if (level <= 0 - // || (level > (stmt[*i].xform.n_out() - 1) / 2 - // || level > stmt[*i].loop_level.size()) - ) { - fprintf(stderr, "FUSE level %d ", level); - fprintf(stderr, "must be greater than zero and \n"); - fprintf(stderr, "must NOT be greater than (%d - 1)/2 == %d and\n", stmt[*i].xform.n_out(), (stmt[*i].xform.n_out() - 1) / 2); - fprintf(stderr, "must NOT be greater than %d\n", stmt[*i].loop_level.size()); - throw std::invalid_argument( - "FUSE invalid loop level " + to_string(level)); - } - if (ref_lex.size() == 0) { - ref_lex = getLexicalOrder(*i); - ref_stmt_num = *i; - } else { - std::vector lex = getLexicalOrder(*i); - for (int j = 0; j < dim - 1; j += 2) - if (lex[j] != ref_lex[j]) - throw std::invalid_argument( - "statements for fusion must be in the same level-" - + to_string(level - 1) + " subloop"); - } - } - - // collect lexicographical order values from to-be-fused statements - std::set lex_values; - for (std::set::const_iterator i = stmt_nums.begin(); - i != stmt_nums.end(); i++) { - std::vector lex = getLexicalOrder(*i); - lex_values.insert(lex[dim - 1]); - } - if (lex_values.size() == 1) - return; - // negative dependence would prevent fusion - - int dep_dim = get_dep_dim_of(ref_stmt_num, level); - - for (std::set::iterator i = lex_values.begin(); i != lex_values.end(); - i++) { - ref_lex[dim - 1] = *i; - std::set a = getStatements(ref_lex, dim - 1); - std::set::iterator j = i; - j++; - for (; j != lex_values.end(); j++) { - ref_lex[dim - 1] = *j; - std::set b = getStatements(ref_lex, dim - 1); - for (std::set::iterator ii = a.begin(); ii != a.end(); ii++) - for (std::set::iterator jj = b.begin(); jj != b.end(); - jj++) { - std::vector dvs; - dvs = dep.getEdge(*ii, *jj); - for (int k = 0; k < dvs.size(); k++) - if (dvs[k].isCarried(dep_dim) - && dvs[k].hasNegative(dep_dim)) - throw loop_error( - "loop error: statements " + to_string(*ii) - + " and " + to_string(*jj) - + " cannot be fused together due to negative dependence"); - dvs = dep.getEdge(*jj, *ii); - for (int k = 0; k < dvs.size(); k++) - if (dvs[k].isCarried(dep_dim) - && dvs[k].hasNegative(dep_dim)) - throw loop_error( - "loop error: statements " + to_string(*jj) - + " and " + to_string(*ii) - + " cannot be fused together due to negative dependence"); - } - } - } - - std::set same_loop = getStatements(ref_lex, dim - 3); - - std::vector > s = sort_by_same_loops(same_loop, level); - - std::vector s2; - - for (int i = 0; i < s.size(); i++) { - s2.push_back(false); - } - - for (std::set::iterator kk = stmt_nums.begin(); kk != stmt_nums.end(); - kk++) - for (int i = 0; i < s.size(); i++) - if (s[i].find(*kk) != s[i].end()) { - - s2[i] = true; - } - - try { - - //Dependence Check for Ordering Constraint - //Graph, bool> dummy = construct_induced_graph_at_level(s5, - // dep, dep_dim); - - Graph, bool> g = construct_induced_graph_at_level(s, dep, - dep_dim); - std::cout << g; - s = typed_fusion(g, s2); - } catch (const loop_error &e) { - - throw loop_error( - "statements cannot be fused together due to negative dependence"); - - } - - int order = 0; - for (int i = 0; i < s.size(); i++) { - for (std::set::iterator it = s[i].begin(); it != s[i].end(); it++) { - assign_const(stmt[*it].xform, 2 * level - 2, order); - } - order++; - } - - - //plan for selective typed fusion - - /* - 1. sort the lex values of the statements - 2. construct induced graph on sorted statements - 3. pick a node from the graph, check if it is before/after from the candidate set for fusion - equal-> set the max fused node of this node to be the start/target node for fusion - before -> augment and continue - - 4. once target node identified and is on work queue update successors and other nodes to start node - 5. augment and continue - 6. if all candidate nodes dont end up in start node throw error - 7. Get nodes and update lexical values - - */ - - /* for (std::set::iterator kk = stmt_nums.begin(); kk != stmt_nums.end(); - kk++) - for (int i = 0; i < s.size(); i++) - if (s[i].find(*kk) != s[i].end()) { - s1.insert(s[i].begin(), s[i].end()); - s2.insert(i); - } - - s3.push_back(s1); - for (int i = 0; i < s.size(); i++) - if (s2.find(i) == s2.end()) { - s3.push_back(s[i]); - s4.insert(s[i].begin(), s[i].end()); - } - try { - std::vector > s5; - s5.push_back(s1); - s5.push_back(s4); - - //Dependence Check for Ordering Constraint - //Graph, bool> dummy = construct_induced_graph_at_level(s5, - // dep, dep_dim); - - Graph, bool> g = construct_induced_graph_at_level(s3, dep, - dep_dim); - std::cout<< g; - s = typed_fusion(g); - } catch (const loop_error &e) { - - throw loop_error( - "statements cannot be fused together due to negative dependence"); - - } - - if (s3.size() == s.size()) { - int order = 0; - for (int i = 0; i < s.size(); i++) { - - for (std::set::iterator it = s[i].begin(); it != s[i].end(); - it++) { - - assign_const(stmt[*it].xform, 2 * level - 2, order); - - } - - order++; - } - } else if (s3.size() > s.size()) { - - int order = 0; - for (int j = 0; j < s.size(); j++) { - std::set::iterator it3; - for (it3 = s1.begin(); it3 != s1.end(); it3++) { - if (s[j].find(*it3) != s[j].end()) - break; - } - if (it3 != s1.end()) { - for (std::set::iterator it = s1.begin(); it != s1.end(); - it++) - assign_const(stmt[*it].xform, 2 * level - 2, order); - - order++; - - } - - for (int i = 0; i < s3.size(); i++) { - std::set::iterator it2; - - for (it2 = s3[i].begin(); it2 != s3[i].end(); it2++) { - if (s[j].find(*it2) != s[j].end()) - break; - } - - if (it2 != s3[i].end()) { - for (std::set::iterator it = s3[i].begin(); - it != s3[i].end(); it++) - assign_const(stmt[*it].xform, 2 * level - 2, order); - - order++; - - } - } - } - - } else - throw loop_error("Typed Fusion Error"); - */ -} - - - -void Loop::distribute(const std::set &stmt_nums, int level) { - if (stmt_nums.size() == 0 || stmt_nums.size() == 1) - return; - fprintf(stderr, "Loop::distribute()\n"); - - - // invalidate saved codegen computation - delete last_compute_cgr_; - last_compute_cgr_ = NULL; - delete last_compute_cg_; - last_compute_cg_ = NULL; - int dim = 2 * level - 1; - int ref_stmt_num; - // check for sanity of parameters - std::vector ref_lex; - for (std::set::const_iterator i = stmt_nums.begin(); - i != stmt_nums.end(); i++) { - if (*i < 0 || *i >= stmt.size()) - throw std::invalid_argument( - "invalid statement number " + to_string(*i)); - - if (level < 1 - || (level > (stmt[*i].xform.n_out() - 1) / 2 - || level > stmt[*i].loop_level.size())) - throw std::invalid_argument( - "8invalid loop level " + to_string(level)); - if (ref_lex.size() == 0) { - ref_lex = getLexicalOrder(*i); - ref_stmt_num = *i; - } else { - std::vector lex = getLexicalOrder(*i); - for (int j = 0; j <= dim - 1; j += 2) - if (lex[j] != ref_lex[j]) - throw std::invalid_argument( - "statements for distribution must be in the same level-" - + to_string(level) + " subloop"); - } - } - - // find SCC in the to-be-distributed loop - int dep_dim = get_dep_dim_of(ref_stmt_num, level); - std::set same_loop = getStatements(ref_lex, dim - 1); - Graph g; - for (std::set::iterator i = same_loop.begin(); i != same_loop.end(); - i++) - g.insert(*i); - for (int i = 0; i < g.vertex.size(); i++) - for (int j = i + 1; j < g.vertex.size(); j++) { - std::vector dvs; - dvs = dep.getEdge(g.vertex[i].first, g.vertex[j].first); - for (int k = 0; k < dvs.size(); k++) - if (dvs[k].isCarried(dep_dim)) { - g.connect(i, j); - break; - } - dvs = dep.getEdge(g.vertex[j].first, g.vertex[i].first); - for (int k = 0; k < dvs.size(); k++) - if (dvs[k].isCarried(dep_dim)) { - g.connect(j, i); - break; - } - } - std::vector > s = g.topoSort(); - // find statements that cannot be distributed due to dependence cycle - Graph, Empty> g2; - for (int i = 0; i < s.size(); i++) { - std::set t; - for (std::set::iterator j = s[i].begin(); j != s[i].end(); j++) - if (stmt_nums.find(g.vertex[*j].first) != stmt_nums.end()) - t.insert(g.vertex[*j].first); - if (!t.empty()) - g2.insert(t); - } - for (int i = 0; i < g2.vertex.size(); i++) - for (int j = i + 1; j < g2.vertex.size(); j++) - for (std::set::iterator ii = g2.vertex[i].first.begin(); - ii != g2.vertex[i].first.end(); ii++) - for (std::set::iterator jj = g2.vertex[j].first.begin(); - jj != g2.vertex[j].first.end(); jj++) { - std::vector dvs; - dvs = dep.getEdge(*ii, *jj); - for (int k = 0; k < dvs.size(); k++) - if (dvs[k].isCarried(dep_dim)) { - g2.connect(i, j); - break; - } - dvs = dep.getEdge(*jj, *ii); - for (int k = 0; k < dvs.size(); k++) - if (dvs[k].isCarried(dep_dim)) { - g2.connect(j, i); - break; - } - } - std::vector > s2 = g2.topoSort(); - // nothing to distribute - if (s2.size() == 1) - throw loop_error( - "loop error: no statement can be distributed due to dependence cycle"); - std::vector > s3; - for (int i = 0; i < s2.size(); i++) { - std::set t; - for (std::set::iterator j = s2[i].begin(); j != s2[i].end(); j++) - std::set_union(t.begin(), t.end(), g2.vertex[*j].first.begin(), - g2.vertex[*j].first.end(), inserter(t, t.begin())); - s3.push_back(t); - } - // associate other affected statements with the right distributed statements - for (std::set::iterator i = same_loop.begin(); i != same_loop.end(); - i++) - if (stmt_nums.find(*i) == stmt_nums.end()) { - bool is_inserted = false; - int potential_insertion_point = 0; - for (int j = 0; j < s3.size(); j++) { - for (std::set::iterator k = s3[j].begin(); - k != s3[j].end(); k++) { - std::vector dvs; - dvs = dep.getEdge(*i, *k); - for (int kk = 0; kk < dvs.size(); kk++) - if (dvs[kk].isCarried(dep_dim)) { - s3[j].insert(*i); - is_inserted = true; - break; - } - dvs = dep.getEdge(*k, *i); - for (int kk = 0; kk < dvs.size(); kk++) - if (dvs[kk].isCarried(dep_dim)) - potential_insertion_point = j; - } - if (is_inserted) - break; - } - if (!is_inserted) - s3[potential_insertion_point].insert(*i); - } - // set lexicographical order after distribution - int order = ref_lex[dim - 1]; - shiftLexicalOrder(ref_lex, dim - 1, s3.size() - 1); - for (std::vector >::iterator i = s3.begin(); i != s3.end(); - i++) { - for (std::set::iterator j = (*i).begin(); j != (*i).end(); j++) - assign_const(stmt[*j].xform, dim - 1, order); - order++; - } - // no need to update dependence graph - - return; -} - - - - -std::vector FindOuterArrayRefs(IR_Code *ir, - std::vector &arr_refs) { - std::vector to_return; - for (int i = 0; i < arr_refs.size(); i++) - if (!ir->parent_is_array(arr_refs[i])) { - int j; - for (j = 0; j < to_return.size(); j++) - if (*to_return[j] == *arr_refs[i]) - break; - if (j == to_return.size()) - to_return.push_back(arr_refs[i]); - } - return to_return; -} - - - - - -std::vector > constructInspectorVariables(IR_Code *ir, - std::set &arr, std::vector &index) { - - fprintf(stderr, "constructInspectorVariables()\n"); - - std::vector > to_return; - - for (std::set::iterator i = arr.begin(); i != arr.end(); - i++) { - - std::vector per_index; - - CG_outputRepr *subscript = (*i)->index(0); - - if ((*i)->n_dim() > 1) - throw ir_error( - "multi-dimensional array support non-existent for flattening currently"); - - while (ir->QueryExpOperation(subscript) == IR_OP_ARRAY_VARIABLE) { - - std::vector v = ir->QueryExpOperand(subscript); - - IR_ArrayRef *ref = static_cast(ir->Repr2Ref(v[0])); - //per_index.push_back(ref->name()); - - subscript = ref->index(0); - - } - - if (ir->QueryExpOperation(subscript) == IR_OP_VARIABLE) { - std::vector v = ir->QueryExpOperand(subscript); - IR_ScalarRef *ref = static_cast(ir->Repr2Ref(v[0])); - per_index.push_back(ref->name()); - int j; - for (j = 0; j < index.size(); j++) - if (index[j] == ref->name()) - break; - - if (j == index.size()) - throw ir_error("Non index variable in array expression"); - - int k; - for (k = 0; k < to_return.size(); k++) - if (to_return[k][0] == ref->name()) - break; - if (k == to_return.size()) { - to_return.push_back(per_index); - fprintf(stderr, "adding index %s\n", ref->name().c_str()); - } - - } - - } - - return to_return; - -} - -/*std::vector constructInspectorData(IR_Code *ir, std::vector > &indices){ - - std::vector to_return; - - for(int i =0; i < indices.size(); i++) - ir->CreateVariableDeclaration(indices[i][0]); - return to_return; - } - - - CG_outputRepr* constructInspectorFunction(IR_Code* ir, std::vector > &indices){ - - CG_outputRepr *to_return; - - - - return to_return; - } - -*/ - -CG_outputRepr * checkAndGenerateIndirectMappings(CG_outputBuilder * ocg, - std::vector > &indices, - CG_outputRepr * instance, CG_outputRepr * class_def, - CG_outputRepr * count_var) { - - CG_outputRepr *to_return = NULL; - - for (int i = 0; i < indices.size(); i++) - if (indices[i].size() > 1) { - std::string index = indices[i][indices[i].size() - 1]; - CG_outputRepr *rep = ocg->CreateArrayRefExpression( - ocg->CreateDotExpression(instance, - ocg->lookup_member_data(class_def, index, instance)), - count_var); - for (int j = indices[i].size() - 2; j >= 0; j--) - rep = ocg->CreateArrayRefExpression(indices[i][j], rep); - - CG_outputRepr *lhs = ocg->CreateArrayRefExpression( - ocg->CreateDotExpression(instance, - ocg->lookup_member_data(class_def, indices[i][0], instance)), - count_var); - - to_return = ocg->StmtListAppend(to_return, - ocg->CreateAssignment(0, lhs, rep)); - - } - - return to_return; - -} - -CG_outputRepr *generatePointerAssignments(CG_outputBuilder *ocg, - std::string prefix_name, - std::vector > &indices, - CG_outputRepr *instance, - CG_outputRepr *class_def) { - - fprintf(stderr, "generatePointerAssignments()\n"); - CG_outputRepr *list = NULL; - - fprintf(stderr, "prefix '%s', %d indices\n", prefix_name.c_str(), indices.size()); - for (int i = 0; i < indices.size(); i++) { - - std::string s = prefix_name + "_" + indices[i][0]; - - fprintf(stderr, "s %s\n", s.c_str()); - - // create a variable definition for a pointer to int with this name - // that seems to be the only actual result of this routine ... - //chillAST_VarDecl *vd = new chillAST_VarDecl( "int", prefix_name.c_str(), "*", NULL); - //vd->print(); printf("\n"); fflush(stdout); - //vd->dump(); printf("\n"); fflush(stdout); - - CG_outputRepr *ptr_exp = ocg->CreatePointer(s); // but dropped on the floor. unused - //fprintf(stderr, "ptr_exp created\n"); - - //CG_outputRepr *rhs = ocg->CreateDotExpression(instance, - // ocg->lookup_member_data(class_def, indices[i][0], instance)); - - //CG_outputRepr *ptr_assignment = ocg->CreateAssignment(0, ptr_exp, rhs); - - //list = ocg->StmtListAppend(list, ptr_assignment); - - } - - fprintf(stderr, "generatePointerAssignments() DONE\n\n"); - return list; -} - -void Loop::normalize(int stmt_num, int loop_level) { - - if (stmt_num < 0 || stmt_num >= stmt.size()) - throw std::invalid_argument( - - "invalid statement number " + to_string(stmt_num)); - - if (loop_level <= 0) - throw std::invalid_argument( - "12invalid loop level " + to_string(loop_level)); - if (loop_level > stmt[stmt_num].loop_level.size()) - throw std::invalid_argument( - "there is no loop level " + to_string(loop_level) - + " for statement " + to_string(stmt_num)); - - apply_xform(stmt_num); - - Relation r = copy(stmt[stmt_num].IS); - - Relation bound = get_loop_bound(r, loop_level, this->known); - if (!bound.has_single_conjunct() || !bound.is_satisfiable() - || bound.is_tautology()) - throw loop_error("unable to extract loop bound for normalize"); - - // extract the loop stride - coef_t stride; - std::pair result = find_simplest_stride(bound, - bound.set_var(loop_level)); - if (result.second == NULL) - stride = 1; - else - stride = abs(result.first.get_coef(result.second)) - / gcd(abs(result.first.get_coef(result.second)), - abs(result.first.get_coef(bound.set_var(loop_level)))); - - if (stride != 1) - throw loop_error( - "normalize currently only handles unit stride, non unit stride present in loop bounds"); - - GEQ_Handle lb; - - Conjunct *c = bound.query_DNF()->single_conjunct(); - for (GEQ_Iterator gi(c->GEQs()); gi; gi++) { - int coef = (*gi).get_coef(bound.set_var(loop_level)); - if (coef > 0) - lb = *gi; - } - - //Loop bound already zero - //Nothing to do. - if (lb.is_const(bound.set_var(loop_level)) && lb.get_const() == 0) - return; - - if (lb.is_const_except_for_global(bound.set_var(loop_level))) { - - int n = stmt[stmt_num].xform.n_out(); - - Relation r(n, n); - F_And *f_root = r.add_and(); - for (int j = 1; j <= n; j++) - if (j != 2 * loop_level) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(r.input_var(j), 1); - h.update_coef(r.output_var(j), -1); - } - - stmt[stmt_num].xform = Composition(r, stmt[stmt_num].xform); - stmt[stmt_num].xform.simplify(); - - for (Constr_Vars_Iter ci(lb); ci; ci++) { - if ((*ci).var->kind() == Global_Var) { - Global_Var_ID g = (*ci).var->get_global_var(); - Variable_ID v; - if (g->arity() == 0) - v = stmt[stmt_num].xform.get_local(g); - else - v = stmt[stmt_num].xform.get_local(g, - (*ci).var->function_of()); - - F_And *f_super_root = stmt[stmt_num].xform.and_with_and(); - F_Exists *f_exists = f_super_root->add_exists(); - F_And *f_root = f_exists->add_and(); - - EQ_Handle h = f_root->add_EQ(); - h.update_coef(stmt[stmt_num].xform.output_var(2 * loop_level), - 1); - h.update_coef(stmt[stmt_num].xform.input_var(loop_level), -1); - h.update_coef(v, 1); - - stmt[stmt_num].xform.simplify(); - } - - } - - } else - throw loop_error("loop bounds too complex for normalize!"); - -} - diff --git a/src/loop_datacopy.cc b/src/loop_datacopy.cc deleted file mode 100644 index 12d74fd..0000000 --- a/src/loop_datacopy.cc +++ /dev/null @@ -1,1369 +0,0 @@ -/***************************************************************************** - Copyright (C) 2008 University of Southern California - Copyright (C) 2009-2010 University of Utah - All Rights Reserved. - - Purpose: - Various data copy schemes. - - Notes: - - History: - 02/20/09 Created by Chun Chen by splitting original datacopy from loop.cc -*****************************************************************************/ - -#include -#include -#include "loop.hh" -#include "omegatools.hh" -#include "ir_code.hh" -#include "chill_error.hh" - -using namespace omega; - -// -// data copy function by referring arrays by numbers. -// e.g. A[i] = A[i-1] + B[i] -// parameter array_ref_num=[0,2] means to copy data touched by A[i-1] and A[i] -// -bool Loop::datacopy(const std::vector > > &array_ref_nums, int level, - bool allow_extra_read, int fastest_changing_dimension, int padding_stride, int padding_alignment, int memory_type) { - //fprintf(stderr, "Loop::datacopy()\n"); - - // check for sanity of parameters - std::set same_loop; - for (int i = 0; i < array_ref_nums.size(); i++) { - int stmt_num = array_ref_nums[i].first; - if (stmt_num < 0 || stmt_num >= stmt.size()) - throw std::invalid_argument("invalid statement number " + to_string(stmt_num)); - if (level <= 0 || level > stmt[stmt_num].loop_level.size()) - throw std::invalid_argument("invalid loop level " + to_string(level)); - if (i == 0) { - std::vector lex = getLexicalOrder(stmt_num); - same_loop = getStatements(lex, 2*level-2); - } - else if (same_loop.find(stmt_num) == same_loop.end()) - throw std::invalid_argument("array references for data copy must be located in the same subloop"); - } - - // convert array reference numbering scheme to actual array references - std::vector > > selected_refs; - for (int i = 0; i < array_ref_nums.size(); i++) { - if (array_ref_nums[i].second.size() == 0) - continue; - - int stmt_num = array_ref_nums[i].first; - selected_refs.push_back(std::make_pair(stmt_num, std::vector())); - std::vector refs = ir->FindArrayRef(stmt[stmt_num].code); - std::vector selected(refs.size(), false); - for (int j = 0; j < array_ref_nums[i].second.size(); j++) { - int ref_num = array_ref_nums[i].second[j]; - if (ref_num < 0 || ref_num >= refs.size()) { - for (int k = 0; k < refs.size(); k++) - delete refs[k]; - throw std::invalid_argument("invalid array reference number " + to_string(ref_num) + " in statement " + to_string(stmt_num)); - } - selected_refs[selected_refs.size()-1].second.push_back(refs[ref_num]); - selected[ref_num] = true; - } - for (int j = 0; j < refs.size(); j++) - if (!selected[j]) - delete refs[j]; - } - if (selected_refs.size() == 0) - throw std::invalid_argument("found no array references to copy"); - - // do the copy - bool whatever = datacopy_privatized(selected_refs, level, std::vector(), allow_extra_read, fastest_changing_dimension, padding_stride, padding_alignment, memory_type); - return whatever; -} - -// -// data copy function by referring arrays by name. -// e.g. A[i] = A[i-1] + B[i] -// parameter array_name=A means to copy data touched by A[i-1] and A[i] -// -bool Loop::datacopy(int stmt_num, int level, const std::string &array_name, - bool allow_extra_read, int fastest_changing_dimension, int padding_stride, int padding_alignment, int memory_type) { - - fflush(stdout); - //fprintf(stderr, "Loop::datacopy2()\n"); - //fprintf(stderr, "array name %s stmt num %d\n", array_name.c_str(), stmt_num); - - // check for sanity of parameters - if (stmt_num < 0 || stmt_num >= stmt.size()) - throw std::invalid_argument("invalid statement number " + to_string(stmt_num)); - if (level <= 0 || level > stmt[stmt_num].loop_level.size()) - throw std::invalid_argument("invalid loop level " + to_string(level)); - - // collect array references by name - std::vector lex = getLexicalOrder(stmt_num); - int dim = 2*level - 1; - std::set same_loop = getStatements(lex, dim-1); - - std::vector > > selected_refs; - for (std::set::iterator i = same_loop.begin(); i != same_loop.end(); i++) { - std::vector t; - std::vector refs = ir->FindArrayRef(stmt[*i].code); - for (int j = 0; j < refs.size(); j++) - if (refs[j]->name() == array_name) - t.push_back(refs[j]); - else - delete refs[j]; - if (t.size() != 0) - selected_refs.push_back(std::make_pair(*i, t)); - } - - //fprintf(stderr, "selected refs:\n"); - //for (int i=0; iDump(); printf("\n"); fflush(stdout); - //} - - if (selected_refs.size() == 0) - throw std::invalid_argument("found no array references with name " + to_string(array_name) + " to copy"); - - IR_ArrayRef *AR = selected_refs[0].second[0]; - //IR_roseArrayRef *RAR = (IR_roseArrayRef *)AR; - //fprintf(stderr, "before datacopy_privatized, "); - //AR->Dump(); - - // do the copy - //fprintf(stderr, "\nLoop::datacopy2 calling privatized\n"); - - bool whatever = datacopy_privatized(selected_refs, level, std::vector(), allow_extra_read, fastest_changing_dimension, padding_stride, padding_alignment, memory_type); - - //AR = selected_refs[0].second[0]; - //fprintf(stderr, "after datacopy_privatized, "); - //AR->Dump(); - - return whatever; -} - - -bool Loop::datacopy_privatized(int stmt_num, int level, const std::string &array_name, const std::vector &privatized_levels, - bool allow_extra_read, int fastest_changing_dimension, int padding_stride, int padding_alignment, int memory_type) { - //fprintf(stderr, "Loop::datacopy_privatized()\n"); - - // check for sanity of parameters - if (stmt_num < 0 || stmt_num >= stmt.size()) - throw std::invalid_argument("invalid statement number " + to_string(stmt_num)); - if (level <= 0 || level > stmt[stmt_num].loop_level.size()) - throw std::invalid_argument("invalid loop level " + to_string(level)); - - // collect array references by name - std::vector lex = getLexicalOrder(stmt_num); - int dim = 2*level - 1; - std::set same_loop = getStatements(lex, dim-1); - - std::vector > > selected_refs; - for (std::set::iterator i = same_loop.begin(); i != same_loop.end(); i++) { - selected_refs.push_back(std::make_pair(*i, std::vector())); - - std::vector refs = ir->FindArrayRef(stmt[*i].code); - for (int j = 0; j < refs.size(); j++) - if (refs[j]->name() == array_name) - selected_refs[selected_refs.size()-1].second.push_back(refs[j]); - else - delete refs[j]; - } - if (selected_refs.size() == 0) - throw std::invalid_argument("found no array references with name " + to_string(array_name) + " to copy"); - - // do the copy - bool whatever = datacopy_privatized(selected_refs, level, privatized_levels, allow_extra_read, fastest_changing_dimension, padding_stride, padding_alignment, memory_type); - return whatever; -} - - -bool Loop::datacopy_privatized(const std::vector > > &array_ref_nums, int level, const std::vector &privatized_levels, bool allow_extra_read, int fastest_changing_dimension, int padding_stride, int padding_alignment, int memory_type) { - //fprintf(stderr, "Loop::datacopy_privatized2()\n"); - - // check for sanity of parameters - std::set same_loop; - for (int i = 0; i < array_ref_nums.size(); i++) { - int stmt_num = array_ref_nums[i].first; - if (stmt_num < 0 || stmt_num >= stmt.size()) - throw std::invalid_argument("invalid statement number " + to_string(stmt_num)); - if (level <= 0 || level > stmt[stmt_num].loop_level.size()) - throw std::invalid_argument("invalid loop level " + to_string(level)); - if (i == 0) { - std::vector lex = getLexicalOrder(stmt_num); - same_loop = getStatements(lex, 2*level-2); - } - else if (same_loop.find(stmt_num) == same_loop.end()) - throw std::invalid_argument("array references for data copy must be located in the same subloop"); - } - - // convert array reference numbering scheme to actual array references - std::vector > > selected_refs; - for (int i = 0; i < array_ref_nums.size(); i++) { - if (array_ref_nums[i].second.size() == 0) - continue; - - int stmt_num = array_ref_nums[i].first; - selected_refs.push_back(std::make_pair(stmt_num, std::vector())); - std::vector refs = ir->FindArrayRef(stmt[stmt_num].code); - std::vector selected(refs.size(), false); - for (int j = 0; j < array_ref_nums[i].second.size(); j++) { - int ref_num = array_ref_nums[i].second[j]; - if (ref_num < 0 || ref_num >= refs.size()) { - for (int k = 0; k < refs.size(); k++) - delete refs[k]; - throw std::invalid_argument("invalid array reference number " + to_string(ref_num) + " in statement " + to_string(stmt_num)); - } - selected_refs[selected_refs.size()-1].second.push_back(refs[ref_num]); - selected[ref_num] = true; - } - for (int j = 0; j < refs.size(); j++) - if (!selected[j]) - delete refs[j]; - } - if (selected_refs.size() == 0) - throw std::invalid_argument("found no array references to copy"); - - // do the copy - bool whatever = datacopy_privatized(selected_refs, level, privatized_levels, allow_extra_read, fastest_changing_dimension, padding_stride, padding_alignment, memory_type); - return whatever; -} - - -// -// Implement low level datacopy function with lots of options. -// - -bool Loop::datacopy_privatized(const std::vector > > &stmt_refs, - int level, - const std::vector &privatized_levels, - bool allow_extra_read, - int fastest_changing_dimension, - int padding_stride, - int padding_alignment, - int memory_type) { - - //fprintf(stderr, "\nLoop::datacopy_privatized3() *****\n"); - //fprintf(stderr, "privatized_levels.size() %d\n", privatized_levels.size()); - //fprintf(stderr, "level %d\n", level); - - if (stmt_refs.size() == 0) - return true; - - // check for sanity of parameters - IR_ArraySymbol *sym = NULL; - std::vector lex; - std::set active; - if (level <= 0) - throw std::invalid_argument("invalid loop level " + to_string(level)); - for (int i = 0; i < privatized_levels.size(); i++) { - if (i == 0) { - if (privatized_levels[i] < level) - throw std::invalid_argument("privatized loop levels must be no less than level " + to_string(level)); - } - else if (privatized_levels[i] <= privatized_levels[i-1]) - throw std::invalid_argument("privatized loop levels must be in ascending order"); - } - for (int i = 0; i < stmt_refs.size(); i++) { - int stmt_num = stmt_refs[i].first; - active.insert(stmt_num); - if (stmt_num < 0 || stmt_num >= stmt.size()) - throw std::invalid_argument("invalid statement number " + to_string(stmt_num)); - if (privatized_levels.size() != 0) { - if (privatized_levels[privatized_levels.size()-1] > stmt[stmt_num].loop_level.size()) - throw std::invalid_argument("invalid loop level " + to_string(privatized_levels[privatized_levels.size()-1]) + " for statement " + to_string(stmt_num)); - } - else { - if (level > stmt[stmt_num].loop_level.size()) - throw std::invalid_argument("invalid loop level " + to_string(level) + " for statement " + to_string(stmt_num)); - } - for (int j = 0; j < stmt_refs[i].second.size(); j++) { - if (sym == NULL) { - sym = stmt_refs[i].second[j]->symbol(); - lex = getLexicalOrder(stmt_num); - } - else { - IR_ArraySymbol *t = stmt_refs[i].second[j]->symbol(); - if (t->name() != sym->name()) { - delete t; - delete sym; - throw std::invalid_argument("try to copy data from different arrays"); - } - delete t; - } - } - } - - //fprintf(stderr, "sym %p\n", sym); - if (!sym) { - fprintf(stderr, "sym NULL, gonna die\n"); int *i=0; int j=i[0]; - } - - if (!(fastest_changing_dimension >= -1 && fastest_changing_dimension < sym->n_dim())) - throw std::invalid_argument("invalid fastest changing dimension for the array to be copied"); - if (padding_stride < 0) - throw std::invalid_argument("invalid temporary array stride requirement"); - if (padding_alignment == -1 || padding_alignment == 0) - throw std::invalid_argument("invalid temporary array alignment requirement"); - - int dim = 2*level - 1; - int n_dim = sym->n_dim(); - - - if (fastest_changing_dimension == -1) - switch (sym->layout_type()) { - case IR_ARRAY_LAYOUT_ROW_MAJOR: - fastest_changing_dimension = n_dim - 1; - break; - case IR_ARRAY_LAYOUT_COLUMN_MAJOR: - fastest_changing_dimension = 0; - break; - default: - throw loop_error("unsupported array layout"); - } - // OK, parameter sanity checked - - - // invalidate saved codegen computation - delete last_compute_cgr_; - last_compute_cgr_ = NULL; - delete last_compute_cg_; - last_compute_cg_ = NULL; - - // build iteration spaces for all reads and for all writes separately - //fprintf(stderr, "dp3: before apply_xform() ARRAY REFS\n"); - //for (int i = 0; i < stmt_refs.size(); i++) { - // for (int j = 0; j < stmt_refs[i].second.size(); j++) { - // IR_ArrayRef *AR = stmt_refs[i].second[j]; - // fprintf(stderr, "array ref ij %d %d ", i, j); AR->Dump(); fprintf(stderr, "\n"); - // } - //} - //for (int i=0; iDump(); - // fprintf(stderr, "\n"); - // } - //} - - //for (int i=0; iname()); - mapping.setup_names(); - mapping.print(); fflush(stdout); // "{[I] -> [_t1] : I = _t1 } - - F_And *f_root = mapping.add_and(); - for (int k = 1; k <= level-1; k++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.input_var(k), 1); - h.update_coef(mapping.output_var(k), -1); - } - for (int k = 0; k < privatized_levels.size(); k++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.input_var(privatized_levels[k]), 1); - h.update_coef(mapping.output_var(level+k), -1); - } - for (int k = 0; k < n_dim; k++) { - IR_ArrayRef *AR = stmt_refs[i].second[j]; - //fprintf(stderr, "array ref "); - AR->Dump(); - - CG_outputRepr *repr = stmt_refs[i].second[j]->index(k); - //fprintf(stderr, "k %d j %d repr ", k, j); repr->dump(); fflush(stdout); - - exp2formula(ir, - mapping, - f_root, - freevar, - repr, - mapping.output_var(level-1+privatized_levels.size()+k+1), - 'w', - IR_COND_EQ, - false, - uninterpreted_symbols[stmt_num], - uninterpreted_symbols_stringrepr[stmt_num]); - repr->clear(); - delete repr; - } - Relation r = omega::Range(Restrict_Domain(mapping, Intersection(copy(stmt[stmt_num].IS), Extend_Set(copy(this->known), stmt[stmt_num].IS.n_set() - this->known.n_set())))); - if (stmt_refs[i].second[j]->is_write()) { - has_write_refs = true; - wo_copy_is = Union(wo_copy_is, r); - wo_copy_is.simplify(2, 4); - - - } - else { - has_read_refs = true; - ro_copy_is = Union(ro_copy_is, r); - ro_copy_is.simplify(2, 4); - - } - } - } - - //fprintf(stderr, "dp3: simplify\n"); - // simplify read and write footprint iteration space - { - if (allow_extra_read) - ro_copy_is = SimpleHull(ro_copy_is, true, true); - else - ro_copy_is = ConvexRepresentation(ro_copy_is); - - wo_copy_is = ConvexRepresentation(wo_copy_is); - if (wo_copy_is.number_of_conjuncts() > 1) { - Relation t = SimpleHull(wo_copy_is, true, true); - if (Must_Be_Subset(copy(t), copy(ro_copy_is))) - wo_copy_is = t; - else if (Must_Be_Subset(copy(wo_copy_is), copy(ro_copy_is))) - wo_copy_is = ro_copy_is; - } - } - - // make copy statement variable names match the ones in the original statements which - // already have the same names due to apply_xform - { - int ref_stmt = *active.begin(); - for (std::set::iterator i = active.begin(); i != active.end(); i++) - if (stmt[*i].IS.n_set() > stmt[ref_stmt].IS.n_set()) - ref_stmt = *i; - for (int i = 1; i < level; i++) { - std::string s = stmt[ref_stmt].IS.input_var(i)->name(); - wo_copy_is.name_set_var(i, s); - ro_copy_is.name_set_var(i, s); - } - for (int i = 0; i < privatized_levels.size(); i++) { - std::string s = stmt[ref_stmt].IS.input_var(privatized_levels[i])->name(); - wo_copy_is.name_set_var(level+i, s); - ro_copy_is.name_set_var(level+i, s); - } - for (int i = level+privatized_levels.size(); i < level+privatized_levels.size()+n_dim; i++) { - std::string s = tmp_loop_var_name_prefix + to_string(tmp_loop_var_name_counter+i-level-privatized_levels.size()); - wo_copy_is.name_set_var(i, s); - ro_copy_is.name_set_var(i, s); - } - tmp_loop_var_name_counter += n_dim; - wo_copy_is.setup_names(); - ro_copy_is.setup_names(); - } - - //fprintf(stderr, "\ndp3: build merged\n"); - // build merged footprint iteration space for calculating temporary array size - Relation copy_is = SimpleHull(Union(copy(ro_copy_is), copy(wo_copy_is)), true, true); - - // extract temporary array information - CG_outputBuilder *ocg = ir->builder(); - std::vector index_lb(n_dim); // initialized to NULL - std::vector index_stride(n_dim); - std::vector is_index_eq(n_dim, false); - std::vector > index_sz(0); - Relation reduced_copy_is = copy(copy_is); - - for (int i = 0; i < n_dim; i++) { - //fprintf(stderr, "i %d/%d\n", i, n_dim); - if (i != 0) - reduced_copy_is = Project(reduced_copy_is, level-1+privatized_levels.size()+i, Set_Var); - Relation bound = get_loop_bound(reduced_copy_is, level-1+privatized_levels.size()+i); - - //fprintf(stderr, "dp3: extract stride\n"); - // extract stride - std::pair result = find_simplest_stride(bound, bound.set_var(level-1+privatized_levels.size()+i+1)); - if (result.second != NULL) - index_stride[i] = abs(result.first.get_coef(result.second))/gcd(abs(result.first.get_coef(result.second)), abs(result.first.get_coef(bound.set_var(level-1+privatized_levels.size()+i+1)))); - else - index_stride[i] = 1; - //fprintf(stderr, "dp3: index_stride[%d] = %d\n", i, index_stride[i]); - - // check if this array index requires loop - Conjunct *c = bound.query_DNF()->single_conjunct(); - for (EQ_Iterator ei(c->EQs()); ei; ei++) { - //fprintf(stderr, "dp3: for\n"); - if ((*ei).has_wildcards()) - continue; - - //fprintf(stderr, "dp3: no wildcards\n"); - int coef = (*ei).get_coef(bound.set_var(level-1+privatized_levels.size()+i+1)); - if (coef != 0) { - //fprintf(stderr, "coef != 0\n"); - int sign = 1; - if (coef < 0) { - //fprintf(stderr, "coef < 0\n"); - coef = -coef; - sign = -1; - } - - CG_outputRepr *op = NULL; - for (Constr_Vars_Iter ci(*ei); ci; ci++) { - //fprintf(stderr, "dp3: ci\n"); - switch ((*ci).var->kind()) { - case Input_Var: - { - //fprintf(stderr, "dp3: Input_Var\n"); - if ((*ci).var != bound.set_var(level-1+privatized_levels.size()+i+1)) { - //fprintf(stderr, "dp3: IF sign %d\n",(*ci).coef*sign); - - if ((*ci).coef*sign == 1) - op = ocg->CreateMinus(op, ocg->CreateIdent((*ci).var->name())); - else if ((*ci).coef*sign == -1) - op = ocg->CreatePlus(op, ocg->CreateIdent((*ci).var->name())); - else if ((*ci).coef*sign > 1) - op = ocg->CreateMinus(op, ocg->CreateTimes(ocg->CreateInt(abs((*ci).coef)), ocg->CreateIdent((*ci).var->name()))); - else // (*ci).coef*sign < -1 - op = ocg->CreatePlus(op, ocg->CreateTimes(ocg->CreateInt(abs((*ci).coef)), ocg->CreateIdent((*ci).var->name()))); - } - break; - } - case Global_Var: - { - //fprintf(stderr, "dp3: Global_Var\n"); - Global_Var_ID g = (*ci).var->get_global_var(); - if ((*ci).coef*sign == 1) - op = ocg->CreateMinus(op, ocg->CreateIdent(g->base_name())); - else if ((*ci).coef*sign == -1) - op = ocg->CreatePlus(op, ocg->CreateIdent(g->base_name())); - else if ((*ci).coef*sign > 1) - op = ocg->CreateMinus(op, ocg->CreateTimes(ocg->CreateInt(abs((*ci).coef)), ocg->CreateIdent(g->base_name()))); - else // (*ci).coef*sign < -1 - op = ocg->CreatePlus(op, ocg->CreateTimes(ocg->CreateInt(abs((*ci).coef)), ocg->CreateIdent(g->base_name()))); - break; - } - default: - throw loop_error("unsupported array index expression"); - } - } - if ((*ei).get_const() != 0) - op = ocg->CreatePlus(op, ocg->CreateInt(-sign*((*ei).get_const()))); - if (coef != 1) - op = ocg->CreateIntegerFloor(op, ocg->CreateInt(coef)); - - index_lb[i] = op; - is_index_eq[i] = true; - break; - } - } - if (is_index_eq[i]) - continue; - - //fprintf(stderr, "dp3: separate lower and upper bounds\n"); - // separate lower and upper bounds - std::vector lb_list, ub_list; - std::set excluded_floor_vars; - excluded_floor_vars.insert(bound.set_var(level-1+privatized_levels.size()+i+1)); - for (GEQ_Iterator gi(c->GEQs()); gi; gi++) { - int coef = (*gi).get_coef(bound.set_var(level-1+privatized_levels.size()+i+1)); - if (coef != 0 && (*gi).has_wildcards()) { - bool clean_bound = true; - GEQ_Handle h; - for (Constr_Vars_Iter cvi(*gi, true); gi; gi++) - if (!find_floor_definition(bound, (*cvi).var, excluded_floor_vars).first) { - clean_bound = false; - break; - } - if (!clean_bound) - continue; - } - - if (coef > 0) - lb_list.push_back(*gi); - else if (coef < 0) - ub_list.push_back(*gi); - } - if (lb_list.size() == 0 || ub_list.size() == 0) - throw loop_error("failed to calcuate array footprint size"); - - //fprintf(stderr, "dp3: build lower bound representation\n"); - // build lower bound representation - std::vector lb_repr_list; - for (int j = 0; j < lb_list.size(); j++){ - if(this->known.n_set() == 0) { - lb_repr_list.push_back(output_lower_bound_repr(ocg, - lb_list[j], - bound.set_var(level-1+privatized_levels.size()+i+1), - result.first, - result.second, - bound, - Relation::True(bound.n_set()), - std::vector >(bound.n_set(), std::make_pair(static_cast(NULL), 0)), - uninterpreted_symbols[stmt_num])); - } - else { - lb_repr_list.push_back(output_lower_bound_repr(ocg, - lb_list[j], - bound.set_var(level-1+privatized_levels.size()+i+1), - result.first, - result.second, - bound, - this->known, - std::vector >(bound.n_set(), std::make_pair(static_cast(NULL), 0)), - uninterpreted_symbols[stmt_num])); - } - } - if (lb_repr_list.size() > 1) { - //fprintf(stderr, "loop_datacopy.cc dp3 createInvoke( max )\n"); - index_lb[i] = ocg->CreateInvoke("max", lb_repr_list); - } - else if (lb_repr_list.size() == 1) - index_lb[i] = lb_repr_list[0]; - - //fprintf(stderr, "dp3: build temporary array size representation\n"); - // build temporary array size representation - { - Relation cal(copy_is.n_set(), 1); - F_And *f_root = cal.add_and(); - for (int j = 0; j < ub_list.size(); j++) - for (int k = 0; k < lb_list.size(); k++) { - GEQ_Handle h = f_root->add_GEQ(); - - for (Constr_Vars_Iter ci(ub_list[j]); ci; ci++) { - switch ((*ci).var->kind()) { - case Input_Var: - { - int pos = (*ci).var->get_position(); - h.update_coef(cal.input_var(pos), (*ci).coef); - break; - } - case Global_Var: - { - Global_Var_ID g = (*ci).var->get_global_var(); - Variable_ID v; - if (g->arity() == 0) - v = cal.get_local(g); - else - v = cal.get_local(g, (*ci).var->function_of()); - h.update_coef(v, (*ci).coef); - break; - } - default: - throw loop_error("cannot calculate temporay array size statically"); - } - } - h.update_const(ub_list[j].get_const()); - - for (Constr_Vars_Iter ci(lb_list[k]); ci; ci++) { - switch ((*ci).var->kind()) { - case Input_Var: - { - int pos = (*ci).var->get_position(); - h.update_coef(cal.input_var(pos), (*ci).coef); - break; - } - case Global_Var: - { - Global_Var_ID g = (*ci).var->get_global_var(); - Variable_ID v; - if (g->arity() == 0) - v = cal.get_local(g); - else - v = cal.get_local(g, (*ci).var->function_of()); - h.update_coef(v, (*ci).coef); - break; - } - default: - throw loop_error("cannot calculate temporay array size statically"); - } - } - h.update_const(lb_list[k].get_const()); - - h.update_const(1); - h.update_coef(cal.output_var(1), -1); - } - - cal = Restrict_Domain(cal, copy(copy_is)); - for (int j = 1; j <= cal.n_inp(); j++) - cal = Project(cal, j, Input_Var); - cal.simplify(); - - //fprintf(stderr, "dp3: pad temporary array size\n"); - // pad temporary array size - // TODO: for variable array size, create padding formula - Conjunct *c = cal.query_DNF()->single_conjunct(); - bool is_index_bound_const = false; - for (GEQ_Iterator gi(c->GEQs()); gi && !is_index_bound_const; gi++) - if ((*gi).is_const(cal.output_var(1))) { - coef_t size = (*gi).get_const() / (-(*gi).get_coef(cal.output_var(1))); - if (padding_stride != 0) { - size = (size + index_stride[i] - 1) / index_stride[i]; - if (i == fastest_changing_dimension) - size = size * padding_stride; - } - if (i == fastest_changing_dimension) { - if (padding_alignment > 1) { // align to boundary for data packing - int residue = size % padding_alignment; - if (residue) - size = size+padding_alignment-residue; - } - else if (padding_alignment < -1) { // un-alignment for memory bank conflicts - while (gcd(size, static_cast(-padding_alignment)) != 1) - size++; - } - } - index_sz.push_back(std::make_pair(i, ocg->CreateInt(size))); - is_index_bound_const = true; - } - - if (!is_index_bound_const) { - for (GEQ_Iterator gi(c->GEQs()); gi && !is_index_bound_const; gi++) { - int coef = (*gi).get_coef(cal.output_var(1)); - if (coef < 0) { - CG_outputRepr *op = NULL; - for (Constr_Vars_Iter ci(*gi); ci; ci++) { - if ((*ci).var != cal.output_var(1)) { - switch((*ci).var->kind()) { - case Global_Var: - { - Global_Var_ID g = (*ci).var->get_global_var(); - if ((*ci).coef == 1) - op = ocg->CreatePlus(op, ocg->CreateIdent(g->base_name())); - else if ((*ci).coef == -1) - op = ocg->CreateMinus(op, ocg->CreateIdent(g->base_name())); - else if ((*ci).coef > 1) - op = ocg->CreatePlus(op, ocg->CreateTimes(ocg->CreateInt((*ci).coef), ocg->CreateIdent(g->base_name()))); - else // (*ci).coef < -1 - op = ocg->CreateMinus(op, ocg->CreateTimes(ocg->CreateInt(-(*ci).coef), ocg->CreateIdent(g->base_name()))); - break; - } - default: - throw loop_error("failed to generate array index bound code"); - } - } - } - int c = (*gi).get_const(); - if (c > 0) - op = ocg->CreatePlus(op, ocg->CreateInt(c)); - else if (c < 0) - op = ocg->CreateMinus(op, ocg->CreateInt(-c)); - if (padding_stride != 0) { - if (i == fastest_changing_dimension) { - coef_t g = gcd(index_stride[i], static_cast(padding_stride)); - coef_t t1 = index_stride[i] / g; - if (t1 != 1) - op = ocg->CreateIntegerFloor(ocg->CreatePlus(op, ocg->CreateInt(t1-1)), ocg->CreateInt(t1)); - coef_t t2 = padding_stride / g; - if (t2 != 1) - op = ocg->CreateTimes(op, ocg->CreateInt(t2)); - } - else if (index_stride[i] != 1) { - op = ocg->CreateIntegerFloor(ocg->CreatePlus(op, ocg->CreateInt(index_stride[i]-1)), ocg->CreateInt(index_stride[i])); - } - } - - index_sz.push_back(std::make_pair(i, op)); - break; - } - } - } - } - } - - //fprintf(stderr, "dp3: change the temporary array index order\n"); - // change the temporary array index order - for (int i = 0; i < index_sz.size(); i++) { - if (index_sz[i].first == fastest_changing_dimension) - switch (sym->layout_type()) { - case IR_ARRAY_LAYOUT_ROW_MAJOR: - std::swap(index_sz[index_sz.size()-1], index_sz[i]); - break; - case IR_ARRAY_LAYOUT_COLUMN_MAJOR: - std::swap(index_sz[0], index_sz[i]); - break; - default: - throw loop_error("unsupported array layout"); - } - } - - //fprintf(stderr, "dp3: declare temporary array or scalar\n"); - // declare temporary array or scalar - IR_Symbol *tmp_sym; - if (index_sz.size() == 0) { - //fprintf(stderr, "tmp_sym is a scalar\n"); - tmp_sym = ir->CreateScalarSymbol(sym, memory_type); - } - else { - //fprintf(stderr, "tmp_sym is an array\n"); - std::vector tmp_array_size(index_sz.size()); - for (int i = 0; i < index_sz.size(); i++) { - tmp_array_size[i] = index_sz[i].second->clone(); - index_sz[i].second->dump(); // THIS PRINTF - } - tmp_sym = ir->CreateArraySymbol(sym, tmp_array_size, memory_type); - } - - //fprintf(stderr, "dp3: create temporary array read initialization code\n"); - // create temporary array read initialization code - CG_outputRepr *copy_code_read; - if (has_read_refs) { - //fprintf(stderr, "has read refs\n"); - if (index_sz.size() == 0) { - //fprintf(stderr, "if\n"); - - //fprintf(stderr, "tmp sym %s\n", tmp_sym->name().c_str()); - IR_ScalarRef *tmp_scalar_ref = ir->CreateScalarRef(static_cast(tmp_sym)); // create ref from symbol - // tmp_scalar_ref is incomplete - - std::vector rhs_index(n_dim); - for (int i = 0; i < index_lb.size(); i++) { - //fprintf(stderr, "i %d\n", i); - if (is_index_eq[i]) - rhs_index[i] = index_lb[i]->clone(); - else - rhs_index[i] = ir->builder()->CreateIdent(copy_is.set_var(level-1+privatized_levels.size()+i+1)->name()); - } - IR_ArrayRef *copied_array_ref = ir->CreateArrayRef(sym, rhs_index); - - // IR_ScalarRef tmp_scalar_ref has no actual reference yet. It only has the variable definition. - copy_code_read = ir->builder()->CreateAssignment(0, tmp_scalar_ref->convert(), copied_array_ref->convert()); - //fprintf(stderr, "if ends\n"); - } - else { - //fprintf(stderr, "else\n"); - std::vector lhs_index(index_sz.size()); - for (int i = 0; i < index_sz.size(); i++) { - int cur_index_num = index_sz[i].first; - CG_outputRepr *cur_index_repr = ocg->CreateMinus(ocg->CreateIdent(copy_is.set_var(level-1+privatized_levels.size()+cur_index_num+1)->name()), index_lb[cur_index_num]->clone()); - if (padding_stride != 0) { - if (i == n_dim-1) { - coef_t g = gcd(index_stride[cur_index_num], static_cast(padding_stride)); - coef_t t1 = index_stride[cur_index_num] / g; - if (t1 != 1) - cur_index_repr = ocg->CreateIntegerFloor(cur_index_repr, ocg->CreateInt(t1)); - coef_t t2 = padding_stride / g; - if (t2 != 1) - cur_index_repr = ocg->CreateTimes(cur_index_repr, ocg->CreateInt(t2)); - } - else if (index_stride[cur_index_num] != 1) { - cur_index_repr = ocg->CreateIntegerFloor(cur_index_repr, ocg->CreateInt(index_stride[cur_index_num])); - } - } - - if (ir->ArrayIndexStartAt() != 0) - cur_index_repr = ocg->CreatePlus(cur_index_repr, ocg->CreateInt(ir->ArrayIndexStartAt())); - lhs_index[i] = cur_index_repr; - } - - //fprintf(stderr, "dp3: making tmp_array_ref\n"); - IR_ArrayRef *tmp_array_ref = ir->CreateArrayRef(static_cast(tmp_sym), lhs_index); - //fprintf(stderr, "dp3: DONE making tmp_array_ref\n"); - - std::vector rhs_index(n_dim); - for (int i = 0; i < index_lb.size(); i++) - if (is_index_eq[i]) - rhs_index[i] = index_lb[i]->clone(); - else - rhs_index[i] = ir->builder()->CreateIdent(copy_is.set_var(level-1+privatized_levels.size()+i+1)->name()); - IR_ArrayRef *copied_array_ref = ir->CreateArrayRef(sym, rhs_index); - - //fprintf(stderr, "dp3: loop_datacopy.cc copy_code_read = CreateAssignment\n"); - //copy_code_read = ir->builder()->CreateAssignment(0, tmp_array_ref->convert(), copied_array_ref->convert()); - CG_outputRepr *lhs = tmp_array_ref->convert(); - CG_outputRepr *rhs = copied_array_ref->convert(); - copy_code_read = ir->builder()->CreateAssignment(0, lhs, rhs); //tmp_array_ref->convert(), copied_array_ref->convert()); - //fprintf(stderr, "dp3: loop_datacopy.cc copy_code_read = CreateAssignment DONE\n\n"); - } - } // has read refs - - //fprintf(stderr, "dp3: create temporary array write back code\n"); - // create temporary array write back code - CG_outputRepr *copy_code_write; - if (has_write_refs) { - //fprintf(stderr, "has_write_refs\n"); - if (index_sz.size() == 0) { - //fprintf(stderr, "index_sz.size() == 0\n"); - IR_ScalarRef *tmp_scalar_ref = ir->CreateScalarRef(static_cast(tmp_sym)); - - std::vector rhs_index(n_dim); - for (int i = 0; i < index_lb.size(); i++) - if (is_index_eq[i]) - rhs_index[i] = index_lb[i]->clone(); - else - rhs_index[i] = ir->builder()->CreateIdent(copy_is.set_var(level-1+privatized_levels.size()+i+1)->name()); - IR_ArrayRef *copied_array_ref = ir->CreateArrayRef(sym, rhs_index); - - copy_code_write = ir->builder()->CreateAssignment(0, copied_array_ref->convert(), tmp_scalar_ref->convert()); - } - else { - //fprintf(stderr, "index_sz.size() NOT = 0\n"); - - std::vector lhs_index(n_dim); - for (int i = 0; i < index_lb.size(); i++) - if (is_index_eq[i]) - lhs_index[i] = index_lb[i]->clone(); - else - lhs_index[i] = ir->builder()->CreateIdent(copy_is.set_var(level-1+privatized_levels.size()+i+1)->name()); - IR_ArrayRef *copied_array_ref = ir->CreateArrayRef(sym, lhs_index); - - std::vector rhs_index(index_sz.size()); - for (int i = 0; i < index_sz.size(); i++) { - int cur_index_num = index_sz[i].first; - CG_outputRepr *cur_index_repr = ocg->CreateMinus(ocg->CreateIdent(copy_is.set_var(level-1+privatized_levels.size()+cur_index_num+1)->name()), index_lb[cur_index_num]->clone()); - if (padding_stride != 0) { - if (i == n_dim-1) { - coef_t g = gcd(index_stride[cur_index_num], static_cast(padding_stride)); - coef_t t1 = index_stride[cur_index_num] / g; - if (t1 != 1) - cur_index_repr = ocg->CreateIntegerFloor(cur_index_repr, ocg->CreateInt(t1)); - coef_t t2 = padding_stride / g; - if (t2 != 1) - cur_index_repr = ocg->CreateTimes(cur_index_repr, ocg->CreateInt(t2)); - } - else if (index_stride[cur_index_num] != 1) { - cur_index_repr = ocg->CreateIntegerFloor(cur_index_repr, ocg->CreateInt(index_stride[cur_index_num])); - } - } - - if (ir->ArrayIndexStartAt() != 0) - cur_index_repr = ocg->CreatePlus(cur_index_repr, ocg->CreateInt(ir->ArrayIndexStartAt())); - rhs_index[i] = cur_index_repr; - } - IR_ArrayRef *tmp_array_ref = ir->CreateArrayRef(static_cast(tmp_sym), rhs_index); - - copy_code_write = ir->builder()->CreateAssignment(0, copied_array_ref->convert(), tmp_array_ref->convert()); - } - } // has write refs - - // now we can remove those loops for array indexes that are - // dependent on others - //fprintf(stderr, "dp3: now we can remove those loops\n"); - if (!(index_sz.size() == n_dim && (sym->layout_type() == IR_ARRAY_LAYOUT_ROW_MAJOR || n_dim <= 1))) { - Relation mapping(level-1+privatized_levels.size()+n_dim, level-1+privatized_levels.size()+index_sz.size()); - F_And *f_root = mapping.add_and(); - for (int i = 1; i <= level-1+privatized_levels.size(); i++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.input_var(i), 1); - h.update_coef(mapping.output_var(i), -1); - } - - int cur_index = 0; - std::vector mapped_index(index_sz.size()); - for (int i = 0; i < n_dim; i++) - if (!is_index_eq[i]) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.input_var(level-1+privatized_levels.size()+i+1), 1); - switch (sym->layout_type()) { - case IR_ARRAY_LAYOUT_COLUMN_MAJOR: { - h.update_coef(mapping.output_var(level-1+privatized_levels.size()+index_sz.size()-cur_index), -1); - mapped_index[index_sz.size()-cur_index-1] = i; - break; - } - case IR_ARRAY_LAYOUT_ROW_MAJOR: { - h.update_coef(mapping.output_var(level-1+privatized_levels.size()+cur_index+1), -1); - mapped_index[cur_index] = i; - break; - } - default: - throw loop_error("unsupported array layout"); - } - cur_index++; - } - - wo_copy_is = omega::Range(Restrict_Domain(copy(mapping), wo_copy_is)); - ro_copy_is = omega::Range(Restrict_Domain(copy(mapping), ro_copy_is)); - for (int i = 1; i <= level-1+privatized_levels.size(); i++) { - wo_copy_is.name_set_var(i, copy_is.set_var(i)->name()); - ro_copy_is.name_set_var(i, copy_is.set_var(i)->name()); - } - for (int i = 0; i < index_sz.size(); i++) { - wo_copy_is.name_set_var(level-1+privatized_levels.size()+i+1, copy_is.set_var(level-1+privatized_levels.size()+mapped_index[i]+1)->name()); - ro_copy_is.name_set_var(level-1+privatized_levels.size()+i+1, copy_is.set_var(level-1+privatized_levels.size()+mapped_index[i]+1)->name()); - } - wo_copy_is.setup_names(); - ro_copy_is.setup_names(); - } - - // insert read copy statement - //fprintf(stderr, "dp3: insert read copy statement\n"); - - int old_num_stmt = stmt.size(); - int ro_copy_stmt_num = -1; - if (has_read_refs) { - Relation copy_xform(ro_copy_is.n_set(), 2*ro_copy_is.n_set()+1); - { - F_And *f_root = copy_xform.add_and(); - for (int i = 1; i <= ro_copy_is.n_set(); i++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(copy_xform.input_var(i), 1); - h.update_coef(copy_xform.output_var(2*i), -1); - } - for (int i = 1; i <= dim; i+=2) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(copy_xform.output_var(i), -1); - h.update_const(lex[i-1]); - } - for (int i = dim+2; i <= copy_xform.n_out(); i+=2) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(copy_xform.output_var(i), 1); - } - } - - Statement copy_stmt_read; - copy_stmt_read.IS = ro_copy_is; - copy_stmt_read.xform = copy_xform; - copy_stmt_read.code = copy_code_read; - //fprintf(stderr, "dp3: copy_stmt_read.code = \n"); - copy_stmt_read.loop_level = std::vector(ro_copy_is.n_set()); - copy_stmt_read.ir_stmt_node = NULL; - copy_stmt_read.has_inspector = false; - for (int i = 0; i < level-1; i++) { - copy_stmt_read.loop_level[i].type = stmt[*(active.begin())].loop_level[i].type; - if (stmt[*(active.begin())].loop_level[i].type == LoopLevelTile && - stmt[*(active.begin())].loop_level[i].payload >= level) { - int j; - for (j = 0; j < privatized_levels.size(); j++) - if (privatized_levels[j] == stmt[*(active.begin())].loop_level[i].payload) - break; - if (j == privatized_levels.size()) - copy_stmt_read.loop_level[i].payload = -1; - else - copy_stmt_read.loop_level[i].payload = level + j; - } - else - copy_stmt_read.loop_level[i].payload = stmt[*(active.begin())].loop_level[i].payload; - copy_stmt_read.loop_level[i].parallel_level = stmt[*(active.begin())].loop_level[i].parallel_level; - } - for (int i = 0; i < privatized_levels.size(); i++) { - copy_stmt_read.loop_level[level-1+i].type = stmt[*(active.begin())].loop_level[privatized_levels[i]].type; - copy_stmt_read.loop_level[level-1+i].payload = stmt[*(active.begin())].loop_level[privatized_levels[i]].payload; - copy_stmt_read.loop_level[level-1+i].parallel_level = stmt[*(active.begin())].loop_level[privatized_levels[i]].parallel_level; - } - int left_num_dim = num_dep_dim - (get_last_dep_dim_before(*(active.begin()), level) + 1); - for (int i = 0; i < std::min(left_num_dim, static_cast(index_sz.size())); i++) { - copy_stmt_read.loop_level[level-1+privatized_levels.size()+i].type = LoopLevelOriginal; - copy_stmt_read.loop_level[level-1+privatized_levels.size()+i].payload = num_dep_dim-left_num_dim+i; - copy_stmt_read.loop_level[level-1+privatized_levels.size()+i].parallel_level = 0; - } - for (int i = std::min(left_num_dim, static_cast(index_sz.size())); i < index_sz.size(); i++) { - copy_stmt_read.loop_level[level-1+privatized_levels.size()+i].type = LoopLevelUnknown; - copy_stmt_read.loop_level[level-1+privatized_levels.size()+i].payload = -1; - copy_stmt_read.loop_level[level-1+privatized_levels.size()+i].parallel_level = 0; - } - - - shiftLexicalOrder(lex, dim-1, 1); - - fprintf(stderr, "loop_datacopy.cc L1071 adding stmt %d\n", stmt.size()); - stmt.push_back(copy_stmt_read); - - uninterpreted_symbols.push_back(uninterpreted_symbols[*(active.begin())]); - uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[*(active.begin())]); - ro_copy_stmt_num = stmt.size() - 1; - dep.insert(); - } - - //fprintf(stderr, "dp3: insert write copy statement\n"); - // insert write copy statement - int wo_copy_stmt_num = -1; - if (has_write_refs) { - Relation copy_xform(wo_copy_is.n_set(), 2*wo_copy_is.n_set()+1); - { - F_And *f_root = copy_xform.add_and(); - for (int i = 1; i <= wo_copy_is.n_set(); i++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(copy_xform.input_var(i), 1); - h.update_coef(copy_xform.output_var(2*i), -1); - } - for (int i = 1; i <= dim; i+=2) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(copy_xform.output_var(i), -1); - h.update_const(lex[i-1]); - } - for (int i = dim+2; i <= copy_xform.n_out(); i+=2) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(copy_xform.output_var(i), 1); - } - } - - Statement copy_stmt_write; - copy_stmt_write.IS = wo_copy_is; - copy_stmt_write.xform = copy_xform; - copy_stmt_write.code = copy_code_write; - copy_stmt_write.loop_level = std::vector(wo_copy_is.n_set()); - copy_stmt_write.ir_stmt_node = NULL; - copy_stmt_write.has_inspector = false; - - for (int i = 0; i < level-1; i++) { - copy_stmt_write.loop_level[i].type = stmt[*(active.begin())].loop_level[i].type; - if (stmt[*(active.begin())].loop_level[i].type == LoopLevelTile && - stmt[*(active.begin())].loop_level[i].payload >= level) { - int j; - for (j = 0; j < privatized_levels.size(); j++) - if (privatized_levels[j] == stmt[*(active.begin())].loop_level[i].payload) - break; - if (j == privatized_levels.size()) - copy_stmt_write.loop_level[i].payload = -1; - else - copy_stmt_write.loop_level[i].payload = level + j; - } - else - copy_stmt_write.loop_level[i].payload = stmt[*(active.begin())].loop_level[i].payload; - copy_stmt_write.loop_level[i].parallel_level = stmt[*(active.begin())].loop_level[i].parallel_level; - } - for (int i = 0; i < privatized_levels.size(); i++) { - copy_stmt_write.loop_level[level-1+i].type = stmt[*(active.begin())].loop_level[privatized_levels[i]].type; - copy_stmt_write.loop_level[level-1+i].payload = stmt[*(active.begin())].loop_level[privatized_levels[i]].payload; - copy_stmt_write.loop_level[level-1+i].parallel_level = stmt[*(active.begin())].loop_level[privatized_levels[i]].parallel_level; - } - int left_num_dim = num_dep_dim - (get_last_dep_dim_before(*(active.begin()), level) + 1); - for (int i = 0; i < std::min(left_num_dim, static_cast(index_sz.size())); i++) { - copy_stmt_write.loop_level[level-1+privatized_levels.size()+i].type = LoopLevelOriginal; - copy_stmt_write.loop_level[level-1+privatized_levels.size()+i].payload = num_dep_dim-left_num_dim+i; - copy_stmt_write.loop_level[level-1+privatized_levels.size()+i].parallel_level = 0; - } - for (int i = std::min(left_num_dim, static_cast(index_sz.size())); i < index_sz.size(); i++) { - copy_stmt_write.loop_level[level-1+privatized_levels.size()+i].type = LoopLevelUnknown; - copy_stmt_write.loop_level[level-1+privatized_levels.size()+i].payload = -1; - copy_stmt_write.loop_level[level-1+privatized_levels.size()+i].parallel_level = 0; - } - lex[dim-1]++; - shiftLexicalOrder(lex, dim-1, -2); - - fprintf(stderr, "loop_datacopy.cc L1147 adding stmt %d\n", stmt.size()); - stmt.push_back(copy_stmt_write); - - uninterpreted_symbols.push_back(uninterpreted_symbols[*(active.begin())]); - uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[*(active.begin())]); - wo_copy_stmt_num = stmt.size() - 1; - dep.insert(); - } - - //fprintf(stderr, "replace original array accesses with temporary array accesses\n"); - // replace original array accesses with temporary array accesses - for (int i =0; i < stmt_refs.size(); i++) - for (int j = 0; j < stmt_refs[i].second.size(); j++) { - if (index_sz.size() == 0) { - IR_ScalarRef *tmp_scalar_ref = ir->CreateScalarRef(static_cast(tmp_sym)); - //fprintf(stderr, "dp3: loop_datacopy.cc calling ReplaceExpression i%d j%d\n", i, j); - ir->ReplaceExpression(stmt_refs[i].second[j], tmp_scalar_ref->convert()); - } - else { - std::vector index_repr(index_sz.size()); - for (int k = 0; k < index_sz.size(); k++) { - int cur_index_num = index_sz[k].first; - - CG_outputRepr *cur_index_repr = ocg->CreateMinus(stmt_refs[i].second[j]->index(cur_index_num), index_lb[cur_index_num]->clone()); - if (padding_stride != 0) { - if (k == n_dim-1) { - coef_t g = gcd(index_stride[cur_index_num], static_cast(padding_stride)); - coef_t t1 = index_stride[cur_index_num] / g; - if (t1 != 1) - cur_index_repr = ocg->CreateIntegerFloor(cur_index_repr, ocg->CreateInt(t1)); - coef_t t2 = padding_stride / g; - if (t2 != 1) - cur_index_repr = ocg->CreateTimes(cur_index_repr, ocg->CreateInt(t2)); - } - else if (index_stride[cur_index_num] != 1) { - cur_index_repr = ocg->CreateIntegerFloor(cur_index_repr, ocg->CreateInt(index_stride[cur_index_num])); - } - } - - if (ir->ArrayIndexStartAt() != 0) - cur_index_repr = ocg->CreatePlus(cur_index_repr, ocg->CreateInt(ir->ArrayIndexStartAt())); - index_repr[k] = cur_index_repr; - } - - IR_ArrayRef *tmp_array_ref = ir->CreateArrayRef(static_cast(tmp_sym), index_repr); - //fprintf(stderr, "loop_datacopy.cc ir->ReplaceExpression( ... )\n"); - ir->ReplaceExpression(stmt_refs[i].second[j], tmp_array_ref->convert()); - } - } - - // update dependence graph - //fprintf(stderr, "update dependence graph\n"); - - int dep_dim = get_last_dep_dim_before(*(active.begin()), level) + 1; - if (ro_copy_stmt_num != -1) { - for (int i = 0; i < old_num_stmt; i++) { - std::vector > D; - - for (DependenceGraph::EdgeList::iterator j = dep.vertex[i].second.begin(); j != dep.vertex[i].second.end();) { - if (active.find(i) != active.end() && active.find(j->first) == active.end()) { - std::vector dvs1, dvs2; - for (int k = 0; k < j->second.size(); k++) { - DependenceVector dv = j->second[k]; - if (dv.sym != NULL && dv.sym->name() == sym->name() && (dv.type == DEP_R2R || dv.type == DEP_R2W)) - dvs1.push_back(dv); - else - dvs2.push_back(dv); - } - j->second = dvs2; - if (dvs1.size() > 0) - dep.connect(ro_copy_stmt_num, j->first, dvs1); - } - else if (active.find(i) == active.end() && active.find(j->first) != active.end()) { - std::vector dvs1, dvs2; - for (int k = 0; k < j->second.size(); k++) { - DependenceVector dv = j->second[k]; - if (dv.sym != NULL && dv.sym->name() == sym->name() && (dv.type == DEP_R2R || dv.type == DEP_W2R)) - dvs1.push_back(dv); - else - dvs2.push_back(dv); - } - j->second = dvs2; - if (dvs1.size() > 0) - D.push_back(dvs1); - } - - if (j->second.size() == 0) - dep.vertex[i].second.erase(j++); - else - j++; - } - - for (int j = 0; j < D.size(); j++) - dep.connect(i, ro_copy_stmt_num, D[j]); - } - - // insert dependences from copy statement loop to copied statements - //fprintf(stderr, "insert dependences from copy statement loop to copied statements\n"); - - DependenceVector dv; - dv.type = DEP_W2R; - dv.sym = tmp_sym->clone(); - dv.lbounds = std::vector(dep.num_dim(), 0); - dv.ubounds = std::vector(dep.num_dim(), 0); - for (int i = dep_dim; i < dep.num_dim(); i++) { - dv.lbounds[i] = -posInfinity; - dv.ubounds[i] = posInfinity; - } - for (std::set::iterator i = active.begin(); i != active.end(); i++) - dep.connect(ro_copy_stmt_num, *i, dv); - } - - if (wo_copy_stmt_num != -1) { - for (int i = 0; i < old_num_stmt; i++) { - std::vector > D; - - for (DependenceGraph::EdgeList::iterator j = dep.vertex[i].second.begin(); j != dep.vertex[i].second.end();) { - if (active.find(i) != active.end() && active.find(j->first) == active.end()) { - std::vector dvs1, dvs2; - for (int k = 0; k < j->second.size(); k++) { - DependenceVector dv = j->second[k]; - if (dv.sym != NULL && dv.sym->name() == sym->name() && (dv.type == DEP_W2R || dv.type == DEP_W2W)) - dvs1.push_back(dv); - else - dvs2.push_back(dv); - } - j->second = dvs2; - if (dvs1.size() > 0) - dep.connect(wo_copy_stmt_num, j->first, dvs1); - } - else if (active.find(i) == active.end() && active.find(j->first) != active.end()) { - std::vector dvs1, dvs2; - for (int k = 0; k < j->second.size(); k++) { - DependenceVector dv = j->second[k]; - if (dv.sym != NULL && dv.sym->name() == sym->name() && (dv.type == DEP_R2W || dv.type == DEP_W2W)) - dvs1.push_back(dv); - else - dvs2.push_back(dv); - } - j->second = dvs2; - if (dvs1.size() > 0) - D.push_back(dvs1); - } - - if (j->second.size() == 0) - dep.vertex[i].second.erase(j++); - else - j++; - } - - for (int j = 0; j < D.size(); j++) - dep.connect(i, wo_copy_stmt_num, D[j]); - } - - // insert dependences from copied statements to write statements - //fprintf(stderr, "dp3: insert dependences from copied statements to write statements\n"); - - DependenceVector dv; - dv.type = DEP_W2R; - dv.sym = tmp_sym->clone(); - dv.lbounds = std::vector(dep.num_dim(), 0); - dv.ubounds = std::vector(dep.num_dim(), 0); - for (int i = dep_dim; i < dep.num_dim(); i++) { - dv.lbounds[i] = -posInfinity; - dv.ubounds[i] = posInfinity; - } - for (std::set::iterator i = active.begin(); i != active.end(); i++) - dep.connect(*i, wo_copy_stmt_num, dv); - - } - - // update variable name for dependences among copied statements - for (int i = 0; i < old_num_stmt; i++) { - if (active.find(i) != active.end()) - for (DependenceGraph::EdgeList::iterator j = dep.vertex[i].second.begin(); j != dep.vertex[i].second.end(); j++) - if (active.find(j->first) != active.end()) - for (int k = 0; k < j->second.size(); k++) { - IR_Symbol *s = tmp_sym->clone(); - j->second[k].sym = s; - } - } - - // insert anti-dependence from write statement to read statement - if (ro_copy_stmt_num != -1 && wo_copy_stmt_num != -1) - if (dep_dim >= 0) { - DependenceVector dv; - dv.type = DEP_R2W; - dv.sym = tmp_sym->clone(); - dv.lbounds = std::vector(dep.num_dim(), 0); - dv.ubounds = std::vector(dep.num_dim(), 0); - for (int k = dep_dim; k < dep.num_dim(); k++) { - dv.lbounds[k] = -posInfinity; - dv.ubounds[k] = posInfinity; - } - for (int k = 0; k < dep_dim; k++) { - if (k != 0) { - dv.lbounds[k-1] = 0; - dv.ubounds[k-1] = 0; - } - dv.lbounds[k] = 1; - dv.ubounds[k] = posInfinity; - dep.connect(wo_copy_stmt_num, ro_copy_stmt_num, dv); - } - } - - //fprintf(stderr, "Loop::datacopy_privatized3() cleanup\n"); - // cleanup - delete sym; - delete tmp_sym; - for (int i = 0; i < index_lb.size(); i++) { - index_lb[i]->clear(); - delete index_lb[i]; - } - for (int i = 0; i < index_sz.size(); i++) { - index_sz[i].second->clear(); - delete index_sz[i].second; - } - - return true; -} - - - diff --git a/src/loop_extra.cc b/src/loop_extra.cc deleted file mode 100644 index dac05bf..0000000 --- a/src/loop_extra.cc +++ /dev/null @@ -1,224 +0,0 @@ -/***************************************************************************** - Copyright (C) 2010 University of Utah - All Rights Reserved. - - Purpose: - Additional loop transformations. - - Notes: - - History: - 07/31/10 Created by Chun Chen -*****************************************************************************/ - -#include -#include -#include "loop.hh" -#include "omegatools.hh" -#include "ir_code.hh" -#include "chill_error.hh" - -using namespace omega; - - -void Loop::shift_to(int stmt_num, int level, int absolute_position) { - // combo - tile(stmt_num, level, 1, level, CountedTile); - std::vector lex = getLexicalOrder(stmt_num); - std::set active = getStatements(lex, 2*level-2); - shift(active, level, absolute_position); - - // remove unnecessary tiled loop since tile size is one - for (std::set::iterator i = active.begin(); i != active.end(); i++) { - int n = stmt[*i].xform.n_out(); - Relation mapping(n, n-2); - F_And *f_root = mapping.add_and(); - for (int j = 1; j <= 2*level; j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(j), 1); - h.update_coef(mapping.input_var(j), -1); - } - for (int j = 2*level+3; j <= n; j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(j-2), 1); - h.update_coef(mapping.input_var(j), -1); - } - stmt[*i].xform = Composition(mapping, stmt[*i].xform); - stmt[*i].xform.simplify(); - - for (int j = 0; j < stmt[*i].loop_level.size(); j++) - if (j != level-1 && - stmt[*i].loop_level[j].type == LoopLevelTile && - stmt[*i].loop_level[j].payload >= level) - stmt[*i].loop_level[j].payload--; - - stmt[*i].loop_level.erase(stmt[*i].loop_level.begin()+level-1); - } -} - - -std::set Loop::unroll_extra(int stmt_num, int level, int unroll_amount, int cleanup_split_level) { - std::set cleanup_stmts = unroll(stmt_num, level, unroll_amount,std::vector< std::vector >(), cleanup_split_level); - for (std::set::iterator i = cleanup_stmts.begin(); i != cleanup_stmts.end(); i++) - unroll(*i, level, 0); - - return cleanup_stmts; -} - -void Loop::peel(int stmt_num, int level, int peel_amount) { - // check for sanity of parameters - if (stmt_num < 0 || stmt_num >= stmt.size()) - throw std::invalid_argument("invalid statement number " + to_string(stmt_num)); - if (level <= 0 || level > stmt[stmt_num].loop_level.size()) - throw std::invalid_argument("invalid loop level " + to_string(level)); - - if (peel_amount == 0) - return; - - std::set subloop = getSubLoopNest(stmt_num, level); - std::vector Rs; - for (std::set::iterator i = subloop.begin(); i != subloop.end(); i++) { - Relation r = getNewIS(*i); - Relation f(r.n_set(), level); - F_And *f_root = f.add_and(); - for (int j = 1; j <= level; j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(f.input_var(2*j), 1); - h.update_coef(f.output_var(j), -1); - } - r = Composition(f, r); - r.simplify(); - Rs.push_back(r); - } - Relation hull = SimpleHull(Rs); - - if (peel_amount > 0) { - GEQ_Handle bound_eq; - bool found_bound = false; - for (GEQ_Iterator e(hull.single_conjunct()->GEQs()); e; e++) - if (!(*e).has_wildcards() && (*e).get_coef(hull.set_var(level)) > 0) { - bound_eq = *e; - found_bound = true; - break; - } - if (!found_bound) - for (GEQ_Iterator e(hull.single_conjunct()->GEQs()); e; e++) - if ((*e).has_wildcards() && (*e).get_coef(hull.set_var(level)) > 0) { - bool is_bound = true; - for (Constr_Vars_Iter cvi(*e, true); cvi; cvi++) { - std::pair result = find_floor_definition(hull, cvi.curr_var()); - if (!result.first) { - is_bound = false; - break; - } - } - if (is_bound) { - bound_eq = *e; - found_bound = true; - break; - } - } - if (!found_bound) - throw loop_error("can't find lower bound for peeling at loop level " + to_string(level)); - - for (int i = 1; i <= peel_amount; i++) { - Relation r(level); - F_Exists *f_exists = r.add_and()->add_exists(); - F_And *f_root = f_exists->add_and(); - GEQ_Handle h = f_root->add_GEQ(); - std::map exists_mapping; - for (Constr_Vars_Iter cvi(bound_eq); cvi; cvi++) - switch (cvi.curr_var()->kind()) { - case Input_Var: - h.update_coef(r.set_var(cvi.curr_var()->get_position()), cvi.curr_coef()); - break; - case Wildcard_Var: { - Variable_ID v = replicate_floor_definition(hull, cvi.curr_var(), r, f_exists, f_root, exists_mapping); - h.update_coef(v, cvi.curr_coef()); - break; - } - case Global_Var: { - Global_Var_ID g = cvi.curr_var()->get_global_var(); - Variable_ID v; - if (g->arity() == 0) - v = r.get_local(g); - else - v = r.get_local(g, cvi.curr_var()->function_of()); - h.update_coef(v, cvi.curr_coef()); - break; - } - default: - assert(false); - } - h.update_const(bound_eq.get_const() - i); - r.simplify(); - - split(stmt_num, level, r); - } - } - else { // peel_amount < 0 - GEQ_Handle bound_eq; - bool found_bound = false; - for (GEQ_Iterator e(hull.single_conjunct()->GEQs()); e; e++) - if (!(*e).has_wildcards() && (*e).get_coef(hull.set_var(level)) < 0) { - bound_eq = *e; - found_bound = true; - break; - } - if (!found_bound) - for (GEQ_Iterator e(hull.single_conjunct()->GEQs()); e; e++) - if ((*e).has_wildcards() && (*e).get_coef(hull.set_var(level)) < 0) { - bool is_bound = true; - for (Constr_Vars_Iter cvi(*e, true); cvi; cvi++) { - std::pair result = find_floor_definition(hull, cvi.curr_var()); - if (!result.first) { - is_bound = false; - break; - } - } - if (is_bound) { - bound_eq = *e; - found_bound = true; - break; - } - } - if (!found_bound) - throw loop_error("can't find upper bound for peeling at loop level " + to_string(level)); - - for (int i = 1; i <= -peel_amount; i++) { - Relation r(level); - F_Exists *f_exists = r.add_and()->add_exists(); - F_And *f_root = f_exists->add_and(); - GEQ_Handle h = f_root->add_GEQ(); - std::map exists_mapping; - for (Constr_Vars_Iter cvi(bound_eq); cvi; cvi++) - switch (cvi.curr_var()->kind()) { - case Input_Var: - h.update_coef(r.set_var(cvi.curr_var()->get_position()), cvi.curr_coef()); - break; - case Wildcard_Var: { - Variable_ID v = replicate_floor_definition(hull, cvi.curr_var(), r, f_exists, f_root, exists_mapping); - h.update_coef(v, cvi.curr_coef()); - break; - } - case Global_Var: { - Global_Var_ID g = cvi.curr_var()->get_global_var(); - Variable_ID v; - if (g->arity() == 0) - v = r.get_local(g); - else - v = r.get_local(g, cvi.curr_var()->function_of()); - h.update_coef(v, cvi.curr_coef()); - break; - } - default: - assert(false); - } - h.update_const(bound_eq.get_const() - i); - r.simplify(); - - split(stmt_num, level, r); - } - } -} - diff --git a/src/loop_tile.cc b/src/loop_tile.cc deleted file mode 100644 index 41c3e7f..0000000 --- a/src/loop_tile.cc +++ /dev/null @@ -1,587 +0,0 @@ -/* - * loop_tile.cc - * - * Created on: Nov 12, 2012 - * Author: anand - */ - -#include -#include "loop.hh" -#include "omegatools.hh" -#include "ir_code.hh" -#include "chill_error.hh" - -using namespace omega; - - - - -void Loop::tile(int stmt_num, int level, int tile_size, int outer_level, - TilingMethodType method, int alignment_offset, int alignment_multiple) { - // check for sanity of parameters - if (tile_size < 0) - throw std::invalid_argument("invalid tile size"); - if (alignment_multiple < 1 || alignment_offset < 0) - throw std::invalid_argument("invalid alignment for tile"); - if (stmt_num < 0 || stmt_num >= stmt.size()) - throw std::invalid_argument("invalid statement " + to_string(stmt_num)); - if (level <= 0) - throw std::invalid_argument("invalid loop level " + to_string(level)); - if (level > stmt[stmt_num].loop_level.size()) - throw std::invalid_argument( - "there is no loop level " + to_string(level) + " for statement " - + to_string(stmt_num)); - if (outer_level <= 0 || outer_level > level) - throw std::invalid_argument( - "invalid tile controlling loop level " - + to_string(outer_level)); - - // invalidate saved codegen computation - delete last_compute_cgr_; - last_compute_cgr_ = NULL; - delete last_compute_cg_; - last_compute_cg_ = NULL; - - int dim = 2 * level - 1; - int outer_dim = 2 * outer_level - 1; - std::vector lex = getLexicalOrder(stmt_num); - std::set same_tiled_loop = getStatements(lex, dim - 1); - std::set same_tile_controlling_loop = getStatements(lex, - outer_dim - 1); - - for (std::set::iterator i = same_tiled_loop.begin(); - i != same_tiled_loop.end(); i++) { - for (DependenceGraph::EdgeList::iterator j = - dep.vertex[*i].second.begin(); j != dep.vertex[*i].second.end(); - j++) { - if (same_tiled_loop.find(j->first) != same_tiled_loop.end()) - for (int k = 0; k < j->second.size(); k++) { - DependenceVector dv = j->second[k]; - int dim2 = level - 1; - if ((dv.type != DEP_CONTROL) && (dv.type != DEP_UNKNOWN)) { - while (stmt[*i].loop_level[dim2].type == LoopLevelTile) { - dim2 = stmt[*i].loop_level[dim2].payload - 1; - } - dim2 = stmt[*i].loop_level[dim2].payload; - - if (dv.hasNegative(dim2) && (!dv.quasi)) { - for (int l = outer_level; l < level; l++) - if (stmt[*i].loop_level[l - 1].type - != LoopLevelTile) { - if (dv.isCarried( - stmt[*i].loop_level[l - 1].payload) - && dv.hasPositive( - stmt[*i].loop_level[l - 1].payload)) - throw loop_error( - "loop error: Tiling is illegal, dependence violation!"); - } else { - - int dim3 = l - 1; - while (stmt[*i].loop_level[l - 1].type - != LoopLevelTile) { - dim3 = - stmt[*i].loop_level[l - 1].payload - - 1; - - } - - dim3 = stmt[*i].loop_level[l - 1].payload; - if (dim3 < level - 1) - if (dv.isCarried(dim3) - && dv.hasPositive(dim3)) - throw loop_error( - "loop error: Tiling is illegal, dependence violation!"); - } - } - } - } - } - } - // special case for no tiling - if (tile_size == 0) { - for (std::set::iterator i = same_tile_controlling_loop.begin(); - i != same_tile_controlling_loop.end(); i++) { - Relation r(stmt[*i].xform.n_out(), stmt[*i].xform.n_out() + 2); - F_And *f_root = r.add_and(); - for (int j = 1; j <= 2 * outer_level - 1; j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(r.input_var(j), 1); - h.update_coef(r.output_var(j), -1); - } - EQ_Handle h1 = f_root->add_EQ(); - h1.update_coef(r.output_var(2 * outer_level), 1); - EQ_Handle h2 = f_root->add_EQ(); - h2.update_coef(r.output_var(2 * outer_level + 1), 1); - for (int j = 2 * outer_level; j <= stmt[*i].xform.n_out(); j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(r.input_var(j), 1); - h.update_coef(r.output_var(j + 2), -1); - } - - stmt[*i].xform = Composition(copy(r), stmt[*i].xform); - } - } - // normal tiling - else { - std::set private_stmt; - for (std::set::iterator i = same_tile_controlling_loop.begin(); - i != same_tile_controlling_loop.end(); i++) { - // should test dim's value directly but it is ok for now - if (same_tiled_loop.find(*i) == same_tiled_loop.end() - && overflow.find(*i) != overflow.end()) - private_stmt.insert(*i); - } - - // extract the union of the iteration space to be considered - Relation hull; - { - std::vector r_list; - - for (std::set::iterator i = same_tile_controlling_loop.begin(); - i != same_tile_controlling_loop.end(); i++) - if (private_stmt.find(*i) == private_stmt.end()) { - Relation r = getNewIS(*i); - for (int j = dim + 2; j <= r.n_set(); j++) - r = Project(r, r.set_var(j)); - for (int j = outer_dim; j < dim; j++) - r = Project(r, j + 1, Set_Var); - for (int j = 0; j < outer_dim; j += 2) - r = Project(r, j + 1, Set_Var); - r.simplify(2, 4); - r_list.push_back(r); - } - - hull = SimpleHull(r_list); - } - - // extract the bound of the dimension to be tiled - Relation bound = get_loop_bound(hull, dim); - if (!bound.has_single_conjunct()) { - // further simplify the bound - hull = Approximate(hull); - bound = get_loop_bound(hull, dim); - - int i = outer_dim - 2; - while (!bound.has_single_conjunct() && i >= 0) { - hull = Project(hull, i + 1, Set_Var); - bound = get_loop_bound(hull, dim); - i -= 2; - } - - if (!bound.has_single_conjunct()) - throw loop_error("cannot handle tile bounds"); - } - - // separate lower and upper bounds - std::vector lb_list, ub_list; - { - Conjunct *c = bound.query_DNF()->single_conjunct(); - for (GEQ_Iterator gi(c->GEQs()); gi; gi++) { - int coef = (*gi).get_coef(bound.set_var(dim + 1)); - if (coef < 0) - ub_list.push_back(*gi); - else if (coef > 0) - lb_list.push_back(*gi); - } - } - if (lb_list.size() == 0) - throw loop_error( - "unable to calculate tile controlling loop lower bound"); - if (ub_list.size() == 0) - throw loop_error( - "unable to calculate tile controlling loop upper bound"); - - // find the simplest lower bound for StridedTile or simplest iteration count for CountedTile - int simplest_lb = 0, simplest_ub = 0; - if (method == StridedTile) { - int best_cost = INT_MAX; - for (int i = 0; i < lb_list.size(); i++) { - int cost = 0; - for (Constr_Vars_Iter ci(lb_list[i]); ci; ci++) { - switch ((*ci).var->kind()) { - case Input_Var: { - cost += 5; - break; - } - case Global_Var: { - cost += 2; - break; - } - default: - cost += 15; - break; - } - } - - if (cost < best_cost) { - best_cost = cost; - simplest_lb = i; - } - } - } else if (method == CountedTile) { - std::map s1, s2, s3; - int best_cost = INT_MAX; - for (int i = 0; i < lb_list.size(); i++) - for (int j = 0; j < ub_list.size(); j++) { - int cost = 0; - - for (Constr_Vars_Iter ci(lb_list[i]); ci; ci++) { - switch ((*ci).var->kind()) { - case Input_Var: { - s1[(*ci).var] += (*ci).coef; - break; - } - case Global_Var: { - s2[(*ci).var] += (*ci).coef; - break; - } - case Exists_Var: - case Wildcard_Var: { - s3[(*ci).var] += (*ci).coef; - break; - } - default: - cost = INT_MAX - 2; - break; - } - } - - for (Constr_Vars_Iter ci(ub_list[j]); ci; ci++) { - switch ((*ci).var->kind()) { - case Input_Var: { - s1[(*ci).var] += (*ci).coef; - break; - } - case Global_Var: { - s2[(*ci).var] += (*ci).coef; - break; - } - case Exists_Var: - case Wildcard_Var: { - s3[(*ci).var] += (*ci).coef; - break; - } - default: - if (cost == INT_MAX - 2) - cost = INT_MAX - 1; - else - cost = INT_MAX - 3; - break; - } - } - - if (cost == 0) { - for (std::map::iterator k = - s1.begin(); k != s1.end(); k++) - if ((*k).second != 0) - cost += 5; - for (std::map::iterator k = - s2.begin(); k != s2.end(); k++) - if ((*k).second != 0) - cost += 2; - for (std::map::iterator k = - s3.begin(); k != s3.end(); k++) - if ((*k).second != 0) - cost += 15; - } - - if (cost < best_cost) { - best_cost = cost; - simplest_lb = i; - simplest_ub = j; - } - } - } - - // prepare the new transformation relations - for (std::set::iterator i = same_tile_controlling_loop.begin(); - i != same_tile_controlling_loop.end(); i++) { - Relation r(stmt[*i].xform.n_out(), stmt[*i].xform.n_out() + 2); - F_And *f_root = r.add_and(); - for (int j = 0; j < outer_dim - 1; j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(r.output_var(j + 1), 1); - h.update_coef(r.input_var(j + 1), -1); - } - - for (int j = outer_dim - 1; j < stmt[*i].xform.n_out(); j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(r.output_var(j + 3), 1); - h.update_coef(r.input_var(j + 1), -1); - } - - EQ_Handle h = f_root->add_EQ(); - h.update_coef(r.output_var(outer_dim), 1); - h.update_const(-lex[outer_dim - 1]); - - stmt[*i].xform = Composition(r, stmt[*i].xform); - } - - // add tiling constraints. - for (std::set::iterator i = same_tile_controlling_loop.begin(); - i != same_tile_controlling_loop.end(); i++) { - F_And *f_super_root = stmt[*i].xform.and_with_and(); - F_Exists *f_exists = f_super_root->add_exists(); - F_And *f_root = f_exists->add_and(); - - // create a lower bound variable for easy formula creation later - Variable_ID aligned_lb; - { - Variable_ID lb = f_exists->declare(); - coef_t coef = lb_list[simplest_lb].get_coef( - bound.set_var(dim + 1)); - if (coef == 1) { // e.g. if i >= m+5, then LB = m+5 - EQ_Handle h = f_root->add_EQ(); - h.update_coef(lb, 1); - for (Constr_Vars_Iter ci(lb_list[simplest_lb]); ci; ci++) { - switch ((*ci).var->kind()) { - case Input_Var: { - int pos = (*ci).var->get_position(); - if (pos != dim + 1) - h.update_coef(stmt[*i].xform.output_var(pos), - (*ci).coef); - break; - } - case Global_Var: { - Global_Var_ID g = (*ci).var->get_global_var(); - Variable_ID v; - if (g->arity() == 0) - v = stmt[*i].xform.get_local(g); - else - v = stmt[*i].xform.get_local(g, - (*ci).var->function_of()); - h.update_coef(v, (*ci).coef); - break; - } - default: - throw loop_error("cannot handle tile bounds"); - } - } - h.update_const(lb_list[simplest_lb].get_const()); - } else { // e.g. if 2i >= m+5, then m+5 <= 2*LB < m+5+2 - GEQ_Handle h1 = f_root->add_GEQ(); - GEQ_Handle h2 = f_root->add_GEQ(); - for (Constr_Vars_Iter ci(lb_list[simplest_lb]); ci; ci++) { - switch ((*ci).var->kind()) { - case Input_Var: { - int pos = (*ci).var->get_position(); - if (pos == dim + 1) { - h1.update_coef(lb, (*ci).coef); - h2.update_coef(lb, -(*ci).coef); - } else { - h1.update_coef(stmt[*i].xform.output_var(pos), - (*ci).coef); - h2.update_coef(stmt[*i].xform.output_var(pos), - -(*ci).coef); - } - break; - } - case Global_Var: { - Global_Var_ID g = (*ci).var->get_global_var(); - Variable_ID v; - if (g->arity() == 0) - v = stmt[*i].xform.get_local(g); - else - v = stmt[*i].xform.get_local(g, - (*ci).var->function_of()); - h1.update_coef(v, (*ci).coef); - h2.update_coef(v, -(*ci).coef); - break; - } - default: - throw loop_error("cannot handle tile bounds"); - } - } - h1.update_const(lb_list[simplest_lb].get_const()); - h2.update_const(-lb_list[simplest_lb].get_const()); - h2.update_const(coef - 1); - } - - Variable_ID offset_lb; - if (alignment_offset == 0) - offset_lb = lb; - else { - EQ_Handle h = f_root->add_EQ(); - offset_lb = f_exists->declare(); - h.update_coef(offset_lb, 1); - h.update_coef(lb, -1); - h.update_const(alignment_offset); - } - - if (alignment_multiple == 1) { // trivial - aligned_lb = offset_lb; - } else { // e.g. to align at 4, aligned_lb = 4*alpha && LB-4 < 4*alpha <= LB - aligned_lb = f_exists->declare(); - Variable_ID e = f_exists->declare(); - - EQ_Handle h = f_root->add_EQ(); - h.update_coef(aligned_lb, 1); - h.update_coef(e, -alignment_multiple); - - GEQ_Handle h1 = f_root->add_GEQ(); - GEQ_Handle h2 = f_root->add_GEQ(); - h1.update_coef(e, alignment_multiple); - h2.update_coef(e, -alignment_multiple); - h1.update_coef(offset_lb, -1); - h2.update_coef(offset_lb, 1); - h1.update_const(alignment_multiple - 1); - } - } - - // create an upper bound variable for easy formula creation later - Variable_ID ub = f_exists->declare(); - { - coef_t coef = -ub_list[simplest_ub].get_coef( - bound.set_var(dim + 1)); - if (coef == 1) { // e.g. if i <= m+5, then UB = m+5 - EQ_Handle h = f_root->add_EQ(); - h.update_coef(ub, -1); - for (Constr_Vars_Iter ci(ub_list[simplest_ub]); ci; ci++) { - switch ((*ci).var->kind()) { - case Input_Var: { - int pos = (*ci).var->get_position(); - if (pos != dim + 1) - h.update_coef(stmt[*i].xform.output_var(pos), - (*ci).coef); - break; - } - case Global_Var: { - Global_Var_ID g = (*ci).var->get_global_var(); - Variable_ID v; - if (g->arity() == 0) - v = stmt[*i].xform.get_local(g); - else - v = stmt[*i].xform.get_local(g, - (*ci).var->function_of()); - h.update_coef(v, (*ci).coef); - break; - } - default: - throw loop_error("cannot handle tile bounds"); - } - } - h.update_const(ub_list[simplest_ub].get_const()); - } else { // e.g. if 2i <= m+5, then m+5-2 < 2*UB <= m+5 - GEQ_Handle h1 = f_root->add_GEQ(); - GEQ_Handle h2 = f_root->add_GEQ(); - for (Constr_Vars_Iter ci(ub_list[simplest_ub]); ci; ci++) { - switch ((*ci).var->kind()) { - case Input_Var: { - int pos = (*ci).var->get_position(); - if (pos == dim + 1) { - h1.update_coef(ub, -(*ci).coef); - h2.update_coef(ub, (*ci).coef); - } else { - h1.update_coef(stmt[*i].xform.output_var(pos), - -(*ci).coef); - h2.update_coef(stmt[*i].xform.output_var(pos), - (*ci).coef); - } - break; - } - case Global_Var: { - Global_Var_ID g = (*ci).var->get_global_var(); - Variable_ID v; - if (g->arity() == 0) - v = stmt[*i].xform.get_local(g); - else - v = stmt[*i].xform.get_local(g, - (*ci).var->function_of()); - h1.update_coef(v, -(*ci).coef); - h2.update_coef(v, (*ci).coef); - break; - } - default: - throw loop_error("cannot handle tile bounds"); - } - } - h1.update_const(-ub_list[simplest_ub].get_const()); - h2.update_const(ub_list[simplest_ub].get_const()); - h1.update_const(coef - 1); - } - } - - // insert tile controlling loop constraints - if (method == StridedTile) { // e.g. ii = LB + 32 * alpha && alpha >= 0 - Variable_ID e = f_exists->declare(); - GEQ_Handle h1 = f_root->add_GEQ(); - h1.update_coef(e, 1); - - EQ_Handle h2 = f_root->add_EQ(); - h2.update_coef(stmt[*i].xform.output_var(outer_dim + 1), 1); - h2.update_coef(e, -tile_size); - h2.update_coef(aligned_lb, -1); - } else if (method == CountedTile) { // e.g. 0 <= ii < ceiling((UB-LB+1)/32) - GEQ_Handle h1 = f_root->add_GEQ(); - h1.update_coef(stmt[*i].xform.output_var(outer_dim + 1), 1); - - GEQ_Handle h2 = f_root->add_GEQ(); - h2.update_coef(stmt[*i].xform.output_var(outer_dim + 1), - -tile_size); - h2.update_coef(aligned_lb, -1); - h2.update_coef(ub, 1); - } - - // special care for private statements like overflow assignment - if (private_stmt.find(*i) != private_stmt.end()) { // e.g. ii <= UB - GEQ_Handle h = f_root->add_GEQ(); - h.update_coef(stmt[*i].xform.output_var(outer_dim + 1), -1); - h.update_coef(ub, 1); - } - - // restrict original loop index inside the tile - else { - if (method == StridedTile) { // e.g. ii <= i < ii + tile_size - GEQ_Handle h1 = f_root->add_GEQ(); - h1.update_coef(stmt[*i].xform.output_var(dim + 3), 1); - h1.update_coef(stmt[*i].xform.output_var(outer_dim + 1), - -1); - - GEQ_Handle h2 = f_root->add_GEQ(); - h2.update_coef(stmt[*i].xform.output_var(dim + 3), -1); - h2.update_coef(stmt[*i].xform.output_var(outer_dim + 1), 1); - h2.update_const(tile_size - 1); - } else if (method == CountedTile) { // e.g. LB+32*ii <= i < LB+32*ii+tile_size - GEQ_Handle h1 = f_root->add_GEQ(); - h1.update_coef(stmt[*i].xform.output_var(outer_dim + 1), - -tile_size); - h1.update_coef(stmt[*i].xform.output_var(dim + 3), 1); - h1.update_coef(aligned_lb, -1); - - GEQ_Handle h2 = f_root->add_GEQ(); - h2.update_coef(stmt[*i].xform.output_var(outer_dim + 1), - tile_size); - h2.update_coef(stmt[*i].xform.output_var(dim + 3), -1); - h2.update_const(tile_size - 1); - h2.update_coef(aligned_lb, 1); - } - } - } - } - - // update loop level information - for (std::set::iterator i = same_tile_controlling_loop.begin(); - i != same_tile_controlling_loop.end(); i++) { - for (int j = 1; j <= stmt[*i].loop_level.size(); j++) - switch (stmt[*i].loop_level[j - 1].type) { - case LoopLevelOriginal: - break; - case LoopLevelTile: - if (stmt[*i].loop_level[j - 1].payload >= outer_level) - stmt[*i].loop_level[j - 1].payload++; - break; - default: - throw loop_error( - "unknown loop level type for statement " - + to_string(*i)); - } - - LoopLevel ll; - ll.type = LoopLevelTile; - ll.payload = level + 1; - ll.parallel_level = 0; - stmt[*i].loop_level.insert( - stmt[*i].loop_level.begin() + (outer_level - 1), ll); - } -} - diff --git a/src/loop_unroll.cc b/src/loop_unroll.cc deleted file mode 100644 index 86ffd84..0000000 --- a/src/loop_unroll.cc +++ /dev/null @@ -1,1222 +0,0 @@ -/* - * loop_unroll.cc - * - * Created on: Nov 12, 2012 - * Author: anand - */ - -#include -#include -#include "loop.hh" -#include "omegatools.hh" -#include "ir_code.hh" -#include "chill_error.hh" -#include - -using namespace omega; - - -std::set Loop::unroll(int stmt_num, int level, int unroll_amount, - std::vector > idxNames, - int cleanup_split_level) { - // check for sanity of parameters - // check for sanity of parameters - if (unroll_amount < 0) - throw std::invalid_argument( - "invalid unroll amount " + to_string(unroll_amount)); - if (stmt_num < 0 || stmt_num >= stmt.size()) - throw std::invalid_argument("invalid statement " + to_string(stmt_num)); - if (level <= 0 || level > stmt[stmt_num].loop_level.size()) - throw std::invalid_argument("invalid loop level " + to_string(level)); - - if (cleanup_split_level == 0) - cleanup_split_level = level; - if (cleanup_split_level > level) - throw std::invalid_argument( - "cleanup code must be split at or outside the unrolled loop level " - + to_string(level)); - if (cleanup_split_level <= 0) - throw std::invalid_argument( - "invalid split loop level " + to_string(cleanup_split_level)); - - // invalidate saved codegen computation - delete last_compute_cgr_; - last_compute_cgr_ = NULL; - delete last_compute_cg_; - last_compute_cg_ = NULL; - - int dim = 2 * level - 1; - std::vector lex = getLexicalOrder(stmt_num); - std::set same_loop = getStatements(lex, dim - 1); - - // nothing to do - if (unroll_amount == 1) - return std::set(); - - for (std::set::iterator i = same_loop.begin(); i != same_loop.end(); - i++) { - std::vector > D; - int n = stmt[*i].xform.n_out(); - for (DependenceGraph::EdgeList::iterator j = - dep.vertex[*i].second.begin(); j != dep.vertex[*i].second.end(); - j++) { - if (same_loop.find(j->first) != same_loop.end()) - for (int k = 0; k < j->second.size(); k++) { - DependenceVector dv = j->second[k]; - int dim2 = level - 1; - if (dv.type != DEP_CONTROL) { - - while (stmt[*i].loop_level[dim2].type == LoopLevelTile) { - dim2 = stmt[*i].loop_level[dim2].payload - 1; - } - dim2 = stmt[*i].loop_level[dim2].payload; - - /*if (dv.isCarried(dim2) - && (dv.hasNegative(dim2) && !dv.quasi)) - throw loop_error( - "loop error: Unrolling is illegal, dependence violation!"); - - if (dv.isCarried(dim2) - && (dv.hasPositive(dim2) && dv.quasi)) - throw loop_error( - "loop error: Unrolling is illegal, dependence violation!"); - */ - bool safe = false; - - if (dv.isCarried(dim2) && dv.hasPositive(dim2)) { - if (dv.quasi) - throw loop_error( - "loop error: a quasi dependence with a positive carried distance"); - if (!dv.quasi) { - if (dv.lbounds[dim2] != posInfinity) { - //if (dv.lbounds[dim2] != negInfinity) - if (dv.lbounds[dim2] > unroll_amount) - safe = true; - } else - safe = true; - }/* else { - if (dv.ubounds[dim2] != negInfinity) { - if (dv.ubounds[dim2] != posInfinity) - if ((-(dv.ubounds[dim2])) > unroll_amount) - safe = true; - } else - safe = true; - }*/ - - if (!safe) { - for (int l = level + 1; l <= (n - 1) / 2; l++) { - int dim3 = l - 1; - - if (stmt[*i].loop_level[dim3].type - != LoopLevelTile) - dim3 = - stmt[*i].loop_level[dim3].payload; - else { - while (stmt[*i].loop_level[dim3].type - == LoopLevelTile) { - dim3 = - stmt[*i].loop_level[dim3].payload - - 1; - } - dim3 = - stmt[*i].loop_level[dim3].payload; - } - - if (dim3 > dim2) { - - if (dv.hasPositive(dim3)) - break; - else if (dv.hasNegative(dim3)) - throw loop_error( - "loop error: Unrolling is illegal, dependence violation!"); - } - } - } - } - } - } - } - } - // extract the intersection of the iteration space to be considered - Relation hull = Relation::True(level); - apply_xform(same_loop); - for (std::set::iterator i = same_loop.begin(); i != same_loop.end(); - i++) { - if (stmt[*i].IS.is_upper_bound_satisfiable()) { - Relation mapping(stmt[*i].IS.n_set(), level); - F_And *f_root = mapping.add_and(); - for (int j = 1; j <= level; j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.input_var(j), 1); - h.update_coef(mapping.output_var(j), -1); - } - hull = Intersection(hull, - omega::Range(Restrict_Domain(mapping, copy(stmt[*i].IS)))); - hull.simplify(2, 4); - - } - } - for (int i = 1; i <= level; i++) { - std::string name = tmp_loop_var_name_prefix + to_string(i); - hull.name_set_var(i, name); - } - hull.setup_names(); - - // extract the exact loop bound of the dimension to be unrolled - if (is_single_loop_iteration(hull, level, this->known)) - return std::set(); - Relation bound = get_loop_bound(hull, level, this->known); - if (!bound.has_single_conjunct() || !bound.is_satisfiable() - || bound.is_tautology()) - throw loop_error("unable to extract loop bound for unrolling"); - - // extract the loop stride - coef_t stride; - std::pair result = find_simplest_stride(bound, - bound.set_var(level)); - if (result.second == NULL) - stride = 1; - else - stride = abs(result.first.get_coef(result.second)) - / gcd(abs(result.first.get_coef(result.second)), - abs(result.first.get_coef(bound.set_var(level)))); - - // separate lower and upper bounds - std::vector lb_list, ub_list; - { - Conjunct *c = bound.query_DNF()->single_conjunct(); - for (GEQ_Iterator gi(c->GEQs()); gi; gi++) { - int coef = (*gi).get_coef(bound.set_var(level)); - if (coef < 0) - ub_list.push_back(*gi); - else if (coef > 0) - lb_list.push_back(*gi); - } - } - - // simplify overflow expression for each pair of upper and lower bounds - std::vector > > overflow_table( - lb_list.size(), - std::vector >(ub_list.size(), - std::map())); - bool is_overflow_simplifiable = true; - for (int i = 0; i < lb_list.size(); i++) { - if (!is_overflow_simplifiable) - break; - - for (int j = 0; j < ub_list.size(); j++) { - // lower bound or upper bound has non-unit coefficient, can't simplify - if (ub_list[j].get_coef(bound.set_var(level)) != -1 - || lb_list[i].get_coef(bound.set_var(level)) != 1) { - is_overflow_simplifiable = false; - break; - } - - for (Constr_Vars_Iter ci(ub_list[j]); ci; ci++) { - switch ((*ci).var->kind()) { - case Input_Var: { - if ((*ci).var != bound.set_var(level)) - overflow_table[i][j][(*ci).var] += (*ci).coef; - - break; - } - case Global_Var: { - Global_Var_ID g = (*ci).var->get_global_var(); - Variable_ID v; - if (g->arity() == 0) - v = bound.get_local(g); - else - v = bound.get_local(g, (*ci).var->function_of()); - overflow_table[i][j][(*ci).var] += (*ci).coef; - break; - } - default: - throw loop_error("failed to calculate overflow amount"); - } - } - overflow_table[i][j][NULL] += ub_list[j].get_const(); - - for (Constr_Vars_Iter ci(lb_list[i]); ci; ci++) { - switch ((*ci).var->kind()) { - case Input_Var: { - if ((*ci).var != bound.set_var(level)) { - overflow_table[i][j][(*ci).var] += (*ci).coef; - if (overflow_table[i][j][(*ci).var] == 0) - overflow_table[i][j].erase( - overflow_table[i][j].find((*ci).var)); - } - break; - } - case Global_Var: { - Global_Var_ID g = (*ci).var->get_global_var(); - Variable_ID v; - if (g->arity() == 0) - v = bound.get_local(g); - else - v = bound.get_local(g, (*ci).var->function_of()); - overflow_table[i][j][(*ci).var] += (*ci).coef; - if (overflow_table[i][j][(*ci).var] == 0) - overflow_table[i][j].erase( - overflow_table[i][j].find((*ci).var)); - break; - } - default: - throw loop_error("failed to calculate overflow amount"); - } - } - overflow_table[i][j][NULL] += lb_list[i].get_const(); - - overflow_table[i][j][NULL] += stride; - if (unroll_amount == 0 - || (overflow_table[i][j].size() == 1 - && overflow_table[i][j][NULL] / stride - < unroll_amount)) - unroll_amount = overflow_table[i][j][NULL] / stride; - } - } - - // loop iteration count can't be determined, bail out gracefully - if (unroll_amount == 0) - return std::set(); - - // further simply overflow calculation using coefficients' modular - if (is_overflow_simplifiable) { - for (int i = 0; i < lb_list.size(); i++) - for (int j = 0; j < ub_list.size(); j++) - if (stride == 1) { - for (std::map::iterator k = - overflow_table[i][j].begin(); - k != overflow_table[i][j].end();) - if ((*k).first != NULL) { - int t = int_mod_hat((*k).second, unroll_amount); - if (t == 0) { - overflow_table[i][j].erase(k++); - } else { - int t2 = hull.query_variable_mod((*k).first, - unroll_amount); - if (t2 != INT_MAX) { - overflow_table[i][j][NULL] += t * t2; - overflow_table[i][j].erase(k++); - } else { - (*k).second = t; - k++; - } - } - } else - k++; - - overflow_table[i][j][NULL] = int_mod_hat( - overflow_table[i][j][NULL], unroll_amount); - - // Since we don't have MODULO instruction in SUIF yet (only MOD), - // make all coef positive in the final formula - for (std::map::iterator k = - overflow_table[i][j].begin(); - k != overflow_table[i][j].end(); k++) - if ((*k).second < 0) - (*k).second += unroll_amount; - } - } - - // build overflow statement - CG_outputBuilder *ocg = ir->builder(); - CG_outputRepr *overflow_code = NULL; - Relation cond_upper(level), cond_lower(level); - Relation overflow_constraint(0); - F_And *overflow_constraint_root = overflow_constraint.add_and(); - std::vector over_var_list; - if (is_overflow_simplifiable && lb_list.size() == 1) { - for (int i = 0; i < ub_list.size(); i++) { - if (overflow_table[0][i].size() == 1) { - // upper splitting condition - GEQ_Handle h = cond_upper.and_with_GEQ(ub_list[i]); - h.update_const( - ((overflow_table[0][i][NULL] / stride) % unroll_amount) - * -stride); - } else { - // upper splitting condition - std::string over_name = overflow_var_name_prefix - + to_string(overflow_var_name_counter++); - Free_Var_Decl *over_free_var = new Free_Var_Decl(over_name); - over_var_list.push_back(over_free_var); - GEQ_Handle h = cond_upper.and_with_GEQ(ub_list[i]); - h.update_coef(cond_upper.get_local(over_free_var), -stride); - - // insert constraint 0 <= overflow < unroll_amount - Variable_ID v = overflow_constraint.get_local(over_free_var); - GEQ_Handle h1 = overflow_constraint_root->add_GEQ(); - h1.update_coef(v, 1); - GEQ_Handle h2 = overflow_constraint_root->add_GEQ(); - h2.update_coef(v, -1); - h2.update_const(unroll_amount - 1); - - // create overflow assignment - bound.setup_names(); // hack to fix omega relation variable names issue - CG_outputRepr *rhs = NULL; - bool is_split_illegal = false; - for (std::map::iterator j = - overflow_table[0][i].begin(); - j != overflow_table[0][i].end(); j++) - if ((*j).first != NULL) { - if ((*j).first->kind() == Input_Var - && (*j).first->get_position() - >= cleanup_split_level) - is_split_illegal = true; - - CG_outputRepr *t = ocg->CreateIdent((*j).first->name()); - if ((*j).second != 1) - t = ocg->CreateTimes(ocg->CreateInt((*j).second), - t); - rhs = ocg->CreatePlus(rhs, t); - } else if ((*j).second != 0) - rhs = ocg->CreatePlus(rhs, ocg->CreateInt((*j).second)); - - if (is_split_illegal) { - rhs->clear(); - delete rhs; - throw loop_error( - "cannot split cleanup code at loop level " - + to_string(cleanup_split_level) - + " due to overflow variable data dependence"); - } - - if (stride != 1) - rhs = ocg->CreateIntegerCeil(rhs, ocg->CreateInt(stride)); - rhs = ocg->CreateIntegerMod(rhs, ocg->CreateInt(unroll_amount)); - - CG_outputRepr *lhs = ocg->CreateIdent(over_name); - init_code = ocg->StmtListAppend(init_code, - ocg->CreateAssignment(0, lhs, ocg->CreateInt(0))); - lhs = ocg->CreateIdent(over_name); - overflow_code = ocg->StmtListAppend(overflow_code, - ocg->CreateAssignment(0, lhs, rhs)); - } - } - - // lower splitting condition - GEQ_Handle h = cond_lower.and_with_GEQ(lb_list[0]); - } else if (is_overflow_simplifiable && ub_list.size() == 1) { - for (int i = 0; i < lb_list.size(); i++) { - - if (overflow_table[i][0].size() == 1) { - // lower splitting condition - GEQ_Handle h = cond_lower.and_with_GEQ(lb_list[i]); - h.update_const(overflow_table[i][0][NULL] * -stride); - } else { - // lower splitting condition - std::string over_name = overflow_var_name_prefix - + to_string(overflow_var_name_counter++); - Free_Var_Decl *over_free_var = new Free_Var_Decl(over_name); - over_var_list.push_back(over_free_var); - GEQ_Handle h = cond_lower.and_with_GEQ(lb_list[i]); - h.update_coef(cond_lower.get_local(over_free_var), -stride); - - // insert constraint 0 <= overflow < unroll_amount - Variable_ID v = overflow_constraint.get_local(over_free_var); - GEQ_Handle h1 = overflow_constraint_root->add_GEQ(); - h1.update_coef(v, 1); - GEQ_Handle h2 = overflow_constraint_root->add_GEQ(); - h2.update_coef(v, -1); - h2.update_const(unroll_amount - 1); - - // create overflow assignment - bound.setup_names(); // hack to fix omega relation variable names issue - CG_outputRepr *rhs = NULL; - for (std::map::iterator j = - overflow_table[0][i].begin(); - j != overflow_table[0][i].end(); j++) - if ((*j).first != NULL) { - CG_outputRepr *t = ocg->CreateIdent((*j).first->name()); - if ((*j).second != 1) - t = ocg->CreateTimes(ocg->CreateInt((*j).second), - t); - rhs = ocg->CreatePlus(rhs, t); - } else if ((*j).second != 0) - rhs = ocg->CreatePlus(rhs, ocg->CreateInt((*j).second)); - - if (stride != 1) - rhs = ocg->CreateIntegerCeil(rhs, ocg->CreateInt(stride)); - rhs = ocg->CreateIntegerMod(rhs, ocg->CreateInt(unroll_amount)); - - CG_outputRepr *lhs = ocg->CreateIdent(over_name); - init_code = ocg->StmtListAppend(init_code, - ocg->CreateAssignment(0, lhs, ocg->CreateInt(0))); - lhs = ocg->CreateIdent(over_name); - overflow_code = ocg->StmtListAppend(overflow_code, - ocg->CreateAssignment(0, lhs, rhs)); - } - } - - // upper splitting condition - GEQ_Handle h = cond_upper.and_with_GEQ(ub_list[0]); - } else { - std::string over_name = overflow_var_name_prefix - + to_string(overflow_var_name_counter++); - Free_Var_Decl *over_free_var = new Free_Var_Decl(over_name); - over_var_list.push_back(over_free_var); - - std::vector lb_repr_list, ub_repr_list; - for (int i = 0; i < lb_list.size(); i++) { - lb_repr_list.push_back( - output_lower_bound_repr(ocg, - lb_list[i], - bound.set_var(dim + 1), result.first, result.second, - bound, Relation::True(bound.n_set()), - std::vector >( - bound.n_set(), - std::make_pair( - static_cast(NULL), - 0)), - uninterpreted_symbols[stmt_num])); - GEQ_Handle h = cond_lower.and_with_GEQ(lb_list[i]); - } - for (int i = 0; i < ub_list.size(); i++) { - ub_repr_list.push_back( - output_upper_bound_repr(ocg, ub_list[i], - bound.set_var(dim + 1), bound, - std::vector >( - bound.n_set(), - std::make_pair( - static_cast(NULL), - 0)), - uninterpreted_symbols[stmt_num])); - GEQ_Handle h = cond_upper.and_with_GEQ(ub_list[i]); - h.update_coef(cond_upper.get_local(over_free_var), -stride); - } - - CG_outputRepr *lbRepr, *ubRepr; - if (lb_repr_list.size() > 1) { - //fprintf(stderr, "loop_unroll.cc createInvoke( max )\n"); - lbRepr = ocg->CreateInvoke("max", lb_repr_list); - } - else if (lb_repr_list.size() == 1) { - lbRepr = lb_repr_list[0]; - } - - if (ub_repr_list.size() > 1) { - //fprintf(stderr, "loop_unroll.cc createInvoke( min )\n"); - ubRepr = ocg->CreateInvoke("min", ub_repr_list); - } - else if (ub_repr_list.size() == 1) { - ubRepr = ub_repr_list[0]; - } - - // create overflow assignment - CG_outputRepr *rhs = ocg->CreatePlus(ocg->CreateMinus(ubRepr, lbRepr), - ocg->CreateInt(1)); - if (stride != 1) - rhs = ocg->CreateIntegerFloor(rhs, ocg->CreateInt(stride)); - rhs = ocg->CreateIntegerMod(rhs, ocg->CreateInt(unroll_amount)); - CG_outputRepr *lhs = ocg->CreateIdent(over_name); - init_code = ocg->StmtListAppend(init_code, - ocg->CreateAssignment(0, lhs, ocg->CreateInt(0))); - lhs = ocg->CreateIdent(over_name); - overflow_code = ocg->CreateAssignment(0, lhs, rhs); - - // insert constraint 0 <= overflow < unroll_amount - Variable_ID v = overflow_constraint.get_local(over_free_var); - GEQ_Handle h1 = overflow_constraint_root->add_GEQ(); - h1.update_coef(v, 1); - GEQ_Handle h2 = overflow_constraint_root->add_GEQ(); - h2.update_coef(v, -1); - h2.update_const(unroll_amount - 1); - } - - // insert overflow statement - int overflow_stmt_num = -1; - if (overflow_code != NULL) { - // build iteration space for overflow statement - Relation mapping(level, cleanup_split_level - 1); - F_And *f_root = mapping.add_and(); - for (int i = 1; i < cleanup_split_level; i++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(i), 1); - h.update_coef(mapping.input_var(i), -1); - } - Relation overflow_IS = omega::Range(Restrict_Domain(mapping, copy(hull))); - for (int i = 1; i < cleanup_split_level; i++) - overflow_IS.name_set_var(i, hull.set_var(i)->name()); - overflow_IS.setup_names(); - - // build dumb transformation relation for overflow statement - Relation overflow_xform(cleanup_split_level - 1, - 2 * (cleanup_split_level - 1) + 1); - f_root = overflow_xform.add_and(); - for (int i = 1; i <= cleanup_split_level - 1; i++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(overflow_xform.output_var(2 * i), 1); - h.update_coef(overflow_xform.input_var(i), -1); - - h = f_root->add_EQ(); - h.update_coef(overflow_xform.output_var(2 * i - 1), 1); - h.update_const(-lex[2 * i - 2]); - } - EQ_Handle h = f_root->add_EQ(); - h.update_coef( - overflow_xform.output_var(2 * (cleanup_split_level - 1) + 1), - 1); - h.update_const(-lex[2 * (cleanup_split_level - 1)]); - - shiftLexicalOrder(lex, 2 * cleanup_split_level - 2, 1); - Statement overflow_stmt; - - overflow_stmt.code = overflow_code; - overflow_stmt.IS = overflow_IS; - overflow_stmt.xform = overflow_xform; - overflow_stmt.loop_level = std::vector(level - 1); - overflow_stmt.ir_stmt_node = NULL; - for (int i = 0; i < level - 1; i++) { - overflow_stmt.loop_level[i].type = - stmt[stmt_num].loop_level[i].type; - if (stmt[stmt_num].loop_level[i].type == LoopLevelTile - && stmt[stmt_num].loop_level[i].payload >= level) - overflow_stmt.loop_level[i].payload = -1; - else - overflow_stmt.loop_level[i].payload = - stmt[stmt_num].loop_level[i].payload; - overflow_stmt.loop_level[i].parallel_level = - stmt[stmt_num].loop_level[i].parallel_level; - } - - fprintf(stderr, "loop_unroll.cc L581 adding stmt %d\n", stmt.size()); - stmt.push_back(overflow_stmt); - - uninterpreted_symbols.push_back(uninterpreted_symbols[stmt_num]); - uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[stmt_num]); - dep.insert(); - overflow_stmt_num = stmt.size() - 1; - overflow[overflow_stmt_num] = over_var_list; - - // update the global known information on overflow variable - this->known = Intersection(this->known, - Extend_Set(copy(overflow_constraint), - this->known.n_set() - overflow_constraint.n_set())); - - // update dependence graph - DependenceVector dv; - dv.type = DEP_CONTROL; - for (std::set::iterator i = same_loop.begin(); - i != same_loop.end(); i++) - dep.connect(overflow_stmt_num, *i, dv); - dv.type = DEP_W2W; - { - IR_ScalarSymbol *overflow_sym = NULL; - std::vector scalars = ir->FindScalarRef(overflow_code); - for (int i = scalars.size() - 1; i >= 0; i--) - if (scalars[i]->is_write()) { - overflow_sym = scalars[i]->symbol(); - break; - } - for (int i = scalars.size() - 1; i >= 0; i--) - delete scalars[i]; - dv.sym = overflow_sym; - } - dv.lbounds = std::vector(dep.num_dim(), 0); - dv.ubounds = std::vector(dep.num_dim(), 0); - int dep_dim = get_last_dep_dim_before(stmt_num, level); - for (int i = dep_dim + 1; i < dep.num_dim(); i++) { - dv.lbounds[i] = -posInfinity; - dv.ubounds[i] = posInfinity; - } - for (int i = 0; i <= dep_dim; i++) { - if (i != 0) { - dv.lbounds[i - 1] = 0; - dv.ubounds[i - 1] = 0; - } - dv.lbounds[i] = 1; - dv.ubounds[i] = posInfinity; - dep.connect(overflow_stmt_num, overflow_stmt_num, dv); - } - } - - // split the loop so it can be fully unrolled - std::set new_stmts = split(stmt_num, cleanup_split_level, cond_upper); - std::set new_stmts2 = split(stmt_num, cleanup_split_level, cond_lower); - new_stmts.insert(new_stmts2.begin(), new_stmts2.end()); - - // check if unrolled statements can be trivially lumped together as one statement - bool can_be_lumped = true; - if (can_be_lumped) { - for (std::set::iterator i = same_loop.begin(); - i != same_loop.end(); i++) - if (*i != stmt_num) { - if (stmt[*i].loop_level.size() - != stmt[stmt_num].loop_level.size()) { - can_be_lumped = false; - break; - } - for (int j = 0; j < stmt[stmt_num].loop_level.size(); j++) - if (!(stmt[*i].loop_level[j].type - == stmt[stmt_num].loop_level[j].type - && stmt[*i].loop_level[j].payload - == stmt[stmt_num].loop_level[j].payload)) { - can_be_lumped = false; - break; - } - if (!can_be_lumped) - break; - std::vector lex2 = getLexicalOrder(*i); - for (int j = 2 * level; j < lex.size() - 1; j += 2) - if (lex[j] != lex2[j]) { - can_be_lumped = false; - break; - } - if (!can_be_lumped) - break; - } - } - if (can_be_lumped) { - for (std::set::iterator i = same_loop.begin(); - i != same_loop.end(); i++) - if (is_inner_loop_depend_on_level(stmt[*i].IS, level, - this->known)) { - can_be_lumped = false; - break; - } - } - if (can_be_lumped) { - for (std::set::iterator i = same_loop.begin(); - i != same_loop.end(); i++) - if (*i != stmt_num) { - if (!(Must_Be_Subset(copy(stmt[*i].IS), copy(stmt[stmt_num].IS)) - && Must_Be_Subset(copy(stmt[stmt_num].IS), - copy(stmt[*i].IS)))) { - can_be_lumped = false; - break; - } - } - } - if (can_be_lumped) { - for (std::set::iterator i = same_loop.begin(); - i != same_loop.end(); i++) { - for (DependenceGraph::EdgeList::iterator j = - dep.vertex[*i].second.begin(); - j != dep.vertex[*i].second.end(); j++) - if (same_loop.find(j->first) != same_loop.end()) { - for (int k = 0; k < j->second.size(); k++) - if (j->second[k].type == DEP_CONTROL - || j->second[k].type == DEP_UNKNOWN) { - can_be_lumped = false; - break; - } - if (!can_be_lumped) - break; - } - if (!can_be_lumped) - break; - } - } - - // insert unrolled statements - int old_num_stmt = stmt.size(); - if (!can_be_lumped) { - std::map > what_stmt_num; - - for (int j = 1; j < unroll_amount; j++) { - for (std::set::iterator i = same_loop.begin(); - i != same_loop.end(); i++) { - Statement new_stmt; - - std::vector loop_vars; - std::vector subs; - loop_vars.push_back(stmt[*i].IS.set_var(level)->name()); - subs.push_back( - ocg->CreatePlus( - ocg->CreateIdent( - stmt[*i].IS.set_var(level)->name()), - ocg->CreateInt(j * stride))); - new_stmt.code = ocg->CreateSubstitutedStmt(0, - stmt[*i].code->clone(), loop_vars, subs); - - new_stmt.IS = adjust_loop_bound(stmt[*i].IS, level, j * stride); - add_loop_stride(new_stmt.IS, bound, level - 1, - unroll_amount * stride); - - new_stmt.xform = copy(stmt[*i].xform); - - new_stmt.loop_level = stmt[*i].loop_level; - new_stmt.ir_stmt_node = NULL; - - fprintf(stderr, "loop_unroll.cc L740 adding stmt %d\n", stmt.size()); - stmt.push_back(new_stmt); - - uninterpreted_symbols.push_back(uninterpreted_symbols[stmt_num]); - uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[stmt_num]); - dep.insert(); - what_stmt_num[*i].push_back(stmt.size() - 1); - } - } - for (std::set::iterator i = same_loop.begin(); - i != same_loop.end(); i++) - add_loop_stride(stmt[*i].IS, bound, level - 1, - unroll_amount * stride); - - // update dependence graph - if (stmt[stmt_num].loop_level[level - 1].type == LoopLevelOriginal) { - int dep_dim = stmt[stmt_num].loop_level[level - 1].payload; - int new_stride = unroll_amount * stride; - for (int i = 0; i < old_num_stmt; i++) { - std::vector > D; - - for (DependenceGraph::EdgeList::iterator j = - dep.vertex[i].second.begin(); - j != dep.vertex[i].second.end();) { - if (same_loop.find(i) != same_loop.end()) { - if (same_loop.find(j->first) != same_loop.end()) { - for (int k = 0; k < j->second.size(); k++) { - DependenceVector dv = j->second[k]; - if (dv.type == DEP_CONTROL - || dv.type == DEP_UNKNOWN) { - D.push_back(std::make_pair(j->first, dv)); - for (int kk = 0; kk < unroll_amount - 1; - kk++) - if (what_stmt_num[i][kk] != -1 - && what_stmt_num[j->first][kk] - != -1) - dep.connect(what_stmt_num[i][kk], - what_stmt_num[j->first][kk], - dv); - } else { - coef_t lb = dv.lbounds[dep_dim]; - coef_t ub = dv.ubounds[dep_dim]; - if (ub == lb - && int_mod(lb, - static_cast(new_stride)) - == 0) { - D.push_back( - std::make_pair(j->first, dv)); - for (int kk = 0; kk < unroll_amount - 1; - kk++) - if (what_stmt_num[i][kk] != -1 - && what_stmt_num[j->first][kk] - != -1) - dep.connect( - what_stmt_num[i][kk], - what_stmt_num[j->first][kk], - dv); - } else if (lb == -posInfinity - && ub == posInfinity) { - D.push_back( - std::make_pair(j->first, dv)); - for (int kk = 0; kk < unroll_amount; - kk++) - if (kk == 0) - D.push_back( - std::make_pair(j->first, - dv)); - else if (what_stmt_num[j->first][kk - - 1] != -1) - D.push_back( - std::make_pair( - what_stmt_num[j->first][kk - - 1], - dv)); - for (int t = 0; t < unroll_amount - 1; - t++) - if (what_stmt_num[i][t] != -1) - for (int kk = 0; - kk < unroll_amount; - kk++) - if (kk == 0) - dep.connect( - what_stmt_num[i][t], - j->first, dv); - else if (what_stmt_num[j->first][kk - - 1] != -1) - dep.connect( - what_stmt_num[i][t], - what_stmt_num[j->first][kk - - 1], - dv); - } else { - for (int kk = 0; kk < unroll_amount; - kk++) { - if (lb != -posInfinity) { - if (kk * stride - < int_mod(lb, - static_cast(new_stride))) - dv.lbounds[dep_dim] = - floor( - static_cast(lb) - / new_stride) - * new_stride - + new_stride; - else - dv.lbounds[dep_dim] = - floor( - static_cast(lb) - / new_stride) - * new_stride; - } - if (ub != posInfinity) { - if (kk * stride - > int_mod(ub, - static_cast(new_stride))) - dv.ubounds[dep_dim] = - floor( - static_cast(ub) - / new_stride) - * new_stride - - new_stride; - else - dv.ubounds[dep_dim] = - floor( - static_cast(ub) - / new_stride) - * new_stride; - } - if (dv.ubounds[dep_dim] - >= dv.lbounds[dep_dim]) { - if (kk == 0) - D.push_back( - std::make_pair( - j->first, - dv)); - else if (what_stmt_num[j->first][kk - - 1] != -1) - D.push_back( - std::make_pair( - what_stmt_num[j->first][kk - - 1], - dv)); - } - } - for (int t = 0; t < unroll_amount - 1; - t++) - if (what_stmt_num[i][t] != -1) - for (int kk = 0; - kk < unroll_amount; - kk++) { - if (lb != -posInfinity) { - if (kk * stride - < int_mod( - lb + t - + 1, - static_cast(new_stride))) - dv.lbounds[dep_dim] = - floor( - static_cast(lb - + (t - + 1) - * stride) - / new_stride) - * new_stride - + new_stride; - else - dv.lbounds[dep_dim] = - floor( - static_cast(lb - + (t - + 1) - * stride) - / new_stride) - * new_stride; - } - if (ub != posInfinity) { - if (kk * stride - > int_mod( - ub + t - + 1, - static_cast(new_stride))) - dv.ubounds[dep_dim] = - floor( - static_cast(ub - + (t - + 1) - * stride) - / new_stride) - * new_stride - - new_stride; - else - dv.ubounds[dep_dim] = - floor( - static_cast(ub - + (t - + 1) - * stride) - / new_stride) - * new_stride; - } - if (dv.ubounds[dep_dim] - >= dv.lbounds[dep_dim]) { - if (kk == 0) - dep.connect( - what_stmt_num[i][t], - j->first, - dv); - else if (what_stmt_num[j->first][kk - - 1] != -1) - dep.connect( - what_stmt_num[i][t], - what_stmt_num[j->first][kk - - 1], - dv); - } - } - } - } - } - - dep.vertex[i].second.erase(j++); - } else { - for (int kk = 0; kk < unroll_amount - 1; kk++) - if (what_stmt_num[i][kk] != -1) - dep.connect(what_stmt_num[i][kk], j->first, - j->second); - - j++; - } - } else { - if (same_loop.find(j->first) != same_loop.end()) - for (int k = 0; k < j->second.size(); k++) - for (int kk = 0; kk < unroll_amount - 1; kk++) - if (what_stmt_num[j->first][kk] != -1) - D.push_back( - std::make_pair( - what_stmt_num[j->first][kk], - j->second[k])); - j++; - } - } - - for (int j = 0; j < D.size(); j++) - dep.connect(i, D[j].first, D[j].second); - } - } - - // reset lexical order for the unrolled loop body - std::set new_same_loop; - - int count = 0; - - for (std::map >::iterator i = - what_stmt_num.begin(); i != what_stmt_num.end(); i++) { - - new_same_loop.insert(i->first); - for (int k = dim + 1; k < stmt[i->first].xform.n_out(); k += 2) - assign_const(stmt[i->first].xform, k, - get_const(stmt[(what_stmt_num.begin())->first].xform, k, - Output_Var) + count); - count++; - for (int j = 0; j < i->second.size(); j++) { - new_same_loop.insert(i->second[j]); - for (int k = dim + 1; k < stmt[i->second[j]].xform.n_out(); k += - 2) - assign_const(stmt[i->second[j]].xform, k, - get_const( - stmt[(what_stmt_num.begin())->first].xform, - k, Output_Var) + count); - count++; - } - } - setLexicalOrder(dim + 1, new_same_loop, 0, idxNames); - } else { - for (std::set::iterator i = same_loop.begin(); - i != same_loop.end(); i++) - add_loop_stride(stmt[*i].IS, bound, level - 1, - unroll_amount * stride); - - int max_level = stmt[stmt_num].loop_level.size(); - std::vector > stmt_order; - for (std::set::iterator i = same_loop.begin(); - i != same_loop.end(); i++) - stmt_order.push_back( - std::make_pair( - get_const(stmt[*i].xform, 2 * max_level, - Output_Var), *i)); - sort(stmt_order.begin(), stmt_order.end()); - - Statement new_stmt; - new_stmt.code = NULL; - for (int j = 1; j < unroll_amount; j++) { - for (int i = 0; i < stmt_order.size(); i++) { - std::vector loop_vars; - std::vector subs; - - //fprintf(stderr, "loop_unroll.cc, will replace '%s with '%s+%d' ??\n", - // stmt[stmt_order[i].second].IS.set_var(level)->name().c_str(), - // stmt[stmt_order[i].second].IS.set_var(level)->name().c_str(), j * stride); - - loop_vars.push_back( - stmt[stmt_order[i].second].IS.set_var(level)->name()); - subs.push_back( - ocg->CreatePlus(ocg->CreateIdent(stmt[stmt_order[i].second].IS.set_var(level)->name()), - ocg->CreateInt(j * stride))); // BUG HERE - //fprintf(stderr, "loop_unroll.cc subs now has %d parts\n", subs.size()); - //for (int k=0; k< subs.size(); k++) //fprintf(stderr, "subs[%d] = 0x%x\n", k, subs[k]); - - //fprintf(stderr, "ij %d %d ", i, j); - //fprintf(stderr, "old src was =\n"); - //stmt[stmt_order[i].second].code->dump(); fflush(stdout); //fprintf(stderr, "\n"); - - - - CG_outputRepr *code = ocg->CreateSubstitutedStmt(0, - stmt[stmt_order[i].second].code->clone(), - loop_vars, - subs); - - //fprintf(stderr, "old src is =\n"); - //stmt[stmt_order[i].second].code->dump(); fflush(stdout); //fprintf(stderr, "\n"); - - //fprintf(stderr, "substituted copy is =\n"); - //code->dump(); //fprintf(stderr, "\n\n"); - - - new_stmt.code = ocg->StmtListAppend(new_stmt.code, code); - //fprintf(stderr, "appended code =\n"); - //new_stmt.code->dump(); - - } - } - - - - //fprintf(stderr, "new_stmt.IS = \n"); - new_stmt.IS = copy(stmt[stmt_num].IS); - new_stmt.xform = copy(stmt[stmt_num].xform); - assign_const(new_stmt.xform, 2 * max_level, - stmt_order[stmt_order.size() - 1].first + 1); - new_stmt.loop_level = stmt[stmt_num].loop_level; - new_stmt.ir_stmt_node = NULL; - - new_stmt.has_inspector = false; // ?? or from copied stmt? - if (stmt[stmt_num].has_inspector) fprintf(stderr, "OLD STMT HAS INSPECTOR\n"); - else fprintf(stderr, "OLD STMT DOES NOT HAVE INSPECTOR\n"); - - fprintf(stderr, "loop_unroll.cc L1083 adding stmt %d\n", stmt.size()); - stmt.push_back(new_stmt); - - uninterpreted_symbols.push_back(uninterpreted_symbols[stmt_num]); - uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[stmt_num]); - dep.insert(); - - //fprintf(stderr, "update dependence graph\n"); - // update dependence graph - if (stmt[stmt_num].loop_level[level - 1].type == LoopLevelOriginal) { - int dep_dim = stmt[stmt_num].loop_level[level - 1].payload; - int new_stride = unroll_amount * stride; - for (int i = 0; i < old_num_stmt; i++) { - std::vector > > D; - - for (DependenceGraph::EdgeList::iterator j = - dep.vertex[i].second.begin(); - j != dep.vertex[i].second.end();) { - if (same_loop.find(i) != same_loop.end()) { - if (same_loop.find(j->first) != same_loop.end()) { - std::vector dvs11, dvs12, dvs22, - dvs21; - for (int k = 0; k < j->second.size(); k++) { - DependenceVector dv = j->second[k]; - if (dv.type == DEP_CONTROL - || dv.type == DEP_UNKNOWN) { - if (i == j->first) { - dvs11.push_back(dv); - dvs22.push_back(dv); - } else - throw loop_error( - "unrolled statements lumped together illegally"); - } else { - coef_t lb = dv.lbounds[dep_dim]; - coef_t ub = dv.ubounds[dep_dim]; - if (ub == lb - && int_mod(lb, - static_cast(new_stride)) - == 0) { - dvs11.push_back(dv); - dvs22.push_back(dv); - } else { - if (lb != -posInfinity) - dv.lbounds[dep_dim] = ceil( - static_cast(lb) - / new_stride) - * new_stride; - if (ub != posInfinity) - dv.ubounds[dep_dim] = floor( - static_cast(ub) - / new_stride) - * new_stride; - if (dv.ubounds[dep_dim] - >= dv.lbounds[dep_dim]) - dvs11.push_back(dv); - - if (lb != -posInfinity) - dv.lbounds[dep_dim] = ceil( - static_cast(lb) - / new_stride) - * new_stride; - if (ub != posInfinity) - dv.ubounds[dep_dim] = ceil( - static_cast(ub) - / new_stride) - * new_stride; - if (dv.ubounds[dep_dim] - >= dv.lbounds[dep_dim]) - dvs21.push_back(dv); - - if (lb != -posInfinity) - dv.lbounds[dep_dim] = floor( - static_cast(lb) - / new_stride) - * new_stride; - if (ub != posInfinity) - dv.ubounds[dep_dim] = floor( - static_cast(ub - - stride) - / new_stride) - * new_stride; - if (dv.ubounds[dep_dim] - >= dv.lbounds[dep_dim]) - dvs12.push_back(dv); - - if (lb != -posInfinity) - dv.lbounds[dep_dim] = floor( - static_cast(lb) - / new_stride) - * new_stride; - if (ub != posInfinity) - dv.ubounds[dep_dim] = ceil( - static_cast(ub - - stride) - / new_stride) - * new_stride; - if (dv.ubounds[dep_dim] - >= dv.lbounds[dep_dim]) - dvs22.push_back(dv); - } - } - } - if (dvs11.size() > 0) - D.push_back(std::make_pair(i, dvs11)); - if (dvs22.size() > 0) - dep.connect(old_num_stmt, old_num_stmt, dvs22); - if (dvs12.size() > 0) - D.push_back( - std::make_pair(old_num_stmt, dvs12)); - if (dvs21.size() > 0) - dep.connect(old_num_stmt, i, dvs21); - - dep.vertex[i].second.erase(j++); - } else { - dep.connect(old_num_stmt, j->first, j->second); - j++; - } - } else { - if (same_loop.find(j->first) != same_loop.end()) - D.push_back( - std::make_pair(old_num_stmt, j->second)); - j++; - } - } - - for (int j = 0; j < D.size(); j++) - dep.connect(i, D[j].first, D[j].second); - } - } - } - - //fprintf(stderr, " loop_unroll.cc returning new_stmts\n"); - return new_stmts; -} - - diff --git a/src/omegatools.cc b/src/omegatools.cc index 0322182..7ebe726 100644 --- a/src/omegatools.cc +++ b/src/omegatools.cc @@ -19,7 +19,7 @@ #include "ir_code.hh" #include "chill_error.hh" -#include "chill_ast.hh" +#include "chillAST/chillASTs.hh" #include "code_gen/CG_chillRepr.h" #include diff --git a/src/transformations/loop.cc b/src/transformations/loop.cc new file mode 100644 index 0000000..570bc90 --- /dev/null +++ b/src/transformations/loop.cc @@ -0,0 +1,4433 @@ +/***************************************************************************** + Copyright (C) 2008 University of Southern California + Copyright (C) 2009-2010 University of Utah + All Rights Reserved. + + Purpose: + Core loop transformation functionality. + + Notes: + "level" (starting from 1) means loop level and it corresponds to "dim" + (starting from 0) in transformed iteration space [c_1,l_1,c_2,l_2,...., + c_n,l_n,c_(n+1)], e.g., l_2 is loop level 2 in generated code, dim 3 + in transformed iteration space, and variable 4 in Omega relation. + All c's are constant numbers only and they will not show up as actual loops. + Formula: + dim = 2*level - 1 + var = dim + 1 + + History: + 10/2005 Created by Chun Chen. + 09/2009 Expand tile functionality, -chun + 10/2009 Initialize unfusible loop nest without bailing out, -chun +*****************************************************************************/ + +#include +#include +#include +#include +#include +#include // Mark. Bad idea. TODO +#include +#include +#include +#include "loop.hh" +#include "omegatools.hh" +#include "irtools.hh" +#include "chill_error.hh" +#include +#include +#include + +// TODO +#define _DEBUG_ true + + + +using namespace omega; + +const std::string Loop::tmp_loop_var_name_prefix = std::string("chill_t"); // Manu:: In fortran, first character of a variable name must be a letter, so this change +const std::string Loop::overflow_var_name_prefix = std::string("over"); + +void echocontroltype( const IR_Control *control ) { + switch(control->type()) { + case IR_CONTROL_BLOCK: { + CHILL_DEBUG_PRINT("IR_CONTROL_BLOCK\n"); + break; + } + case IR_CONTROL_LOOP: { + CHILL_DEBUG_PRINT("IR_CONTROL_LOOP\n"); + break; + } + case IR_CONTROL_IF: { + CHILL_DEBUG_PRINT("IR_CONTROL_IF\n"); + break; + } + default: + CHILL_DEBUG_PRINT("just a bunch of statements?\n"); + + } // switch +} + +omega::Relation Loop::getNewIS(int stmt_num) const { + + omega::Relation result; + + if (stmt[stmt_num].xform.is_null()) { + omega::Relation known = omega::Extend_Set(omega::copy(this->known), + stmt[stmt_num].IS.n_set() - this->known.n_set()); + result = omega::Intersection(omega::copy(stmt[stmt_num].IS), known); + } else { + omega::Relation known = omega::Extend_Set(omega::copy(this->known), + stmt[stmt_num].xform.n_out() - this->known.n_set()); + result = omega::Intersection( + omega::Range( + omega::Restrict_Domain( + omega::copy(stmt[stmt_num].xform), + omega::copy(stmt[stmt_num].IS))), known); + } + + result.simplify(2, 4); + + return result; +} + + + +void Loop::reduce(int stmt_num, + std::vector &level, + int param, + std::string func_name, + std::vector &seq_levels, + std::vector cudaized_levels, + int bound_level) { + + // illegal instruction?? fprintf(stderr, " Loop::reduce( stmt %d, param %d, func_name (encrypted)...)\n", stmt, param); // , func_name.c_str()); + + //std::cout << "Reducing stmt# " << stmt_num << " at level " << level << "\n"; + //ir->printStmt(stmt[stmt_num].code); + + if (stmt[stmt_num].reduction != 1) { + CHILL_DEBUG_PRINT("Cannot reduce this statement\n"); + return; + } + CHILL_DEBUG_PRINT("CAN reduce this statment?\n"); + + /*for (int i = 0; i < level.size(); i++) + if (stmt[stmt_num].loop_level[level[i] - 1].segreducible != true) { + std::cout << "Cannot reduce this statement\n"; + return; + } + for (int i = 0; i < seq_levels.size(); i++) + if (stmt[stmt_num].loop_level[seq_levels[i] - 1].segreducible != true) { + std::cout << "Cannot reduce this statement\n"; + return; + } + */ + // std::pair to_insert(level, func_name); + // reduced_statements.insert(std::pair >(stmt_num, to_insert )); + // invalidate saved codegen computation + delete last_compute_cgr_; + last_compute_cgr_ = NULL; + delete last_compute_cg_; + last_compute_cg_ = NULL; + fprintf(stderr, "set last_compute_cg_ = NULL;\n"); + + omega::CG_outputBuilder *ocg = ir->builder(); + + omega::CG_outputRepr *funCallRepr; + std::vector arg_repr_list; + apply_xform(stmt_num); + std::vector access = ir->FindArrayRef(stmt[stmt_num].code); + std::set names; + for (int i = 0; i < access.size(); i++) { + std::vector access2; + for (int j = 0; j < access[i]->n_dim(); j++) { + std::vector access3 = ir->FindArrayRef( + access[i]->index(j)); + access2.insert(access2.end(), access3.begin(), access3.end()); + } + if (access2.size() == 0) { + if (names.find(access[i]->name()) == names.end()) { + arg_repr_list.push_back( + ocg->CreateAddressOf(access[i]->convert())); + names.insert(access[i]->name()); + if (access[i]->is_write()) + reduced_write_refs.insert(access[i]->name()); + } + } else { + if (names.find(access[i]->name()) == names.end()) { + arg_repr_list.push_back(ocg->CreateAddressOf(ocg->CreateArrayRefExpression(ocg->CreateIdent(access[i]->name()), + ocg->CreateInt(0)))); + names.insert(access[i]->name()); + if (access[i]->is_write()) + reduced_write_refs.insert(access[i]->name()); + } + } + } + + for (int i = 0; i < seq_levels.size(); i++) + arg_repr_list.push_back( + ocg->CreateIdent( + stmt[stmt_num].IS.set_var(seq_levels[i])->name())); + + if (bound_level != -1) { + + omega::Relation new_IS = copy(stmt[stmt_num].IS); + new_IS.copy_names(stmt[stmt_num].IS); + new_IS.setup_names(); + new_IS.simplify(); + int dim = bound_level; + //omega::Relation r = getNewIS(stmt_num); + for (int j = dim + 1; j <= new_IS.n_set(); j++) + new_IS = omega::Project(new_IS, new_IS.set_var(j)); + + new_IS.simplify(2, 4); + + omega::Relation bound_ = get_loop_bound(copy(new_IS), dim - 1); + omega::Variable_ID v = bound_.set_var(dim); + std::vector ubList; + for (omega::GEQ_Iterator e( + const_cast(bound_).single_conjunct()->GEQs()); + e; e++) { + if ((*e).get_coef(v) < 0) { + // && (*e).is_const_except_for_global(v)) + omega::CG_outputRepr *UPPERBOUND = + omega::output_upper_bound_repr(ir->builder(), *e, v, + bound_, + std::vector< + std::pair >( + bound_.n_set(), + std::make_pair( + static_cast(NULL), + 0)), uninterpreted_symbols[stmt_num]); + if (UPPERBOUND != NULL) + ubList.push_back(UPPERBOUND); + + } + + } + + omega::CG_outputRepr * ubRepr; + if (ubList.size() > 1) { + + ubRepr = ir->builder()->CreateInvoke("min", ubList); + arg_repr_list.push_back(ubRepr); + } else if (ubList.size() == 1) + arg_repr_list.push_back(ubList[0]); + } + + funCallRepr = ocg->CreateInvoke(func_name, arg_repr_list); + stmt[stmt_num].code = funCallRepr; + for (int i = 0; i < level.size(); i++) { + //stmt[*i].code = outputStatement(ocg, stmt[*i].code, 0, mapping, known, std::vector(mapping.n_out(), NULL)); + std::vector loop_vars; + loop_vars.push_back(stmt[stmt_num].IS.set_var(level[i])->name()); + + std::vector subs; + subs.push_back(ocg->CreateInt(0)); + + stmt[stmt_num].code = ocg->CreateSubstitutedStmt(0, stmt[stmt_num].code, + loop_vars, subs); + + } + + omega::Relation new_IS = copy(stmt[stmt_num].IS); + new_IS.copy_names(stmt[stmt_num].IS); + new_IS.setup_names(); + new_IS.simplify(); + int old_size = new_IS.n_set(); + + omega::Relation R = omega::copy(stmt[stmt_num].IS); + R.copy_names(stmt[stmt_num].IS); + R.setup_names(); + + for (int i = level.size() - 1; i >= 0; i--) { + int j; + + for (j = 0; j < cudaized_levels.size(); j++) { + if (cudaized_levels[j] == level[i]) + break; + + } + + if (j == cudaized_levels.size()) { + R = omega::Project(R, level[i], omega::Input_Var); + R.simplify(); + + } + // + + } + + omega::F_And *f_Root = R.and_with_and(); + for (int i = level.size() - 1; i >= 0; i--) { + int j; + + for (j = 0; j < cudaized_levels.size(); j++) { + if (cudaized_levels[j] == level[i]) + break; + + } + + if (j == cudaized_levels.size()) { + + omega::EQ_Handle h = f_Root->add_EQ(); + + h.update_coef(R.set_var(level[i]), 1); + h.update_const(-1); + } + // + + } + + R.simplify(); + stmt[stmt_num].IS = R; +} + + + + + + +//----------------------------------------------------------------------------- +// Class Loop +//----------------------------------------------------------------------------- +// --begin Anand: Added from CHiLL 0.2 + +bool Loop::isInitialized() const { + return stmt.size() != 0 && !stmt[0].xform.is_null(); +} + +//--end Anand: added from CHiLL 0.2 + +bool Loop::init_loop(std::vector &ir_tree, + std::vector &ir_stmt) { + + CHILL_DEBUG_PRINT("extract_ir_stmts()\n"); + CHILL_DEBUG_PRINT("ir_tree has %d statements\n", ir_tree.size()); + + ir_stmt = extract_ir_stmts(ir_tree); + + CHILL_DEBUG_PRINT("nesting level stmt size = %d\n", (int)ir_stmt.size()); + stmt_nesting_level_.resize(ir_stmt.size()); + + std::vector stmt_nesting_level(ir_stmt.size()); + + CHILL_DEBUG_PRINT("%d statements?\n", (int)ir_stmt.size()); + + // find out how deeply nested each statement is. (how can these be different?) + for (int i = 0; i < ir_stmt.size(); i++) { + fprintf(stderr, "i %d\n", i); + ir_stmt[i]->payload = i; + int t = 0; + ir_tree_node *itn = ir_stmt[i]; + while (itn->parent != NULL) { + itn = itn->parent; + if (itn->content->type() == IR_CONTROL_LOOP) + t++; + } + stmt_nesting_level_[i] = t; + stmt_nesting_level[i] = t; + CHILL_DEBUG_PRINT("stmt_nesting_level[%d] = %d\n", i, t); + } + + if (actual_code.size() == 0) + actual_code = std::vector(ir_stmt.size()); + + stmt = std::vector(ir_stmt.size()); + CHILL_DEBUG_PRINT("in init_loop, made %d stmts\n", (int)ir_stmt.size()); + + uninterpreted_symbols = std::vector > >(ir_stmt.size()); + uninterpreted_symbols_stringrepr = std::vector > >(ir_stmt.size()); + + int n_dim = -1; + int max_loc; + //std::vector index; + for (int i = 0; i < ir_stmt.size(); i++) { + int max_nesting_level = -1; + int loc; + + // find the max nesting level and remember the statement that was at that level + for (int j = 0; j < ir_stmt.size(); j++) { + if (stmt_nesting_level[j] > max_nesting_level) { + max_nesting_level = stmt_nesting_level[j]; + loc = j; + } + } + + CHILL_DEBUG_PRINT("max nesting level %d at location %d\n", max_nesting_level, loc); + + // most deeply nested statement acting as a reference point + if (n_dim == -1) { + CHILL_DEBUG_PRINT("n_dim now max_nesting_level %d\n", max_nesting_level); + n_dim = max_nesting_level; + max_loc = loc; + + index = std::vector(n_dim); + + ir_tree_node *itn = ir_stmt[loc]; + CHILL_DEBUG_PRINT("itn = stmt[%d]\n", loc); + int cur_dim = n_dim - 1; + while (itn->parent != NULL) { + CHILL_DEBUG_PRINT("parent\n"); + + itn = itn->parent; + if (itn->content->type() == IR_CONTROL_LOOP) { + CHILL_DEBUG_PRINT("IR_CONTROL_LOOP cur_dim %d\n", cur_dim); + IR_Loop *IRL = static_cast(itn->content); + index[cur_dim] = IRL->index()->name(); + CHILL_DEBUG_PRINT("index[%d] = '%s'\n", cur_dim, index[cur_dim].c_str()); + itn->payload = cur_dim--; + } + } + } + + CHILL_DEBUG_PRINT("align loops by names,\n"); + // align loops by names, temporary solution + ir_tree_node *itn = ir_stmt[loc]; // defined outside loops?? + int depth = stmt_nesting_level_[loc] - 1; + + for (int t = depth; t >= 0; t--) { + int y = t; + itn = ir_stmt[loc]; + + while ((itn->parent != NULL) && (y >= 0)) { + itn = itn->parent; + if (itn->content->type() == IR_CONTROL_LOOP) + y--; + } + + if (itn->content->type() == IR_CONTROL_LOOP && itn->payload == -1) { + CG_outputBuilder *ocg = ir->builder(); + + itn->payload = depth - t; + + CG_outputRepr *code = + static_cast(ir_stmt[loc]->content)->extract(); + + std::vector index_expr; + std::vector old_index; + CG_outputRepr *repl = ocg->CreateIdent(index[itn->payload]); + index_expr.push_back(repl); + old_index.push_back( + static_cast(itn->content)->index()->name()); + code = ocg->CreateSubstitutedStmt(0, code, old_index, + index_expr); + + replace.insert(std::pair(loc, code)); + //stmt[loc].code = code; + + } + } + + CHILL_DEBUG_PRINT("set relation variable names ****\n"); + // set relation variable names + + // this finds the loop variables for loops enclosing this statement and puts + // them in an Omega Relation (just their names, which could fail) + + CHILL_DEBUG_PRINT("Relation r(%d)\n", n_dim); + Relation r(n_dim); + F_And *f_root = r.add_and(); + itn = ir_stmt[loc]; + int temp_depth = depth; + while (itn->parent != NULL) { + + itn = itn->parent; + if (itn->content->type() == IR_CONTROL_LOOP) { + fprintf(stderr, "it's a loop. temp_depth %d\n", temp_depth); + fprintf(stderr, "r.name_set_var( %d, %s )\n", itn->payload + 1, index[temp_depth].c_str()); + r.name_set_var(itn->payload + 1, index[temp_depth]); + + temp_depth--; + } + //static_cast(itn->content)->index()->name()); + } + fprintf(stderr, "Relation r "); r.print(); fflush(stdout); + //fprintf(stderr, "f_root "); f_root->print(stderr); fprintf(stderr, "\n"); + + /*while (itn->parent != NULL) { + itn = itn->parent; + if (itn->content->type() == IR_CONTROL_LOOP) + r.name_set_var(itn->payload+1, static_cast(itn->content)->index()->name()); + }*/ + + + + + fprintf(stderr, "extract information from loop/if structures\n"); + // extract information from loop/if structures + std::vector processed(n_dim, false); + std::vector vars_to_be_reversed; + + std::vector insp_lb; + std::vector insp_ub; + + itn = ir_stmt[loc]; + while (itn->parent != NULL) { // keep heading upward + itn = itn->parent; + + switch (itn->content->type()) { + case IR_CONTROL_LOOP: { + fprintf(stderr, "loop.cc l 462 IR_CONTROL_LOOP\n"); + IR_Loop *lp = static_cast(itn->content); + Variable_ID v = r.set_var(itn->payload + 1); + int c; + + try { + c = lp->step_size(); + //fprintf(stderr, "step size %d\n", c); + if (c > 0) { + CG_outputRepr *lb = lp->lower_bound(); + fprintf(stderr, "loop.cc, got the lower bound. it is:\n"); + lb->dump(); printf("\n"); fflush(stdout); + + exp2formula(ir, r, f_root, freevar, lb, v, 's', + IR_COND_GE, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); + + CG_outputRepr *ub = lp->upper_bound(); + //fprintf(stderr, "loop.cc, got the upper bound. it is:\n"); + //ub->dump(); printf("\n"); fflush(stdout); + + + + IR_CONDITION_TYPE cond = lp->stop_cond(); + if (cond == IR_COND_LT || cond == IR_COND_LE) + exp2formula(ir, r, f_root, freevar, ub, v, 's', + cond, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); + else + throw ir_error("loop condition not supported"); + + + if ((ir->QueryExpOperation(lp->lower_bound()) + == IR_OP_ARRAY_VARIABLE) + && (ir->QueryExpOperation(lp->lower_bound()) + == ir->QueryExpOperation( + lp->upper_bound()))) { + + fprintf(stderr, "loop.cc lower and upper are both IR_OP_ARRAY_VARIABLE?\n"); + + std::vector v = + ir->QueryExpOperand(lp->lower_bound()); + IR_ArrayRef *ref = + static_cast(ir->Repr2Ref( + v[0])); + std::string s0 = ref->name(); + std::vector v2 = + ir->QueryExpOperand(lp->upper_bound()); + IR_ArrayRef *ref2 = + static_cast(ir->Repr2Ref( + v2[0])); + std::string s1 = ref2->name(); + + if (s0 == s1) { + insp_lb.push_back(s0); + insp_ub.push_back(s1); + + } + + } + + + } else if (c < 0) { + CG_outputBuilder *ocg = ir->builder(); + CG_outputRepr *lb = lp->lower_bound(); + lb = ocg->CreateMinus(NULL, lb); + exp2formula(ir, r, f_root, freevar, lb, v, 's', + IR_COND_GE, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); + CG_outputRepr *ub = lp->upper_bound(); + ub = ocg->CreateMinus(NULL, ub); + IR_CONDITION_TYPE cond = lp->stop_cond(); + if (cond == IR_COND_GE) + exp2formula(ir, r, f_root, freevar, ub, v, 's', + IR_COND_LE, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); + else if (cond == IR_COND_GT) + exp2formula(ir, r, f_root, freevar, ub, v, 's', + IR_COND_LT, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); + else + throw ir_error("loop condition not supported"); + + vars_to_be_reversed.push_back(lp->index()->name()); + } else + throw ir_error("loop step size zero"); + } catch (const ir_error &e) { + actual_code[loc] = + static_cast(ir_stmt[loc]->content)->extract(); + for (int i = 0; i < itn->children.size(); i++) + delete itn->children[i]; + itn->children = std::vector(); + itn->content = itn->content->convert(); + return false; + } + + // check for loop increment or decrement that is not 1 + //fprintf(stderr, "abs(c)\n"); + if (abs(c) != 1) { + F_Exists *f_exists = f_root->add_exists(); + Variable_ID e = f_exists->declare(); + F_And *f_and = f_exists->add_and(); + Stride_Handle h = f_and->add_stride(abs(c)); + if (c > 0) + h.update_coef(e, 1); + else + h.update_coef(e, -1); + h.update_coef(v, -1); + CG_outputRepr *lb = lp->lower_bound(); + exp2formula(ir, r, f_and, freevar, lb, e, 's', IR_COND_EQ, + true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); + } + + processed[itn->payload] = true; + break; + } + + + case IR_CONTROL_IF: { + fprintf(stderr, "IR_CONTROL_IF\n"); + IR_If *theif = static_cast(itn->content); + + CG_outputRepr *cond = + static_cast(itn->content)->condition(); + + try { + if (itn->payload % 2 == 1) + exp2constraint(ir, r, f_root, freevar, cond, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); + else { + F_Not *f_not = f_root->add_not(); + F_And *f_and = f_not->add_and(); + exp2constraint(ir, r, f_and, freevar, cond, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); + } + } catch (const ir_error &e) { + std::vector *t; + if (itn->parent == NULL) + t = &ir_tree; + else + t = &(itn->parent->children); + int id = itn->payload; + int i = t->size() - 1; + while (i >= 0) { + if ((*t)[i] == itn) { + for (int j = 0; j < itn->children.size(); j++) + delete itn->children[j]; + itn->children = std::vector(); + itn->content = itn->content->convert(); + } else if ((*t)[i]->payload >> 1 == id >> 1) { + delete (*t)[i]; + t->erase(t->begin() + i); + } + i--; + } + return false; + } + + break; + } + default: + //fprintf(stderr, "default?\n"); + for (int i = 0; i < itn->children.size(); i++) + delete itn->children[i]; + itn->children = std::vector(); + itn->content = itn->content->convert(); + return false; + } + } + + + //fprintf(stderr, "add information for missing loops n_dim(%d)\n", n_dim); + // add information for missing loops + for (int j = 0; j < n_dim; j++) + if (!processed[j]) { + ir_tree_node *itn = ir_stmt[max_loc]; + while (itn->parent != NULL) { + itn = itn->parent; + if (itn->content->type() == IR_CONTROL_LOOP + && itn->payload == j) + break; + } + + Variable_ID v = r.set_var(j + 1); + if (loc < max_loc) { + + CG_outputBuilder *ocg = ir->builder(); + + CG_outputRepr *lb = + static_cast(itn->content)->lower_bound(); + + exp2formula(ir, r, f_root, freevar, lb, v, 's', IR_COND_EQ, + false,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); + + /* if (ir->QueryExpOperation( + static_cast(itn->content)->lower_bound()) + == IR_OP_VARIABLE) { + IR_ScalarRef *ref = + static_cast(ir->Repr2Ref( + static_cast(itn->content)->lower_bound())); + std::string name_ = ref->name(); + + for (int i = 0; i < index.size(); i++) + if (index[i] == name_) { + exp2formula(ir, r, f_root, freevar, lb, v, 's', + IR_COND_GE, false); + + CG_outputRepr *ub = + static_cast(itn->content)->upper_bound(); + IR_CONDITION_TYPE cond = + static_cast(itn->content)->stop_cond(); + if (cond == IR_COND_LT || cond == IR_COND_LE) + exp2formula(ir, r, f_root, freevar, ub, v, + 's', cond, false); + + + + } + + } + */ + + } else { // loc > max_loc + + CG_outputBuilder *ocg = ir->builder(); + CG_outputRepr *ub = + static_cast(itn->content)->upper_bound(); + + exp2formula(ir, r, f_root, freevar, ub, v, 's', IR_COND_EQ, + false,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); + /*if (ir->QueryExpOperation( + static_cast(itn->content)->upper_bound()) + == IR_OP_VARIABLE) { + IR_ScalarRef *ref = + static_cast(ir->Repr2Ref( + static_cast(itn->content)->upper_bound())); + std::string name_ = ref->name(); + + for (int i = 0; i < index.size(); i++) + if (index[i] == name_) { + + CG_outputRepr *lb = + static_cast(itn->content)->lower_bound(); + + exp2formula(ir, r, f_root, freevar, lb, v, 's', + IR_COND_GE, false); + + CG_outputRepr *ub = + static_cast(itn->content)->upper_bound(); + IR_CONDITION_TYPE cond = + static_cast(itn->content)->stop_cond(); + if (cond == IR_COND_LT || cond == IR_COND_LE) + exp2formula(ir, r, f_root, freevar, ub, v, + 's', cond, false); + + + } + } + */ + } + } + + r.setup_names(); + r.simplify(); + + // THIS IS MISSING IN PROTONU's + for (int j = 0; j < insp_lb.size(); j++) { + + std::string lb = insp_lb[j] + "_"; + std::string ub = lb + "_"; + + Global_Var_ID u, l; + bool found_ub = false; + bool found_lb = false; + for (DNF_Iterator di(copy(r).query_DNF()); di; di++) + for (Constraint_Iterator ci = (*di)->constraints(); ci; ci++) + + for (Constr_Vars_Iter cvi(*ci); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + if (v->kind() == Global_Var) + if (v->get_global_var()->arity() > 0) { + + std::string name = + v->get_global_var()->base_name(); + if (name == lb) { + l = v->get_global_var(); + found_lb = true; + } else if (name == ub) { + u = v->get_global_var(); + found_ub = true; + } + } + + } + + if (found_lb && found_ub) { + Relation known_(copy(r).n_set()); + known_.copy_names(copy(r)); + known_.setup_names(); + Variable_ID index_lb = known_.get_local(l, Input_Tuple); + Variable_ID index_ub = known_.get_local(u, Input_Tuple); + F_And *fr = known_.add_and(); + GEQ_Handle g = fr->add_GEQ(); + g.update_coef(index_ub, 1); + g.update_coef(index_lb, -1); + g.update_const(-1); + addKnown(known_); + + } + + } + + + fprintf(stderr, "loop.cc L441 insert the statement\n"); + // insert the statement + CG_outputBuilder *ocg = ir->builder(); + std::vector reverse_expr; + for (int j = 1; j <= vars_to_be_reversed.size(); j++) { + CG_outputRepr *repl = ocg->CreateIdent(vars_to_be_reversed[j]); + repl = ocg->CreateMinus(NULL, repl); + reverse_expr.push_back(repl); + } + fprintf(stderr, "loop.cc before extract\n"); + CG_outputRepr *code = + static_cast(ir_stmt[loc]->content)->extract(); + fprintf(stderr, "code = ocg->CreateSubstitutedStmt(...)\n"); + ((CG_chillRepr *)code)->Dump(); fflush(stdout); + + code = ocg->CreateSubstitutedStmt(0, code, vars_to_be_reversed, + reverse_expr); + fprintf(stderr, "stmt\n"); + ((CG_chillRepr *)code)->Dump(); fflush(stdout); + + stmt[loc].code = code; + stmt[loc].IS = r; + + //Anand: Add Information on uninterpreted function constraints to + //Known relation + + fprintf(stderr, "loop.cc stmt[%d].loop_level has size n_dim %d\n", loc, n_dim); + + stmt[loc].loop_level = std::vector(n_dim); + stmt[loc].ir_stmt_node = ir_stmt[loc]; + stmt[loc].has_inspector = false; + fprintf(stderr, "for int i < n_dim(%d)\n", n_dim); + for (int ii = 0; ii < n_dim; ii++) { + stmt[loc].loop_level[ii].type = LoopLevelOriginal; + stmt[loc].loop_level[ii].payload = ii; + stmt[loc].loop_level[ii].parallel_level = 0; + } + fprintf(stderr, "whew\n"); + + stmt_nesting_level[loc] = -1; + } + dump(); + fprintf(stderr, " loop.cc Loop::init_loop() END\n\n"); + + return true; +} + + + +Loop::Loop(const IR_Control *control) { + + CHILL_DEBUG_PRINT("control type is %d ", control->type()); + echocontroltype(control); + + CHILL_DEBUG_PRINT("2set last_compute_cg_ = NULL; \n"); + last_compute_cgr_ = NULL; + last_compute_cg_ = NULL; + + ir = const_cast(control->ir_); // point to the CHILL IR that this loop came from + if (ir == 0) { + CHILL_DEBUG_PRINT("ir gotten from control = 0x%x\n", (long)ir); + CHILL_DEBUG_PRINT("loop.cc GONNA DIE SOON *******************************\n\n"); + } + + init_code = NULL; + cleanup_code = NULL; + tmp_loop_var_name_counter = 1; + overflow_var_name_counter = 1; + known = Relation::True(0); + + CHILL_DEBUG_PRINT("calling build_ir_tree()\n"); + CHILL_DEBUG_PRINT("about to clone control\n"); + ir_tree = build_ir_tree(control->clone(), NULL); + //fprintf(stderr,"in Loop::Loop. ir_tree has %ld parts\n", ir_tree.size()); + + // std::vector ir_stmt; + //fprintf(stderr, "loop.cc after build_ir_tree() %ld statements\n", stmt.size()); + + int count = 0; + //fprintf(stderr, "before init_loops, %d freevar\n", freevar.size()); + //fprintf(stderr, "count %d\n", count++); + //fprintf(stderr, "loop.cc before init_loop, %ld statements\n", stmt.size()); + while (!init_loop(ir_tree, ir_stmt)) { + //fprintf(stderr, "count %d\n", count++); + } + fprintf(stderr, "after init_loop, %d freevar\n", (int)freevar.size()); + + + fprintf(stderr, "loop.cc after init_loop, %d statements\n", (int)stmt.size()); + for (int i = 0; i < stmt.size(); i++) { + std::map::iterator it = replace.find(i); + + if (it != replace.end()) + stmt[i].code = it->second; + else + stmt[i].code = stmt[i].code; + } + + if (stmt.size() != 0) + dep = DependenceGraph(stmt[0].IS.n_set()); + else + dep = DependenceGraph(0); + // init the dependence graph + for (int i = 0; i < stmt.size(); i++) + dep.insert(); + + fprintf(stderr, "this really REALLY needs some comments\n"); + // this really REALLY needs some comments + for (int i = 0; i < stmt.size(); i++) { + fprintf(stderr, "i %d\n", i); + stmt[i].reduction = 0; // Manu -- initialization + for (int j = i; j < stmt.size(); j++) { + fprintf(stderr, "j %d\n", j); + std::pair, + std::vector > dv = test_data_dependences( + ir, + stmt[i].code, + stmt[i].IS, + stmt[j].code, + stmt[j].IS, + freevar, + index, + stmt_nesting_level_[i], + stmt_nesting_level_[j], + uninterpreted_symbols[ i ], + uninterpreted_symbols_stringrepr[ i ]); + + fprintf(stderr, "dv.first.size() %d\n", (int)dv.first.size()); + for (int k = 0; k < dv.first.size(); k++) { + fprintf(stderr, "k1 %d\n", k); + if (is_dependence_valid(ir_stmt[i], ir_stmt[j], dv.first[k], + true)) + dep.connect(i, j, dv.first[k]); + else { + dep.connect(j, i, dv.first[k].reverse()); + } + + } + + for (int k = 0; k < dv.second.size(); k++) { + fprintf(stderr, "k2 %d\n", k); + if (is_dependence_valid(ir_stmt[j], ir_stmt[i], dv.second[k], + false)) + dep.connect(j, i, dv.second[k]); + else { + dep.connect(i, j, dv.second[k].reverse()); + } + } + } + } + + fprintf(stderr, "\n\n*** LOTS OF REDUCTIONS ***\n\n"); + + // TODO: Reduction check + // Manu:: Initial implementation / algorithm + std::set reducCand = std::set(); + std::vector canReduce = std::vector(); + fprintf(stderr, "\ni range %d\n", stmt.size()); + for (int i = 0; i < stmt.size(); i++) { + fprintf(stderr, "i %d\n", i); + if (!dep.hasEdge(i, i)) { + continue; + } + fprintf(stderr, "dep.hasEdge(%d, %d)\n", i, i); + + // for each statement check if it has all the three dependences (RAW, WAR, WAW) + // If there is such a statement, it is a reduction candidate. Mark all reduction candidates. + std::vector tdv = dep.getEdge(i, i); + fprintf(stderr, "tdv size %d\n", tdv.size()); + for (int j = 0; j < tdv.size(); j++) { + fprintf(stderr, "ij %d %d\n", i, j); + if (tdv[j].is_reduction_cand) { + fprintf(stderr, "reducCand.insert( %d )\n", i); + reducCand.insert(i); + } + } + } + + fprintf(stderr, "loop.cc reducCand.size() %d\n", reducCand.size()); + bool reduc; + std::set::iterator it; + int counter = 0; + for (it = reducCand.begin(); it != reducCand.end(); it++) { + fprintf(stderr, "counter %d\n", counter); + reduc = true; + for (int j = 0; j < stmt.size(); j++) { + fprintf(stderr, "j %d\n", j); + if ((*it != j) + && (stmt_nesting_level_[*it] < stmt_nesting_level_[j])) { + if (dep.hasEdge(*it, j) || dep.hasEdge(j, *it)) { + fprintf(stderr, "counter %d j %d reduc = false\n", counter, j); + reduc = false; + break; + } + } + counter += 1; + } + + if (reduc) { + fprintf(stderr, "canReduce.push_back()\n"); + canReduce.push_back(*it); + stmt[*it].reduction = 2; // First, assume that reduction is possible with some processing + } + } + + + // If reduction is possible without processing, update the value of the reduction variable to 1 + fprintf(stderr, "loop.cc canReduce.size() %d\n", canReduce.size()); + for (int i = 0; i < canReduce.size(); i++) { + // Here, assuming that stmtType returns 1 when there is a single statement within stmt[i] + if (stmtType(ir, stmt[canReduce[i]].code) == 1) { + stmt[canReduce[i]].reduction = 1; + IR_OPERATION_TYPE opType; + opType = getReductionOperator(ir, stmt[canReduce[i]].code); + stmt[canReduce[i]].reductionOp = opType; + } + } + + // printing out stuff for debugging + + if (DEP_DEBUG) { + std::cout << "STATEMENTS THAT CAN BE REDUCED: \n"; + for (int i = 0; i < canReduce.size(); i++) { + std::cout << "------- " << canReduce[i] << " ------- " + << stmt[canReduce[i]].reduction << "\n"; + ir->printStmt(stmt[canReduce[i]].code); // Manu + if (stmt[canReduce[i]].reductionOp == IR_OP_PLUS) + std::cout << "Reduction type:: + \n"; + else if (stmt[canReduce[i]].reductionOp == IR_OP_MINUS) + std::cout << "Reduction type:: - \n"; + else if (stmt[canReduce[i]].reductionOp == IR_OP_MULTIPLY) + std::cout << "Reduction type:: * \n"; + else if (stmt[canReduce[i]].reductionOp == IR_OP_DIVIDE) + std::cout << "Reduction type:: / \n"; + else + std::cout << "Unknown reduction type\n"; + } + } + // cleanup the IR tree + + fprintf(stderr, "init dumb transformation relations\n"); + + // init dumb transformation relations e.g. [i, j] -> [ 0, i, 0, j, 0] + for (int i = 0; i < stmt.size(); i++) { + int n = stmt[i].IS.n_set(); + stmt[i].xform = Relation(n, 2 * n + 1); + F_And *f_root = stmt[i].xform.add_and(); + + for (int j = 1; j <= n; j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(stmt[i].xform.output_var(2 * j), 1); + h.update_coef(stmt[i].xform.input_var(j), -1); + } + + for (int j = 1; j <= 2 * n + 1; j += 2) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(stmt[i].xform.output_var(j), 1); + } + stmt[i].xform.simplify(); + } + //fprintf(stderr, "done with dumb\n"); + + if (stmt.size() != 0) + num_dep_dim = stmt[0].IS.n_set(); + else + num_dep_dim = 0; + // debug + /*for (int i = 0; i < stmt.size(); i++) { + std::cout << i << ": "; + //stmt[i].xform.print(); + stmt[i].IS.print(); + std::cout << std::endl; + + }*/ + //end debug + fprintf(stderr, " at bottom of Loop::Loop, printCode\n"); + printCode(); // this dies TODO figure out why +} + +Loop::~Loop() { + + delete last_compute_cgr_; + delete last_compute_cg_; + + for (int i = 0; i < stmt.size(); i++) + if (stmt[i].code != NULL) { + stmt[i].code->clear(); + delete stmt[i].code; + } + + for (int i = 0; i < ir_tree.size(); i++) + delete ir_tree[i]; + + if (init_code != NULL) { + init_code->clear(); + delete init_code; + } + if (cleanup_code != NULL) { + cleanup_code->clear(); + delete cleanup_code; + } +} + + + + +int Loop::get_dep_dim_of(int stmt_num, int level) const { + if (stmt_num < 0 || stmt_num >= stmt.size()) + throw std::invalid_argument("invaid statement " + to_string(stmt_num)); + + if (level < 1 || level > stmt[stmt_num].loop_level.size()) + return -1; + + int trip_count = 0; + while (true) { + switch (stmt[stmt_num].loop_level[level - 1].type) { + case LoopLevelOriginal: + return stmt[stmt_num].loop_level[level - 1].payload; + case LoopLevelTile: + level = stmt[stmt_num].loop_level[level - 1].payload; + if (level < 1) + return -1; + if (level > stmt[stmt_num].loop_level.size()) + throw loop_error("incorrect loop level information for statement " + + to_string(stmt_num)); + break; + default: + throw loop_error( + "unknown loop level information for statement " + + to_string(stmt_num)); + } + trip_count++; + if (trip_count >= stmt[stmt_num].loop_level.size()) + throw loop_error( + "incorrect loop level information for statement " + + to_string(stmt_num)); + } +} + +int Loop::get_last_dep_dim_before(int stmt_num, int level) const { + if (stmt_num < 0 || stmt_num >= stmt.size()) + throw std::invalid_argument("invaid statement " + to_string(stmt_num)); + + if (level < 1) + return -1; + if (level > stmt[stmt_num].loop_level.size()) + level = stmt[stmt_num].loop_level.size() + 1; + + for (int i = level - 1; i >= 1; i--) + if (stmt[stmt_num].loop_level[i - 1].type == LoopLevelOriginal) + return stmt[stmt_num].loop_level[i - 1].payload; + + return -1; +} + +void Loop::print_internal_loop_structure() const { + for (int i = 0; i < stmt.size(); i++) { + std::vector lex = getLexicalOrder(i); + std::cout << "s" << i + 1 << ": "; + for (int j = 0; j < stmt[i].loop_level.size(); j++) { + if (2 * j < lex.size()) + std::cout << lex[2 * j]; + switch (stmt[i].loop_level[j].type) { + case LoopLevelOriginal: + std::cout << "(dim:" << stmt[i].loop_level[j].payload << ")"; + break; + case LoopLevelTile: + std::cout << "(tile:" << stmt[i].loop_level[j].payload << ")"; + break; + default: + std::cout << "(unknown)"; + } + std::cout << ' '; + } + for (int j = 2 * stmt[i].loop_level.size(); j < lex.size(); j += 2) { + std::cout << lex[j]; + if (j != lex.size() - 1) + std::cout << ' '; + } + std::cout << std::endl; + } +} + +void Loop::debugRelations() const { + const int m = stmt.size(); + { + std::vector IS(m); + std::vector xforms(m); + + for (int i = 0; i < m; i++) { + IS[i] = stmt[i].IS; + xforms[i] = stmt[i].xform; // const stucks + } + + printf("\nxforms:\n"); + for (int i = 0; i < m; i++) { xforms[i].print(); printf("\n"); } + printf("\nIS:\n"); + for (int i = 0; i < m; i++) { IS[i].print(); printf("\n"); } + fflush(stdout); + } +} + + +CG_outputRepr *Loop::getCode(int effort) const { + fprintf(stderr,"\nloop.cc Loop::getCode( effort %d )\n", effort ); + + const int m = stmt.size(); + if (m == 0) + return NULL; + const int n = stmt[0].xform.n_out(); + + if (last_compute_cg_ == NULL) { + fprintf(stderr, "Loop::getCode() last_compute_cg_ == NULL\n"); + + std::vector IS(m); + std::vector xforms(m); + for (int i = 0; i < m; i++) { + IS[i] = stmt[i].IS; + xforms[i] = stmt[i].xform; + } + + debugRelations(); + + + Relation known = Extend_Set(copy(this->known), n - this->known.n_set()); + printf("\nknown:\n"); known.print(); printf("\n\n"); fflush(stdout); + + last_compute_cg_ = new CodeGen(xforms, IS, known); + delete last_compute_cgr_; + last_compute_cgr_ = NULL; + } + else { + fprintf(stderr, "Loop::getCode() last_compute_cg_ NOT NULL\n"); + } + + + if (last_compute_cgr_ == NULL || last_compute_effort_ != effort) { + delete last_compute_cgr_; + last_compute_cgr_ = last_compute_cg_->buildAST(effort); + last_compute_effort_ = effort; + } + + std::vector stmts(m); + fprintf(stderr, "%d stmts\n", m); + for (int i = 0; i < m; i++) + stmts[i] = stmt[i].code; + CG_outputBuilder *ocg = ir->builder(); + + fprintf(stderr, "calling last_compute_cgr_->printRepr()\n"); + CG_outputRepr *repr = last_compute_cgr_->printRepr(ocg, stmts, + uninterpreted_symbols); + + if (init_code != NULL) + repr = ocg->StmtListAppend(init_code->clone(), repr); + if (cleanup_code != NULL) + repr = ocg->StmtListAppend(repr, cleanup_code->clone()); + + fprintf(stderr,"\nloop.cc Loop::getCode( effort %d ) DONE\n", effort ); + return repr; +} + + + + +void Loop::printCode(int effort) const { + fprintf(stderr,"\nloop.cc Loop::printCode( effort %d )\n", effort ); + const int m = stmt.size(); + if (m == 0) + return; + const int n = stmt[0].xform.n_out(); + + if (last_compute_cg_ == NULL) { + fprintf(stderr, "Loop::printCode(), last_compute_cg_ == NULL\n"); + std::vector IS(m); + std::vector xforms(m); + for (int i = 0; i < m; i++) { + IS[i] = stmt[i].IS; + xforms[i] = stmt[i].xform; + } + Relation known = Extend_Set(copy(this->known), n - this->known.n_set()); + + last_compute_cg_ = new CodeGen(xforms, IS, known); + delete last_compute_cgr_; + last_compute_cgr_ = NULL; + } + else fprintf(stderr, "Loop::printCode(), last_compute_cg_ NOT NULL\n"); + + if (last_compute_cgr_ == NULL || last_compute_effort_ != effort) { + delete last_compute_cgr_; + last_compute_cgr_ = last_compute_cg_->buildAST(effort); + last_compute_effort_ = effort; + } + + std::string repr = last_compute_cgr_->printString( + uninterpreted_symbols_stringrepr); + fprintf(stderr, "leaving Loop::printCode()\n"); + std::cout << repr << std::endl; +} + +void Loop::printIterationSpace() const { + for (int i = 0; i < stmt.size(); i++) { + std::cout << "s" << i << ": "; + Relation r = getNewIS(i); + for (int j = 1; j <= r.n_inp(); j++) + r.name_input_var(j, CodeGen::loop_var_name_prefix + to_string(j)); + r.setup_names(); + r.print(); + } +} + +void Loop::printDependenceGraph() const { + if (dep.edgeCount() == 0) + std::cout << "no dependence exists" << std::endl; + else { + std::cout << "dependence graph:" << std::endl; + std::cout << dep; + } +} + +std::vector Loop::getNewIS() const { + const int m = stmt.size(); + + std::vector new_IS(m); + for (int i = 0; i < m; i++) + new_IS[i] = getNewIS(i); + + return new_IS; +} + +// pragmas are tied to loops only ??? +void Loop::pragma(int stmt_num, int level, const std::string &pragmaText) { + // check sanity of parameters + if(stmt_num < 0) + throw std::invalid_argument("invalid statement " + to_string(stmt_num)); + + CG_outputBuilder *ocg = ir->builder(); + CG_outputRepr *code = stmt[stmt_num].code; + ocg->CreatePragmaAttribute(code, level, pragmaText); +} + + +/* + void Loop::prefetch(int stmt_num, int level, const std::string &arrName, const std::string &indexName, int offset, int hint) { + // check sanity of parameters + if(stmt_num < 0) + throw std::invalid_argument("invalid statement " + to_string(stmt_num)); + + CG_outputBuilder *ocg = ir->builder(); + CG_outputRepr *code = stmt[stmt_num].code; + ocg->CreatePrefetchAttribute(code, level, arrName, indexName, int offset, hint); + } +*/ + +void Loop::prefetch(int stmt_num, int level, const std::string &arrName, int hint) { + // check sanity of parameters + if(stmt_num < 0) + throw std::invalid_argument("invalid statement " + to_string(stmt_num)); + + CG_outputBuilder *ocg = ir->builder(); + CG_outputRepr *code = stmt[stmt_num].code; + ocg->CreatePrefetchAttribute(code, level, arrName, hint); +} + +std::vector Loop::getLexicalOrder(int stmt_num) const { + assert(stmt_num < stmt.size()); + + const int n = stmt[stmt_num].xform.n_out(); + std::vector lex(n, 0); + + for (int i = 0; i < n; i += 2) + lex[i] = get_const(stmt[stmt_num].xform, i, Output_Var); + + return lex; +} + +// find the sub loop nest specified by stmt_num and level, +// only iteration space satisfiable statements returned. +std::set Loop::getSubLoopNest(int stmt_num, int level) const { + assert(stmt_num >= 0 && stmt_num < stmt.size()); + assert(level > 0 && level <= stmt[stmt_num].loop_level.size()); + + std::set working; + for (int i = 0; i < stmt.size(); i++) + if (const_cast(this)->stmt[i].IS.is_upper_bound_satisfiable() + && stmt[i].loop_level.size() >= level) + working.insert(i); + + for (int i = 1; i <= level; i++) { + int a = getLexicalOrder(stmt_num, i); + for (std::set::iterator j = working.begin(); j != working.end();) { + int b = getLexicalOrder(*j, i); + if (b != a) + working.erase(j++); + else + ++j; + } + } + + return working; +} + +int Loop::getLexicalOrder(int stmt_num, int level) const { + assert(stmt_num >= 0 && stmt_num < stmt.size()); + assert(level > 0 && level <= stmt[stmt_num].loop_level.size()+1); + + Relation &r = const_cast(this)->stmt[stmt_num].xform; + for (EQ_Iterator e(r.single_conjunct()->EQs()); e; e++) + if (abs((*e).get_coef(r.output_var(2 * level - 1))) == 1) { + bool is_const = true; + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) + if (cvi.curr_var() != r.output_var(2 * level - 1)) { + is_const = false; + break; + } + if (is_const) { + int t = static_cast((*e).get_const()); + return (*e).get_coef(r.output_var(2 * level - 1)) > 0 ? -t : t; + } + } + + throw loop_error( + "can't find lexical order for statement " + to_string(stmt_num) + + "'s loop level " + to_string(level)); +} + +std::set Loop::getStatements(const std::vector &lex, int dim) const { + const int m = stmt.size(); + + std::set same_loops; + for (int i = 0; i < m; i++) { + if (dim < 0) + same_loops.insert(i); + else { + std::vector a_lex = getLexicalOrder(i); + int j; + for (j = 0; j <= dim; j += 2) + if (lex[j] != a_lex[j]) + break; + if (j > dim) + same_loops.insert(i); + } + + } + + return same_loops; +} + +void Loop::shiftLexicalOrder(const std::vector &lex, int dim, int amount) { + const int m = stmt.size(); + + if (amount == 0) + return; + + for (int i = 0; i < m; i++) { + std::vector lex2 = getLexicalOrder(i); + + bool need_shift = true; + + for (int j = 0; j < dim; j++) + if (lex2[j] != lex[j]) { + need_shift = false; + break; + } + + if (!need_shift) + continue; + + if (amount > 0) { + if (lex2[dim] < lex[dim]) + continue; + } else if (amount < 0) { + if (lex2[dim] > lex[dim]) + continue; + } + + assign_const(stmt[i].xform, dim, lex2[dim] + amount); + } +} + +std::vector > Loop::sort_by_same_loops(std::set active, + int level) { + + std::set not_nested_at_this_level; + std::map > sorted_by_loop; + std::map > sorted_by_lex_order; + std::vector > to_return; + bool lex_order_already_set = false; + for (std::set::iterator it = active.begin(); it != active.end(); + it++) { + + if (stmt[*it].ir_stmt_node == NULL) + lex_order_already_set = true; + } + + if (lex_order_already_set) { + + for (std::set::iterator it = active.begin(); it != active.end(); + it++) { + std::map >::iterator it2 = + sorted_by_lex_order.find( + get_const(stmt[*it].xform, 2 * (level - 1), + Output_Var)); + + if (it2 != sorted_by_lex_order.end()) + it2->second.insert(*it); + else { + + std::set to_insert; + + to_insert.insert(*it); + + sorted_by_lex_order.insert( + std::pair >( + get_const(stmt[*it].xform, 2 * (level - 1), + Output_Var), to_insert)); + + } + + } + + for (std::map >::iterator it2 = + sorted_by_lex_order.begin(); it2 != sorted_by_lex_order.end(); + it2++) + to_return.push_back(it2->second); + + } else { + + for (std::set::iterator it = active.begin(); it != active.end(); + it++) { + + ir_tree_node* itn = stmt[*it].ir_stmt_node; + itn = itn->parent; + //while (itn->content->type() != IR_CONTROL_LOOP && itn != NULL) + // itn = itn->parent; + + while ((itn != NULL) && (itn->payload != level - 1)) { + itn = itn->parent; + while (itn != NULL && itn->content->type() != IR_CONTROL_LOOP ) + itn = itn->parent; + } + + if (itn == NULL) + not_nested_at_this_level.insert(*it); + else { + std::map >::iterator it2 = + sorted_by_loop.find(itn); + + if (it2 != sorted_by_loop.end()) + it2->second.insert(*it); + else { + std::set to_insert; + + to_insert.insert(*it); + + sorted_by_loop.insert( + std::pair >(itn, + to_insert)); + + } + + } + + } + if (not_nested_at_this_level.size() > 0) { + for (std::set::iterator it = not_nested_at_this_level.begin(); + it != not_nested_at_this_level.end(); it++) { + std::set temp; + temp.insert(*it); + to_return.push_back(temp); + + } + } + for (std::map >::iterator it2 = + sorted_by_loop.begin(); it2 != sorted_by_loop.end(); it2++) + to_return.push_back(it2->second); + } + return to_return; +} + +void update_successors(int n, + int node_num[], + int cant_fuse_with[], + Graph, bool> &g, + std::list &work_list, + std::list &type_list, + std::vector types) { + + std::set disconnect; + for (Graph, bool>::EdgeList::iterator i = + g.vertex[n].second.begin(); i != g.vertex[n].second.end(); i++) { + int m = i->first; + + if (node_num[m] != -1) + throw loop_error("Graph input for fusion has cycles not a DAG!!"); + + std::vector check_ = g.getEdge(n, m); + + bool has_bad_edge_path = false; + for (int i = 0; i < check_.size(); i++) + if (!check_[i]) { + has_bad_edge_path = true; + break; + } + if (!types[m]) { + cant_fuse_with[m] = std::max(cant_fuse_with[m], cant_fuse_with[n]); + } else { + if (has_bad_edge_path) + cant_fuse_with[m] = std::max(cant_fuse_with[m], node_num[n]); + else + cant_fuse_with[m] = std::max(cant_fuse_with[m], cant_fuse_with[n]); + } + disconnect.insert(m); + } + + + for (std::set::iterator i = disconnect.begin(); i != disconnect.end(); + i++) { + g.disconnect(n, *i); + + bool no_incoming_edges = true; + for (int j = 0; j < g.vertex.size(); j++) + if (j != *i) + if (g.hasEdge(j, *i)) { + no_incoming_edges = false; + break; + } + + if (no_incoming_edges) { + work_list.push_back(*i); + type_list.push_back(types[*i]); + } + } +} + + + +int Loop::getMinLexValue(std::set stmts, int level) { + + int min; + + std::set::iterator it = stmts.begin(); + min = getLexicalOrder(*it, level); + + for (; it != stmts.end(); it++) { + int curr = getLexicalOrder(*it, level); + if (curr < min) + min = curr; + } + + return min; +} + + + + +Graph, bool> Loop::construct_induced_graph_at_level( + std::vector > s, DependenceGraph dep, int dep_dim) { + Graph, bool> g; + + for (int i = 0; i < s.size(); i++) + g.insert(s[i]); + + for (int i = 0; i < s.size(); i++) { + + for (int j = i + 1; j < s.size(); j++) { + bool has_true_edge_i_to_j = false; + bool has_true_edge_j_to_i = false; + bool is_connected_i_to_j = false; + bool is_connected_j_to_i = false; + for (std::set::iterator ii = s[i].begin(); ii != s[i].end(); + ii++) { + + for (std::set::iterator jj = s[j].begin(); + jj != s[j].end(); jj++) { + + std::vector dvs = dep.getEdge(*ii, *jj); + for (int k = 0; k < dvs.size(); k++) + if (dvs[k].is_control_dependence() + || (dvs[k].is_data_dependence() + && dvs[k].has_been_carried_at(dep_dim))) { + + if (dvs[k].is_data_dependence() + && dvs[k].has_negative_been_carried_at( + dep_dim)) { + //g.connect(i, j, false); + is_connected_i_to_j = true; + break; + } else { + //g.connect(i, j, true); + + has_true_edge_i_to_j = true; + //break + } + } + + //if (is_connected) + + // break; + // if (has_true_edge_i_to_j && !is_connected_i_to_j) + // g.connect(i, j, true); + dvs = dep.getEdge(*jj, *ii); + for (int k = 0; k < dvs.size(); k++) + if (dvs[k].is_control_dependence() + || (dvs[k].is_data_dependence() + && dvs[k].has_been_carried_at(dep_dim))) { + + if (is_connected_i_to_j || has_true_edge_i_to_j) + throw loop_error( + "Graph input for fusion has cycles not a DAG!!"); + + if (dvs[k].is_data_dependence() + && dvs[k].has_negative_been_carried_at( + dep_dim)) { + //g.connect(i, j, false); + is_connected_j_to_i = true; + break; + } else { + //g.connect(i, j, true); + + has_true_edge_j_to_i = true; + //break; + } + } + + // if (is_connected) + //break; + // if (is_connected) + //break; + } + + //if (is_connected) + // break; + } + + + if (is_connected_i_to_j) + g.connect(i, j, false); + else if (has_true_edge_i_to_j) + g.connect(i, j, true); + + if (is_connected_j_to_i) + g.connect(j, i, false); + else if (has_true_edge_j_to_i) + g.connect(j, i, true); + + } + } + return g; +} + + + +std::vector > Loop::typed_fusion(Graph, bool> g, + std::vector &types) { + + bool roots[g.vertex.size()]; + + for (int i = 0; i < g.vertex.size(); i++) + roots[i] = true; + + for (int i = 0; i < g.vertex.size(); i++) + for (int j = i + 1; j < g.vertex.size(); j++) { + + if (g.hasEdge(i, j)) + roots[j] = false; + + if (g.hasEdge(j, i)) + roots[i] = false; + + } + + std::list work_list; + std::list type_list; + int cant_fuse_with[g.vertex.size()]; + int fused = 0; + int lastfused = 0; + int lastnum = 0; + std::vector > s; + //Each Fused set's representative node + + int node_to_fused_nodes[g.vertex.size()]; + int node_num[g.vertex.size()]; + int next[g.vertex.size()]; + + for (int i = 0; i < g.vertex.size(); i++) { + if (roots[i] == true) { + work_list.push_back(i); + type_list.push_back(types[i]); + } + cant_fuse_with[i] = 0; + node_to_fused_nodes[i] = 0; + node_num[i] = -1; + next[i] = 0; + } + + + // topological sort according to chun's permute algorithm + // std::vector > s = g.topoSort(); + std::vector > s2 = g.topoSort(); + if (work_list.empty() || (s2.size() != g.vertex.size())) { + + std::cout << s2.size() << "\t" << g.vertex.size() << std::endl; + throw loop_error("Input for fusion not a DAG!!"); + + + } + int fused_nodes_counter = 0; + while (!work_list.empty()) { + int n = work_list.front(); + bool type = type_list.front(); + //int n_ = g.vertex[n].first; + work_list.pop_front(); + type_list.pop_front(); + int node; + /*if (cant_fuse_with[n] == 0) + node = 0; + else + node = cant_fuse_with[n]; + */ + int p; + if (type) { + //if ((fused_nodes_counter != 0) && (node != fused_nodes_counter)) { + if (cant_fuse_with[n] == 0) + p = fused; + else + p = next[cant_fuse_with[n]]; + + if (p != 0) { + int rep_node = node_to_fused_nodes[p]; + node_num[n] = node_num[rep_node]; + + try { + update_successors(n, node_num, cant_fuse_with, g, work_list, + type_list, types); + } catch (const loop_error &e) { + + throw loop_error( + "statements cannot be fused together due to negative dependence"); + + } + for (std::set::iterator it = g.vertex[n].first.begin(); + it != g.vertex[n].first.end(); it++) + s[node_num[n] - 1].insert(*it); + } else { + //std::set new_node; + //new_node.insert(n_); + s.push_back(g.vertex[n].first); + lastnum = lastnum + 1; + node_num[n] = lastnum; + node_to_fused_nodes[node_num[n]] = n; + + if (lastfused == 0) { + fused = lastnum; + lastfused = fused; + } else { + next[lastfused] = lastnum; + lastfused = lastnum; + + } + + try { + update_successors(n, node_num, cant_fuse_with, g, work_list, + type_list, types); + } catch (const loop_error &e) { + + throw loop_error( + "statements cannot be fused together due to negative dependence"); + + } + fused_nodes_counter++; + } + + } else { + s.push_back(g.vertex[n].first); + lastnum = lastnum + 1; + node_num[n] = lastnum; + node_to_fused_nodes[node_num[n]] = n; + + try { + update_successors(n, node_num, cant_fuse_with, g, work_list, + type_list, types); + } catch (const loop_error &e) { + + throw loop_error( + "statements cannot be fused together due to negative dependence"); + + } + //fused_nodes_counter++; + + } + + } + + return s; +} + + + + +void Loop::setLexicalOrder(int dim, const std::set &active, + int starting_order, std::vector > idxNames) { + fprintf(stderr, "Loop::setLexicalOrder() %d idxNames active size %d starting_order %d\n", idxNames.size(), active.size(), starting_order); + if (active.size() == 0) + return; + + for (int i=0; i< idxNames.size(); i++) { + std::vector what = idxNames[i]; + for (int j=0; j lex; + int ref_stmt_num; + for (std::set::iterator i = active.begin(); i != active.end(); i++) { + if ((*i) < 0 || (*i) >= stmt.size()) + throw std::invalid_argument( + "invalid statement number " + to_string(*i)); + if (dim >= stmt[*i].xform.n_out()) + throw std::invalid_argument( + "invalid constant loop level to set lexicographical order"); + if (i == active.begin()) { + lex = getLexicalOrder(*i); + ref_stmt_num = *i; + } else { + std::vector lex2 = getLexicalOrder(*i); + for (int j = 0; j < dim; j += 2) + if (lex[j] != lex2[j]) + throw std::invalid_argument( + "statements are not in the same sub loop nest"); + } + } + + // separate statements by current loop level types + int level = (dim + 2) / 2; + std::map, std::set > active_by_level_type; + std::set active_by_no_level; + for (std::set::iterator i = active.begin(); i != active.end(); i++) { + if (level > stmt[*i].loop_level.size()) + active_by_no_level.insert(*i); + else + active_by_level_type[std::make_pair( + stmt[*i].loop_level[level - 1].type, + stmt[*i].loop_level[level - 1].payload)].insert(*i); + } + + // further separate statements due to control dependences + std::vector > active_by_level_type_splitted; + for (std::map, std::set >::iterator i = + active_by_level_type.begin(); i != active_by_level_type.end(); i++) + active_by_level_type_splitted.push_back(i->second); + for (std::set::iterator i = active_by_no_level.begin(); + i != active_by_no_level.end(); i++) + for (int j = active_by_level_type_splitted.size() - 1; j >= 0; j--) { + std::set controlled, not_controlled; + for (std::set::iterator k = + active_by_level_type_splitted[j].begin(); + k != active_by_level_type_splitted[j].end(); k++) { + std::vector dvs = dep.getEdge(*i, *k); + bool is_controlled = false; + for (int kk = 0; kk < dvs.size(); kk++) + if (dvs[kk].type = DEP_CONTROL) { + is_controlled = true; + break; + } + if (is_controlled) + controlled.insert(*k); + else + not_controlled.insert(*k); + } + if (controlled.size() != 0 && not_controlled.size() != 0) { + active_by_level_type_splitted.erase( + active_by_level_type_splitted.begin() + j); + active_by_level_type_splitted.push_back(controlled); + active_by_level_type_splitted.push_back(not_controlled); + } + } + + // set lexical order separating loops with different loop types first + if (active_by_level_type_splitted.size() + active_by_no_level.size() > 1) { + int dep_dim = get_last_dep_dim_before(ref_stmt_num, level) + 1; + + Graph, Empty> g; + for (std::vector >::iterator i = + active_by_level_type_splitted.begin(); + i != active_by_level_type_splitted.end(); i++) + g.insert(*i); + for (std::set::iterator i = active_by_no_level.begin(); + i != active_by_no_level.end(); i++) { + std::set t; + t.insert(*i); + g.insert(t); + } + for (int i = 0; i < g.vertex.size(); i++) + for (int j = i + 1; j < g.vertex.size(); j++) { + bool connected = false; + for (std::set::iterator ii = g.vertex[i].first.begin(); + ii != g.vertex[i].first.end(); ii++) { + for (std::set::iterator jj = g.vertex[j].first.begin(); + jj != g.vertex[j].first.end(); jj++) { + std::vector dvs = dep.getEdge(*ii, + *jj); + for (int k = 0; k < dvs.size(); k++) + if (dvs[k].is_control_dependence() + || (dvs[k].is_data_dependence() + && !dvs[k].has_been_carried_before( + dep_dim))) { + g.connect(i, j); + connected = true; + break; + } + if (connected) + break; + } + if (connected) + break; + } + connected = false; + for (std::set::iterator ii = g.vertex[i].first.begin(); + ii != g.vertex[i].first.end(); ii++) { + for (std::set::iterator jj = g.vertex[j].first.begin(); + jj != g.vertex[j].first.end(); jj++) { + std::vector dvs = dep.getEdge(*jj, + *ii); + // find the sub loop nest specified by stmt_num and level, + // only iteration space satisfiable statements returned. + for (int k = 0; k < dvs.size(); k++) + if (dvs[k].is_control_dependence() + || (dvs[k].is_data_dependence() + && !dvs[k].has_been_carried_before( + dep_dim))) { + g.connect(j, i); + connected = true; + break; + } + if (connected) + break; + } + if (connected) + break; + } + } + + std::vector > s = g.topoSort(); + if (s.size() != g.vertex.size()) + throw loop_error( + "cannot separate statements with different loop types at loop level " + + to_string(level)); + + // assign lexical order + int order = starting_order; + for (int i = 0; i < s.size(); i++) { + std::set &cur_scc = g.vertex[*(s[i].begin())].first; + int sz = cur_scc.size(); + if (sz == 1) { + int cur_stmt = *(cur_scc.begin()); + assign_const(stmt[cur_stmt].xform, dim, order); + for (int j = dim + 2; j < stmt[cur_stmt].xform.n_out(); j += 2) + assign_const(stmt[cur_stmt].xform, j, 0); + order++; + } else { // recurse ! + fprintf(stderr, "Loop:setLexicalOrder() recursing\n"); + setLexicalOrder(dim, cur_scc, order, idxNames); + order += sz; + } + } + } + else { // set lexical order separating single iteration statements and loops + + std::set true_singles; + std::set nonsingles; + std::map > fake_singles; + std::set fake_singles_; + + // sort out statements that do not require loops + for (std::set::iterator i = active.begin(); i != active.end(); + i++) { + Relation cur_IS = getNewIS(*i); + if (is_single_iteration(cur_IS, dim + 1)) { + bool is_all_single = true; + for (int j = dim + 3; j < stmt[*i].xform.n_out(); j += 2) + if (!is_single_iteration(cur_IS, j)) { + is_all_single = false; + break; + } + if (is_all_single) + true_singles.insert(*i); + else { + fake_singles_.insert(*i); + try { + fake_singles[get_const(cur_IS, dim + 1, Set_Var)].insert( + *i); + } catch (const std::exception &e) { + fake_singles[posInfinity].insert(*i); + } + } + } else + nonsingles.insert(*i); + } + + + // split nonsingles forcibly according to negative dependences present (loop unfusible) + int dep_dim = get_dep_dim_of(ref_stmt_num, level); + + if (dim < stmt[ref_stmt_num].xform.n_out() - 1) { + + bool dummy_level_found = false; + + std::vector > s; + + s = sort_by_same_loops(active, level); + bool further_levels_exist = false; + + if (!idxNames.empty()) + if (level <= idxNames[ref_stmt_num].size()) + if (idxNames[ref_stmt_num][level - 1].length() == 0) { + // && s.size() == 1) { + int order1 = 0; + dummy_level_found = true; + + for (int i = level; i < idxNames[ref_stmt_num].size(); + i++) + if (idxNames[ref_stmt_num][i].length() > 0) + further_levels_exist = true; + + } + + //if (!dummy_level_found) { + + if (s.size() > 1) { + + std::vector types; + for (int i = 0; i < s.size(); i++) + types.push_back(true); + + Graph, bool> g = construct_induced_graph_at_level( + s, dep, dep_dim); + s = typed_fusion(g, types); + } + int order = starting_order; + for (int i = 0; i < s.size(); i++) { + + for (std::set::iterator it = s[i].begin(); + it != s[i].end(); it++) { + assign_const(stmt[*it].xform, dim, order); + stmt[*it].xform.simplify(); + } + + if ((dim + 2) <= (stmt[ref_stmt_num].xform.n_out() - 1)) { // recurse ! + fprintf(stderr, "Loop:setLexicalOrder() recursing\n"); + setLexicalOrder(dim + 2, s[i], order, idxNames); + } + + order++; + } + //} + /* else { + + int order1 = 0; + int order = 0; + for (std::set::iterator i = active.begin(); + i != active.end(); i++) { + if (!further_levels_exist) + assign_const(stmt[*i].xform, dim, order1++); + else + assign_const(stmt[*i].xform, dim, order1); + + } + + if ((dim + 2) <= (stmt[ref_stmt_num].xform.n_out() - 1) && further_levels_exist) + setLexicalOrder(dim + 2, active, order, idxNames); + } + */ + } else { + int dummy_order = 0; + for (std::set::iterator i = active.begin(); i != active.end(); + i++) { + assign_const(stmt[*i].xform, dim, dummy_order++); + stmt[*i].xform.simplify(); + } + } + /*for (int i = 0; i < g2.vertex.size(); i++) + for (int j = i+1; j < g2.vertex.size(); j++) { + std::vector dvs = dep.getEdge(g2.vertex[i].first, g2.vertex[j].first); + for (int k = 0; k < dvs.size(); k++) + if (dvs[k].is_control_dependence() || + (dvs[k].is_data_dependence() && dvs[k].has_negative_been_carried_at(dep_dim))) { + g2.connect(i, j); + break; + } + dvs = dep.getEdge(g2.vertex[j].first, g2.vertex[i].first); + for (int k = 0; k < dvs.size(); k++) + if (dvs[k].is_control_dependence() || + (dvs[k].is_data_dependence() && dvs[k].has_negative_been_carried_at(dep_dim))) { + g2.connect(j, i); + break; + } + } + + std::vector > s2 = g2.packed_topoSort(); + + std::vector > splitted_nonsingles; + for (int i = 0; i < s2.size(); i++) { + std::set cur_scc; + for (std::set::iterator j = s2[i].begin(); j != s2[i].end(); j++) + cur_scc.insert(g2.vertex[*j].first); + splitted_nonsingles.push_back(cur_scc); + } + */ + //convert to dependence graph for grouped statements + //dep_dim = get_last_dep_dim_before(ref_stmt_num, level) + 1; + /*int order = 0; + for (std::set::iterator j = active.begin(); j != active.end(); + j++) { + std::set continuous; + std::cout<< active.size()< 0) { + std::vector > s = typed_fusion(continuous, dep, + dep_dim); + + for (int i = 0; i < s.size(); i++) { + for (std::set::iterator l = s[i].begin(); + l != s[i].end(); l++) { + assign_const(stmt[*l].xform, dim + 2, order); + setLexicalOrder(dim + 2, s[i]); + } + order++; + } + } + + if (j != active.end()) { + assign_const(stmt[*j].xform, dim + 2, order); + + for (int k = dim + 4; k < stmt[*j].xform.n_out(); k += 2) + assign_const(stmt[*j].xform, k, 0); + order++; + } + + if( j == active.end()) + break; + } + */ + + + // assign lexical order + /*int order = starting_order; + for (int i = 0; i < s.size(); i++) { + // translate each SCC into original statements + std::set cur_scc; + for (std::set::iterator j = s[i].begin(); j != s[i].end(); j++) + copy(s[i].begin(), s[i].end(), + inserter(cur_scc, cur_scc.begin())); + + // now assign the constant + for (std::set::iterator j = cur_scc.begin(); + j != cur_scc.end(); j++) + assign_const(stmt[*j].xform, dim, order); + + if (cur_scc.size() > 1) + setLexicalOrder(dim + 2, cur_scc); + else if (cur_scc.size() == 1) { + int cur_stmt = *(cur_scc.begin()); + for (int j = dim + 2; j < stmt[cur_stmt].xform.n_out(); j += 2) + assign_const(stmt[cur_stmt].xform, j, 0); + } + + if (cur_scc.size() > 0) + order++; + } + */ + } + + fprintf(stderr, "LEAVING Loop::setLexicalOrder() %d idxNames\n", idxNames.size()); + for (int i=0; i< idxNames.size(); i++) { + std::vector what = idxNames[i]; + for (int j=0; j active; + for (int i = 0; i < stmt.size(); i++) + active.insert(i); + apply_xform(active); +} + +void Loop::apply_xform(int stmt_num) { + fprintf(stderr, "apply_xform( %d )\n", stmt_num); + std::set active; + active.insert(stmt_num); + apply_xform(active); +} + +void Loop::apply_xform(std::set &active) { + fflush(stdout); + fprintf(stderr, "loop.cc apply_xform( set )\n"); + + int max_n = 0; + + omega::CG_outputBuilder *ocg = ir->builder(); + for (std::set::iterator i = active.begin(); i != active.end(); i++) { + int n = stmt[*i].loop_level.size(); + if (n > max_n) + max_n = n; + + std::vector lex = getLexicalOrder(*i); + + omega::Relation mapping(2 * n + 1, n); + omega::F_And *f_root = mapping.add_and(); + for (int j = 1; j <= n; j++) { + omega::EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.output_var(j), 1); + h.update_coef(mapping.input_var(2 * j), -1); + } + mapping = omega::Composition(mapping, stmt[*i].xform); + mapping.simplify(); + + // match omega input/output variables to variable names in the code + for (int j = 1; j <= stmt[*i].IS.n_set(); j++) + mapping.name_input_var(j, stmt[*i].IS.set_var(j)->name()); + for (int j = 1; j <= n; j++) + mapping.name_output_var(j, + tmp_loop_var_name_prefix + + omega::to_string( + tmp_loop_var_name_counter + j - 1)); + mapping.setup_names(); + mapping.print(); // "{[I] -> [_t1] : I = _t1 } + fflush(stdout); + + omega::Relation known = Extend_Set(copy(this->known), + mapping.n_out() - this->known.n_set()); + //stmt[*i].code = outputStatement(ocg, stmt[*i].code, 0, mapping, known, std::vector(mapping.n_out(), NULL)); + + omega::CG_outputBuilder *ocgr = ir->builder(); + + + //this is probably CG_chillBuilder; + + omega::CG_stringBuilder *ocgs = new omega::CG_stringBuilder; + if (uninterpreted_symbols[*i].size() == 0) { + + + std::set globals; + + for (omega::DNF_Iterator di(stmt[*i].IS.query_DNF()); di; di++) { + + for (omega::Constraint_Iterator e(*di); e; e++) { + for (omega::Constr_Vars_Iter cvi(*e); cvi; cvi++) { + omega::Variable_ID v = cvi.curr_var(); + if (v->kind() == omega::Global_Var + && v->get_global_var()->arity() > 0 + && globals.find(v->name()) == globals.end()) { + omega::Global_Var_ID g = v->get_global_var(); + globals.insert(v->name()); + std::vector reprs; + std::vector reprs2; + + for (int l = 1; l <= g->arity(); l++) { + omega::CG_outputRepr *temp = ocgr->CreateIdent( + stmt[*i].IS.set_var(l)->name()); + omega::CG_outputRepr *temp2 = ocgs->CreateIdent( + stmt[*i].IS.set_var(l)->name()); + + reprs.push_back(temp); + reprs2.push_back(temp2); + } + uninterpreted_symbols[*i].insert( + std::pair >( + v->get_global_var()->base_name(), + reprs)); + uninterpreted_symbols_stringrepr[*i].insert( + std::pair >( + v->get_global_var()->base_name(), + reprs2)); + } + } + } + } + } + + std::vector loop_vars; + for (int j = 1; j <= stmt[*i].IS.n_set(); j++) { + loop_vars.push_back(stmt[*i].IS.set_var(j)->name()); + } + for (int j = 0; j subs = output_substitutions(ocg, + Inverse(copy(mapping)), + std::vector >( + mapping.n_out(), + std::make_pair( + static_cast(NULL), 0)), + uninterpreted_symbols[*i]); + + std::vector subs2; + for (int l = 0; l < subs.size(); l++) + subs2.push_back(subs[l]->clone()); + + fprintf(stderr, "%d uninterpreted symbols\n", (int)uninterpreted_symbols.size()); + for (int j = 0; j >::iterator it = + uninterpreted_symbols[*i].begin(); + it != uninterpreted_symbols[*i].end(); it++) { + fprintf(stderr, "\ncount %d\n", count); + + std::vector reprs_ = it->second; + fprintf(stderr, "%d reprs_\n", (int)reprs_.size()); + + std::vector reprs_2; + for (int k = 0; k < reprs_.size(); k++) { + fprintf(stderr, "k %d\n", k); + std::vector subs; + for (int l = 0; l < subs2.size(); l++) { + fprintf(stderr, "l %d\n", l); + subs.push_back(subs2[l]->clone()); + } + + fprintf(stderr, "clone\n"); + CG_outputRepr *c = reprs_[k]->clone(); + c->dump(); fflush(stdout); + + fprintf(stderr, "createsub\n"); + CG_outputRepr *s = ocgr->CreateSubstitutedStmt(0, c, + loop_vars, subs, true); + + fprintf(stderr, "push back\n"); + reprs_2.push_back( s ); + + } + + it->second = reprs_2; + count++; + fprintf(stderr, "bottom\n"); + } + + std::vector subs3 = output_substitutions( + ocgs, Inverse(copy(mapping)), + std::vector >( + mapping.n_out(), + std::make_pair( + static_cast(NULL), 0)), + uninterpreted_symbols_stringrepr[*i]); + + for (std::map >::iterator it = + uninterpreted_symbols_stringrepr[*i].begin(); + it != uninterpreted_symbols_stringrepr[*i].end(); it++) { + + std::vector reprs_ = it->second; + std::vector reprs_2; + for (int k = 0; k < reprs_.size(); k++) { + std::vector subs; + /* for (int l = 0; l < subs3.size(); l++) + subs.push_back(subs3[l]->clone()); + reprs_2.push_back( + ocgs->CreateSubstitutedStmt(0, reprs_[k]->clone(), + loop_vars, subs)); + */ + reprs_2.push_back(subs3[k]->clone()); + } + + it->second = reprs_2; + + } + + + fprintf(stderr, "loop.cc stmt[*i].code =\n"); + //stmt[*i].code->dump(); + //fprintf(stderr, "\n"); + stmt[*i].code = ocg->CreateSubstitutedStmt(0, stmt[*i].code, loop_vars, + subs); + //fprintf(stderr, "loop.cc substituted code =\n"); + //stmt[*i].code->dump(); + //fprintf(stderr, "\n"); + + stmt[*i].IS = omega::Range(Restrict_Domain(mapping, stmt[*i].IS)); + stmt[*i].IS.simplify(); + + // replace original transformation relation with straight 1-1 mapping + //fprintf(stderr, "replace original transformation relation with straight 1-1 mapping\n"); + mapping = Relation(n, 2 * n + 1); + f_root = mapping.add_and(); + for (int j = 1; j <= n; j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.output_var(2 * j), 1); + h.update_coef(mapping.input_var(j), -1); + } + for (int j = 1; j <= 2 * n + 1; j += 2) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.output_var(j), 1); + h.update_const(-lex[j - 1]); + } + stmt[*i].xform = mapping; + + //fprintf(stderr, "\ncode is: \n"); + //stmt[*i].code->dump(); + //fprintf(stderr, "\n\n"); + + } + + tmp_loop_var_name_counter += max_n; + fflush(stdout); + fprintf(stderr, "loop.cc LEAVING apply_xform( set )\n\n"); + //for (std::set::iterator i = active.begin(); i != active.end(); i++) { + // fprintf(stderr, "\nloop.cc stmt[i].code =\n"); + // stmt[*i].code->dump(); + // fprintf(stderr, "\n\n"); + //} + +} + + + + +void Loop::addKnown(const Relation &cond) { + + // invalidate saved codegen computation + delete last_compute_cgr_; + last_compute_cgr_ = NULL; + delete last_compute_cg_; + last_compute_cg_ = NULL; + fprintf(stderr, "Loop::addKnown(), SETTING last_compute_cg_ = NULL\n"); + + int n1 = this->known.n_set(); + + Relation r = copy(cond); + int n2 = r.n_set(); + + if (n1 < n2) + this->known = Extend_Set(this->known, n2 - n1); + else if (n1 > n2) + r = Extend_Set(r, n1 - n2); + + this->known = Intersection(this->known, r); +} + +void Loop::removeDependence(int stmt_num_from, int stmt_num_to) { + // check for sanity of parameters + if (stmt_num_from >= stmt.size()) + throw std::invalid_argument( + "invalid statement number " + to_string(stmt_num_from)); + if (stmt_num_to >= stmt.size()) + throw std::invalid_argument( + "invalid statement number " + to_string(stmt_num_to)); + + dep.disconnect(stmt_num_from, stmt_num_to); +} + +void Loop::dump() const { + for (int i = 0; i < stmt.size(); i++) { + std::vector lex = getLexicalOrder(i); + std::cout << "s" << i + 1 << ": "; + for (int j = 0; j < stmt[i].loop_level.size(); j++) { + if (2 * j < lex.size()) + std::cout << lex[2 * j]; + switch (stmt[i].loop_level[j].type) { + case LoopLevelOriginal: + std::cout << "(dim:" << stmt[i].loop_level[j].payload << ")"; + break; + case LoopLevelTile: + std::cout << "(tile:" << stmt[i].loop_level[j].payload << ")"; + break; + default: + std::cout << "(unknown)"; + } + std::cout << ' '; + } + for (int j = 2 * stmt[i].loop_level.size(); j < lex.size(); j += 2) { + std::cout << lex[j]; + if (j != lex.size() - 1) + std::cout << ' '; + } + std::cout << std::endl; + } +} + +bool Loop::nonsingular(const std::vector > &T) { + if (stmt.size() == 0) + return true; + + // check for sanity of parameters + for (int i = 0; i < stmt.size(); i++) { + if (stmt[i].loop_level.size() != num_dep_dim) + throw std::invalid_argument( + "nonsingular loop transformations must be applied to original perfect loop nest"); + for (int j = 0; j < stmt[i].loop_level.size(); j++) + if (stmt[i].loop_level[j].type != LoopLevelOriginal) + throw std::invalid_argument( + "nonsingular loop transformations must be applied to original perfect loop nest"); + } + if (T.size() != num_dep_dim) + throw std::invalid_argument("invalid transformation matrix"); + for (int i = 0; i < stmt.size(); i++) + if (T[i].size() != num_dep_dim + 1 && T[i].size() != num_dep_dim) + throw std::invalid_argument("invalid transformation matrix"); + // invalidate saved codegen computation + delete last_compute_cgr_; + last_compute_cgr_ = NULL; + delete last_compute_cg_; + last_compute_cg_ = NULL; + fprintf(stderr, "Loop::nonsingular(), SETTING last_compute_cg_ = NULL\n"); + + // build relation from matrix + Relation mapping(2 * num_dep_dim + 1, 2 * num_dep_dim + 1); + F_And *f_root = mapping.add_and(); + for (int i = 0; i < num_dep_dim; i++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.output_var(2 * (i + 1)), -1); + for (int j = 0; j < num_dep_dim; j++) + if (T[i][j] != 0) + h.update_coef(mapping.input_var(2 * (j + 1)), T[i][j]); + if (T[i].size() == num_dep_dim + 1) + h.update_const(T[i][num_dep_dim]); + } + for (int i = 1; i <= 2 * num_dep_dim + 1; i += 2) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.output_var(i), -1); + h.update_coef(mapping.input_var(i), 1); + } + + // update transformation relations + for (int i = 0; i < stmt.size(); i++) + stmt[i].xform = Composition(copy(mapping), stmt[i].xform); + + // update dependence graph + for (int i = 0; i < dep.vertex.size(); i++) + for (DependenceGraph::EdgeList::iterator j = + dep.vertex[i].second.begin(); j != dep.vertex[i].second.end(); + j++) { + std::vector dvs = j->second; + for (int k = 0; k < dvs.size(); k++) { + DependenceVector &dv = dvs[k]; + switch (dv.type) { + case DEP_W2R: + case DEP_R2W: + case DEP_W2W: + case DEP_R2R: { + std::vector lbounds(num_dep_dim), ubounds( + num_dep_dim); + for (int p = 0; p < num_dep_dim; p++) { + coef_t lb = 0; + coef_t ub = 0; + for (int q = 0; q < num_dep_dim; q++) { + if (T[p][q] > 0) { + if (lb == -posInfinity + || dv.lbounds[q] == -posInfinity) + lb = -posInfinity; + else + lb += T[p][q] * dv.lbounds[q]; + if (ub == posInfinity + || dv.ubounds[q] == posInfinity) + ub = posInfinity; + else + ub += T[p][q] * dv.ubounds[q]; + } else if (T[p][q] < 0) { + if (lb == -posInfinity + || dv.ubounds[q] == posInfinity) + lb = -posInfinity; + else + lb += T[p][q] * dv.ubounds[q]; + if (ub == posInfinity + || dv.lbounds[q] == -posInfinity) + ub = posInfinity; + else + ub += T[p][q] * dv.lbounds[q]; + } + } + if (T[p].size() == num_dep_dim + 1) { + if (lb != -posInfinity) + lb += T[p][num_dep_dim]; + if (ub != posInfinity) + ub += T[p][num_dep_dim]; + } + lbounds[p] = lb; + ubounds[p] = ub; + } + dv.lbounds = lbounds; + dv.ubounds = ubounds; + + break; + } + default: + ; + } + } + j->second = dvs; + } + + // set constant loop values + std::set active; + for (int i = 0; i < stmt.size(); i++) + active.insert(i); + setLexicalOrder(0, active); + + return true; +} + + +bool Loop::is_dependence_valid_based_on_lex_order(int i, int j, + const DependenceVector &dv, bool before) { + std::vector lex_i = getLexicalOrder(i); + std::vector lex_j = getLexicalOrder(j); + int last_dim; + if (!dv.is_scalar_dependence) { + for (last_dim = 0; + last_dim < lex_i.size() && (lex_i[last_dim] == lex_j[last_dim]); + last_dim++) + ; + last_dim = last_dim / 2; + if (last_dim == 0) + return true; + + for (int i = 0; i < last_dim; i++) { + if (dv.lbounds[i] > 0) + return true; + else if (dv.lbounds[i] < 0) + return false; + } + } + if (before) + return true; + + return false; + +} + +// Manu:: reduction operation + +void Loop::scalar_expand(int stmt_num, const std::vector &levels, + std::string arrName, int memory_type, int padding_alignment, + int assign_then_accumulate, int padding_stride) { + + //std::cout << "In scalar_expand function: " << stmt_num << ", " << arrName << "\n"; + //std::cout.flush(); + + //fprintf(stderr, "\n%d statements\n", stmt.size()); + //for (int i=0; iDump(); + //} + //fprintf(stderr, "\n"); + + // check for sanity of parameters + bool found_non_constant_size_dimension = false; + + if (stmt_num < 0 || stmt_num >= stmt.size()) + throw std::invalid_argument( + "invalid statement number " + to_string(stmt_num)); + //Anand: adding check for privatized levels + //if (arrName != "RHS") + // throw std::invalid_argument( + // "invalid 3rd argument: only 'RHS' supported " + arrName); + for (int i = 0; i < levels.size(); i++) { + if (levels[i] <= 0 || levels[i] > stmt[stmt_num].loop_level.size()) + throw std::invalid_argument( + "1invalid loop level " + to_string(levels[i])); + + if (i > 0) { + if (levels[i] < levels[i - 1]) + throw std::invalid_argument( + "loop levels must be in ascending order"); + } + } + //end --adding check for privatized levels + + delete last_compute_cgr_; + last_compute_cgr_ = NULL; + delete last_compute_cg_; + last_compute_cg_ = NULL; + fprintf(stderr, "Loop::scalar_expand(), SETTING last_compute_cg_ = NULL\n"); + + fprintf(stderr, "\nloop.cc finding array accesses in stmt %d of the code\n",stmt_num ); + std::vector access = ir->FindArrayRef(stmt[stmt_num].code); + fprintf(stderr, "loop.cc L2726 %d access\n", access.size()); + + IR_ArraySymbol *sym = NULL; + fprintf(stderr, "arrName %s\n", arrName.c_str()); + if (arrName == "RHS") { + fprintf(stderr, "sym RHS\n"); + sym = access[0]->symbol(); + } + else { + fprintf(stderr, "looking for array %s in access\n", arrName.c_str()); + for (int k = 0; k < access.size(); k++) { // BUH + + //fprintf(stderr, "access[%d] = %s ", k, access[k]->getTypeString()); access[k]->print(0,stderr); fprintf(stderr, "\n"); + + std::string name = access[k]->symbol()->name(); + //fprintf(stderr, "comparing %s to %s\n", name.c_str(), arrName.c_str()); + + if (access[k]->symbol()->name() == arrName) { + fprintf(stderr, "found it sym access[ k=%d ]\n", k); + sym = access[k]->symbol(); + } + } + } + if (!sym) fprintf(stderr, "DIDN'T FIND IT\n"); + fprintf(stderr, "sym %p\n", sym); + + // collect array references by name + std::vector lex = getLexicalOrder(stmt_num); + int dim = 2 * levels[levels.size() - 1] - 1; + std::set same_loop = getStatements(lex, dim - 1); + + //Anand: shifting this down + // assign_const(stmt[newStmt_num].xform, 2*level+1, 1); + + // std::cout << " before temp array name \n "; + // create a temporary variable + IR_Symbol *tmp_sym; + + // get the loop upperbound, that would be the size of the temp array. + omega::coef_t lb[levels.size()], ub[levels.size()], size[levels.size()]; + + //Anand Adding apply xform so that tiled loop bounds are reflected + fprintf(stderr, "Adding apply xform so that tiled loop bounds are reflected\n"); + apply_xform(same_loop); + fprintf(stderr, "loop.cc, back from apply_xform()\n"); + + //Anand commenting out the folowing 4 lines + /* copy(stmt[stmt_num].IS).query_variable_bounds( + copy(stmt[stmt_num].IS).set_var(level), lb, ub); + std::cout << "Upper Bound = " << ub << "\n"; + std::cout << "lower Bound = " << lb << "\n"; + */ + // testing testing -- Manu //////////////////////////////////////////////// + /* + // int n_dim = sym->n_dim(); + // std::cout << "------- n_dim ----------- " << n_dim << "\n"; + std::pair result = find_simplest_stride(stmt[stmt_num].IS, stmt[stmt_num].IS.set_var(level)); + omega::coef_t index_stride; + if (result.second != NULL) { + index_stride = abs(result.first.get_coef(result.second))/gcd(abs(result.first.get_coef(result.second)), abs(result.first.get_coef(stmt[stmt_num].IS.set_var(level)))); + std::cout << "simplest_stride :: " << index_stride << ", " << result.first.get_coef(result.second) << ", " << result.first.get_coef(stmt[stmt_num].IS.set_var(level))<< "\n"; + } + Relation bound; + // bound = get_loop_bound(stmt[stmt_num].IS, level); + bound = SimpleHull(stmt[stmt_num].IS,true, true); + bound.print(); + + bound = copy(stmt[stmt_num].IS); + for (int i = 1; i < level; i++) { + bound = Project(bound, i, Set_Var); + std::cout << "-------------------------------\n"; + bound.print(); + } + + bound.simplify(); + bound.print(); + // bound = get_loop_bound(bound, level); + + copy(bound).query_variable_bounds(copy(bound).set_var(level), lb, ub); + std::cout << "Upper Bound = " << ub << "\n"; + std::cout << "lower Bound = " << lb << "\n"; + + result = find_simplest_stride(bound, bound.set_var(level)); + if (result.second != NULL) + index_stride = abs(result.first.get_coef(result.second))/gcd(abs(result.first.get_coef(result.second)), abs(result.first.get_coef(bound.set_var(level)))); + else + index_stride = 1; + std::cout << "simplest_stride 11:: " << index_stride << "\n"; + */ + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////// copied datacopy code here ///////////////////////////////////////////// + + //std::cout << "In scalar_expand function 2: " << stmt_num << ", " << arrName << "\n"; + //std::cout.flush(); + + //fprintf(stderr, "\n%d statements\n", stmt.size()); + //for (int i=0; iDump(); + //} + //fprintf(stderr, "\n"); + + + + int n_dim = levels.size(); + Relation copy_is = copy(stmt[stmt_num].IS); + // extract temporary array information + CG_outputBuilder *ocg1 = ir->builder(); + std::vector index_lb(n_dim); // initialized to NULL + std::vector index_stride(n_dim); + std::vector is_index_eq(n_dim, false); + std::vector > index_sz(0); + Relation reduced_copy_is = copy(copy_is); + std::vector size_repr; + std::vector size_int; + Relation xform = copy(stmt[stmt_num].xform); + for (int i = 0; i < n_dim; i++) { + + dim = 2 * levels[i] - 1; + //Anand: Commenting out the lines below: not required + // if (i != 0) + // reduced_copy_is = Project(reduced_copy_is, level - 1 + i, Set_Var); + Relation bound = get_loop_bound(copy(reduced_copy_is), levels[i] - 1); + + // extract stride + std::pair result = find_simplest_stride(bound, + bound.set_var(levels[i])); + if (result.second != NULL) + index_stride[i] = abs(result.first.get_coef(result.second)) + / gcd(abs(result.first.get_coef(result.second)), + abs( + result.first.get_coef( + bound.set_var(levels[i])))); + else + index_stride[i] = 1; + // std::cout << "simplest_stride 11:: " << index_stride[i] << "\n"; + + // check if this array index requires loop + Conjunct *c = bound.query_DNF()->single_conjunct(); + for (EQ_Iterator ei(c->EQs()); ei; ei++) { + if ((*ei).has_wildcards()) + continue; + + int coef = (*ei).get_coef(bound.set_var(levels[i])); + if (coef != 0) { + int sign = 1; + if (coef < 0) { + coef = -coef; + sign = -1; + } + + CG_outputRepr *op = NULL; + for (Constr_Vars_Iter ci(*ei); ci; ci++) { + switch ((*ci).var->kind()) { + case Input_Var: { + if ((*ci).var != bound.set_var(levels[i])) + if ((*ci).coef * sign == 1) + op = ocg1->CreateMinus(op, + ocg1->CreateIdent((*ci).var->name())); + else if ((*ci).coef * sign == -1) + op = ocg1->CreatePlus(op, + ocg1->CreateIdent((*ci).var->name())); + else if ((*ci).coef * sign > 1) { + op = ocg1->CreateMinus(op, + ocg1->CreateTimes( + ocg1->CreateInt( + abs((*ci).coef)), + ocg1->CreateIdent( + (*ci).var->name()))); + } + else + // (*ci).coef*sign < -1 + op = ocg1->CreatePlus(op, + ocg1->CreateTimes( + ocg1->CreateInt( + abs((*ci).coef)), + ocg1->CreateIdent( + (*ci).var->name()))); + break; + } + case Global_Var: { + Global_Var_ID g = (*ci).var->get_global_var(); + if ((*ci).coef * sign == 1) + op = ocg1->CreateMinus(op, + ocg1->CreateIdent(g->base_name())); + else if ((*ci).coef * sign == -1) + op = ocg1->CreatePlus(op, + ocg1->CreateIdent(g->base_name())); + else if ((*ci).coef * sign > 1) + op = ocg1->CreateMinus(op, + ocg1->CreateTimes( + ocg1->CreateInt(abs((*ci).coef)), + ocg1->CreateIdent(g->base_name()))); + else + // (*ci).coef*sign < -1 + op = ocg1->CreatePlus(op, + ocg1->CreateTimes( + ocg1->CreateInt(abs((*ci).coef)), + ocg1->CreateIdent(g->base_name()))); + break; + } + default: + throw loop_error("unsupported array index expression"); + } + } + if ((*ei).get_const() != 0) + op = ocg1->CreatePlus(op, + ocg1->CreateInt(-sign * ((*ei).get_const()))); + if (coef != 1) + op = ocg1->CreateIntegerFloor(op, ocg1->CreateInt(coef)); + + index_lb[i] = op; + is_index_eq[i] = true; + break; + } + } + if (is_index_eq[i]) + continue; + + // separate lower and upper bounds + std::vector lb_list, ub_list; + std::set excluded_floor_vars; + excluded_floor_vars.insert(bound.set_var(levels[i])); + for (GEQ_Iterator gi(c->GEQs()); gi; gi++) { + int coef = (*gi).get_coef(bound.set_var(levels[i])); + if (coef != 0 && (*gi).has_wildcards()) { + bool clean_bound = true; + GEQ_Handle h; + for (Constr_Vars_Iter cvi(*gi, true); gi; gi++) + if (!find_floor_definition(bound, (*cvi).var, + excluded_floor_vars).first) { + clean_bound = false; + break; + } + else + h= find_floor_definition(bound, (*cvi).var, + excluded_floor_vars).second; + + if (!clean_bound) + continue; + else{ + if (coef > 0) + lb_list.push_back(h); + else if (coef < 0) + ub_list.push_back(h); + continue; + } + + } + + if (coef > 0) + lb_list.push_back(*gi); + else if (coef < 0) + ub_list.push_back(*gi); + } + if (lb_list.size() == 0 || ub_list.size() == 0) + throw loop_error("failed to calcuate array footprint size"); + + // build lower bound representation + std::vector lb_repr_list; + /* for (int j = 0; j < lb_list.size(); j++){ + if(this->known.n_set() == 0) + lb_repr_list.push_back(output_lower_bound_repr(ocg1, lb_list[j], bound.set_var(level-1+i+1), result.first, result.second, bound, Relation::True(bound.n_set()), std::vector >(bound.n_set(), std::make_pair(static_cast(NULL), 0)))); + else + lb_repr_list.push_back(output_lower_bound_repr(ocg1, lb_list[j], bound.set_var(level-1+i+1), result.first, result.second, bound, this->known, std::vector >(bound.n_set(), std::make_pair(static_cast(NULL), 0)))); + + } + */ + if (lb_repr_list.size() > 1) + index_lb[i] = ocg1->CreateInvoke("max", lb_repr_list); + else if (lb_repr_list.size() == 1) + index_lb[i] = lb_repr_list[0]; + + // build temporary array size representation + { + Relation cal(copy_is.n_set(), 1); + F_And *f_root = cal.add_and(); + for (int j = 0; j < ub_list.size(); j++) + for (int k = 0; k < lb_list.size(); k++) { + GEQ_Handle h = f_root->add_GEQ(); + + for (Constr_Vars_Iter ci(ub_list[j]); ci; ci++) { + switch ((*ci).var->kind()) { + case Input_Var: { + int pos = (*ci).var->get_position(); + h.update_coef(cal.input_var(pos), (*ci).coef); + break; + } + case Global_Var: { + Global_Var_ID g = (*ci).var->get_global_var(); + Variable_ID v; + if (g->arity() == 0) + v = cal.get_local(g); + else + v = cal.get_local(g, (*ci).var->function_of()); + h.update_coef(v, (*ci).coef); + break; + } + default: + throw loop_error( + "cannot calculate temporay array size statically"); + } + } + h.update_const(ub_list[j].get_const()); + + for (Constr_Vars_Iter ci(lb_list[k]); ci; ci++) { + switch ((*ci).var->kind()) { + case Input_Var: { + int pos = (*ci).var->get_position(); + h.update_coef(cal.input_var(pos), (*ci).coef); + break; + } + case Global_Var: { + Global_Var_ID g = (*ci).var->get_global_var(); + Variable_ID v; + if (g->arity() == 0) + v = cal.get_local(g); + else + v = cal.get_local(g, (*ci).var->function_of()); + h.update_coef(v, (*ci).coef); + break; + } + default: + throw loop_error( + "cannot calculate temporay array size statically"); + } + } + h.update_const(lb_list[k].get_const()); + + h.update_const(1); + h.update_coef(cal.output_var(1), -1); + } + + cal = Restrict_Domain(cal, copy(copy_is)); + for (int j = 1; j <= cal.n_inp(); j++) { + cal = Project(cal, j, Input_Var); + } + cal.simplify(); + + // pad temporary array size + // TODO: for variable array size, create padding formula + //int padding_stride = 0; + Conjunct *c = cal.query_DNF()->single_conjunct(); + bool is_index_bound_const = false; + if (padding_stride != 0 && i == n_dim - 1) { + //size = (size + index_stride[i] - 1) / index_stride[i]; + size_repr.push_back(ocg1->CreateInt(padding_stride)); + } else { + for (GEQ_Iterator gi(c->GEQs()); gi && !is_index_bound_const; + gi++) + if ((*gi).is_const(cal.output_var(1))) { + coef_t size = (*gi).get_const() + / (-(*gi).get_coef(cal.output_var(1))); + + if (padding_alignment > 1 && i == n_dim - 1) { // align to boundary for data packing + int residue = size % padding_alignment; + if (residue) + size = size + padding_alignment - residue; + } + + index_sz.push_back( + std::make_pair(i, ocg1->CreateInt(size))); + is_index_bound_const = true; + size_int.push_back(size); + size_repr.push_back(ocg1->CreateInt(size)); + + // std::cout << "============================== size :: " + // << size << "\n"; + + } + + if (!is_index_bound_const) { + + found_non_constant_size_dimension = true; + Conjunct *c = bound.query_DNF()->single_conjunct(); + for (GEQ_Iterator gi(c->GEQs()); + gi && !is_index_bound_const; gi++) { + int coef = (*gi).get_coef(bound.set_var(levels[i])); + if (coef < 0) { + + size_repr.push_back( + ocg1->CreatePlus( + output_upper_bound_repr(ocg1, *gi, + bound.set_var(levels[i]), + bound, + std::vector< + std::pair< + CG_outputRepr *, + int> >( + bound.n_set(), + std::make_pair( + static_cast(NULL), + 0)), + uninterpreted_symbols[stmt_num]), + ocg1->CreateInt(1))); + + /*CG_outputRepr *op = NULL; + for (Constr_Vars_Iter ci(*gi); ci; ci++) { + if ((*ci).var != cal.output_var(1)) { + switch ((*ci).var->kind()) { + case Global_Var: { + Global_Var_ID g = + (*ci).var->get_global_var(); + if ((*ci).coef == 1) + op = ocg1->CreatePlus(op, + ocg1->CreateIdent( + g->base_name())); + else if ((*ci).coef == -1) + op = ocg1->CreateMinus(op, + ocg1->CreateIdent( + g->base_name())); + else if ((*ci).coef > 1) + op = + ocg1->CreatePlus(op, + ocg1->CreateTimes( + ocg1->CreateInt( + (*ci).coef), + ocg1->CreateIdent( + g->base_name()))); + else + // (*ci).coef < -1 + op = + ocg1->CreateMinus(op, + ocg1->CreateTimes( + ocg1->CreateInt( + -(*ci).coef), + ocg1->CreateIdent( + g->base_name()))); + break; + } + default: + throw loop_error( + "failed to generate array index bound code"); + } + } + } + int c = (*gi).get_const(); + if (c > 0) + op = ocg1->CreatePlus(op, ocg1->CreateInt(c)); + else if (c < 0) + op = ocg1->CreateMinus(op, ocg1->CreateInt(-c)); + */ + /* if (padding_stride != 0) { + if (i == fastest_changing_dimension) { + coef_t g = gcd(index_stride[i], static_cast(padding_stride)); + coef_t t1 = index_stride[i] / g; + if (t1 != 1) + op = ocg->CreateIntegerFloor(ocg->CreatePlus(op, ocg->CreateInt(t1-1)), ocg->CreateInt(t1)); + coef_t t2 = padding_stride / g; + if (t2 != 1) + op = ocg->CreateTimes(op, ocg->CreateInt(t2)); + } + else if (index_stride[i] != 1) { + op = ocg->CreateIntegerFloor(ocg->CreatePlus(op, ocg->CreateInt(index_stride[i]-1)), ocg->CreateInt(index_stride[i])); + } + } + */ + //index_sz.push_back(std::make_pair(i, op)); + //break; + } + } + } + } + } + //size[i] = ub[i]; + + } + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // + + //Anand: Creating IS of new statement + + //for(int l = dim; l < stmt[stmt_num].xform.n_out(); l+=2) + //std::cout << "In scalar_expand function 3: " << stmt_num << ", " << arrName << "\n"; + //std::cout.flush(); + + //fprintf(stderr, "\n%d statements\n", stmt.size()); + //for (int i=0; iDump(); + //} + //fprintf(stderr, "\n"); + + + shiftLexicalOrder(lex, dim + 1, 1); + Statement s = stmt[stmt_num]; + s.ir_stmt_node = NULL; + int newStmt_num = stmt.size(); + + fprintf(stderr, "loop.cc L3249 adding stmt %d\n", stmt.size()); + stmt.push_back(s); + + fprintf(stderr, "uninterpreted_symbols.push_back() newStmt_num %d\n", newStmt_num); + uninterpreted_symbols.push_back(uninterpreted_symbols[stmt_num]); + uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[stmt_num]); + stmt[newStmt_num].code = stmt[stmt_num].code->clone(); + stmt[newStmt_num].IS = copy(stmt[stmt_num].IS); + stmt[newStmt_num].xform = xform; + stmt[newStmt_num].reduction = stmt[stmt_num].reduction; + stmt[newStmt_num].reductionOp = stmt[stmt_num].reductionOp; + + + //fprintf(stderr, "\nafter clone, %d statements\n", stmt.size()); + //for (int i=0; iDump(); + //} + //fprintf(stderr, "\n"); + + + + //assign_const(stmt[newStmt_num].xform, stmt[stmt_num].xform.n_out(), 1);//Anand: change from 2*level + 1 to stmt[stmt_num].xform.size() + //Anand-End creating IS of new statement + + CG_outputRepr * tmpArrSz; + CG_outputBuilder *ocg = ir->builder(); + + //for(int k =0; k < levels.size(); k++ ) + // size_repr.push_back(ocg->CreateInt(size[k]));//Anand: copying apply_xform functionality to prevent IS modification + //due to side effects with uninterpreted function symbols and failures in omega + + //int n = stmt[stmt_num].loop_level.size(); + + /*Relation mapping(2 * n + 1, n); + F_And *f_root = mapping.add_and(); + for (int j = 1; j <= n; j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.output_var(j), 1); + h.update_coef(mapping.input_var(2 * j), -1); + } + mapping = Composition(mapping, copy(stmt[stmt_num].xform)); + mapping.simplify(); + + // match omega input/output variables to variable names in the code + for (int j = 1; j <= stmt[stmt_num].IS.n_set(); j++) + mapping.name_input_var(j, stmt[stmt_num].IS.set_var(j)->name()); + for (int j = 1; j <= n; j++) + mapping.name_output_var(j, + tmp_loop_var_name_prefix + + to_string(tmp_loop_var_name_counter + j - 1)); + mapping.setup_names(); + + Relation size_ = omega::Range(Restrict_Domain(mapping, copy(stmt[stmt_num].IS))); + size_.simplify(); + */ + + //Anand -commenting out tmp sym creation as symbol may have more than one dimension + //tmp_sym = ir->CreateArraySymbol(tmpArrSz, sym); + std::vector lhs_index; + CG_outputRepr *arr_ref_repr; + arr_ref_repr = ocg->CreateIdent( + stmt[stmt_num].IS.set_var(levels[levels.size() - 1])->name()); + + CG_outputRepr *total_size = size_repr[0]; + fprintf(stderr, "total_size = "); total_size->dump(); fflush(stdout); + + for (int i = 1; i < size_repr.size(); i++) { + fprintf(stderr, "total_size now "); total_size->dump(); fflush(stdout); fprintf(stderr, " times something\n\n"); + + total_size = ocg->CreateTimes(total_size->clone(), + size_repr[i]->clone()); + + } + + // COMMENT NEEDED + //fprintf(stderr, "\nloop.cc COMMENT NEEDED\n"); + for (int k = levels.size() - 2; k >= 0; k--) { + CG_outputRepr *temp_repr =ocg->CreateIdent(stmt[stmt_num].IS.set_var(levels[k])->name()); + for (int l = k + 1; l < levels.size(); l++) { + //fprintf(stderr, "\nloop.cc CREATETIMES\n"); + temp_repr = ocg->CreateTimes(temp_repr->clone(), + size_repr[l]->clone()); + } + + //fprintf(stderr, "\nloop.cc CREATEPLUS\n"); + arr_ref_repr = ocg->CreatePlus(arr_ref_repr->clone(), + temp_repr->clone()); + } + + + //fprintf(stderr, "loop.cc, about to die\n"); + std::vector to_push; + to_push.push_back(total_size); + + if (!found_non_constant_size_dimension) { + fprintf(stderr, "constant size dimension\n"); + tmp_sym = ir->CreateArraySymbol(sym, to_push, memory_type); + } + else { + fprintf(stderr, "NON constant size dimension?\n"); + //tmp_sym = ir->CreatePointerSymbol(sym, to_push); + tmp_sym = ir->CreatePointerSymbol(sym, to_push); + + static_cast(tmp_sym)->set_size(0, total_size); // ?? + ptr_variables.push_back(static_cast(tmp_sym)); + fprintf(stderr, "ptr_variables now has %d entries\n", ptr_variables.size()); + } + + // add tmp_sym to Loop symtables ?? + + + // std::cout << " temp array name == " << tmp_sym->name().c_str() << "\n"; + + // get loop index variable at the given "level" + // Relation R = omega::Range(Restrict_Domain(copy(stmt[stmt_num].xform), copy(stmt[stmt_num].IS))); + // stmt[stmt_num].IS.print(); + //stmt[stmt_num].IS. + // std::cout << stmt[stmt_num].IS.n_set() << std::endl; + // std::string v = stmt[stmt_num].IS.set_var(level)->name(); + // std::cout << "loop index variable is '" << v.c_str() << "'\n"; + + // create a reference for the temporary array + fprintf(stderr, "create a reference for the temporary array\n"); + //std::cout << "In scalar_expand function 4: " << stmt_num << ", " << arrName << "\n"; + //std::cout.flush(); + + //fprintf(stderr, "\n%d statements\n", stmt.size()); + //for (int i=0; iDump(); + //} + //fprintf(stderr, "\n"); + + + + std::vector to_push2; + to_push2.push_back(arr_ref_repr); // can have only one entry + + //lhs_index[0] = ocg->CreateIdent(v); + + + IR_ArrayRef *tmp_array_ref; + IR_PointerArrayRef * tmp_ptr_array_ref; // was IR_PointerArrayref + + if (!found_non_constant_size_dimension) { + fprintf(stderr, "constant size\n"); + + tmp_array_ref = ir->CreateArrayRef( + static_cast(tmp_sym), to_push2); + } + else { + fprintf(stderr, "NON constant size\n"); + tmp_ptr_array_ref = ir->CreatePointerArrayRef( + static_cast(tmp_sym), to_push2); + // TODO static_cast(tmp_sym), to_push2); + } + fflush(stdout); + + //fprintf(stderr, "\n%d statements\n", stmt.size()); + //for (int i=0; iDump(); + //} + //fprintf(stderr, "\n"); + + + //std::string stemp; + //stemp = tmp_array_ref->name(); + //std::cout << "Created array reference --> " << stemp.c_str() << "\n"; + + // get the RHS expression + fprintf(stderr, "get the RHS expression arrName %s\n", arrName.c_str()); + + CG_outputRepr *rhs; + if (arrName == "RHS") { + rhs = ir->GetRHSExpression(stmt[stmt_num].code); + + std::vector symbols = ir->FindArrayRef(rhs); + } + std::set sym_names; + + //for (int i = 0; i < symbols.size(); i++) + // sym_names.insert(symbols[i]->symbol()->name()); + + fflush(stdout); + + //fprintf(stderr, "\nbefore if (arrName == RHS)\n%d statements\n", stmt.size()); // problem is after here + //for (int i=0; iDump(); + //} + //fprintf(stderr, "\n"); + + if (arrName == "RHS") { + + std::vector symbols = ir->FindArrayRef(rhs); + + for (int i = 0; i < symbols.size(); i++) + sym_names.insert(symbols[i]->symbol()->name()); + } + else { + + fprintf(stderr, "finding array refs in stmt_num %d\n", stmt_num); + //fprintf(stderr, "\n%d statements\n", stmt.size()); + //for (int i=0; iDump(); + //} + //fprintf(stderr, "\n"); + + std::vector refs = ir->FindArrayRef(stmt[stmt_num].code); + fprintf(stderr, "\n%d refs\n", refs.size()); + + + bool found = false; + + for (int j = 0; j < refs.size(); j++) { + CG_outputRepr* to_replace; + + fprintf(stderr, "j %d build new assignment statement with temporary array\n",j); + // build new assignment statement with temporary array + if (!found_non_constant_size_dimension) { + to_replace = tmp_array_ref->convert(); + } else { + to_replace = tmp_ptr_array_ref->convert(); + } + //fprintf(stderr, "to_replace %p\n", to_replace); + //CG_chillRepr *CR = (CG_chillRepr *) to_replace; + //CR->Dump(); + + if (refs[j]->name() == arrName) { + fflush(stdout); + fprintf(stderr, "loop.cc L353\n"); // problem is after here + //fprintf(stderr, "\n%d statements\n", stmt.size()); + //for (int i=0; iDump(); + //} + //fprintf(stderr, "\n"); + + + sym_names.insert(refs[j]->symbol()->name()); + + if (!found) { + if (!found_non_constant_size_dimension) { + fprintf(stderr, "constant size2\n"); + omega::CG_outputRepr * t = tmp_array_ref->convert(); + omega::CG_outputRepr * r = refs[j]->convert()->clone(); + //CR = (CG_chillRepr *) t; + //CR->Dump(); + //CR = (CG_chillRepr *) r; + //CR->Dump(); + + //fprintf(stderr, "lhs t %p lhs r %p\n", t, r); + stmt[newStmt_num].code = + ir->builder()->CreateAssignment(0, + t, // tmp_array_ref->convert(), + r); // refs[j]->convert()->clone() + } + else { + fprintf(stderr, "NON constant size2\n"); + omega::CG_outputRepr * t = tmp_ptr_array_ref->convert(); // this fails + omega::CG_outputRepr * r = refs[j]->convert()->clone(); + + //omega::CG_chillRepr *CR = (omega::CG_chillRepr *) t; + //CR->Dump(); + //CR = (omega::CG_chillRepr *) r; + //CR->Dump(); + + //fprintf(stderr, "lhs t %p lhs r %p\n", t, r); + stmt[newStmt_num].code = + ir->builder()->CreateAssignment(0, + t, // tmp_ptr_array_ref->convert(), + r ); // refs[j]->convert()->clone()); + } + found = true; + + } + + // refs[j] has no parent? + fprintf(stderr, "replacing refs[%d]\n", j ); + ir->ReplaceExpression(refs[j], to_replace); + } + + } + + } + //ToDo need to update the dependence graph + //Anand adding dependence graph update + fprintf(stderr, "adding dependence graph update\n"); // problem is before here + //fprintf(stderr, "\n%d statements\n", stmt.size()); + //for (int i=0; iDump(); + //} + //fprintf(stderr, "\n"); + + dep.insert(); + + //Anand:Copying Dependence checks from datacopy code, might need to be a separate function/module + // in the future + + /*for (int i = 0; i < newStmt_num; i++) { + std::vector > D; + + for (DependenceGraph::EdgeList::iterator j = + dep.vertex[i].second.begin(); j != dep.vertex[i].second.end(); + ) { + if (same_loop.find(i) != same_loop.end() + && same_loop.find(j->first) == same_loop.end()) { + std::vector dvs1, dvs2; + for (int k = 0; k < j->second.size(); k++) { + DependenceVector dv = j->second[k]; + if (dv.sym != NULL + && sym_names.find(dv.sym->name()) != sym_names.end() + && (dv.type == DEP_R2R || dv.type == DEP_R2W)) + dvs1.push_back(dv); + else + dvs2.push_back(dv); + } + j->second = dvs2; + if (dvs1.size() > 0) + dep.connect(newStmt_num, j->first, dvs1); + } else if (same_loop.find(i) == same_loop.end() + && same_loop.find(j->first) != same_loop.end()) { + std::vector dvs1, dvs2; + for (int k = 0; k < j->second.size(); k++) { + DependenceVector dv = j->second[k]; + if (dv.sym != NULL + && sym_names.find(dv.sym->name()) != sym_names.end() + && (dv.type == DEP_R2R || dv.type == DEP_W2R)) + dvs1.push_back(dv); + else + dvs2.push_back(dv); + } + j->second = dvs2; + if (dvs1.size() > 0) + D.push_back(dvs1); + } + + if (j->second.size() == 0) + dep.vertex[i].second.erase(j++); + else + j++; + } + + for (int j = 0; j < D.size(); j++) + dep.connect(i, newStmt_num, D[j]); + } + */ + //Anand--end dependence check + if (arrName == "RHS") { + + // build new assignment statement with temporary array + if (!found_non_constant_size_dimension) { + if (assign_then_accumulate) { + stmt[newStmt_num].code = ir->builder()->CreateAssignment(0, + tmp_array_ref->convert(), rhs); + fprintf(stderr, "ir->ReplaceRHSExpression( stmt_ num %d )\n", stmt_num); + ir->ReplaceRHSExpression(stmt[stmt_num].code, tmp_array_ref); + } else { + CG_outputRepr *temp = tmp_array_ref->convert()->clone(); + if (ir->QueryExpOperation(stmt[stmt_num].code) + != IR_OP_PLUS_ASSIGNMENT) + throw ir_error( + "Statement is not a += accumulation statement"); + + fprintf(stderr, "replacing in a +=\n"); + stmt[newStmt_num].code = ir->builder()->CreatePlusAssignment(0, + temp->clone(), rhs); + + CG_outputRepr * lhs = ir->GetLHSExpression(stmt[stmt_num].code); + + CG_outputRepr *assignment = ir->builder()->CreateAssignment(0, + lhs, temp->clone()); + Statement init_ = stmt[newStmt_num]; // copy ?? + init_.ir_stmt_node = NULL; + + init_.code = stmt[newStmt_num].code->clone(); + init_.IS = copy(stmt[newStmt_num].IS); + init_.xform = copy(stmt[newStmt_num].xform); + init_.has_inspector = false; // ?? + + Relation mapping(init_.IS.n_set(), init_.IS.n_set()); + + F_And *f_root = mapping.add_and(); + + for (int i = 1; i <= mapping.n_inp(); i++) { + EQ_Handle h = f_root->add_EQ(); + //if (i < levels[0]) { + if (i <= levels[levels.size() - 1]) { + h.update_coef(mapping.input_var(i), 1); + h.update_coef(mapping.output_var(i), -1); + } else { + h.update_const(-1); + h.update_coef(mapping.output_var(i), 1); + } + + /*else { + int j; + for (j = 0; j < levels.size(); j++) + if (i == levels[j]) + break; + + if (j == levels.size()) { + + h.update_coef(mapping.output_var(i), 1); + h.update_const(-1); + + } else { + + + h.update_coef(mapping.input_var(i), 1); + h.update_coef(mapping.output_var(i), -1); + + + } + */ + //} + } + + mapping.simplify(); + // match omega input/output variables to variable names in the code + for (int j = 1; j <= init_.IS.n_set(); j++) + mapping.name_output_var(j, init_.IS.set_var(j)->name()); + for (int j = 1; j <= init_.IS.n_set(); j++) + mapping.name_input_var(j, init_.IS.set_var(j)->name()); + + mapping.setup_names(); + + init_.IS = omega::Range( + omega::Restrict_Domain(mapping, init_.IS)); + std::vector lex = getLexicalOrder(newStmt_num); + int dim = 2 * levels[0] - 1; + //init_.IS.print(); + // init_.xform.print(); + //stmt[newStmt_num].xform.print(); + // shiftLexicalOrder(lex, dim + 1, 1); + shiftLexicalOrder(lex, dim + 1, 1); + init_.reduction = stmt[newStmt_num].reduction; + init_.reductionOp = stmt[newStmt_num].reductionOp; + + init_.code = ir->builder()->CreateAssignment(0, temp->clone(), + ir->builder()->CreateInt(0)); + + fprintf(stderr, "loop.cc L3693 adding stmt %d\n", stmt.size()); + stmt.push_back(init_); + + uninterpreted_symbols.push_back(uninterpreted_symbols[newStmt_num]); + uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[newStmt_num]); + stmt[stmt_num].code = assignment; + } + } else { + if (assign_then_accumulate) { + stmt[newStmt_num].code = ir->builder()->CreateAssignment(0, + tmp_ptr_array_ref->convert(), rhs); + ir->ReplaceRHSExpression(stmt[stmt_num].code, + tmp_ptr_array_ref); + } else { + CG_outputRepr *temp = tmp_ptr_array_ref->convert()->clone(); + if (ir->QueryExpOperation(stmt[stmt_num].code) + != IR_OP_PLUS_ASSIGNMENT) + throw ir_error( + "Statement is not a += accumulation statement"); + stmt[newStmt_num].code = ir->builder()->CreatePlusAssignment(0, + temp->clone(), rhs); + + CG_outputRepr * lhs = ir->GetLHSExpression(stmt[stmt_num].code); + + CG_outputRepr *assignment = ir->builder()->CreateAssignment(0, + lhs, temp->clone()); + + stmt[stmt_num].code = assignment; + } + // call function to replace rhs with temporary array + } + } + + //std::cout << "End of scalar_expand function!! \n"; + + // if(arrName == "RHS"){ + DependenceVector dv; + std::vector E; + dv.lbounds = std::vector(4); + dv.ubounds = std::vector(4); + dv.type = DEP_W2R; + + for (int k = 0; k < 4; k++) { + dv.lbounds[k] = 0; + dv.ubounds[k] = 0; + + } + + //std::vector array_refs = ir->FindArrayRef(stmt[newStmt_num].code); + dv.sym = tmp_sym->clone(); + + E.push_back(dv); + + dep.connect(newStmt_num, stmt_num, E); + // } + +} + + + + +std::pair createCSRstyleISandXFORM(CG_outputBuilder *ocg, + std::vector &outer_loop_bounds, std::string index_name, + std::map &zero_loop_bounds, + std::map > &uninterpreted_symbols, + std::map > &uninterpreted_symbols_string, + Loop *this_loop) { + + Relation IS(outer_loop_bounds.size() + 1 + zero_loop_bounds.size()); + Relation XFORM(outer_loop_bounds.size() + 1 + zero_loop_bounds.size(), + 2 * (outer_loop_bounds.size() + 1 + zero_loop_bounds.size()) + 1); + + F_And * f_r_ = IS.add_and(); + F_And * f_root = XFORM.add_and(); + + if (outer_loop_bounds.size() > 0) { + for (int it = 0; it < IS.n_set(); it++) { + IS.name_set_var(it + 1, + const_cast(outer_loop_bounds[0]).set_var(it + 1)->name()); + XFORM.name_input_var(it + 1, + const_cast(outer_loop_bounds[0]).set_var(it + 1)->name()); + + } + } else if (zero_loop_bounds.size() > 0) { + for (int it = 0; it < IS.n_set(); it++) { + IS.name_set_var(it + 1, + const_cast(zero_loop_bounds.begin()->second).set_var( + it + 1)->name()); + XFORM.name_input_var(it + 1, + const_cast(zero_loop_bounds.begin()->second).set_var( + it + 1)->name()); + + } + + } + + for (int i = 0; i < outer_loop_bounds.size(); i++) + IS = replace_set_var_as_another_set_var(IS, outer_loop_bounds[i], i + 1, + i + 1); + + int count = 1; + for (std::map::iterator i = zero_loop_bounds.begin(); + i != zero_loop_bounds.end(); i++, count++) + IS = replace_set_var_as_another_set_var(IS, i->second, + outer_loop_bounds.size() + 1 + count, i->first); + + if (outer_loop_bounds.size() > 0) { + Free_Var_Decl *lb = new Free_Var_Decl(index_name + "_", 1); // index_ + Variable_ID csr_lb = IS.get_local(lb, Input_Tuple); + + Free_Var_Decl *ub = new Free_Var_Decl(index_name + "__", 1); // index__ + Variable_ID csr_ub = IS.get_local(ub, Input_Tuple); + + //lower bound + + F_And * f_r = IS.and_with_and(); + GEQ_Handle lower_bound = f_r->add_GEQ(); + lower_bound.update_coef(csr_lb, -1); + lower_bound.update_coef(IS.set_var(outer_loop_bounds.size() + 1), 1); + + //upper bound + + GEQ_Handle upper_bound = f_r->add_GEQ(); + upper_bound.update_coef(csr_ub, 1); + upper_bound.update_coef(IS.set_var(outer_loop_bounds.size() + 1), -1); + upper_bound.update_const(-1); + + omega::CG_stringBuilder *ocgs = new CG_stringBuilder; + + std::vector reprs; + std::vector reprs2; + + std::vector reprs3; + std::vector reprs4; + + reprs.push_back( + ocg->CreateIdent(IS.set_var(outer_loop_bounds.size())->name())); + reprs2.push_back( + ocgs->CreateIdent( + IS.set_var(outer_loop_bounds.size())->name())); + uninterpreted_symbols.insert( + std::pair >( + index_name + "_", reprs)); + uninterpreted_symbols_string.insert( + std::pair >( + index_name + "_", reprs2)); + + std::string arg = "(" + IS.set_var(outer_loop_bounds.size())->name() + + ")"; + std::vector< std::string > argvec; + argvec.push_back( arg ); + + CG_outputRepr *repr = ocg->CreateArrayRefExpression(index_name, + ocg->CreateIdent(IS.set_var(outer_loop_bounds.size())->name())); + + //fprintf(stderr, "( VECTOR _)\n"); + //fprintf(stderr, "loop.cc calling CreateDefineMacro( %s, argvec, repr)\n", (index_name + "_").c_str()); + this_loop->ir->CreateDefineMacro(index_name + "_", argvec, repr); + + Relation known_(copy(IS).n_set()); + known_.copy_names(copy(IS)); + known_.setup_names(); + Variable_ID index_lb = known_.get_local(lb, Input_Tuple); + Variable_ID index_ub = known_.get_local(ub, Input_Tuple); + F_And *fr = known_.add_and(); + GEQ_Handle g = fr->add_GEQ(); + g.update_coef(index_ub, 1); + g.update_coef(index_lb, -1); + g.update_const(-1); + this_loop->addKnown(known_); + + reprs3.push_back( + + ocg->CreateIdent(IS.set_var(outer_loop_bounds.size())->name())); + reprs4.push_back( + + ocgs->CreateIdent(IS.set_var(outer_loop_bounds.size())->name())); + + CG_outputRepr *repr2 = ocg->CreateArrayRefExpression(index_name, + ocg->CreatePlus( + ocg->CreateIdent( + IS.set_var(outer_loop_bounds.size())->name()), + ocg->CreateInt(1))); + + //fprintf(stderr, "( VECTOR __)\n"); + //fprintf(stderr, "loop.cc calling CreateDefineMacro( %s, argvec, repr)\n", (index_name + "__").c_str()); + + this_loop->ir->CreateDefineMacro(index_name + "__", argvec, repr2); + + uninterpreted_symbols.insert( + std::pair >( + index_name + "__", reprs3)); + uninterpreted_symbols_string.insert( + std::pair >( + index_name + "__", reprs4)); + } else { + Free_Var_Decl *ub = new Free_Var_Decl(index_name); + Variable_ID csr_ub = IS.get_local(ub); + F_And * f_r = IS.and_with_and(); + GEQ_Handle upper_bound = f_r->add_GEQ(); + upper_bound.update_coef(csr_ub, 1); + upper_bound.update_coef(IS.set_var(outer_loop_bounds.size() + 1), -1); + upper_bound.update_const(-1); + + GEQ_Handle lower_bound = f_r->add_GEQ(); + lower_bound.update_coef(IS.set_var(outer_loop_bounds.size() + 1), 1); + + } + + for (int j = 1; j <= XFORM.n_inp(); j++) { + omega::EQ_Handle h = f_root->add_EQ(); + h.update_coef(XFORM.output_var(2 * j), 1); + h.update_coef(XFORM.input_var(j), -1); + } + + for (int j = 1; j <= XFORM.n_out(); j += 2) { + omega::EQ_Handle h = f_root->add_EQ(); + h.update_coef(XFORM.output_var(j), 1); + } + + if (_DEBUG_) { + IS.print(); + XFORM.print(); + + } + + return std::pair(IS, XFORM); + +} + +std::pair construct_reduced_IS_And_XFORM(IR_Code *ir, + const Relation &is, const Relation &xform, const std::vector loops, + std::vector &lex_order, Relation &known, + std::map > &uninterpreted_symbols) { + + Relation IS(loops.size()); + Relation XFORM(loops.size(), 2 * loops.size() + 1); + int count_ = 1; + std::map pos_mapping; + + int n = is.n_set(); + Relation is_and_known = Intersection(copy(is), + Extend_Set(copy(known), n - known.n_set())); + + for (int it = 0; it < loops.size(); it++, count_++) { + IS.name_set_var(count_, + const_cast(is).set_var(loops[it])->name()); + XFORM.name_input_var(count_, + const_cast(xform).input_var(loops[it])->name()); + XFORM.name_output_var(2 * count_, + const_cast(xform).output_var((loops[it]) * 2)->name()); + XFORM.name_output_var(2 * count_ - 1, + const_cast(xform).output_var((loops[it]) * 2 - 1)->name()); + pos_mapping.insert(std::pair(count_, loops[it])); + } + + XFORM.name_output_var(2 * loops.size() + 1, + const_cast(xform).output_var(is.n_set() * 2 + 1)->name()); + + F_And * f_r = IS.add_and(); + for (std::map::iterator it = pos_mapping.begin(); + it != pos_mapping.end(); it++) + IS = replace_set_var_as_another_set_var(IS, is_and_known, it->first, + it->second); + /* + for (std::map >::iterator it2 = + uninterpreted_symbols.begin(); + it2 != uninterpreted_symbols.end(); it2++) { + std::vector reprs_ = it2->second; + //std::vector reprs_2; + + for (int k = 0; k < reprs_.size(); k++) { + std::vector refs = ir->FindScalarRef(reprs_[k]); + bool exception_found = false; + for (int m = 0; m < refs.size(); m++){ + + if (refs[m]->name() + == const_cast(is).set_var(it->second)->name()) + try { + ir->ReplaceExpression(refs[m], + ir->builder()->CreateIdent( + IS.set_var(it->first)->name())); + } catch (ir_error &e) { + + reprs_[k] = ir->builder()->CreateIdent( + IS.set_var(it->first)->name()); + exception_found = true; + } + if(exception_found) + break; + } + + } + it2->second = reprs_; + } + + } + */ + CHILL_DEBUG_BEGIN + std::cout << "relation debug" << std::endl; + IS.print(); + CHILL_DEBUG_END + + F_And *f_root = XFORM.add_and(); + + count_ = 1; + + for (int j = 1; j <= loops.size(); j++) { + omega::EQ_Handle h = f_root->add_EQ(); + h.update_coef(XFORM.output_var(2 * j), 1); + h.update_coef(XFORM.input_var(j), -1); + } + for (int j = 0; j < loops.size(); j++, count_++) { + omega::EQ_Handle h = f_root->add_EQ(); + h.update_coef(XFORM.output_var(count_ * 2 - 1), 1); + h.update_const(-lex_order[count_ * 2 - 2]); + } + + omega::EQ_Handle h = f_root->add_EQ(); + h.update_coef(XFORM.output_var((loops.size()) * 2 + 1), 1); + h.update_const(-lex_order[xform.n_out() - 1]); + + CHILL_DEBUG_BEGIN + std::cout << "relation debug" << std::endl; + IS.print(); + XFORM.print(); + CHILL_DEBUG_END + + return std::pair(IS, XFORM); + +} + +std::set inspect_repr_for_scalars(IR_Code *ir, + CG_outputRepr * repr, std::set ignore) { + + std::vector refs = ir->FindScalarRef(repr); + std::set loop_vars; + + for (int i = 0; i < refs.size(); i++) + if (ignore.find(refs[i]->name()) == ignore.end()) + loop_vars.insert(refs[i]->name()); + + return loop_vars; + +} + +std::set inspect_loop_bounds(IR_Code *ir, const Relation &R, + int pos, + std::map > &uninterpreted_symbols) { + + if (!R.is_set()) + throw loop_error("Input R has to be a set not a relation!"); + + std::set vars; + + std::vector refs; + Variable_ID v = const_cast(R).set_var(pos); + for (DNF_Iterator di(const_cast(R).query_DNF()); di; di++) { + for (GEQ_Iterator gi = (*di)->GEQs(); gi; gi++) { + if ((*gi).get_coef(v) != 0 && (*gi).is_const_except_for_global(v)) { + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + + case Global_Var: { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() > 0) { + + std::string s = g->base_name(); + std::copy( + uninterpreted_symbols.find(s)->second.begin(), + uninterpreted_symbols.find(s)->second.end(), + back_inserter(refs)); + + } + + break; + } + default: + break; + } + } + + } + } + } + + for (int i = 0; i < refs.size(); i++) { + std::vector refs_ = ir->FindScalarRef(refs[i]); + + for (int j = 0; j < refs_.size(); j++) + vars.insert(refs_[j]->name()); + + } + return vars; +} + +CG_outputRepr * create_counting_loop_body(IR_Code *ir, const Relation &R, + int pos, CG_outputRepr * count, + std::map > &uninterpreted_symbols) { + + if (!R.is_set()) + throw loop_error("Input R has to be a set not a relation!"); + + CG_outputRepr *ub, *lb; + ub = NULL; + lb = NULL; + std::vector refs; + Variable_ID v = const_cast(R).set_var(pos); + for (DNF_Iterator di(const_cast(R).query_DNF()); di; di++) { + for (GEQ_Iterator gi = (*di)->GEQs(); gi; gi++) { + if ((*gi).get_coef(v) != 0 && (*gi).is_const_except_for_global(v)) { + bool same_ge_1 = false; + bool same_ge_2 = false; + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + + case Global_Var: { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() > 0) { + + std::string s = g->base_name(); + + if ((*gi).get_coef(v) > 0) { + if (ub != NULL) + throw ir_error( + "bound expression too complex!"); + + ub = ir->builder()->CreateInvoke(s, + uninterpreted_symbols.find(s)->second); + //ub = ir->builder()->CreateMinus(ub->clone(), ir->builder()->CreateInt(-(*gi).get_const())); + same_ge_1 = true; + + } else { + if (lb != NULL) + throw ir_error( + "bound expression too complex!"); + lb = ir->builder()->CreateInvoke(s, + uninterpreted_symbols.find(s)->second); + same_ge_2 = true; + + } + } + + break; + } + default: + break; + } + } + + if (same_ge_1 && same_ge_2) + lb = ir->builder()->CreatePlus(lb->clone(), + ir->builder()->CreateInt(-(*gi).get_const())); + else if (same_ge_1) + ub = ir->builder()->CreatePlus(ub->clone(), + ir->builder()->CreateInt(-(*gi).get_const())); + else if (same_ge_2) + lb = ir->builder()->CreatePlus(lb->clone(), + ir->builder()->CreateInt(-(*gi).get_const())); + } + } + + } + + return ir->builder()->CreatePlusAssignment(0, count, + ir->builder()->CreatePlus( + ir->builder()->CreateMinus(ub->clone(), lb->clone()), + ir->builder()->CreateInt(1))); +} + + + +std::map > recurse_on_exp_for_arrays( + IR_Code * ir, CG_outputRepr * exp) { + + std::map > arr_index_to_ref; + switch (ir->QueryExpOperation(exp)) { + + case IR_OP_ARRAY_VARIABLE: { + IR_ArrayRef *ref = dynamic_cast(ir->Repr2Ref(exp)); + IR_PointerArrayRef *ref_ = + dynamic_cast(ir->Repr2Ref(exp)); + if (ref == NULL && ref_ == NULL) + throw loop_error("Array symbol unidentifiable!"); + + if (ref != NULL) { + std::vector s0; + + for (int i = 0; i < ref->n_dim(); i++) { + CG_outputRepr * index = ref->index(i); + std::map > a0 = + recurse_on_exp_for_arrays(ir, index); + std::vector s; + for (std::map >::iterator j = + a0.begin(); j != a0.end(); j++) { + if (j->second.size() != 1 && (j->second)[0] != "") + throw loop_error( + "indirect array references not allowed in guard!"); + s.push_back(j->first); + } + std::copy(s.begin(), s.end(), back_inserter(s0)); + } + arr_index_to_ref.insert( + std::pair >( + ref->name(), s0)); + } else { + std::vector s0; + for (int i = 0; i < ref_->n_dim(); i++) { + CG_outputRepr * index = ref_->index(i); + std::map > a0 = + recurse_on_exp_for_arrays(ir, index); + std::vector s; + for (std::map >::iterator j = + a0.begin(); j != a0.end(); j++) { + if (j->second.size() != 1 && (j->second)[0] != "") + throw loop_error( + "indirect array references not allowed in guard!"); + s.push_back(j->first); + } + std::copy(s.begin(), s.end(), back_inserter(s0)); + } + arr_index_to_ref.insert( + std::pair >( + ref_->name(), s0)); + } + break; + } + case IR_OP_PLUS: + case IR_OP_MINUS: + case IR_OP_MULTIPLY: + case IR_OP_DIVIDE: { + std::vector v = ir->QueryExpOperand(exp); + std::map > a0 = + recurse_on_exp_for_arrays(ir, v[0]); + std::map > a1 = + recurse_on_exp_for_arrays(ir, v[1]); + arr_index_to_ref.insert(a0.begin(), a0.end()); + arr_index_to_ref.insert(a1.begin(), a1.end()); + break; + + } + case IR_OP_POSITIVE: + case IR_OP_NEGATIVE: { + std::vector v = ir->QueryExpOperand(exp); + std::map > a0 = + recurse_on_exp_for_arrays(ir, v[0]); + + arr_index_to_ref.insert(a0.begin(), a0.end()); + break; + + } + case IR_OP_VARIABLE: { + std::vector v = ir->QueryExpOperand(exp); + IR_ScalarRef *ref = static_cast(ir->Repr2Ref(v[0])); + + std::string s = ref->name(); + std::vector to_insert; + to_insert.push_back(""); + arr_index_to_ref.insert( + std::pair >(s, + to_insert)); + break; + } + case IR_OP_CONSTANT: + break; + + default: { + std::vector v = ir->QueryExpOperand(exp); + + for (int i = 0; i < v.size(); i++) { + std::map > a0 = + recurse_on_exp_for_arrays(ir, v[i]); + + arr_index_to_ref.insert(a0.begin(), a0.end()); + } + + break; + } + } + return arr_index_to_ref; +} + + + +std::vector find_guards(IR_Code *ir, IR_Control *code) { + CHILL_DEBUG_PRINT("find_guards()\n"); + std::vector guards; + switch (code->type()) { + case IR_CONTROL_IF: { + CHILL_DEBUG_PRINT("find_guards() it's an if\n"); + CG_outputRepr *cond = dynamic_cast(code)->condition(); + + std::vector then_body; + std::vector else_body; + IR_Block *ORTB = dynamic_cast(code)->then_body(); + if (ORTB != NULL) { + CHILL_DEBUG_PRINT("recursing on then\n"); + then_body = find_guards(ir, ORTB); + //dynamic_cast(code)->then_body()); + } + if (dynamic_cast(code)->else_body() != NULL) { + CHILL_DEBUG_PRINT("recursing on then\n"); + else_body = find_guards(ir, + dynamic_cast(code)->else_body()); + } + + guards.push_back(cond); + if (then_body.size() > 0) + std::copy(then_body.begin(), then_body.end(), + back_inserter(guards)); + if (else_body.size() > 0) + std::copy(else_body.begin(), else_body.end(), + back_inserter(guards)); + break; + } + case IR_CONTROL_BLOCK: { + CHILL_DEBUG_PRINT("it's a control block\n"); + IR_Block* IRCB = dynamic_cast(code); + CHILL_DEBUG_PRINT("calling ir->FindOneLevelControlStructure(IRCB);\n"); + std::vector stmts = ir->FindOneLevelControlStructure(IRCB); + + for (int i = 0; i < stmts.size(); i++) { + std::vector stmt_repr = find_guards(ir, stmts[i]); + std::copy(stmt_repr.begin(), stmt_repr.end(), + back_inserter(guards)); + } + break; + } + case IR_CONTROL_LOOP: { + CHILL_DEBUG_PRINT("it's a control loop\n"); + std::vector body = find_guards(ir, + dynamic_cast(code)->body()); + if (body.size() > 0) + std::copy(body.begin(), body.end(), back_inserter(guards)); + break; + } // loop + } // switch + return guards; +} + +bool sort_helper(std::pair > i, + std::pair > j) { + int c1 = 0; + int c2 = 0; + for (int k = 0; k < i.second.size(); k++) + if (i.second[k] != "") + c1++; + + for (int k = 0; k < j.second.size(); k++) + if (j.second[k] != "") + c2++; + return (c1 < c2); + +} + +bool sort_helper_2(std::pair i, std::pair j) { + + return (i.second < j.second); + +} + +std::vector construct_iteration_order( + std::map > & input) { + std::vector arrays; + std::vector scalars; + std::vector > > input_aid; + + for (std::map >::iterator j = + input.begin(); j != input.end(); j++) + input_aid.push_back( + std::pair >(j->first, + j->second)); + + std::sort(input_aid.begin(), input_aid.end(), sort_helper); + + for (int j = 0; j < input_aid[input_aid.size() - 1].second.size(); j++) + if (input_aid[input_aid.size() - 1].second[j] != "") { + arrays.push_back(input_aid[input_aid.size() - 1].second[j]); + + } + + if (arrays.size() > 0) { + for (int i = input_aid.size() - 2; i >= 0; i--) { + + int max_count = 0; + for (int j = 0; j < input_aid[i].second.size(); j++) + if (input_aid[i].second[j] != "") { + max_count++; + } + if (max_count > 0) { + for (int j = 0; j < max_count; j++) { + std::string s = input_aid[i].second[j]; + bool found = false; + for (int k = 0; k < max_count; k++) + if (s == arrays[k]) + found = true; + if (!found) + throw loop_error("guard condition not solvable"); + } + } else { + bool found = false; + for (int k = 0; k < arrays.size(); k++) + if (arrays[k] == input_aid[i].first) + found = true; + if (!found) + arrays.push_back(input_aid[i].first); + } + } + } else { + + for (int i = input_aid.size() - 1; i >= 0; i--) { + arrays.push_back(input_aid[i].first); + } + } + return arrays; +} + + + diff --git a/src/transformations/loop_basic.cc b/src/transformations/loop_basic.cc new file mode 100644 index 0000000..a058598 --- /dev/null +++ b/src/transformations/loop_basic.cc @@ -0,0 +1,1839 @@ +/* + * loop_basic.cc + * + * Created on: Nov 12, 2012 + * Author: anand + */ + +#include "loop.hh" +#include "chill_error.hh" +#include +#include "omegatools.hh" +#include + +#include + +using namespace omega; + +void Loop::permute(const std::vector &pi) { + std::set active; + for (int i = 0; i < stmt.size(); i++) + active.insert(i); + + permute(active, pi); +} + +void Loop::original() { + std::set active; + for (int i = 0; i < stmt.size(); i++) + active.insert(i); + setLexicalOrder(0, active); + //apply_xform(); +} +void Loop::permute(int stmt_num, int level, const std::vector &pi) { + // check for sanity of parameters + int starting_order; + if (stmt_num < 0 || stmt_num >= stmt.size()) + throw std::invalid_argument( + "invalid statement number " + to_string(stmt_num)); + std::set active; + if (level < 0 || level > stmt[stmt_num].loop_level.size()) + throw std::invalid_argument("3invalid loop level " + to_string(level)); + else if (level == 0) { + for (int i = 0; i < stmt.size(); i++) + active.insert(i); + level = 1; + starting_order = 0; + } else { + std::vector lex = getLexicalOrder(stmt_num); + active = getStatements(lex, 2 * level - 2); + starting_order = lex[2 * level - 2]; + lex[2 * level - 2]++; + shiftLexicalOrder(lex, 2 * level - 2, active.size() - 1); + } + std::vector pi_inverse(pi.size(), 0); + for (int i = 0; i < pi.size(); i++) { + if (pi[i] >= level + pi.size() || pi[i] < level + || pi_inverse[pi[i] - level] != 0) + throw std::invalid_argument("invalid permuation"); + pi_inverse[pi[i] - level] = level + i; + } + for (std::set::iterator i = active.begin(); i != active.end(); i++) + if (level + pi.size() - 1 > stmt[*i].loop_level.size()) + throw std::invalid_argument( + "invalid permutation for statement " + to_string(*i)); + + // invalidate saved codegen computation + delete last_compute_cgr_; + last_compute_cgr_ = NULL; + delete last_compute_cg_; + last_compute_cg_ = NULL; + + // Update transformation relations + for (std::set::iterator i = active.begin(); i != active.end(); i++) { + int n = stmt[*i].xform.n_out(); + Relation mapping(n, n); + F_And *f_root = mapping.add_and(); + for (int j = 1; j <= 2 * level - 2; j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.output_var(j), 1); + h.update_coef(mapping.input_var(j), -1); + } + for (int j = level; j <= level + pi.size() - 1; j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.output_var(2 * j), 1); + h.update_coef(mapping.input_var(2 * pi[j - level]), -1); + } + for (int j = level; j <= level + pi.size() - 1; j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.output_var(2 * j - 1), 1); + h.update_coef(mapping.input_var(2 * j - 1), -1); + } + for (int j = 2 * (level + pi.size() - 1) + 1; j <= n; j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.output_var(j), 1); + h.update_coef(mapping.input_var(j), -1); + } + stmt[*i].xform = Composition(mapping, stmt[*i].xform); + stmt[*i].xform.simplify(); + } + + // get the permuation for dependence vectors + std::vector t; + for (int i = 0; i < pi.size(); i++) + if (stmt[stmt_num].loop_level[pi[i] - 1].type == LoopLevelOriginal) + t.push_back(stmt[stmt_num].loop_level[pi[i] - 1].payload); + int max_dep_dim = -1; + int min_dep_dim = dep.num_dim(); + for (int i = 0; i < t.size(); i++) { + if (t[i] > max_dep_dim) + max_dep_dim = t[i]; + if (t[i] < min_dep_dim) + min_dep_dim = t[i]; + } + if (min_dep_dim > max_dep_dim) + return; + if (max_dep_dim - min_dep_dim + 1 != t.size()) + throw loop_error("cannot update the dependence graph after permuation"); + std::vector dep_pi(dep.num_dim()); + for (int i = 0; i < min_dep_dim; i++) + dep_pi[i] = i; + for (int i = min_dep_dim; i <= max_dep_dim; i++) + dep_pi[i] = t[i - min_dep_dim]; + for (int i = max_dep_dim + 1; i < dep.num_dim(); i++) + dep_pi[i] = i; + + dep.permute(dep_pi, active); + + // update the dependence graph + DependenceGraph g(dep.num_dim()); + for (int i = 0; i < dep.vertex.size(); i++) + g.insert(); + for (int i = 0; i < dep.vertex.size(); i++) + for (DependenceGraph::EdgeList::iterator j = + dep.vertex[i].second.begin(); j != dep.vertex[i].second.end(); + j++) { + if ((active.find(i) != active.end() + && active.find(j->first) != active.end())) { + std::vector dv = j->second; + for (int k = 0; k < dv.size(); k++) { + switch (dv[k].type) { + case DEP_W2R: + case DEP_R2W: + case DEP_W2W: + case DEP_R2R: { + std::vector lbounds(dep.num_dim()); + std::vector ubounds(dep.num_dim()); + for (int d = 0; d < dep.num_dim(); d++) { + lbounds[d] = dv[k].lbounds[dep_pi[d]]; + ubounds[d] = dv[k].ubounds[dep_pi[d]]; + } + dv[k].lbounds = lbounds; + dv[k].ubounds = ubounds; + break; + } + case DEP_CONTROL: { + break; + } + default: + throw loop_error("unknown dependence type"); + } + } + g.connect(i, j->first, dv); + } else if (active.find(i) == active.end() + && active.find(j->first) == active.end()) { + std::vector dv = j->second; + g.connect(i, j->first, dv); + } else { + std::vector dv = j->second; + for (int k = 0; k < dv.size(); k++) + switch (dv[k].type) { + case DEP_W2R: + case DEP_R2W: + case DEP_W2W: + case DEP_R2R: { + for (int d = 0; d < dep.num_dim(); d++) + if (dep_pi[d] != d) { + dv[k].lbounds[d] = -posInfinity; + dv[k].ubounds[d] = posInfinity; + } + break; + } + case DEP_CONTROL: + break; + default: + throw loop_error("unknown dependence type"); + } + g.connect(i, j->first, dv); + } + } + dep = g; + + // update loop level information + for (std::set::iterator i = active.begin(); i != active.end(); i++) { + int cur_dep_dim = min_dep_dim; + std::vector new_loop_level(stmt[*i].loop_level.size()); + for (int j = 1; j <= stmt[*i].loop_level.size(); j++) + if (j >= level && j < level + pi.size()) { + switch (stmt[*i].loop_level[pi_inverse[j - level] - 1].type) { + case LoopLevelOriginal: + new_loop_level[j - 1].type = LoopLevelOriginal; + new_loop_level[j - 1].payload = cur_dep_dim++; + new_loop_level[j - 1].parallel_level = + stmt[*i].loop_level[pi_inverse[j - level] - 1].parallel_level; + break; + case LoopLevelTile: { + new_loop_level[j - 1].type = LoopLevelTile; + int ref_level = stmt[*i].loop_level[pi_inverse[j - level] + - 1].payload; + if (ref_level >= level && ref_level < level + pi.size()) + new_loop_level[j - 1].payload = pi_inverse[ref_level + - level]; + else + new_loop_level[j - 1].payload = ref_level; + new_loop_level[j - 1].parallel_level = stmt[*i].loop_level[j + - 1].parallel_level; + break; + } + default: + throw loop_error( + "unknown loop level information for statement " + + to_string(*i)); + } + } else { + switch (stmt[*i].loop_level[j - 1].type) { + case LoopLevelOriginal: + new_loop_level[j - 1].type = LoopLevelOriginal; + new_loop_level[j - 1].payload = + stmt[*i].loop_level[j - 1].payload; + new_loop_level[j - 1].parallel_level = stmt[*i].loop_level[j + - 1].parallel_level; + break; + case LoopLevelTile: { + new_loop_level[j - 1].type = LoopLevelTile; + int ref_level = stmt[*i].loop_level[j - 1].payload; + if (ref_level >= level && ref_level < level + pi.size()) + new_loop_level[j - 1].payload = pi_inverse[ref_level + - level]; + else + new_loop_level[j - 1].payload = ref_level; + new_loop_level[j - 1].parallel_level = stmt[*i].loop_level[j + - 1].parallel_level; + break; + } + default: + throw loop_error( + "unknown loop level information for statement " + + to_string(*i)); + } + } + stmt[*i].loop_level = new_loop_level; + } + + setLexicalOrder(2 * level - 2, active, starting_order); +} +void Loop::permute(const std::set &active, const std::vector &pi) { + if (active.size() == 0 || pi.size() == 0) + return; + + // check for sanity of parameters + int level = pi[0]; + for (int i = 1; i < pi.size(); i++) + if (pi[i] < level) + level = pi[i]; + if (level < 1) + throw std::invalid_argument("invalid permuation"); + std::vector reverse_pi(pi.size(), 0); + for (int i = 0; i < pi.size(); i++) + if (pi[i] >= level + pi.size()) + throw std::invalid_argument("invalid permutation"); + else + reverse_pi[pi[i] - level] = i + level; + for (int i = 0; i < reverse_pi.size(); i++) + if (reverse_pi[i] == 0) + throw std::invalid_argument("invalid permuation"); + int ref_stmt_num; + std::vector lex; + for (std::set::iterator i = active.begin(); i != active.end(); i++) { + if (*i < 0 || *i >= stmt.size()) + throw std::invalid_argument("invalid statement " + to_string(*i)); + if (i == active.begin()) { + ref_stmt_num = *i; + lex = getLexicalOrder(*i); + } else { + if (level + pi.size() - 1 > stmt[*i].loop_level.size()) + throw std::invalid_argument("invalid permuation"); + std::vector lex2 = getLexicalOrder(*i); + for (int j = 0; j < 2 * level - 3; j += 2) + if (lex[j] != lex2[j]) + throw std::invalid_argument( + "statements to permute must be in the same subloop"); + for (int j = 0; j < pi.size(); j++) + if (!(stmt[*i].loop_level[level + j - 1].type + == stmt[ref_stmt_num].loop_level[level + j - 1].type + && stmt[*i].loop_level[level + j - 1].payload + == stmt[ref_stmt_num].loop_level[level + j - 1].payload)) + throw std::invalid_argument( + "permuted loops must have the same loop level types"); + } + } + // invalidate saved codegen computation + delete last_compute_cgr_; + last_compute_cgr_ = NULL; + delete last_compute_cg_; + last_compute_cg_ = NULL; + + // Update transformation relations + for (std::set::iterator i = active.begin(); i != active.end(); i++) { + int n = stmt[*i].xform.n_out(); + Relation mapping(n, n); + F_And *f_root = mapping.add_and(); + for (int j = 1; j <= n; j += 2) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.output_var(j), 1); + h.update_coef(mapping.input_var(j), -1); + } + for (int j = 0; j < pi.size(); j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.output_var(2 * (level + j)), 1); + h.update_coef(mapping.input_var(2 * pi[j]), -1); + } + for (int j = 1; j < level; j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.output_var(2 * j), 1); + h.update_coef(mapping.input_var(2 * j), -1); + } + for (int j = level + pi.size(); j <= stmt[*i].loop_level.size(); j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.output_var(2 * j), 1); + h.update_coef(mapping.input_var(2 * j), -1); + } + + stmt[*i].xform = Composition(mapping, stmt[*i].xform); + stmt[*i].xform.simplify(); + } + + // get the permuation for dependence vectors + std::vector t; + for (int i = 0; i < pi.size(); i++) + if (stmt[ref_stmt_num].loop_level[pi[i] - 1].type == LoopLevelOriginal) + t.push_back(stmt[ref_stmt_num].loop_level[pi[i] - 1].payload); + int max_dep_dim = -1; + int min_dep_dim = num_dep_dim; + for (int i = 0; i < t.size(); i++) { + if (t[i] > max_dep_dim) + max_dep_dim = t[i]; + if (t[i] < min_dep_dim) + min_dep_dim = t[i]; + } + if (min_dep_dim > max_dep_dim) + return; + if (max_dep_dim - min_dep_dim + 1 != t.size()) + throw loop_error("cannot update the dependence graph after permuation"); + std::vector dep_pi(num_dep_dim); + for (int i = 0; i < min_dep_dim; i++) + dep_pi[i] = i; + for (int i = min_dep_dim; i <= max_dep_dim; i++) + dep_pi[i] = t[i - min_dep_dim]; + for (int i = max_dep_dim + 1; i < num_dep_dim; i++) + dep_pi[i] = i; + + dep.permute(dep_pi, active); + + // update the dependence graph + DependenceGraph g(dep.num_dim()); + for (int i = 0; i < dep.vertex.size(); i++) + g.insert(); + for (int i = 0; i < dep.vertex.size(); i++) + for (DependenceGraph::EdgeList::iterator j = + dep.vertex[i].second.begin(); j != dep.vertex[i].second.end(); + j++) { // + if ((active.find(i) != active.end() + && active.find(j->first) != active.end())) { + std::vector dv = j->second; + for (int k = 0; k < dv.size(); k++) { + switch (dv[k].type) { + case DEP_W2R: + case DEP_R2W: + case DEP_W2W: + case DEP_R2R: { + std::vector lbounds(num_dep_dim); + std::vector ubounds(num_dep_dim); + for (int d = 0; d < num_dep_dim; d++) { + lbounds[d] = dv[k].lbounds[dep_pi[d]]; + ubounds[d] = dv[k].ubounds[dep_pi[d]]; + } + dv[k].lbounds = lbounds; + dv[k].ubounds = ubounds; + break; + } + case DEP_CONTROL: { + break; + } + default: + throw loop_error("unknown dependence type"); + } + } + g.connect(i, j->first, dv); + } else if (active.find(i) == active.end() + && active.find(j->first) == active.end()) { + std::vector dv = j->second; + g.connect(i, j->first, dv); + } else { + std::vector dv = j->second; + for (int k = 0; k < dv.size(); k++) + switch (dv[k].type) { + case DEP_W2R: + case DEP_R2W: + case DEP_W2W: + case DEP_R2R: { + for (int d = 0; d < num_dep_dim; d++) + if (dep_pi[d] != d) { + dv[k].lbounds[d] = -posInfinity; + dv[k].ubounds[d] = posInfinity; + } + break; + } + case DEP_CONTROL: + break; + default: + throw loop_error("unknown dependence type"); + } + g.connect(i, j->first, dv); + } + } + dep = g; + + // update loop level information + for (std::set::iterator i = active.begin(); i != active.end(); i++) { + int cur_dep_dim = min_dep_dim; + std::vector new_loop_level(stmt[*i].loop_level.size()); + for (int j = 1; j <= stmt[*i].loop_level.size(); j++) + if (j >= level && j < level + pi.size()) { + switch (stmt[*i].loop_level[reverse_pi[j - level] - 1].type) { + case LoopLevelOriginal: + new_loop_level[j - 1].type = LoopLevelOriginal; + new_loop_level[j - 1].payload = cur_dep_dim++; + new_loop_level[j - 1].parallel_level = + stmt[*i].loop_level[reverse_pi[j - level] - 1].parallel_level; + break; + case LoopLevelTile: { + new_loop_level[j - 1].type = LoopLevelTile; + int ref_level = stmt[*i].loop_level[reverse_pi[j - level]-1].payload; + if (ref_level >= level && ref_level < level + pi.size()) + new_loop_level[j - 1].payload = reverse_pi[ref_level + - level]; + else + new_loop_level[j - 1].payload = ref_level; + new_loop_level[j - 1].parallel_level = + stmt[*i].loop_level[reverse_pi[j - level] - 1].parallel_level; + break; + } + default: + throw loop_error( + "unknown loop level information for statement " + + to_string(*i)); + } + } else { + switch (stmt[*i].loop_level[j - 1].type) { + case LoopLevelOriginal: + new_loop_level[j - 1].type = LoopLevelOriginal; + new_loop_level[j - 1].payload = + stmt[*i].loop_level[j - 1].payload; + new_loop_level[j - 1].parallel_level = stmt[*i].loop_level[j + - 1].parallel_level; + break; + case LoopLevelTile: { + new_loop_level[j - 1].type = LoopLevelTile; + int ref_level = stmt[*i].loop_level[j - 1].payload; + if (ref_level >= level && ref_level < level + pi.size()) + new_loop_level[j - 1].payload = reverse_pi[ref_level + - level]; + else + new_loop_level[j - 1].payload = ref_level; + new_loop_level[j - 1].parallel_level = stmt[*i].loop_level[j + - 1].parallel_level; + break; + } + default: + throw loop_error( + "unknown loop level information for statement " + + to_string(*i)); + } + } + stmt[*i].loop_level = new_loop_level; + } + + setLexicalOrder(2 * level - 2, active); +} + + +void Loop::set_array_size(std::string name, int size ){ + array_dims.insert(std::pair(name, size)); +} + + +std::set Loop::split(int stmt_num, int level, const Relation &cond) { + // check for sanity of parameters + if (stmt_num < 0 || stmt_num >= stmt.size()) + throw std::invalid_argument("invalid statement " + to_string(stmt_num)); + if (level <= 0 || level > stmt[stmt_num].loop_level.size()) + throw std::invalid_argument("4invalid loop level " + to_string(level)); + + std::set result; + int dim = 2 * level - 1; + std::vector lex = getLexicalOrder(stmt_num); + std::set same_loop = getStatements(lex, dim - 1); + + Relation cond2 = copy(cond); + cond2.simplify(); + cond2 = EQs_to_GEQs(cond2); + Conjunct *c = cond2.single_conjunct(); + int cur_lex = lex[dim - 1]; + + for (GEQ_Iterator gi(c->GEQs()); gi; gi++) { + int max_level = (*gi).max_tuple_pos(); + Relation single_cond(max_level); + single_cond.and_with_GEQ(*gi); + + // TODO: should decide where to place newly created statements with + // complementary split condition from dependence graph. + bool place_after; + if (max_level == 0) + place_after = true; + else if ((*gi).get_coef(cond2.set_var(max_level)) < 0) + place_after = true; + else + place_after = false; + + bool temp_place_after; // = place_after; + bool assigned = false; + int part1_to_part2; + int part2_to_part1; + // original statements with split condition, + // new statements with complement of split condition + int old_num_stmt = stmt.size(); + std::map what_stmt_num; + apply_xform(same_loop); + for (std::set::iterator i = same_loop.begin(); + i != same_loop.end(); i++) { + int n = stmt[*i].IS.n_set(); + Relation part1, part2; + if (max_level > n) { + part1 = copy(stmt[*i].IS); + part2 = Relation::False(0); + } else { + part1 = Intersection(copy(stmt[*i].IS), + Extend_Set(copy(single_cond), n - max_level)); + part2 = Intersection(copy(stmt[*i].IS), + Extend_Set(Complement(copy(single_cond)), + n - max_level)); + } + + //split dependence check + + if (max_level > level) { + + DNF_Iterator di1(stmt[*i].IS.query_DNF()); + DNF_Iterator di2(part1.query_DNF()); + for (; di1 && di2; di1++, di2++) { + //printf("In next conjunct,\n"); + EQ_Iterator ei1 = (*di1)->EQs(); + EQ_Iterator ei2 = (*di2)->EQs(); + for (; ei1 && ei2; ei1++, ei2++) { + //printf(" In next equality constraint,\n"); + Constr_Vars_Iter cvi1(*ei1); + Constr_Vars_Iter cvi2(*ei2); + int dimension = (*cvi1).var->get_position(); + int same = 0; + bool identical = false; + if (identical = !strcmp((*cvi1).var->char_name(), + (*cvi2).var->char_name())) { + + for (; cvi1 && cvi2; cvi1++, cvi2++) { + + if (((*cvi1).coef != (*cvi2).coef + || (*ei1).get_const() + != (*ei2).get_const()) + || (strcmp((*cvi1).var->char_name(), + (*cvi2).var->char_name()))) { + + same++; + } + } + } + if ((same != 0) || !identical) { + + dimension = dimension - 1; + + while (stmt[*i].loop_level[dimension].type + == LoopLevelTile) + dimension = + stmt[*i].loop_level[dimension].payload; + + dimension = stmt[*i].loop_level[dimension].payload; + + for (int i = 0; i < stmt.size(); i++) { + std::vector > D; + for (DependenceGraph::EdgeList::iterator j = + dep.vertex[i].second.begin(); + j != dep.vertex[i].second.end(); j++) { + for (int k = 0; k < j->second.size(); k++) { + DependenceVector dv = j->second[k]; + if (dv.type != DEP_CONTROL) + if (dv.hasNegative(dimension) + && !dv.quasi) + throw loop_error( + "loop error: Split is illegal, dependence violation!"); + + } + } + } + + } + + GEQ_Iterator gi1 = (*di1)->GEQs(); + GEQ_Iterator gi2 = (*di2)->GEQs(); + + for (; gi1 && gi2; gi++, gi2++) { + + Constr_Vars_Iter cvi1(*gi1); + Constr_Vars_Iter cvi2(*gi2); + int dimension = (*cvi1).var->get_position(); + int same = 0; + bool identical = false; + if (identical = !strcmp((*cvi1).var->char_name(), + (*cvi2).var->char_name())) { + + for (; cvi1 && cvi2; cvi1++, cvi2++) { + + if (((*cvi1).coef != (*cvi2).coef + || (*gi1).get_const() + != (*gi2).get_const()) + || (strcmp((*cvi1).var->char_name(), + (*cvi2).var->char_name()))) { + + same++; + } + } + } + if ((same != 0) || !identical) { + dimension = dimension - 1; + + while (stmt[*i].loop_level[dimension].type + == LoopLevelTile) + stmt[*i].loop_level[dimension].payload; + + dimension = + stmt[*i].loop_level[dimension].payload; + + for (int i = 0; i < stmt.size(); i++) { + std::vector > D; + for (DependenceGraph::EdgeList::iterator j = + dep.vertex[i].second.begin(); + j != dep.vertex[i].second.end(); + j++) { + for (int k = 0; k < j->second.size(); + k++) { + DependenceVector dv = j->second[k]; + if (dv.type != DEP_CONTROL) + if (dv.hasNegative(dimension) + && !dv.quasi) + + throw loop_error( + "loop error: Split is illegal, dependence violation!"); + + } + } + } + + } + + } + + } + + } + + DNF_Iterator di3(stmt[*i].IS.query_DNF()); + DNF_Iterator di4(part2.query_DNF()); // + for (; di3 && di4; di3++, di4++) { + EQ_Iterator ei1 = (*di3)->EQs(); + EQ_Iterator ei2 = (*di4)->EQs(); + for (; ei1 && ei2; ei1++, ei2++) { + Constr_Vars_Iter cvi1(*ei1); + Constr_Vars_Iter cvi2(*ei2); + int dimension = (*cvi1).var->get_position(); + int same = 0; + bool identical = false; + if (identical = !strcmp((*cvi1).var->char_name(), + (*cvi2).var->char_name())) { + + for (; cvi1 && cvi2; cvi1++, cvi2++) { + + if (((*cvi1).coef != (*cvi2).coef + || (*ei1).get_const() + != (*ei2).get_const()) + || (strcmp((*cvi1).var->char_name(), + (*cvi2).var->char_name()))) { + + same++; + } + } + } + if ((same != 0) || !identical) { + dimension = dimension - 1; + + while (stmt[*i].loop_level[dimension].type + == LoopLevelTile) + stmt[*i].loop_level[dimension].payload; + + dimension = stmt[*i].loop_level[dimension].payload; + + for (int i = 0; i < stmt.size(); i++) { + std::vector > D; + for (DependenceGraph::EdgeList::iterator j = + dep.vertex[i].second.begin(); + j != dep.vertex[i].second.end(); j++) { + for (int k = 0; k < j->second.size(); k++) { + DependenceVector dv = j->second[k]; + if (dv.type != DEP_CONTROL) + if (dv.hasNegative(dimension) + && !dv.quasi) + + throw loop_error( + "loop error: Split is illegal, dependence violation!"); + + } + } + } + + } + + } + GEQ_Iterator gi1 = (*di3)->GEQs(); + GEQ_Iterator gi2 = (*di4)->GEQs(); + + for (; gi1 && gi2; gi++, gi2++) { + Constr_Vars_Iter cvi1(*gi1); + Constr_Vars_Iter cvi2(*gi2); + int dimension = (*cvi1).var->get_position(); + int same = 0; + bool identical = false; + if (identical = !strcmp((*cvi1).var->char_name(), + (*cvi2).var->char_name())) { + + for (; cvi1 && cvi2; cvi1++, cvi2++) { + + if (((*cvi1).coef != (*cvi2).coef + || (*gi1).get_const() + != (*gi2).get_const()) + || (strcmp((*cvi1).var->char_name(), + (*cvi2).var->char_name()))) { + + same++; + } + } + } + if ((same != 0) || !identical) { + dimension = dimension - 1; + + while (stmt[*i].loop_level[dimension].type // + == LoopLevelTile) + stmt[*i].loop_level[dimension].payload; + + dimension = stmt[*i].loop_level[dimension].payload; + + for (int i = 0; i < stmt.size(); i++) { + std::vector > D; + for (DependenceGraph::EdgeList::iterator j = + dep.vertex[i].second.begin(); + j != dep.vertex[i].second.end(); j++) { + for (int k = 0; k < j->second.size(); k++) { + DependenceVector dv = j->second[k]; + if (dv.type != DEP_CONTROL) + if (dv.hasNegative(dimension) + && !dv.quasi) + + throw loop_error( + "loop error: Split is illegal, dependence violation!"); + + } + } + } + + } + + } + + } + + } + + stmt[*i].IS = part1; + + int n1 = part2.n_set(); + int m = this->known.n_set(); + Relation test; + if(m > n1) + test = Intersection(copy(this->known), + Extend_Set(copy(part2), m - part2.n_set())); + else + test = Intersection(copy(part2), + Extend_Set(copy(this->known), n1 - this->known.n_set())); + + if (test.is_upper_bound_satisfiable()) { + Statement new_stmt; + new_stmt.code = stmt[*i].code->clone(); + new_stmt.IS = part2; + new_stmt.xform = copy(stmt[*i].xform); + new_stmt.ir_stmt_node = NULL; + new_stmt.loop_level = stmt[*i].loop_level; + + new_stmt.has_inspector = stmt[*i].has_inspector; + new_stmt.reduction = stmt[*i].reduction; + new_stmt.reductionOp = stmt[*i].reductionOp; + + stmt_nesting_level_.push_back(stmt_nesting_level_[*i]); + + + if (place_after) + assign_const(new_stmt.xform, dim - 1, cur_lex + 1); + else + assign_const(new_stmt.xform, dim - 1, cur_lex - 1); + + fprintf(stderr, "loop_basic.cc L828 adding stmt %d\n", stmt.size()); + stmt.push_back(new_stmt); + + uninterpreted_symbols.push_back(uninterpreted_symbols[stmt_num]); + uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[stmt_num]); + dep.insert(); + what_stmt_num[*i] = stmt.size() - 1; + if (*i == stmt_num) + result.insert(stmt.size() - 1); + } + + } + // make adjacent lexical number available for new statements + if (place_after) { + lex[dim - 1] = cur_lex + 1; + shiftLexicalOrder(lex, dim - 1, 1); + } else { + lex[dim - 1] = cur_lex - 1; + shiftLexicalOrder(lex, dim - 1, -1); + } + // update dependence graph + int dep_dim = get_dep_dim_of(stmt_num, level); + for (int i = 0; i < old_num_stmt; i++) { + std::vector > > D; + + for (DependenceGraph::EdgeList::iterator j = + dep.vertex[i].second.begin(); + j != dep.vertex[i].second.end(); j++) { + if (same_loop.find(i) != same_loop.end()) { + if (same_loop.find(j->first) != same_loop.end()) { + if (what_stmt_num.find(i) != what_stmt_num.end() + && what_stmt_num.find(j->first) + != what_stmt_num.end()) + dep.connect(what_stmt_num[i], + what_stmt_num[j->first], j->second); + if (place_after + && what_stmt_num.find(j->first) + != what_stmt_num.end()) { + std::vector dvs; + for (int k = 0; k < j->second.size(); k++) { + DependenceVector dv = j->second[k]; + if (dv.is_data_dependence() && dep_dim != -1) { + dv.lbounds[dep_dim] = -posInfinity; + dv.ubounds[dep_dim] = posInfinity; + } + dvs.push_back(dv); + } + if (dvs.size() > 0) + D.push_back( + std::make_pair(what_stmt_num[j->first], + dvs)); + } else if (!place_after + && what_stmt_num.find(i) + != what_stmt_num.end()) { + std::vector dvs; + for (int k = 0; k < j->second.size(); k++) { + DependenceVector dv = j->second[k]; + if (dv.is_data_dependence() && dep_dim != -1) { + dv.lbounds[dep_dim] = -posInfinity; + dv.ubounds[dep_dim] = posInfinity; + } + dvs.push_back(dv); + } + if (dvs.size() > 0) + dep.connect(what_stmt_num[i], j->first, dvs); + + } + } else { + if (what_stmt_num.find(i) != what_stmt_num.end()) + dep.connect(what_stmt_num[i], j->first, j->second); + } + } else if (same_loop.find(j->first) != same_loop.end()) { + if (what_stmt_num.find(j->first) != what_stmt_num.end()) + D.push_back( + std::make_pair(what_stmt_num[j->first], + j->second)); + } + } + + for (int j = 0; j < D.size(); j++) + dep.connect(i, D[j].first, D[j].second); + } + + } + + return result; +} + +void Loop::skew(const std::set &stmt_nums, int level, + const std::vector &skew_amount) { + if (stmt_nums.size() == 0) + return; + + // check for sanity of parameters + int ref_stmt_num = *(stmt_nums.begin()); + for (std::set::const_iterator i = stmt_nums.begin(); + i != stmt_nums.end(); i++) { + if (*i < 0 || *i >= stmt.size()) + throw std::invalid_argument( + "invalid statement number " + to_string(*i)); + if (level < 1 || level > stmt[*i].loop_level.size()) + throw std::invalid_argument( + "5invalid loop level " + to_string(level)); + for (int j = stmt[*i].loop_level.size(); j < skew_amount.size(); j++) + if (skew_amount[j] != 0) + throw std::invalid_argument("invalid skewing formula"); + } + + // invalidate saved codegen computation + delete last_compute_cgr_; + last_compute_cgr_ = NULL; + delete last_compute_cg_; + last_compute_cg_ = NULL; + + // set trasformation relations + for (std::set::const_iterator i = stmt_nums.begin(); + i != stmt_nums.end(); i++) { + int n = stmt[*i].xform.n_out(); + Relation r(n, n); + F_And *f_root = r.add_and(); + for (int j = 1; j <= n; j++) + if (j != 2 * level) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(r.input_var(j), 1); + h.update_coef(r.output_var(j), -1); + } + EQ_Handle h = f_root->add_EQ(); + h.update_coef(r.output_var(2 * level), -1); + for (int j = 0; j < skew_amount.size(); j++) + if (skew_amount[j] != 0) + h.update_coef(r.input_var(2 * (j + 1)), skew_amount[j]); + + stmt[*i].xform = Composition(r, stmt[*i].xform); + stmt[*i].xform.simplify(); + } + + // update dependence graph + if (stmt[ref_stmt_num].loop_level[level - 1].type == LoopLevelOriginal) { + int dep_dim = stmt[ref_stmt_num].loop_level[level - 1].payload; + for (std::set::const_iterator i = stmt_nums.begin(); + i != stmt_nums.end(); i++) + for (DependenceGraph::EdgeList::iterator j = + dep.vertex[*i].second.begin(); + j != dep.vertex[*i].second.end(); j++) + if (stmt_nums.find(j->first) != stmt_nums.end()) { + // dependence between skewed statements + std::vector dvs = j->second; + for (int k = 0; k < dvs.size(); k++) { + DependenceVector &dv = dvs[k]; + if (dv.is_data_dependence()) { + coef_t lb = 0; + coef_t ub = 0; + for (int kk = 0; kk < skew_amount.size(); kk++) { + int cur_dep_dim = get_dep_dim_of(*i, kk + 1); + if (skew_amount[kk] > 0) { + if (lb != -posInfinity + && stmt[*i].loop_level[kk].type == LoopLevelOriginal + && dv.lbounds[cur_dep_dim] != -posInfinity) + lb += skew_amount[kk] * dv.lbounds[cur_dep_dim]; + else { + if (cur_dep_dim != -1 + && !(dv.lbounds[cur_dep_dim] == 0 + && dv.ubounds[cur_dep_dim]== 0)) + lb = -posInfinity; + } + if (ub != posInfinity + && stmt[*i].loop_level[kk].type == LoopLevelOriginal + && dv.ubounds[cur_dep_dim] != posInfinity) + ub += skew_amount[kk] * dv.ubounds[cur_dep_dim]; + else { + if (cur_dep_dim != -1 + && !(dv.lbounds[cur_dep_dim] == 0 + && dv.ubounds[cur_dep_dim] == 0)) + ub = posInfinity; + } + } else if (skew_amount[kk] < 0) { + if (lb != -posInfinity + && stmt[*i].loop_level[kk].type == LoopLevelOriginal + && dv.ubounds[cur_dep_dim] != posInfinity) + lb += skew_amount[kk] * dv.ubounds[cur_dep_dim]; + else { + if (cur_dep_dim != -1 + && !(dv.lbounds[cur_dep_dim] == 0 + && dv.ubounds[cur_dep_dim] == 0)) + lb = -posInfinity; + } + if (ub != posInfinity + && stmt[*i].loop_level[kk].type == LoopLevelOriginal + && dv.lbounds[cur_dep_dim] != -posInfinity) + ub += skew_amount[kk] * dv.lbounds[cur_dep_dim]; + else { + if (cur_dep_dim != -1 + && !(dv.lbounds[cur_dep_dim] == 0 + && dv.ubounds[cur_dep_dim] == 0)) + ub = posInfinity; + } + } + } + dv.lbounds[dep_dim] = lb; + dv.ubounds[dep_dim] = ub; + if ((dv.isCarried(dep_dim) && dv.hasPositive(dep_dim)) + && dv.quasi) + dv.quasi = false; + + if ((dv.isCarried(dep_dim) && dv.hasNegative(dep_dim)) + && !dv.quasi) + throw loop_error( + "loop error: Skewing is illegal, dependence violation!"); + dv.lbounds[dep_dim] = lb; + dv.ubounds[dep_dim] = ub; + if ((dv.isCarried(dep_dim) + && dv.hasPositive(dep_dim)) && dv.quasi) + dv.quasi = false; + + if ((dv.isCarried(dep_dim) + && dv.hasNegative(dep_dim)) && !dv.quasi) + throw loop_error( + "loop error: Skewing is illegal, dependence violation!"); + } + } + j->second = dvs; + } else { + // dependence from skewed statement to unskewed statement becomes jumbled, + // put distance value at skewed dimension to unknown + std::vector dvs = j->second; + for (int k = 0; k < dvs.size(); k++) { + DependenceVector &dv = dvs[k]; + if (dv.is_data_dependence()) { + dv.lbounds[dep_dim] = -posInfinity; + dv.ubounds[dep_dim] = posInfinity; + } + } + j->second = dvs; + } + for (int i = 0; i < dep.vertex.size(); i++) + if (stmt_nums.find(i) == stmt_nums.end()) + for (DependenceGraph::EdgeList::iterator j = + dep.vertex[i].second.begin(); + j != dep.vertex[i].second.end(); j++) + if (stmt_nums.find(j->first) != stmt_nums.end()) { + // dependence from unskewed statement to skewed statement becomes jumbled, + // put distance value at skewed dimension to unknown + std::vector dvs = j->second; + for (int k = 0; k < dvs.size(); k++) { + DependenceVector &dv = dvs[k]; + if (dv.is_data_dependence()) { + dv.lbounds[dep_dim] = -posInfinity; + dv.ubounds[dep_dim] = posInfinity; + } + } + j->second = dvs; + } + } +} + + +void Loop::shift(const std::set &stmt_nums, int level, int shift_amount) { + if (stmt_nums.size() == 0) + return; + + // check for sanity of parameters + int ref_stmt_num = *(stmt_nums.begin()); + for (std::set::const_iterator i = stmt_nums.begin(); + i != stmt_nums.end(); i++) { + if (*i < 0 || *i >= stmt.size()) + throw std::invalid_argument( + "invalid statement number " + to_string(*i)); + if (level < 1 || level > stmt[*i].loop_level.size()) + throw std::invalid_argument( + "6invalid loop level " + to_string(level)); + } + + // do nothing + if (shift_amount == 0) + return; + + // invalidate saved codegen computation + delete last_compute_cgr_; + last_compute_cgr_ = NULL; + delete last_compute_cg_; + last_compute_cg_ = NULL; + + // set trasformation relations + for (std::set::const_iterator i = stmt_nums.begin(); + i != stmt_nums.end(); i++) { + int n = stmt[*i].xform.n_out(); + + Relation r(n, n); + F_And *f_root = r.add_and(); + for (int j = 1; j <= n; j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(r.input_var(j), 1); + h.update_coef(r.output_var(j), -1); + if (j == 2 * level) + h.update_const(shift_amount); + } + + stmt[*i].xform = Composition(r, stmt[*i].xform); + stmt[*i].xform.simplify(); + } + + // update dependence graph + if (stmt[ref_stmt_num].loop_level[level - 1].type == LoopLevelOriginal) { + int dep_dim = stmt[ref_stmt_num].loop_level[level - 1].payload; + for (std::set::const_iterator i = stmt_nums.begin(); + i != stmt_nums.end(); i++) + for (DependenceGraph::EdgeList::iterator j = + dep.vertex[*i].second.begin(); + j != dep.vertex[*i].second.end(); j++) + if (stmt_nums.find(j->first) == stmt_nums.end()) { + // dependence from shifted statement to unshifted statement + std::vector dvs = j->second; + for (int k = 0; k < dvs.size(); k++) { + DependenceVector &dv = dvs[k]; + if (dv.is_data_dependence()) { + if (dv.lbounds[dep_dim] != -posInfinity) + dv.lbounds[dep_dim] -= shift_amount; + if (dv.ubounds[dep_dim] != posInfinity) + dv.ubounds[dep_dim] -= shift_amount; + } + } + j->second = dvs; + } + for (int i = 0; i < dep.vertex.size(); i++) + if (stmt_nums.find(i) == stmt_nums.end()) + for (DependenceGraph::EdgeList::iterator j = + dep.vertex[i].second.begin(); + j != dep.vertex[i].second.end(); j++) + if (stmt_nums.find(j->first) != stmt_nums.end()) { + // dependence from unshifted statement to shifted statement + std::vector dvs = j->second; + for (int k = 0; k < dvs.size(); k++) { + DependenceVector &dv = dvs[k]; + if (dv.is_data_dependence()) { + if (dv.lbounds[dep_dim] != -posInfinity) + dv.lbounds[dep_dim] += shift_amount; + if (dv.ubounds[dep_dim] != posInfinity) + dv.ubounds[dep_dim] += shift_amount; + } + } + j->second = dvs; + } + } +} + +void Loop::scale(const std::set &stmt_nums, int level, int scale_amount) { + std::vector skew_amount(level, 0); + skew_amount[level - 1] = scale_amount; + skew(stmt_nums, level, skew_amount); +} + +void Loop::reverse(const std::set &stmt_nums, int level) { + scale(stmt_nums, level, -1); +} + +void Loop::fuse(const std::set &stmt_nums, int level) { + if (stmt_nums.size() == 0 || stmt_nums.size() == 1) + return; + + // invalidate saved codegen computation + delete last_compute_cgr_; + last_compute_cgr_ = NULL; + delete last_compute_cg_; + last_compute_cg_ = NULL; + + int dim = 2 * level - 1; + // check for sanity of parameters + std::vector ref_lex; + int ref_stmt_num; + apply_xform(); + for (std::set::const_iterator i = stmt_nums.begin(); + i != stmt_nums.end(); i++) { + if (*i < 0 || *i >= stmt.size()) { + fprintf(stderr, "statement number %d should be in [0, %d)\n", *i, stmt.size()); + throw std::invalid_argument( + "FUSE invalid statement number " + to_string(*i)); + } + if (level <= 0 + // || (level > (stmt[*i].xform.n_out() - 1) / 2 + // || level > stmt[*i].loop_level.size()) + ) { + fprintf(stderr, "FUSE level %d ", level); + fprintf(stderr, "must be greater than zero and \n"); + fprintf(stderr, "must NOT be greater than (%d - 1)/2 == %d and\n", stmt[*i].xform.n_out(), (stmt[*i].xform.n_out() - 1) / 2); + fprintf(stderr, "must NOT be greater than %d\n", stmt[*i].loop_level.size()); + throw std::invalid_argument( + "FUSE invalid loop level " + to_string(level)); + } + if (ref_lex.size() == 0) { + ref_lex = getLexicalOrder(*i); + ref_stmt_num = *i; + } else { + std::vector lex = getLexicalOrder(*i); + for (int j = 0; j < dim - 1; j += 2) + if (lex[j] != ref_lex[j]) + throw std::invalid_argument( + "statements for fusion must be in the same level-" + + to_string(level - 1) + " subloop"); + } + } + + // collect lexicographical order values from to-be-fused statements + std::set lex_values; + for (std::set::const_iterator i = stmt_nums.begin(); + i != stmt_nums.end(); i++) { + std::vector lex = getLexicalOrder(*i); + lex_values.insert(lex[dim - 1]); + } + if (lex_values.size() == 1) + return; + // negative dependence would prevent fusion + + int dep_dim = get_dep_dim_of(ref_stmt_num, level); + + for (std::set::iterator i = lex_values.begin(); i != lex_values.end(); + i++) { + ref_lex[dim - 1] = *i; + std::set a = getStatements(ref_lex, dim - 1); + std::set::iterator j = i; + j++; + for (; j != lex_values.end(); j++) { + ref_lex[dim - 1] = *j; + std::set b = getStatements(ref_lex, dim - 1); + for (std::set::iterator ii = a.begin(); ii != a.end(); ii++) + for (std::set::iterator jj = b.begin(); jj != b.end(); + jj++) { + std::vector dvs; + dvs = dep.getEdge(*ii, *jj); + for (int k = 0; k < dvs.size(); k++) + if (dvs[k].isCarried(dep_dim) + && dvs[k].hasNegative(dep_dim)) + throw loop_error( + "loop error: statements " + to_string(*ii) + + " and " + to_string(*jj) + + " cannot be fused together due to negative dependence"); + dvs = dep.getEdge(*jj, *ii); + for (int k = 0; k < dvs.size(); k++) + if (dvs[k].isCarried(dep_dim) + && dvs[k].hasNegative(dep_dim)) + throw loop_error( + "loop error: statements " + to_string(*jj) + + " and " + to_string(*ii) + + " cannot be fused together due to negative dependence"); + } + } + } + + std::set same_loop = getStatements(ref_lex, dim - 3); + + std::vector > s = sort_by_same_loops(same_loop, level); + + std::vector s2; + + for (int i = 0; i < s.size(); i++) { + s2.push_back(false); + } + + for (std::set::iterator kk = stmt_nums.begin(); kk != stmt_nums.end(); + kk++) + for (int i = 0; i < s.size(); i++) + if (s[i].find(*kk) != s[i].end()) { + + s2[i] = true; + } + + try { + + //Dependence Check for Ordering Constraint + //Graph, bool> dummy = construct_induced_graph_at_level(s5, + // dep, dep_dim); + + Graph, bool> g = construct_induced_graph_at_level(s, dep, + dep_dim); + std::cout << g; + s = typed_fusion(g, s2); + } catch (const loop_error &e) { + + throw loop_error( + "statements cannot be fused together due to negative dependence"); + + } + + int order = 0; + for (int i = 0; i < s.size(); i++) { + for (std::set::iterator it = s[i].begin(); it != s[i].end(); it++) { + assign_const(stmt[*it].xform, 2 * level - 2, order); + } + order++; + } + + + //plan for selective typed fusion + + /* + 1. sort the lex values of the statements + 2. construct induced graph on sorted statements + 3. pick a node from the graph, check if it is before/after from the candidate set for fusion + equal-> set the max fused node of this node to be the start/target node for fusion + before -> augment and continue + + 4. once target node identified and is on work queue update successors and other nodes to start node + 5. augment and continue + 6. if all candidate nodes dont end up in start node throw error + 7. Get nodes and update lexical values + + */ + + /* for (std::set::iterator kk = stmt_nums.begin(); kk != stmt_nums.end(); + kk++) + for (int i = 0; i < s.size(); i++) + if (s[i].find(*kk) != s[i].end()) { + s1.insert(s[i].begin(), s[i].end()); + s2.insert(i); + } + + s3.push_back(s1); + for (int i = 0; i < s.size(); i++) + if (s2.find(i) == s2.end()) { + s3.push_back(s[i]); + s4.insert(s[i].begin(), s[i].end()); + } + try { + std::vector > s5; + s5.push_back(s1); + s5.push_back(s4); + + //Dependence Check for Ordering Constraint + //Graph, bool> dummy = construct_induced_graph_at_level(s5, + // dep, dep_dim); + + Graph, bool> g = construct_induced_graph_at_level(s3, dep, + dep_dim); + std::cout<< g; + s = typed_fusion(g); + } catch (const loop_error &e) { + + throw loop_error( + "statements cannot be fused together due to negative dependence"); + + } + + if (s3.size() == s.size()) { + int order = 0; + for (int i = 0; i < s.size(); i++) { + + for (std::set::iterator it = s[i].begin(); it != s[i].end(); + it++) { + + assign_const(stmt[*it].xform, 2 * level - 2, order); + + } + + order++; + } + } else if (s3.size() > s.size()) { + + int order = 0; + for (int j = 0; j < s.size(); j++) { + std::set::iterator it3; + for (it3 = s1.begin(); it3 != s1.end(); it3++) { + if (s[j].find(*it3) != s[j].end()) + break; + } + if (it3 != s1.end()) { + for (std::set::iterator it = s1.begin(); it != s1.end(); + it++) + assign_const(stmt[*it].xform, 2 * level - 2, order); + + order++; + + } + + for (int i = 0; i < s3.size(); i++) { + std::set::iterator it2; + + for (it2 = s3[i].begin(); it2 != s3[i].end(); it2++) { + if (s[j].find(*it2) != s[j].end()) + break; + } + + if (it2 != s3[i].end()) { + for (std::set::iterator it = s3[i].begin(); + it != s3[i].end(); it++) + assign_const(stmt[*it].xform, 2 * level - 2, order); + + order++; + + } + } + } + + } else + throw loop_error("Typed Fusion Error"); + */ +} + + + +void Loop::distribute(const std::set &stmt_nums, int level) { + if (stmt_nums.size() == 0 || stmt_nums.size() == 1) + return; + fprintf(stderr, "Loop::distribute()\n"); + + + // invalidate saved codegen computation + delete last_compute_cgr_; + last_compute_cgr_ = NULL; + delete last_compute_cg_; + last_compute_cg_ = NULL; + int dim = 2 * level - 1; + int ref_stmt_num; + // check for sanity of parameters + std::vector ref_lex; + for (std::set::const_iterator i = stmt_nums.begin(); + i != stmt_nums.end(); i++) { + if (*i < 0 || *i >= stmt.size()) + throw std::invalid_argument( + "invalid statement number " + to_string(*i)); + + if (level < 1 + || (level > (stmt[*i].xform.n_out() - 1) / 2 + || level > stmt[*i].loop_level.size())) + throw std::invalid_argument( + "8invalid loop level " + to_string(level)); + if (ref_lex.size() == 0) { + ref_lex = getLexicalOrder(*i); + ref_stmt_num = *i; + } else { + std::vector lex = getLexicalOrder(*i); + for (int j = 0; j <= dim - 1; j += 2) + if (lex[j] != ref_lex[j]) + throw std::invalid_argument( + "statements for distribution must be in the same level-" + + to_string(level) + " subloop"); + } + } + + // find SCC in the to-be-distributed loop + int dep_dim = get_dep_dim_of(ref_stmt_num, level); + std::set same_loop = getStatements(ref_lex, dim - 1); + Graph g; + for (std::set::iterator i = same_loop.begin(); i != same_loop.end(); + i++) + g.insert(*i); + for (int i = 0; i < g.vertex.size(); i++) + for (int j = i + 1; j < g.vertex.size(); j++) { + std::vector dvs; + dvs = dep.getEdge(g.vertex[i].first, g.vertex[j].first); + for (int k = 0; k < dvs.size(); k++) + if (dvs[k].isCarried(dep_dim)) { + g.connect(i, j); + break; + } + dvs = dep.getEdge(g.vertex[j].first, g.vertex[i].first); + for (int k = 0; k < dvs.size(); k++) + if (dvs[k].isCarried(dep_dim)) { + g.connect(j, i); + break; + } + } + std::vector > s = g.topoSort(); + // find statements that cannot be distributed due to dependence cycle + Graph, Empty> g2; + for (int i = 0; i < s.size(); i++) { + std::set t; + for (std::set::iterator j = s[i].begin(); j != s[i].end(); j++) + if (stmt_nums.find(g.vertex[*j].first) != stmt_nums.end()) + t.insert(g.vertex[*j].first); + if (!t.empty()) + g2.insert(t); + } + for (int i = 0; i < g2.vertex.size(); i++) + for (int j = i + 1; j < g2.vertex.size(); j++) + for (std::set::iterator ii = g2.vertex[i].first.begin(); + ii != g2.vertex[i].first.end(); ii++) + for (std::set::iterator jj = g2.vertex[j].first.begin(); + jj != g2.vertex[j].first.end(); jj++) { + std::vector dvs; + dvs = dep.getEdge(*ii, *jj); + for (int k = 0; k < dvs.size(); k++) + if (dvs[k].isCarried(dep_dim)) { + g2.connect(i, j); + break; + } + dvs = dep.getEdge(*jj, *ii); + for (int k = 0; k < dvs.size(); k++) + if (dvs[k].isCarried(dep_dim)) { + g2.connect(j, i); + break; + } + } + std::vector > s2 = g2.topoSort(); + // nothing to distribute + if (s2.size() == 1) + throw loop_error( + "loop error: no statement can be distributed due to dependence cycle"); + std::vector > s3; + for (int i = 0; i < s2.size(); i++) { + std::set t; + for (std::set::iterator j = s2[i].begin(); j != s2[i].end(); j++) + std::set_union(t.begin(), t.end(), g2.vertex[*j].first.begin(), + g2.vertex[*j].first.end(), inserter(t, t.begin())); + s3.push_back(t); + } + // associate other affected statements with the right distributed statements + for (std::set::iterator i = same_loop.begin(); i != same_loop.end(); + i++) + if (stmt_nums.find(*i) == stmt_nums.end()) { + bool is_inserted = false; + int potential_insertion_point = 0; + for (int j = 0; j < s3.size(); j++) { + for (std::set::iterator k = s3[j].begin(); + k != s3[j].end(); k++) { + std::vector dvs; + dvs = dep.getEdge(*i, *k); + for (int kk = 0; kk < dvs.size(); kk++) + if (dvs[kk].isCarried(dep_dim)) { + s3[j].insert(*i); + is_inserted = true; + break; + } + dvs = dep.getEdge(*k, *i); + for (int kk = 0; kk < dvs.size(); kk++) + if (dvs[kk].isCarried(dep_dim)) + potential_insertion_point = j; + } + if (is_inserted) + break; + } + if (!is_inserted) + s3[potential_insertion_point].insert(*i); + } + // set lexicographical order after distribution + int order = ref_lex[dim - 1]; + shiftLexicalOrder(ref_lex, dim - 1, s3.size() - 1); + for (std::vector >::iterator i = s3.begin(); i != s3.end(); + i++) { + for (std::set::iterator j = (*i).begin(); j != (*i).end(); j++) + assign_const(stmt[*j].xform, dim - 1, order); + order++; + } + // no need to update dependence graph + + return; +} + + + + +std::vector FindOuterArrayRefs(IR_Code *ir, + std::vector &arr_refs) { + std::vector to_return; + for (int i = 0; i < arr_refs.size(); i++) + if (!ir->parent_is_array(arr_refs[i])) { + int j; + for (j = 0; j < to_return.size(); j++) + if (*to_return[j] == *arr_refs[i]) + break; + if (j == to_return.size()) + to_return.push_back(arr_refs[i]); + } + return to_return; +} + + + + + +std::vector > constructInspectorVariables(IR_Code *ir, + std::set &arr, std::vector &index) { + + fprintf(stderr, "constructInspectorVariables()\n"); + + std::vector > to_return; + + for (std::set::iterator i = arr.begin(); i != arr.end(); + i++) { + + std::vector per_index; + + CG_outputRepr *subscript = (*i)->index(0); + + if ((*i)->n_dim() > 1) + throw ir_error( + "multi-dimensional array support non-existent for flattening currently"); + + while (ir->QueryExpOperation(subscript) == IR_OP_ARRAY_VARIABLE) { + + std::vector v = ir->QueryExpOperand(subscript); + + IR_ArrayRef *ref = static_cast(ir->Repr2Ref(v[0])); + //per_index.push_back(ref->name()); + + subscript = ref->index(0); + + } + + if (ir->QueryExpOperation(subscript) == IR_OP_VARIABLE) { + std::vector v = ir->QueryExpOperand(subscript); + IR_ScalarRef *ref = static_cast(ir->Repr2Ref(v[0])); + per_index.push_back(ref->name()); + int j; + for (j = 0; j < index.size(); j++) + if (index[j] == ref->name()) + break; + + if (j == index.size()) + throw ir_error("Non index variable in array expression"); + + int k; + for (k = 0; k < to_return.size(); k++) + if (to_return[k][0] == ref->name()) + break; + if (k == to_return.size()) { + to_return.push_back(per_index); + fprintf(stderr, "adding index %s\n", ref->name().c_str()); + } + + } + + } + + return to_return; + +} + +/*std::vector constructInspectorData(IR_Code *ir, std::vector > &indices){ + + std::vector to_return; + + for(int i =0; i < indices.size(); i++) + ir->CreateVariableDeclaration(indices[i][0]); + return to_return; + } + + + CG_outputRepr* constructInspectorFunction(IR_Code* ir, std::vector > &indices){ + + CG_outputRepr *to_return; + + + + return to_return; + } + +*/ + +CG_outputRepr * checkAndGenerateIndirectMappings(CG_outputBuilder * ocg, + std::vector > &indices, + CG_outputRepr * instance, CG_outputRepr * class_def, + CG_outputRepr * count_var) { + + CG_outputRepr *to_return = NULL; + + for (int i = 0; i < indices.size(); i++) + if (indices[i].size() > 1) { + std::string index = indices[i][indices[i].size() - 1]; + CG_outputRepr *rep = ocg->CreateArrayRefExpression( + ocg->CreateDotExpression(instance, + ocg->lookup_member_data(class_def, index, instance)), + count_var); + for (int j = indices[i].size() - 2; j >= 0; j--) + rep = ocg->CreateArrayRefExpression(indices[i][j], rep); + + CG_outputRepr *lhs = ocg->CreateArrayRefExpression( + ocg->CreateDotExpression(instance, + ocg->lookup_member_data(class_def, indices[i][0], instance)), + count_var); + + to_return = ocg->StmtListAppend(to_return, + ocg->CreateAssignment(0, lhs, rep)); + + } + + return to_return; + +} + +CG_outputRepr *generatePointerAssignments(CG_outputBuilder *ocg, + std::string prefix_name, + std::vector > &indices, + CG_outputRepr *instance, + CG_outputRepr *class_def) { + + fprintf(stderr, "generatePointerAssignments()\n"); + CG_outputRepr *list = NULL; + + fprintf(stderr, "prefix '%s', %d indices\n", prefix_name.c_str(), indices.size()); + for (int i = 0; i < indices.size(); i++) { + + std::string s = prefix_name + "_" + indices[i][0]; + + fprintf(stderr, "s %s\n", s.c_str()); + + // create a variable definition for a pointer to int with this name + // that seems to be the only actual result of this routine ... + //chillAST_VarDecl *vd = new chillAST_VarDecl( "int", prefix_name.c_str(), "*", NULL); + //vd->print(); printf("\n"); fflush(stdout); + //vd->dump(); printf("\n"); fflush(stdout); + + CG_outputRepr *ptr_exp = ocg->CreatePointer(s); // but dropped on the floor. unused + //fprintf(stderr, "ptr_exp created\n"); + + //CG_outputRepr *rhs = ocg->CreateDotExpression(instance, + // ocg->lookup_member_data(class_def, indices[i][0], instance)); + + //CG_outputRepr *ptr_assignment = ocg->CreateAssignment(0, ptr_exp, rhs); + + //list = ocg->StmtListAppend(list, ptr_assignment); + + } + + fprintf(stderr, "generatePointerAssignments() DONE\n\n"); + return list; +} + +void Loop::normalize(int stmt_num, int loop_level) { + + if (stmt_num < 0 || stmt_num >= stmt.size()) + throw std::invalid_argument( + + "invalid statement number " + to_string(stmt_num)); + + if (loop_level <= 0) + throw std::invalid_argument( + "12invalid loop level " + to_string(loop_level)); + if (loop_level > stmt[stmt_num].loop_level.size()) + throw std::invalid_argument( + "there is no loop level " + to_string(loop_level) + + " for statement " + to_string(stmt_num)); + + apply_xform(stmt_num); + + Relation r = copy(stmt[stmt_num].IS); + + Relation bound = get_loop_bound(r, loop_level, this->known); + if (!bound.has_single_conjunct() || !bound.is_satisfiable() + || bound.is_tautology()) + throw loop_error("unable to extract loop bound for normalize"); + + // extract the loop stride + coef_t stride; + std::pair result = find_simplest_stride(bound, + bound.set_var(loop_level)); + if (result.second == NULL) + stride = 1; + else + stride = abs(result.first.get_coef(result.second)) + / gcd(abs(result.first.get_coef(result.second)), + abs(result.first.get_coef(bound.set_var(loop_level)))); + + if (stride != 1) + throw loop_error( + "normalize currently only handles unit stride, non unit stride present in loop bounds"); + + GEQ_Handle lb; + + Conjunct *c = bound.query_DNF()->single_conjunct(); + for (GEQ_Iterator gi(c->GEQs()); gi; gi++) { + int coef = (*gi).get_coef(bound.set_var(loop_level)); + if (coef > 0) + lb = *gi; + } + + //Loop bound already zero + //Nothing to do. + if (lb.is_const(bound.set_var(loop_level)) && lb.get_const() == 0) + return; + + if (lb.is_const_except_for_global(bound.set_var(loop_level))) { + + int n = stmt[stmt_num].xform.n_out(); + + Relation r(n, n); + F_And *f_root = r.add_and(); + for (int j = 1; j <= n; j++) + if (j != 2 * loop_level) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(r.input_var(j), 1); + h.update_coef(r.output_var(j), -1); + } + + stmt[stmt_num].xform = Composition(r, stmt[stmt_num].xform); + stmt[stmt_num].xform.simplify(); + + for (Constr_Vars_Iter ci(lb); ci; ci++) { + if ((*ci).var->kind() == Global_Var) { + Global_Var_ID g = (*ci).var->get_global_var(); + Variable_ID v; + if (g->arity() == 0) + v = stmt[stmt_num].xform.get_local(g); + else + v = stmt[stmt_num].xform.get_local(g, + (*ci).var->function_of()); + + F_And *f_super_root = stmt[stmt_num].xform.and_with_and(); + F_Exists *f_exists = f_super_root->add_exists(); + F_And *f_root = f_exists->add_and(); + + EQ_Handle h = f_root->add_EQ(); + h.update_coef(stmt[stmt_num].xform.output_var(2 * loop_level), + 1); + h.update_coef(stmt[stmt_num].xform.input_var(loop_level), -1); + h.update_coef(v, 1); + + stmt[stmt_num].xform.simplify(); + } + + } + + } else + throw loop_error("loop bounds too complex for normalize!"); + +} + diff --git a/src/transformations/loop_datacopy.cc b/src/transformations/loop_datacopy.cc new file mode 100644 index 0000000..12d74fd --- /dev/null +++ b/src/transformations/loop_datacopy.cc @@ -0,0 +1,1369 @@ +/***************************************************************************** + Copyright (C) 2008 University of Southern California + Copyright (C) 2009-2010 University of Utah + All Rights Reserved. + + Purpose: + Various data copy schemes. + + Notes: + + History: + 02/20/09 Created by Chun Chen by splitting original datacopy from loop.cc +*****************************************************************************/ + +#include +#include +#include "loop.hh" +#include "omegatools.hh" +#include "ir_code.hh" +#include "chill_error.hh" + +using namespace omega; + +// +// data copy function by referring arrays by numbers. +// e.g. A[i] = A[i-1] + B[i] +// parameter array_ref_num=[0,2] means to copy data touched by A[i-1] and A[i] +// +bool Loop::datacopy(const std::vector > > &array_ref_nums, int level, + bool allow_extra_read, int fastest_changing_dimension, int padding_stride, int padding_alignment, int memory_type) { + //fprintf(stderr, "Loop::datacopy()\n"); + + // check for sanity of parameters + std::set same_loop; + for (int i = 0; i < array_ref_nums.size(); i++) { + int stmt_num = array_ref_nums[i].first; + if (stmt_num < 0 || stmt_num >= stmt.size()) + throw std::invalid_argument("invalid statement number " + to_string(stmt_num)); + if (level <= 0 || level > stmt[stmt_num].loop_level.size()) + throw std::invalid_argument("invalid loop level " + to_string(level)); + if (i == 0) { + std::vector lex = getLexicalOrder(stmt_num); + same_loop = getStatements(lex, 2*level-2); + } + else if (same_loop.find(stmt_num) == same_loop.end()) + throw std::invalid_argument("array references for data copy must be located in the same subloop"); + } + + // convert array reference numbering scheme to actual array references + std::vector > > selected_refs; + for (int i = 0; i < array_ref_nums.size(); i++) { + if (array_ref_nums[i].second.size() == 0) + continue; + + int stmt_num = array_ref_nums[i].first; + selected_refs.push_back(std::make_pair(stmt_num, std::vector())); + std::vector refs = ir->FindArrayRef(stmt[stmt_num].code); + std::vector selected(refs.size(), false); + for (int j = 0; j < array_ref_nums[i].second.size(); j++) { + int ref_num = array_ref_nums[i].second[j]; + if (ref_num < 0 || ref_num >= refs.size()) { + for (int k = 0; k < refs.size(); k++) + delete refs[k]; + throw std::invalid_argument("invalid array reference number " + to_string(ref_num) + " in statement " + to_string(stmt_num)); + } + selected_refs[selected_refs.size()-1].second.push_back(refs[ref_num]); + selected[ref_num] = true; + } + for (int j = 0; j < refs.size(); j++) + if (!selected[j]) + delete refs[j]; + } + if (selected_refs.size() == 0) + throw std::invalid_argument("found no array references to copy"); + + // do the copy + bool whatever = datacopy_privatized(selected_refs, level, std::vector(), allow_extra_read, fastest_changing_dimension, padding_stride, padding_alignment, memory_type); + return whatever; +} + +// +// data copy function by referring arrays by name. +// e.g. A[i] = A[i-1] + B[i] +// parameter array_name=A means to copy data touched by A[i-1] and A[i] +// +bool Loop::datacopy(int stmt_num, int level, const std::string &array_name, + bool allow_extra_read, int fastest_changing_dimension, int padding_stride, int padding_alignment, int memory_type) { + + fflush(stdout); + //fprintf(stderr, "Loop::datacopy2()\n"); + //fprintf(stderr, "array name %s stmt num %d\n", array_name.c_str(), stmt_num); + + // check for sanity of parameters + if (stmt_num < 0 || stmt_num >= stmt.size()) + throw std::invalid_argument("invalid statement number " + to_string(stmt_num)); + if (level <= 0 || level > stmt[stmt_num].loop_level.size()) + throw std::invalid_argument("invalid loop level " + to_string(level)); + + // collect array references by name + std::vector lex = getLexicalOrder(stmt_num); + int dim = 2*level - 1; + std::set same_loop = getStatements(lex, dim-1); + + std::vector > > selected_refs; + for (std::set::iterator i = same_loop.begin(); i != same_loop.end(); i++) { + std::vector t; + std::vector refs = ir->FindArrayRef(stmt[*i].code); + for (int j = 0; j < refs.size(); j++) + if (refs[j]->name() == array_name) + t.push_back(refs[j]); + else + delete refs[j]; + if (t.size() != 0) + selected_refs.push_back(std::make_pair(*i, t)); + } + + //fprintf(stderr, "selected refs:\n"); + //for (int i=0; iDump(); printf("\n"); fflush(stdout); + //} + + if (selected_refs.size() == 0) + throw std::invalid_argument("found no array references with name " + to_string(array_name) + " to copy"); + + IR_ArrayRef *AR = selected_refs[0].second[0]; + //IR_roseArrayRef *RAR = (IR_roseArrayRef *)AR; + //fprintf(stderr, "before datacopy_privatized, "); + //AR->Dump(); + + // do the copy + //fprintf(stderr, "\nLoop::datacopy2 calling privatized\n"); + + bool whatever = datacopy_privatized(selected_refs, level, std::vector(), allow_extra_read, fastest_changing_dimension, padding_stride, padding_alignment, memory_type); + + //AR = selected_refs[0].second[0]; + //fprintf(stderr, "after datacopy_privatized, "); + //AR->Dump(); + + return whatever; +} + + +bool Loop::datacopy_privatized(int stmt_num, int level, const std::string &array_name, const std::vector &privatized_levels, + bool allow_extra_read, int fastest_changing_dimension, int padding_stride, int padding_alignment, int memory_type) { + //fprintf(stderr, "Loop::datacopy_privatized()\n"); + + // check for sanity of parameters + if (stmt_num < 0 || stmt_num >= stmt.size()) + throw std::invalid_argument("invalid statement number " + to_string(stmt_num)); + if (level <= 0 || level > stmt[stmt_num].loop_level.size()) + throw std::invalid_argument("invalid loop level " + to_string(level)); + + // collect array references by name + std::vector lex = getLexicalOrder(stmt_num); + int dim = 2*level - 1; + std::set same_loop = getStatements(lex, dim-1); + + std::vector > > selected_refs; + for (std::set::iterator i = same_loop.begin(); i != same_loop.end(); i++) { + selected_refs.push_back(std::make_pair(*i, std::vector())); + + std::vector refs = ir->FindArrayRef(stmt[*i].code); + for (int j = 0; j < refs.size(); j++) + if (refs[j]->name() == array_name) + selected_refs[selected_refs.size()-1].second.push_back(refs[j]); + else + delete refs[j]; + } + if (selected_refs.size() == 0) + throw std::invalid_argument("found no array references with name " + to_string(array_name) + " to copy"); + + // do the copy + bool whatever = datacopy_privatized(selected_refs, level, privatized_levels, allow_extra_read, fastest_changing_dimension, padding_stride, padding_alignment, memory_type); + return whatever; +} + + +bool Loop::datacopy_privatized(const std::vector > > &array_ref_nums, int level, const std::vector &privatized_levels, bool allow_extra_read, int fastest_changing_dimension, int padding_stride, int padding_alignment, int memory_type) { + //fprintf(stderr, "Loop::datacopy_privatized2()\n"); + + // check for sanity of parameters + std::set same_loop; + for (int i = 0; i < array_ref_nums.size(); i++) { + int stmt_num = array_ref_nums[i].first; + if (stmt_num < 0 || stmt_num >= stmt.size()) + throw std::invalid_argument("invalid statement number " + to_string(stmt_num)); + if (level <= 0 || level > stmt[stmt_num].loop_level.size()) + throw std::invalid_argument("invalid loop level " + to_string(level)); + if (i == 0) { + std::vector lex = getLexicalOrder(stmt_num); + same_loop = getStatements(lex, 2*level-2); + } + else if (same_loop.find(stmt_num) == same_loop.end()) + throw std::invalid_argument("array references for data copy must be located in the same subloop"); + } + + // convert array reference numbering scheme to actual array references + std::vector > > selected_refs; + for (int i = 0; i < array_ref_nums.size(); i++) { + if (array_ref_nums[i].second.size() == 0) + continue; + + int stmt_num = array_ref_nums[i].first; + selected_refs.push_back(std::make_pair(stmt_num, std::vector())); + std::vector refs = ir->FindArrayRef(stmt[stmt_num].code); + std::vector selected(refs.size(), false); + for (int j = 0; j < array_ref_nums[i].second.size(); j++) { + int ref_num = array_ref_nums[i].second[j]; + if (ref_num < 0 || ref_num >= refs.size()) { + for (int k = 0; k < refs.size(); k++) + delete refs[k]; + throw std::invalid_argument("invalid array reference number " + to_string(ref_num) + " in statement " + to_string(stmt_num)); + } + selected_refs[selected_refs.size()-1].second.push_back(refs[ref_num]); + selected[ref_num] = true; + } + for (int j = 0; j < refs.size(); j++) + if (!selected[j]) + delete refs[j]; + } + if (selected_refs.size() == 0) + throw std::invalid_argument("found no array references to copy"); + + // do the copy + bool whatever = datacopy_privatized(selected_refs, level, privatized_levels, allow_extra_read, fastest_changing_dimension, padding_stride, padding_alignment, memory_type); + return whatever; +} + + +// +// Implement low level datacopy function with lots of options. +// + +bool Loop::datacopy_privatized(const std::vector > > &stmt_refs, + int level, + const std::vector &privatized_levels, + bool allow_extra_read, + int fastest_changing_dimension, + int padding_stride, + int padding_alignment, + int memory_type) { + + //fprintf(stderr, "\nLoop::datacopy_privatized3() *****\n"); + //fprintf(stderr, "privatized_levels.size() %d\n", privatized_levels.size()); + //fprintf(stderr, "level %d\n", level); + + if (stmt_refs.size() == 0) + return true; + + // check for sanity of parameters + IR_ArraySymbol *sym = NULL; + std::vector lex; + std::set active; + if (level <= 0) + throw std::invalid_argument("invalid loop level " + to_string(level)); + for (int i = 0; i < privatized_levels.size(); i++) { + if (i == 0) { + if (privatized_levels[i] < level) + throw std::invalid_argument("privatized loop levels must be no less than level " + to_string(level)); + } + else if (privatized_levels[i] <= privatized_levels[i-1]) + throw std::invalid_argument("privatized loop levels must be in ascending order"); + } + for (int i = 0; i < stmt_refs.size(); i++) { + int stmt_num = stmt_refs[i].first; + active.insert(stmt_num); + if (stmt_num < 0 || stmt_num >= stmt.size()) + throw std::invalid_argument("invalid statement number " + to_string(stmt_num)); + if (privatized_levels.size() != 0) { + if (privatized_levels[privatized_levels.size()-1] > stmt[stmt_num].loop_level.size()) + throw std::invalid_argument("invalid loop level " + to_string(privatized_levels[privatized_levels.size()-1]) + " for statement " + to_string(stmt_num)); + } + else { + if (level > stmt[stmt_num].loop_level.size()) + throw std::invalid_argument("invalid loop level " + to_string(level) + " for statement " + to_string(stmt_num)); + } + for (int j = 0; j < stmt_refs[i].second.size(); j++) { + if (sym == NULL) { + sym = stmt_refs[i].second[j]->symbol(); + lex = getLexicalOrder(stmt_num); + } + else { + IR_ArraySymbol *t = stmt_refs[i].second[j]->symbol(); + if (t->name() != sym->name()) { + delete t; + delete sym; + throw std::invalid_argument("try to copy data from different arrays"); + } + delete t; + } + } + } + + //fprintf(stderr, "sym %p\n", sym); + if (!sym) { + fprintf(stderr, "sym NULL, gonna die\n"); int *i=0; int j=i[0]; + } + + if (!(fastest_changing_dimension >= -1 && fastest_changing_dimension < sym->n_dim())) + throw std::invalid_argument("invalid fastest changing dimension for the array to be copied"); + if (padding_stride < 0) + throw std::invalid_argument("invalid temporary array stride requirement"); + if (padding_alignment == -1 || padding_alignment == 0) + throw std::invalid_argument("invalid temporary array alignment requirement"); + + int dim = 2*level - 1; + int n_dim = sym->n_dim(); + + + if (fastest_changing_dimension == -1) + switch (sym->layout_type()) { + case IR_ARRAY_LAYOUT_ROW_MAJOR: + fastest_changing_dimension = n_dim - 1; + break; + case IR_ARRAY_LAYOUT_COLUMN_MAJOR: + fastest_changing_dimension = 0; + break; + default: + throw loop_error("unsupported array layout"); + } + // OK, parameter sanity checked + + + // invalidate saved codegen computation + delete last_compute_cgr_; + last_compute_cgr_ = NULL; + delete last_compute_cg_; + last_compute_cg_ = NULL; + + // build iteration spaces for all reads and for all writes separately + //fprintf(stderr, "dp3: before apply_xform() ARRAY REFS\n"); + //for (int i = 0; i < stmt_refs.size(); i++) { + // for (int j = 0; j < stmt_refs[i].second.size(); j++) { + // IR_ArrayRef *AR = stmt_refs[i].second[j]; + // fprintf(stderr, "array ref ij %d %d ", i, j); AR->Dump(); fprintf(stderr, "\n"); + // } + //} + //for (int i=0; iDump(); + // fprintf(stderr, "\n"); + // } + //} + + //for (int i=0; iname()); + mapping.setup_names(); + mapping.print(); fflush(stdout); // "{[I] -> [_t1] : I = _t1 } + + F_And *f_root = mapping.add_and(); + for (int k = 1; k <= level-1; k++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.input_var(k), 1); + h.update_coef(mapping.output_var(k), -1); + } + for (int k = 0; k < privatized_levels.size(); k++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.input_var(privatized_levels[k]), 1); + h.update_coef(mapping.output_var(level+k), -1); + } + for (int k = 0; k < n_dim; k++) { + IR_ArrayRef *AR = stmt_refs[i].second[j]; + //fprintf(stderr, "array ref "); + AR->Dump(); + + CG_outputRepr *repr = stmt_refs[i].second[j]->index(k); + //fprintf(stderr, "k %d j %d repr ", k, j); repr->dump(); fflush(stdout); + + exp2formula(ir, + mapping, + f_root, + freevar, + repr, + mapping.output_var(level-1+privatized_levels.size()+k+1), + 'w', + IR_COND_EQ, + false, + uninterpreted_symbols[stmt_num], + uninterpreted_symbols_stringrepr[stmt_num]); + repr->clear(); + delete repr; + } + Relation r = omega::Range(Restrict_Domain(mapping, Intersection(copy(stmt[stmt_num].IS), Extend_Set(copy(this->known), stmt[stmt_num].IS.n_set() - this->known.n_set())))); + if (stmt_refs[i].second[j]->is_write()) { + has_write_refs = true; + wo_copy_is = Union(wo_copy_is, r); + wo_copy_is.simplify(2, 4); + + + } + else { + has_read_refs = true; + ro_copy_is = Union(ro_copy_is, r); + ro_copy_is.simplify(2, 4); + + } + } + } + + //fprintf(stderr, "dp3: simplify\n"); + // simplify read and write footprint iteration space + { + if (allow_extra_read) + ro_copy_is = SimpleHull(ro_copy_is, true, true); + else + ro_copy_is = ConvexRepresentation(ro_copy_is); + + wo_copy_is = ConvexRepresentation(wo_copy_is); + if (wo_copy_is.number_of_conjuncts() > 1) { + Relation t = SimpleHull(wo_copy_is, true, true); + if (Must_Be_Subset(copy(t), copy(ro_copy_is))) + wo_copy_is = t; + else if (Must_Be_Subset(copy(wo_copy_is), copy(ro_copy_is))) + wo_copy_is = ro_copy_is; + } + } + + // make copy statement variable names match the ones in the original statements which + // already have the same names due to apply_xform + { + int ref_stmt = *active.begin(); + for (std::set::iterator i = active.begin(); i != active.end(); i++) + if (stmt[*i].IS.n_set() > stmt[ref_stmt].IS.n_set()) + ref_stmt = *i; + for (int i = 1; i < level; i++) { + std::string s = stmt[ref_stmt].IS.input_var(i)->name(); + wo_copy_is.name_set_var(i, s); + ro_copy_is.name_set_var(i, s); + } + for (int i = 0; i < privatized_levels.size(); i++) { + std::string s = stmt[ref_stmt].IS.input_var(privatized_levels[i])->name(); + wo_copy_is.name_set_var(level+i, s); + ro_copy_is.name_set_var(level+i, s); + } + for (int i = level+privatized_levels.size(); i < level+privatized_levels.size()+n_dim; i++) { + std::string s = tmp_loop_var_name_prefix + to_string(tmp_loop_var_name_counter+i-level-privatized_levels.size()); + wo_copy_is.name_set_var(i, s); + ro_copy_is.name_set_var(i, s); + } + tmp_loop_var_name_counter += n_dim; + wo_copy_is.setup_names(); + ro_copy_is.setup_names(); + } + + //fprintf(stderr, "\ndp3: build merged\n"); + // build merged footprint iteration space for calculating temporary array size + Relation copy_is = SimpleHull(Union(copy(ro_copy_is), copy(wo_copy_is)), true, true); + + // extract temporary array information + CG_outputBuilder *ocg = ir->builder(); + std::vector index_lb(n_dim); // initialized to NULL + std::vector index_stride(n_dim); + std::vector is_index_eq(n_dim, false); + std::vector > index_sz(0); + Relation reduced_copy_is = copy(copy_is); + + for (int i = 0; i < n_dim; i++) { + //fprintf(stderr, "i %d/%d\n", i, n_dim); + if (i != 0) + reduced_copy_is = Project(reduced_copy_is, level-1+privatized_levels.size()+i, Set_Var); + Relation bound = get_loop_bound(reduced_copy_is, level-1+privatized_levels.size()+i); + + //fprintf(stderr, "dp3: extract stride\n"); + // extract stride + std::pair result = find_simplest_stride(bound, bound.set_var(level-1+privatized_levels.size()+i+1)); + if (result.second != NULL) + index_stride[i] = abs(result.first.get_coef(result.second))/gcd(abs(result.first.get_coef(result.second)), abs(result.first.get_coef(bound.set_var(level-1+privatized_levels.size()+i+1)))); + else + index_stride[i] = 1; + //fprintf(stderr, "dp3: index_stride[%d] = %d\n", i, index_stride[i]); + + // check if this array index requires loop + Conjunct *c = bound.query_DNF()->single_conjunct(); + for (EQ_Iterator ei(c->EQs()); ei; ei++) { + //fprintf(stderr, "dp3: for\n"); + if ((*ei).has_wildcards()) + continue; + + //fprintf(stderr, "dp3: no wildcards\n"); + int coef = (*ei).get_coef(bound.set_var(level-1+privatized_levels.size()+i+1)); + if (coef != 0) { + //fprintf(stderr, "coef != 0\n"); + int sign = 1; + if (coef < 0) { + //fprintf(stderr, "coef < 0\n"); + coef = -coef; + sign = -1; + } + + CG_outputRepr *op = NULL; + for (Constr_Vars_Iter ci(*ei); ci; ci++) { + //fprintf(stderr, "dp3: ci\n"); + switch ((*ci).var->kind()) { + case Input_Var: + { + //fprintf(stderr, "dp3: Input_Var\n"); + if ((*ci).var != bound.set_var(level-1+privatized_levels.size()+i+1)) { + //fprintf(stderr, "dp3: IF sign %d\n",(*ci).coef*sign); + + if ((*ci).coef*sign == 1) + op = ocg->CreateMinus(op, ocg->CreateIdent((*ci).var->name())); + else if ((*ci).coef*sign == -1) + op = ocg->CreatePlus(op, ocg->CreateIdent((*ci).var->name())); + else if ((*ci).coef*sign > 1) + op = ocg->CreateMinus(op, ocg->CreateTimes(ocg->CreateInt(abs((*ci).coef)), ocg->CreateIdent((*ci).var->name()))); + else // (*ci).coef*sign < -1 + op = ocg->CreatePlus(op, ocg->CreateTimes(ocg->CreateInt(abs((*ci).coef)), ocg->CreateIdent((*ci).var->name()))); + } + break; + } + case Global_Var: + { + //fprintf(stderr, "dp3: Global_Var\n"); + Global_Var_ID g = (*ci).var->get_global_var(); + if ((*ci).coef*sign == 1) + op = ocg->CreateMinus(op, ocg->CreateIdent(g->base_name())); + else if ((*ci).coef*sign == -1) + op = ocg->CreatePlus(op, ocg->CreateIdent(g->base_name())); + else if ((*ci).coef*sign > 1) + op = ocg->CreateMinus(op, ocg->CreateTimes(ocg->CreateInt(abs((*ci).coef)), ocg->CreateIdent(g->base_name()))); + else // (*ci).coef*sign < -1 + op = ocg->CreatePlus(op, ocg->CreateTimes(ocg->CreateInt(abs((*ci).coef)), ocg->CreateIdent(g->base_name()))); + break; + } + default: + throw loop_error("unsupported array index expression"); + } + } + if ((*ei).get_const() != 0) + op = ocg->CreatePlus(op, ocg->CreateInt(-sign*((*ei).get_const()))); + if (coef != 1) + op = ocg->CreateIntegerFloor(op, ocg->CreateInt(coef)); + + index_lb[i] = op; + is_index_eq[i] = true; + break; + } + } + if (is_index_eq[i]) + continue; + + //fprintf(stderr, "dp3: separate lower and upper bounds\n"); + // separate lower and upper bounds + std::vector lb_list, ub_list; + std::set excluded_floor_vars; + excluded_floor_vars.insert(bound.set_var(level-1+privatized_levels.size()+i+1)); + for (GEQ_Iterator gi(c->GEQs()); gi; gi++) { + int coef = (*gi).get_coef(bound.set_var(level-1+privatized_levels.size()+i+1)); + if (coef != 0 && (*gi).has_wildcards()) { + bool clean_bound = true; + GEQ_Handle h; + for (Constr_Vars_Iter cvi(*gi, true); gi; gi++) + if (!find_floor_definition(bound, (*cvi).var, excluded_floor_vars).first) { + clean_bound = false; + break; + } + if (!clean_bound) + continue; + } + + if (coef > 0) + lb_list.push_back(*gi); + else if (coef < 0) + ub_list.push_back(*gi); + } + if (lb_list.size() == 0 || ub_list.size() == 0) + throw loop_error("failed to calcuate array footprint size"); + + //fprintf(stderr, "dp3: build lower bound representation\n"); + // build lower bound representation + std::vector lb_repr_list; + for (int j = 0; j < lb_list.size(); j++){ + if(this->known.n_set() == 0) { + lb_repr_list.push_back(output_lower_bound_repr(ocg, + lb_list[j], + bound.set_var(level-1+privatized_levels.size()+i+1), + result.first, + result.second, + bound, + Relation::True(bound.n_set()), + std::vector >(bound.n_set(), std::make_pair(static_cast(NULL), 0)), + uninterpreted_symbols[stmt_num])); + } + else { + lb_repr_list.push_back(output_lower_bound_repr(ocg, + lb_list[j], + bound.set_var(level-1+privatized_levels.size()+i+1), + result.first, + result.second, + bound, + this->known, + std::vector >(bound.n_set(), std::make_pair(static_cast(NULL), 0)), + uninterpreted_symbols[stmt_num])); + } + } + if (lb_repr_list.size() > 1) { + //fprintf(stderr, "loop_datacopy.cc dp3 createInvoke( max )\n"); + index_lb[i] = ocg->CreateInvoke("max", lb_repr_list); + } + else if (lb_repr_list.size() == 1) + index_lb[i] = lb_repr_list[0]; + + //fprintf(stderr, "dp3: build temporary array size representation\n"); + // build temporary array size representation + { + Relation cal(copy_is.n_set(), 1); + F_And *f_root = cal.add_and(); + for (int j = 0; j < ub_list.size(); j++) + for (int k = 0; k < lb_list.size(); k++) { + GEQ_Handle h = f_root->add_GEQ(); + + for (Constr_Vars_Iter ci(ub_list[j]); ci; ci++) { + switch ((*ci).var->kind()) { + case Input_Var: + { + int pos = (*ci).var->get_position(); + h.update_coef(cal.input_var(pos), (*ci).coef); + break; + } + case Global_Var: + { + Global_Var_ID g = (*ci).var->get_global_var(); + Variable_ID v; + if (g->arity() == 0) + v = cal.get_local(g); + else + v = cal.get_local(g, (*ci).var->function_of()); + h.update_coef(v, (*ci).coef); + break; + } + default: + throw loop_error("cannot calculate temporay array size statically"); + } + } + h.update_const(ub_list[j].get_const()); + + for (Constr_Vars_Iter ci(lb_list[k]); ci; ci++) { + switch ((*ci).var->kind()) { + case Input_Var: + { + int pos = (*ci).var->get_position(); + h.update_coef(cal.input_var(pos), (*ci).coef); + break; + } + case Global_Var: + { + Global_Var_ID g = (*ci).var->get_global_var(); + Variable_ID v; + if (g->arity() == 0) + v = cal.get_local(g); + else + v = cal.get_local(g, (*ci).var->function_of()); + h.update_coef(v, (*ci).coef); + break; + } + default: + throw loop_error("cannot calculate temporay array size statically"); + } + } + h.update_const(lb_list[k].get_const()); + + h.update_const(1); + h.update_coef(cal.output_var(1), -1); + } + + cal = Restrict_Domain(cal, copy(copy_is)); + for (int j = 1; j <= cal.n_inp(); j++) + cal = Project(cal, j, Input_Var); + cal.simplify(); + + //fprintf(stderr, "dp3: pad temporary array size\n"); + // pad temporary array size + // TODO: for variable array size, create padding formula + Conjunct *c = cal.query_DNF()->single_conjunct(); + bool is_index_bound_const = false; + for (GEQ_Iterator gi(c->GEQs()); gi && !is_index_bound_const; gi++) + if ((*gi).is_const(cal.output_var(1))) { + coef_t size = (*gi).get_const() / (-(*gi).get_coef(cal.output_var(1))); + if (padding_stride != 0) { + size = (size + index_stride[i] - 1) / index_stride[i]; + if (i == fastest_changing_dimension) + size = size * padding_stride; + } + if (i == fastest_changing_dimension) { + if (padding_alignment > 1) { // align to boundary for data packing + int residue = size % padding_alignment; + if (residue) + size = size+padding_alignment-residue; + } + else if (padding_alignment < -1) { // un-alignment for memory bank conflicts + while (gcd(size, static_cast(-padding_alignment)) != 1) + size++; + } + } + index_sz.push_back(std::make_pair(i, ocg->CreateInt(size))); + is_index_bound_const = true; + } + + if (!is_index_bound_const) { + for (GEQ_Iterator gi(c->GEQs()); gi && !is_index_bound_const; gi++) { + int coef = (*gi).get_coef(cal.output_var(1)); + if (coef < 0) { + CG_outputRepr *op = NULL; + for (Constr_Vars_Iter ci(*gi); ci; ci++) { + if ((*ci).var != cal.output_var(1)) { + switch((*ci).var->kind()) { + case Global_Var: + { + Global_Var_ID g = (*ci).var->get_global_var(); + if ((*ci).coef == 1) + op = ocg->CreatePlus(op, ocg->CreateIdent(g->base_name())); + else if ((*ci).coef == -1) + op = ocg->CreateMinus(op, ocg->CreateIdent(g->base_name())); + else if ((*ci).coef > 1) + op = ocg->CreatePlus(op, ocg->CreateTimes(ocg->CreateInt((*ci).coef), ocg->CreateIdent(g->base_name()))); + else // (*ci).coef < -1 + op = ocg->CreateMinus(op, ocg->CreateTimes(ocg->CreateInt(-(*ci).coef), ocg->CreateIdent(g->base_name()))); + break; + } + default: + throw loop_error("failed to generate array index bound code"); + } + } + } + int c = (*gi).get_const(); + if (c > 0) + op = ocg->CreatePlus(op, ocg->CreateInt(c)); + else if (c < 0) + op = ocg->CreateMinus(op, ocg->CreateInt(-c)); + if (padding_stride != 0) { + if (i == fastest_changing_dimension) { + coef_t g = gcd(index_stride[i], static_cast(padding_stride)); + coef_t t1 = index_stride[i] / g; + if (t1 != 1) + op = ocg->CreateIntegerFloor(ocg->CreatePlus(op, ocg->CreateInt(t1-1)), ocg->CreateInt(t1)); + coef_t t2 = padding_stride / g; + if (t2 != 1) + op = ocg->CreateTimes(op, ocg->CreateInt(t2)); + } + else if (index_stride[i] != 1) { + op = ocg->CreateIntegerFloor(ocg->CreatePlus(op, ocg->CreateInt(index_stride[i]-1)), ocg->CreateInt(index_stride[i])); + } + } + + index_sz.push_back(std::make_pair(i, op)); + break; + } + } + } + } + } + + //fprintf(stderr, "dp3: change the temporary array index order\n"); + // change the temporary array index order + for (int i = 0; i < index_sz.size(); i++) { + if (index_sz[i].first == fastest_changing_dimension) + switch (sym->layout_type()) { + case IR_ARRAY_LAYOUT_ROW_MAJOR: + std::swap(index_sz[index_sz.size()-1], index_sz[i]); + break; + case IR_ARRAY_LAYOUT_COLUMN_MAJOR: + std::swap(index_sz[0], index_sz[i]); + break; + default: + throw loop_error("unsupported array layout"); + } + } + + //fprintf(stderr, "dp3: declare temporary array or scalar\n"); + // declare temporary array or scalar + IR_Symbol *tmp_sym; + if (index_sz.size() == 0) { + //fprintf(stderr, "tmp_sym is a scalar\n"); + tmp_sym = ir->CreateScalarSymbol(sym, memory_type); + } + else { + //fprintf(stderr, "tmp_sym is an array\n"); + std::vector tmp_array_size(index_sz.size()); + for (int i = 0; i < index_sz.size(); i++) { + tmp_array_size[i] = index_sz[i].second->clone(); + index_sz[i].second->dump(); // THIS PRINTF + } + tmp_sym = ir->CreateArraySymbol(sym, tmp_array_size, memory_type); + } + + //fprintf(stderr, "dp3: create temporary array read initialization code\n"); + // create temporary array read initialization code + CG_outputRepr *copy_code_read; + if (has_read_refs) { + //fprintf(stderr, "has read refs\n"); + if (index_sz.size() == 0) { + //fprintf(stderr, "if\n"); + + //fprintf(stderr, "tmp sym %s\n", tmp_sym->name().c_str()); + IR_ScalarRef *tmp_scalar_ref = ir->CreateScalarRef(static_cast(tmp_sym)); // create ref from symbol + // tmp_scalar_ref is incomplete + + std::vector rhs_index(n_dim); + for (int i = 0; i < index_lb.size(); i++) { + //fprintf(stderr, "i %d\n", i); + if (is_index_eq[i]) + rhs_index[i] = index_lb[i]->clone(); + else + rhs_index[i] = ir->builder()->CreateIdent(copy_is.set_var(level-1+privatized_levels.size()+i+1)->name()); + } + IR_ArrayRef *copied_array_ref = ir->CreateArrayRef(sym, rhs_index); + + // IR_ScalarRef tmp_scalar_ref has no actual reference yet. It only has the variable definition. + copy_code_read = ir->builder()->CreateAssignment(0, tmp_scalar_ref->convert(), copied_array_ref->convert()); + //fprintf(stderr, "if ends\n"); + } + else { + //fprintf(stderr, "else\n"); + std::vector lhs_index(index_sz.size()); + for (int i = 0; i < index_sz.size(); i++) { + int cur_index_num = index_sz[i].first; + CG_outputRepr *cur_index_repr = ocg->CreateMinus(ocg->CreateIdent(copy_is.set_var(level-1+privatized_levels.size()+cur_index_num+1)->name()), index_lb[cur_index_num]->clone()); + if (padding_stride != 0) { + if (i == n_dim-1) { + coef_t g = gcd(index_stride[cur_index_num], static_cast(padding_stride)); + coef_t t1 = index_stride[cur_index_num] / g; + if (t1 != 1) + cur_index_repr = ocg->CreateIntegerFloor(cur_index_repr, ocg->CreateInt(t1)); + coef_t t2 = padding_stride / g; + if (t2 != 1) + cur_index_repr = ocg->CreateTimes(cur_index_repr, ocg->CreateInt(t2)); + } + else if (index_stride[cur_index_num] != 1) { + cur_index_repr = ocg->CreateIntegerFloor(cur_index_repr, ocg->CreateInt(index_stride[cur_index_num])); + } + } + + if (ir->ArrayIndexStartAt() != 0) + cur_index_repr = ocg->CreatePlus(cur_index_repr, ocg->CreateInt(ir->ArrayIndexStartAt())); + lhs_index[i] = cur_index_repr; + } + + //fprintf(stderr, "dp3: making tmp_array_ref\n"); + IR_ArrayRef *tmp_array_ref = ir->CreateArrayRef(static_cast(tmp_sym), lhs_index); + //fprintf(stderr, "dp3: DONE making tmp_array_ref\n"); + + std::vector rhs_index(n_dim); + for (int i = 0; i < index_lb.size(); i++) + if (is_index_eq[i]) + rhs_index[i] = index_lb[i]->clone(); + else + rhs_index[i] = ir->builder()->CreateIdent(copy_is.set_var(level-1+privatized_levels.size()+i+1)->name()); + IR_ArrayRef *copied_array_ref = ir->CreateArrayRef(sym, rhs_index); + + //fprintf(stderr, "dp3: loop_datacopy.cc copy_code_read = CreateAssignment\n"); + //copy_code_read = ir->builder()->CreateAssignment(0, tmp_array_ref->convert(), copied_array_ref->convert()); + CG_outputRepr *lhs = tmp_array_ref->convert(); + CG_outputRepr *rhs = copied_array_ref->convert(); + copy_code_read = ir->builder()->CreateAssignment(0, lhs, rhs); //tmp_array_ref->convert(), copied_array_ref->convert()); + //fprintf(stderr, "dp3: loop_datacopy.cc copy_code_read = CreateAssignment DONE\n\n"); + } + } // has read refs + + //fprintf(stderr, "dp3: create temporary array write back code\n"); + // create temporary array write back code + CG_outputRepr *copy_code_write; + if (has_write_refs) { + //fprintf(stderr, "has_write_refs\n"); + if (index_sz.size() == 0) { + //fprintf(stderr, "index_sz.size() == 0\n"); + IR_ScalarRef *tmp_scalar_ref = ir->CreateScalarRef(static_cast(tmp_sym)); + + std::vector rhs_index(n_dim); + for (int i = 0; i < index_lb.size(); i++) + if (is_index_eq[i]) + rhs_index[i] = index_lb[i]->clone(); + else + rhs_index[i] = ir->builder()->CreateIdent(copy_is.set_var(level-1+privatized_levels.size()+i+1)->name()); + IR_ArrayRef *copied_array_ref = ir->CreateArrayRef(sym, rhs_index); + + copy_code_write = ir->builder()->CreateAssignment(0, copied_array_ref->convert(), tmp_scalar_ref->convert()); + } + else { + //fprintf(stderr, "index_sz.size() NOT = 0\n"); + + std::vector lhs_index(n_dim); + for (int i = 0; i < index_lb.size(); i++) + if (is_index_eq[i]) + lhs_index[i] = index_lb[i]->clone(); + else + lhs_index[i] = ir->builder()->CreateIdent(copy_is.set_var(level-1+privatized_levels.size()+i+1)->name()); + IR_ArrayRef *copied_array_ref = ir->CreateArrayRef(sym, lhs_index); + + std::vector rhs_index(index_sz.size()); + for (int i = 0; i < index_sz.size(); i++) { + int cur_index_num = index_sz[i].first; + CG_outputRepr *cur_index_repr = ocg->CreateMinus(ocg->CreateIdent(copy_is.set_var(level-1+privatized_levels.size()+cur_index_num+1)->name()), index_lb[cur_index_num]->clone()); + if (padding_stride != 0) { + if (i == n_dim-1) { + coef_t g = gcd(index_stride[cur_index_num], static_cast(padding_stride)); + coef_t t1 = index_stride[cur_index_num] / g; + if (t1 != 1) + cur_index_repr = ocg->CreateIntegerFloor(cur_index_repr, ocg->CreateInt(t1)); + coef_t t2 = padding_stride / g; + if (t2 != 1) + cur_index_repr = ocg->CreateTimes(cur_index_repr, ocg->CreateInt(t2)); + } + else if (index_stride[cur_index_num] != 1) { + cur_index_repr = ocg->CreateIntegerFloor(cur_index_repr, ocg->CreateInt(index_stride[cur_index_num])); + } + } + + if (ir->ArrayIndexStartAt() != 0) + cur_index_repr = ocg->CreatePlus(cur_index_repr, ocg->CreateInt(ir->ArrayIndexStartAt())); + rhs_index[i] = cur_index_repr; + } + IR_ArrayRef *tmp_array_ref = ir->CreateArrayRef(static_cast(tmp_sym), rhs_index); + + copy_code_write = ir->builder()->CreateAssignment(0, copied_array_ref->convert(), tmp_array_ref->convert()); + } + } // has write refs + + // now we can remove those loops for array indexes that are + // dependent on others + //fprintf(stderr, "dp3: now we can remove those loops\n"); + if (!(index_sz.size() == n_dim && (sym->layout_type() == IR_ARRAY_LAYOUT_ROW_MAJOR || n_dim <= 1))) { + Relation mapping(level-1+privatized_levels.size()+n_dim, level-1+privatized_levels.size()+index_sz.size()); + F_And *f_root = mapping.add_and(); + for (int i = 1; i <= level-1+privatized_levels.size(); i++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.input_var(i), 1); + h.update_coef(mapping.output_var(i), -1); + } + + int cur_index = 0; + std::vector mapped_index(index_sz.size()); + for (int i = 0; i < n_dim; i++) + if (!is_index_eq[i]) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.input_var(level-1+privatized_levels.size()+i+1), 1); + switch (sym->layout_type()) { + case IR_ARRAY_LAYOUT_COLUMN_MAJOR: { + h.update_coef(mapping.output_var(level-1+privatized_levels.size()+index_sz.size()-cur_index), -1); + mapped_index[index_sz.size()-cur_index-1] = i; + break; + } + case IR_ARRAY_LAYOUT_ROW_MAJOR: { + h.update_coef(mapping.output_var(level-1+privatized_levels.size()+cur_index+1), -1); + mapped_index[cur_index] = i; + break; + } + default: + throw loop_error("unsupported array layout"); + } + cur_index++; + } + + wo_copy_is = omega::Range(Restrict_Domain(copy(mapping), wo_copy_is)); + ro_copy_is = omega::Range(Restrict_Domain(copy(mapping), ro_copy_is)); + for (int i = 1; i <= level-1+privatized_levels.size(); i++) { + wo_copy_is.name_set_var(i, copy_is.set_var(i)->name()); + ro_copy_is.name_set_var(i, copy_is.set_var(i)->name()); + } + for (int i = 0; i < index_sz.size(); i++) { + wo_copy_is.name_set_var(level-1+privatized_levels.size()+i+1, copy_is.set_var(level-1+privatized_levels.size()+mapped_index[i]+1)->name()); + ro_copy_is.name_set_var(level-1+privatized_levels.size()+i+1, copy_is.set_var(level-1+privatized_levels.size()+mapped_index[i]+1)->name()); + } + wo_copy_is.setup_names(); + ro_copy_is.setup_names(); + } + + // insert read copy statement + //fprintf(stderr, "dp3: insert read copy statement\n"); + + int old_num_stmt = stmt.size(); + int ro_copy_stmt_num = -1; + if (has_read_refs) { + Relation copy_xform(ro_copy_is.n_set(), 2*ro_copy_is.n_set()+1); + { + F_And *f_root = copy_xform.add_and(); + for (int i = 1; i <= ro_copy_is.n_set(); i++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(copy_xform.input_var(i), 1); + h.update_coef(copy_xform.output_var(2*i), -1); + } + for (int i = 1; i <= dim; i+=2) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(copy_xform.output_var(i), -1); + h.update_const(lex[i-1]); + } + for (int i = dim+2; i <= copy_xform.n_out(); i+=2) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(copy_xform.output_var(i), 1); + } + } + + Statement copy_stmt_read; + copy_stmt_read.IS = ro_copy_is; + copy_stmt_read.xform = copy_xform; + copy_stmt_read.code = copy_code_read; + //fprintf(stderr, "dp3: copy_stmt_read.code = \n"); + copy_stmt_read.loop_level = std::vector(ro_copy_is.n_set()); + copy_stmt_read.ir_stmt_node = NULL; + copy_stmt_read.has_inspector = false; + for (int i = 0; i < level-1; i++) { + copy_stmt_read.loop_level[i].type = stmt[*(active.begin())].loop_level[i].type; + if (stmt[*(active.begin())].loop_level[i].type == LoopLevelTile && + stmt[*(active.begin())].loop_level[i].payload >= level) { + int j; + for (j = 0; j < privatized_levels.size(); j++) + if (privatized_levels[j] == stmt[*(active.begin())].loop_level[i].payload) + break; + if (j == privatized_levels.size()) + copy_stmt_read.loop_level[i].payload = -1; + else + copy_stmt_read.loop_level[i].payload = level + j; + } + else + copy_stmt_read.loop_level[i].payload = stmt[*(active.begin())].loop_level[i].payload; + copy_stmt_read.loop_level[i].parallel_level = stmt[*(active.begin())].loop_level[i].parallel_level; + } + for (int i = 0; i < privatized_levels.size(); i++) { + copy_stmt_read.loop_level[level-1+i].type = stmt[*(active.begin())].loop_level[privatized_levels[i]].type; + copy_stmt_read.loop_level[level-1+i].payload = stmt[*(active.begin())].loop_level[privatized_levels[i]].payload; + copy_stmt_read.loop_level[level-1+i].parallel_level = stmt[*(active.begin())].loop_level[privatized_levels[i]].parallel_level; + } + int left_num_dim = num_dep_dim - (get_last_dep_dim_before(*(active.begin()), level) + 1); + for (int i = 0; i < std::min(left_num_dim, static_cast(index_sz.size())); i++) { + copy_stmt_read.loop_level[level-1+privatized_levels.size()+i].type = LoopLevelOriginal; + copy_stmt_read.loop_level[level-1+privatized_levels.size()+i].payload = num_dep_dim-left_num_dim+i; + copy_stmt_read.loop_level[level-1+privatized_levels.size()+i].parallel_level = 0; + } + for (int i = std::min(left_num_dim, static_cast(index_sz.size())); i < index_sz.size(); i++) { + copy_stmt_read.loop_level[level-1+privatized_levels.size()+i].type = LoopLevelUnknown; + copy_stmt_read.loop_level[level-1+privatized_levels.size()+i].payload = -1; + copy_stmt_read.loop_level[level-1+privatized_levels.size()+i].parallel_level = 0; + } + + + shiftLexicalOrder(lex, dim-1, 1); + + fprintf(stderr, "loop_datacopy.cc L1071 adding stmt %d\n", stmt.size()); + stmt.push_back(copy_stmt_read); + + uninterpreted_symbols.push_back(uninterpreted_symbols[*(active.begin())]); + uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[*(active.begin())]); + ro_copy_stmt_num = stmt.size() - 1; + dep.insert(); + } + + //fprintf(stderr, "dp3: insert write copy statement\n"); + // insert write copy statement + int wo_copy_stmt_num = -1; + if (has_write_refs) { + Relation copy_xform(wo_copy_is.n_set(), 2*wo_copy_is.n_set()+1); + { + F_And *f_root = copy_xform.add_and(); + for (int i = 1; i <= wo_copy_is.n_set(); i++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(copy_xform.input_var(i), 1); + h.update_coef(copy_xform.output_var(2*i), -1); + } + for (int i = 1; i <= dim; i+=2) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(copy_xform.output_var(i), -1); + h.update_const(lex[i-1]); + } + for (int i = dim+2; i <= copy_xform.n_out(); i+=2) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(copy_xform.output_var(i), 1); + } + } + + Statement copy_stmt_write; + copy_stmt_write.IS = wo_copy_is; + copy_stmt_write.xform = copy_xform; + copy_stmt_write.code = copy_code_write; + copy_stmt_write.loop_level = std::vector(wo_copy_is.n_set()); + copy_stmt_write.ir_stmt_node = NULL; + copy_stmt_write.has_inspector = false; + + for (int i = 0; i < level-1; i++) { + copy_stmt_write.loop_level[i].type = stmt[*(active.begin())].loop_level[i].type; + if (stmt[*(active.begin())].loop_level[i].type == LoopLevelTile && + stmt[*(active.begin())].loop_level[i].payload >= level) { + int j; + for (j = 0; j < privatized_levels.size(); j++) + if (privatized_levels[j] == stmt[*(active.begin())].loop_level[i].payload) + break; + if (j == privatized_levels.size()) + copy_stmt_write.loop_level[i].payload = -1; + else + copy_stmt_write.loop_level[i].payload = level + j; + } + else + copy_stmt_write.loop_level[i].payload = stmt[*(active.begin())].loop_level[i].payload; + copy_stmt_write.loop_level[i].parallel_level = stmt[*(active.begin())].loop_level[i].parallel_level; + } + for (int i = 0; i < privatized_levels.size(); i++) { + copy_stmt_write.loop_level[level-1+i].type = stmt[*(active.begin())].loop_level[privatized_levels[i]].type; + copy_stmt_write.loop_level[level-1+i].payload = stmt[*(active.begin())].loop_level[privatized_levels[i]].payload; + copy_stmt_write.loop_level[level-1+i].parallel_level = stmt[*(active.begin())].loop_level[privatized_levels[i]].parallel_level; + } + int left_num_dim = num_dep_dim - (get_last_dep_dim_before(*(active.begin()), level) + 1); + for (int i = 0; i < std::min(left_num_dim, static_cast(index_sz.size())); i++) { + copy_stmt_write.loop_level[level-1+privatized_levels.size()+i].type = LoopLevelOriginal; + copy_stmt_write.loop_level[level-1+privatized_levels.size()+i].payload = num_dep_dim-left_num_dim+i; + copy_stmt_write.loop_level[level-1+privatized_levels.size()+i].parallel_level = 0; + } + for (int i = std::min(left_num_dim, static_cast(index_sz.size())); i < index_sz.size(); i++) { + copy_stmt_write.loop_level[level-1+privatized_levels.size()+i].type = LoopLevelUnknown; + copy_stmt_write.loop_level[level-1+privatized_levels.size()+i].payload = -1; + copy_stmt_write.loop_level[level-1+privatized_levels.size()+i].parallel_level = 0; + } + lex[dim-1]++; + shiftLexicalOrder(lex, dim-1, -2); + + fprintf(stderr, "loop_datacopy.cc L1147 adding stmt %d\n", stmt.size()); + stmt.push_back(copy_stmt_write); + + uninterpreted_symbols.push_back(uninterpreted_symbols[*(active.begin())]); + uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[*(active.begin())]); + wo_copy_stmt_num = stmt.size() - 1; + dep.insert(); + } + + //fprintf(stderr, "replace original array accesses with temporary array accesses\n"); + // replace original array accesses with temporary array accesses + for (int i =0; i < stmt_refs.size(); i++) + for (int j = 0; j < stmt_refs[i].second.size(); j++) { + if (index_sz.size() == 0) { + IR_ScalarRef *tmp_scalar_ref = ir->CreateScalarRef(static_cast(tmp_sym)); + //fprintf(stderr, "dp3: loop_datacopy.cc calling ReplaceExpression i%d j%d\n", i, j); + ir->ReplaceExpression(stmt_refs[i].second[j], tmp_scalar_ref->convert()); + } + else { + std::vector index_repr(index_sz.size()); + for (int k = 0; k < index_sz.size(); k++) { + int cur_index_num = index_sz[k].first; + + CG_outputRepr *cur_index_repr = ocg->CreateMinus(stmt_refs[i].second[j]->index(cur_index_num), index_lb[cur_index_num]->clone()); + if (padding_stride != 0) { + if (k == n_dim-1) { + coef_t g = gcd(index_stride[cur_index_num], static_cast(padding_stride)); + coef_t t1 = index_stride[cur_index_num] / g; + if (t1 != 1) + cur_index_repr = ocg->CreateIntegerFloor(cur_index_repr, ocg->CreateInt(t1)); + coef_t t2 = padding_stride / g; + if (t2 != 1) + cur_index_repr = ocg->CreateTimes(cur_index_repr, ocg->CreateInt(t2)); + } + else if (index_stride[cur_index_num] != 1) { + cur_index_repr = ocg->CreateIntegerFloor(cur_index_repr, ocg->CreateInt(index_stride[cur_index_num])); + } + } + + if (ir->ArrayIndexStartAt() != 0) + cur_index_repr = ocg->CreatePlus(cur_index_repr, ocg->CreateInt(ir->ArrayIndexStartAt())); + index_repr[k] = cur_index_repr; + } + + IR_ArrayRef *tmp_array_ref = ir->CreateArrayRef(static_cast(tmp_sym), index_repr); + //fprintf(stderr, "loop_datacopy.cc ir->ReplaceExpression( ... )\n"); + ir->ReplaceExpression(stmt_refs[i].second[j], tmp_array_ref->convert()); + } + } + + // update dependence graph + //fprintf(stderr, "update dependence graph\n"); + + int dep_dim = get_last_dep_dim_before(*(active.begin()), level) + 1; + if (ro_copy_stmt_num != -1) { + for (int i = 0; i < old_num_stmt; i++) { + std::vector > D; + + for (DependenceGraph::EdgeList::iterator j = dep.vertex[i].second.begin(); j != dep.vertex[i].second.end();) { + if (active.find(i) != active.end() && active.find(j->first) == active.end()) { + std::vector dvs1, dvs2; + for (int k = 0; k < j->second.size(); k++) { + DependenceVector dv = j->second[k]; + if (dv.sym != NULL && dv.sym->name() == sym->name() && (dv.type == DEP_R2R || dv.type == DEP_R2W)) + dvs1.push_back(dv); + else + dvs2.push_back(dv); + } + j->second = dvs2; + if (dvs1.size() > 0) + dep.connect(ro_copy_stmt_num, j->first, dvs1); + } + else if (active.find(i) == active.end() && active.find(j->first) != active.end()) { + std::vector dvs1, dvs2; + for (int k = 0; k < j->second.size(); k++) { + DependenceVector dv = j->second[k]; + if (dv.sym != NULL && dv.sym->name() == sym->name() && (dv.type == DEP_R2R || dv.type == DEP_W2R)) + dvs1.push_back(dv); + else + dvs2.push_back(dv); + } + j->second = dvs2; + if (dvs1.size() > 0) + D.push_back(dvs1); + } + + if (j->second.size() == 0) + dep.vertex[i].second.erase(j++); + else + j++; + } + + for (int j = 0; j < D.size(); j++) + dep.connect(i, ro_copy_stmt_num, D[j]); + } + + // insert dependences from copy statement loop to copied statements + //fprintf(stderr, "insert dependences from copy statement loop to copied statements\n"); + + DependenceVector dv; + dv.type = DEP_W2R; + dv.sym = tmp_sym->clone(); + dv.lbounds = std::vector(dep.num_dim(), 0); + dv.ubounds = std::vector(dep.num_dim(), 0); + for (int i = dep_dim; i < dep.num_dim(); i++) { + dv.lbounds[i] = -posInfinity; + dv.ubounds[i] = posInfinity; + } + for (std::set::iterator i = active.begin(); i != active.end(); i++) + dep.connect(ro_copy_stmt_num, *i, dv); + } + + if (wo_copy_stmt_num != -1) { + for (int i = 0; i < old_num_stmt; i++) { + std::vector > D; + + for (DependenceGraph::EdgeList::iterator j = dep.vertex[i].second.begin(); j != dep.vertex[i].second.end();) { + if (active.find(i) != active.end() && active.find(j->first) == active.end()) { + std::vector dvs1, dvs2; + for (int k = 0; k < j->second.size(); k++) { + DependenceVector dv = j->second[k]; + if (dv.sym != NULL && dv.sym->name() == sym->name() && (dv.type == DEP_W2R || dv.type == DEP_W2W)) + dvs1.push_back(dv); + else + dvs2.push_back(dv); + } + j->second = dvs2; + if (dvs1.size() > 0) + dep.connect(wo_copy_stmt_num, j->first, dvs1); + } + else if (active.find(i) == active.end() && active.find(j->first) != active.end()) { + std::vector dvs1, dvs2; + for (int k = 0; k < j->second.size(); k++) { + DependenceVector dv = j->second[k]; + if (dv.sym != NULL && dv.sym->name() == sym->name() && (dv.type == DEP_R2W || dv.type == DEP_W2W)) + dvs1.push_back(dv); + else + dvs2.push_back(dv); + } + j->second = dvs2; + if (dvs1.size() > 0) + D.push_back(dvs1); + } + + if (j->second.size() == 0) + dep.vertex[i].second.erase(j++); + else + j++; + } + + for (int j = 0; j < D.size(); j++) + dep.connect(i, wo_copy_stmt_num, D[j]); + } + + // insert dependences from copied statements to write statements + //fprintf(stderr, "dp3: insert dependences from copied statements to write statements\n"); + + DependenceVector dv; + dv.type = DEP_W2R; + dv.sym = tmp_sym->clone(); + dv.lbounds = std::vector(dep.num_dim(), 0); + dv.ubounds = std::vector(dep.num_dim(), 0); + for (int i = dep_dim; i < dep.num_dim(); i++) { + dv.lbounds[i] = -posInfinity; + dv.ubounds[i] = posInfinity; + } + for (std::set::iterator i = active.begin(); i != active.end(); i++) + dep.connect(*i, wo_copy_stmt_num, dv); + + } + + // update variable name for dependences among copied statements + for (int i = 0; i < old_num_stmt; i++) { + if (active.find(i) != active.end()) + for (DependenceGraph::EdgeList::iterator j = dep.vertex[i].second.begin(); j != dep.vertex[i].second.end(); j++) + if (active.find(j->first) != active.end()) + for (int k = 0; k < j->second.size(); k++) { + IR_Symbol *s = tmp_sym->clone(); + j->second[k].sym = s; + } + } + + // insert anti-dependence from write statement to read statement + if (ro_copy_stmt_num != -1 && wo_copy_stmt_num != -1) + if (dep_dim >= 0) { + DependenceVector dv; + dv.type = DEP_R2W; + dv.sym = tmp_sym->clone(); + dv.lbounds = std::vector(dep.num_dim(), 0); + dv.ubounds = std::vector(dep.num_dim(), 0); + for (int k = dep_dim; k < dep.num_dim(); k++) { + dv.lbounds[k] = -posInfinity; + dv.ubounds[k] = posInfinity; + } + for (int k = 0; k < dep_dim; k++) { + if (k != 0) { + dv.lbounds[k-1] = 0; + dv.ubounds[k-1] = 0; + } + dv.lbounds[k] = 1; + dv.ubounds[k] = posInfinity; + dep.connect(wo_copy_stmt_num, ro_copy_stmt_num, dv); + } + } + + //fprintf(stderr, "Loop::datacopy_privatized3() cleanup\n"); + // cleanup + delete sym; + delete tmp_sym; + for (int i = 0; i < index_lb.size(); i++) { + index_lb[i]->clear(); + delete index_lb[i]; + } + for (int i = 0; i < index_sz.size(); i++) { + index_sz[i].second->clear(); + delete index_sz[i].second; + } + + return true; +} + + + diff --git a/src/transformations/loop_extra.cc b/src/transformations/loop_extra.cc new file mode 100644 index 0000000..dac05bf --- /dev/null +++ b/src/transformations/loop_extra.cc @@ -0,0 +1,224 @@ +/***************************************************************************** + Copyright (C) 2010 University of Utah + All Rights Reserved. + + Purpose: + Additional loop transformations. + + Notes: + + History: + 07/31/10 Created by Chun Chen +*****************************************************************************/ + +#include +#include +#include "loop.hh" +#include "omegatools.hh" +#include "ir_code.hh" +#include "chill_error.hh" + +using namespace omega; + + +void Loop::shift_to(int stmt_num, int level, int absolute_position) { + // combo + tile(stmt_num, level, 1, level, CountedTile); + std::vector lex = getLexicalOrder(stmt_num); + std::set active = getStatements(lex, 2*level-2); + shift(active, level, absolute_position); + + // remove unnecessary tiled loop since tile size is one + for (std::set::iterator i = active.begin(); i != active.end(); i++) { + int n = stmt[*i].xform.n_out(); + Relation mapping(n, n-2); + F_And *f_root = mapping.add_and(); + for (int j = 1; j <= 2*level; j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.output_var(j), 1); + h.update_coef(mapping.input_var(j), -1); + } + for (int j = 2*level+3; j <= n; j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.output_var(j-2), 1); + h.update_coef(mapping.input_var(j), -1); + } + stmt[*i].xform = Composition(mapping, stmt[*i].xform); + stmt[*i].xform.simplify(); + + for (int j = 0; j < stmt[*i].loop_level.size(); j++) + if (j != level-1 && + stmt[*i].loop_level[j].type == LoopLevelTile && + stmt[*i].loop_level[j].payload >= level) + stmt[*i].loop_level[j].payload--; + + stmt[*i].loop_level.erase(stmt[*i].loop_level.begin()+level-1); + } +} + + +std::set Loop::unroll_extra(int stmt_num, int level, int unroll_amount, int cleanup_split_level) { + std::set cleanup_stmts = unroll(stmt_num, level, unroll_amount,std::vector< std::vector >(), cleanup_split_level); + for (std::set::iterator i = cleanup_stmts.begin(); i != cleanup_stmts.end(); i++) + unroll(*i, level, 0); + + return cleanup_stmts; +} + +void Loop::peel(int stmt_num, int level, int peel_amount) { + // check for sanity of parameters + if (stmt_num < 0 || stmt_num >= stmt.size()) + throw std::invalid_argument("invalid statement number " + to_string(stmt_num)); + if (level <= 0 || level > stmt[stmt_num].loop_level.size()) + throw std::invalid_argument("invalid loop level " + to_string(level)); + + if (peel_amount == 0) + return; + + std::set subloop = getSubLoopNest(stmt_num, level); + std::vector Rs; + for (std::set::iterator i = subloop.begin(); i != subloop.end(); i++) { + Relation r = getNewIS(*i); + Relation f(r.n_set(), level); + F_And *f_root = f.add_and(); + for (int j = 1; j <= level; j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(f.input_var(2*j), 1); + h.update_coef(f.output_var(j), -1); + } + r = Composition(f, r); + r.simplify(); + Rs.push_back(r); + } + Relation hull = SimpleHull(Rs); + + if (peel_amount > 0) { + GEQ_Handle bound_eq; + bool found_bound = false; + for (GEQ_Iterator e(hull.single_conjunct()->GEQs()); e; e++) + if (!(*e).has_wildcards() && (*e).get_coef(hull.set_var(level)) > 0) { + bound_eq = *e; + found_bound = true; + break; + } + if (!found_bound) + for (GEQ_Iterator e(hull.single_conjunct()->GEQs()); e; e++) + if ((*e).has_wildcards() && (*e).get_coef(hull.set_var(level)) > 0) { + bool is_bound = true; + for (Constr_Vars_Iter cvi(*e, true); cvi; cvi++) { + std::pair result = find_floor_definition(hull, cvi.curr_var()); + if (!result.first) { + is_bound = false; + break; + } + } + if (is_bound) { + bound_eq = *e; + found_bound = true; + break; + } + } + if (!found_bound) + throw loop_error("can't find lower bound for peeling at loop level " + to_string(level)); + + for (int i = 1; i <= peel_amount; i++) { + Relation r(level); + F_Exists *f_exists = r.add_and()->add_exists(); + F_And *f_root = f_exists->add_and(); + GEQ_Handle h = f_root->add_GEQ(); + std::map exists_mapping; + for (Constr_Vars_Iter cvi(bound_eq); cvi; cvi++) + switch (cvi.curr_var()->kind()) { + case Input_Var: + h.update_coef(r.set_var(cvi.curr_var()->get_position()), cvi.curr_coef()); + break; + case Wildcard_Var: { + Variable_ID v = replicate_floor_definition(hull, cvi.curr_var(), r, f_exists, f_root, exists_mapping); + h.update_coef(v, cvi.curr_coef()); + break; + } + case Global_Var: { + Global_Var_ID g = cvi.curr_var()->get_global_var(); + Variable_ID v; + if (g->arity() == 0) + v = r.get_local(g); + else + v = r.get_local(g, cvi.curr_var()->function_of()); + h.update_coef(v, cvi.curr_coef()); + break; + } + default: + assert(false); + } + h.update_const(bound_eq.get_const() - i); + r.simplify(); + + split(stmt_num, level, r); + } + } + else { // peel_amount < 0 + GEQ_Handle bound_eq; + bool found_bound = false; + for (GEQ_Iterator e(hull.single_conjunct()->GEQs()); e; e++) + if (!(*e).has_wildcards() && (*e).get_coef(hull.set_var(level)) < 0) { + bound_eq = *e; + found_bound = true; + break; + } + if (!found_bound) + for (GEQ_Iterator e(hull.single_conjunct()->GEQs()); e; e++) + if ((*e).has_wildcards() && (*e).get_coef(hull.set_var(level)) < 0) { + bool is_bound = true; + for (Constr_Vars_Iter cvi(*e, true); cvi; cvi++) { + std::pair result = find_floor_definition(hull, cvi.curr_var()); + if (!result.first) { + is_bound = false; + break; + } + } + if (is_bound) { + bound_eq = *e; + found_bound = true; + break; + } + } + if (!found_bound) + throw loop_error("can't find upper bound for peeling at loop level " + to_string(level)); + + for (int i = 1; i <= -peel_amount; i++) { + Relation r(level); + F_Exists *f_exists = r.add_and()->add_exists(); + F_And *f_root = f_exists->add_and(); + GEQ_Handle h = f_root->add_GEQ(); + std::map exists_mapping; + for (Constr_Vars_Iter cvi(bound_eq); cvi; cvi++) + switch (cvi.curr_var()->kind()) { + case Input_Var: + h.update_coef(r.set_var(cvi.curr_var()->get_position()), cvi.curr_coef()); + break; + case Wildcard_Var: { + Variable_ID v = replicate_floor_definition(hull, cvi.curr_var(), r, f_exists, f_root, exists_mapping); + h.update_coef(v, cvi.curr_coef()); + break; + } + case Global_Var: { + Global_Var_ID g = cvi.curr_var()->get_global_var(); + Variable_ID v; + if (g->arity() == 0) + v = r.get_local(g); + else + v = r.get_local(g, cvi.curr_var()->function_of()); + h.update_coef(v, cvi.curr_coef()); + break; + } + default: + assert(false); + } + h.update_const(bound_eq.get_const() - i); + r.simplify(); + + split(stmt_num, level, r); + } + } +} + diff --git a/src/transformations/loop_tile.cc b/src/transformations/loop_tile.cc new file mode 100644 index 0000000..41c3e7f --- /dev/null +++ b/src/transformations/loop_tile.cc @@ -0,0 +1,587 @@ +/* + * loop_tile.cc + * + * Created on: Nov 12, 2012 + * Author: anand + */ + +#include +#include "loop.hh" +#include "omegatools.hh" +#include "ir_code.hh" +#include "chill_error.hh" + +using namespace omega; + + + + +void Loop::tile(int stmt_num, int level, int tile_size, int outer_level, + TilingMethodType method, int alignment_offset, int alignment_multiple) { + // check for sanity of parameters + if (tile_size < 0) + throw std::invalid_argument("invalid tile size"); + if (alignment_multiple < 1 || alignment_offset < 0) + throw std::invalid_argument("invalid alignment for tile"); + if (stmt_num < 0 || stmt_num >= stmt.size()) + throw std::invalid_argument("invalid statement " + to_string(stmt_num)); + if (level <= 0) + throw std::invalid_argument("invalid loop level " + to_string(level)); + if (level > stmt[stmt_num].loop_level.size()) + throw std::invalid_argument( + "there is no loop level " + to_string(level) + " for statement " + + to_string(stmt_num)); + if (outer_level <= 0 || outer_level > level) + throw std::invalid_argument( + "invalid tile controlling loop level " + + to_string(outer_level)); + + // invalidate saved codegen computation + delete last_compute_cgr_; + last_compute_cgr_ = NULL; + delete last_compute_cg_; + last_compute_cg_ = NULL; + + int dim = 2 * level - 1; + int outer_dim = 2 * outer_level - 1; + std::vector lex = getLexicalOrder(stmt_num); + std::set same_tiled_loop = getStatements(lex, dim - 1); + std::set same_tile_controlling_loop = getStatements(lex, + outer_dim - 1); + + for (std::set::iterator i = same_tiled_loop.begin(); + i != same_tiled_loop.end(); i++) { + for (DependenceGraph::EdgeList::iterator j = + dep.vertex[*i].second.begin(); j != dep.vertex[*i].second.end(); + j++) { + if (same_tiled_loop.find(j->first) != same_tiled_loop.end()) + for (int k = 0; k < j->second.size(); k++) { + DependenceVector dv = j->second[k]; + int dim2 = level - 1; + if ((dv.type != DEP_CONTROL) && (dv.type != DEP_UNKNOWN)) { + while (stmt[*i].loop_level[dim2].type == LoopLevelTile) { + dim2 = stmt[*i].loop_level[dim2].payload - 1; + } + dim2 = stmt[*i].loop_level[dim2].payload; + + if (dv.hasNegative(dim2) && (!dv.quasi)) { + for (int l = outer_level; l < level; l++) + if (stmt[*i].loop_level[l - 1].type + != LoopLevelTile) { + if (dv.isCarried( + stmt[*i].loop_level[l - 1].payload) + && dv.hasPositive( + stmt[*i].loop_level[l - 1].payload)) + throw loop_error( + "loop error: Tiling is illegal, dependence violation!"); + } else { + + int dim3 = l - 1; + while (stmt[*i].loop_level[l - 1].type + != LoopLevelTile) { + dim3 = + stmt[*i].loop_level[l - 1].payload + - 1; + + } + + dim3 = stmt[*i].loop_level[l - 1].payload; + if (dim3 < level - 1) + if (dv.isCarried(dim3) + && dv.hasPositive(dim3)) + throw loop_error( + "loop error: Tiling is illegal, dependence violation!"); + } + } + } + } + } + } + // special case for no tiling + if (tile_size == 0) { + for (std::set::iterator i = same_tile_controlling_loop.begin(); + i != same_tile_controlling_loop.end(); i++) { + Relation r(stmt[*i].xform.n_out(), stmt[*i].xform.n_out() + 2); + F_And *f_root = r.add_and(); + for (int j = 1; j <= 2 * outer_level - 1; j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(r.input_var(j), 1); + h.update_coef(r.output_var(j), -1); + } + EQ_Handle h1 = f_root->add_EQ(); + h1.update_coef(r.output_var(2 * outer_level), 1); + EQ_Handle h2 = f_root->add_EQ(); + h2.update_coef(r.output_var(2 * outer_level + 1), 1); + for (int j = 2 * outer_level; j <= stmt[*i].xform.n_out(); j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(r.input_var(j), 1); + h.update_coef(r.output_var(j + 2), -1); + } + + stmt[*i].xform = Composition(copy(r), stmt[*i].xform); + } + } + // normal tiling + else { + std::set private_stmt; + for (std::set::iterator i = same_tile_controlling_loop.begin(); + i != same_tile_controlling_loop.end(); i++) { + // should test dim's value directly but it is ok for now + if (same_tiled_loop.find(*i) == same_tiled_loop.end() + && overflow.find(*i) != overflow.end()) + private_stmt.insert(*i); + } + + // extract the union of the iteration space to be considered + Relation hull; + { + std::vector r_list; + + for (std::set::iterator i = same_tile_controlling_loop.begin(); + i != same_tile_controlling_loop.end(); i++) + if (private_stmt.find(*i) == private_stmt.end()) { + Relation r = getNewIS(*i); + for (int j = dim + 2; j <= r.n_set(); j++) + r = Project(r, r.set_var(j)); + for (int j = outer_dim; j < dim; j++) + r = Project(r, j + 1, Set_Var); + for (int j = 0; j < outer_dim; j += 2) + r = Project(r, j + 1, Set_Var); + r.simplify(2, 4); + r_list.push_back(r); + } + + hull = SimpleHull(r_list); + } + + // extract the bound of the dimension to be tiled + Relation bound = get_loop_bound(hull, dim); + if (!bound.has_single_conjunct()) { + // further simplify the bound + hull = Approximate(hull); + bound = get_loop_bound(hull, dim); + + int i = outer_dim - 2; + while (!bound.has_single_conjunct() && i >= 0) { + hull = Project(hull, i + 1, Set_Var); + bound = get_loop_bound(hull, dim); + i -= 2; + } + + if (!bound.has_single_conjunct()) + throw loop_error("cannot handle tile bounds"); + } + + // separate lower and upper bounds + std::vector lb_list, ub_list; + { + Conjunct *c = bound.query_DNF()->single_conjunct(); + for (GEQ_Iterator gi(c->GEQs()); gi; gi++) { + int coef = (*gi).get_coef(bound.set_var(dim + 1)); + if (coef < 0) + ub_list.push_back(*gi); + else if (coef > 0) + lb_list.push_back(*gi); + } + } + if (lb_list.size() == 0) + throw loop_error( + "unable to calculate tile controlling loop lower bound"); + if (ub_list.size() == 0) + throw loop_error( + "unable to calculate tile controlling loop upper bound"); + + // find the simplest lower bound for StridedTile or simplest iteration count for CountedTile + int simplest_lb = 0, simplest_ub = 0; + if (method == StridedTile) { + int best_cost = INT_MAX; + for (int i = 0; i < lb_list.size(); i++) { + int cost = 0; + for (Constr_Vars_Iter ci(lb_list[i]); ci; ci++) { + switch ((*ci).var->kind()) { + case Input_Var: { + cost += 5; + break; + } + case Global_Var: { + cost += 2; + break; + } + default: + cost += 15; + break; + } + } + + if (cost < best_cost) { + best_cost = cost; + simplest_lb = i; + } + } + } else if (method == CountedTile) { + std::map s1, s2, s3; + int best_cost = INT_MAX; + for (int i = 0; i < lb_list.size(); i++) + for (int j = 0; j < ub_list.size(); j++) { + int cost = 0; + + for (Constr_Vars_Iter ci(lb_list[i]); ci; ci++) { + switch ((*ci).var->kind()) { + case Input_Var: { + s1[(*ci).var] += (*ci).coef; + break; + } + case Global_Var: { + s2[(*ci).var] += (*ci).coef; + break; + } + case Exists_Var: + case Wildcard_Var: { + s3[(*ci).var] += (*ci).coef; + break; + } + default: + cost = INT_MAX - 2; + break; + } + } + + for (Constr_Vars_Iter ci(ub_list[j]); ci; ci++) { + switch ((*ci).var->kind()) { + case Input_Var: { + s1[(*ci).var] += (*ci).coef; + break; + } + case Global_Var: { + s2[(*ci).var] += (*ci).coef; + break; + } + case Exists_Var: + case Wildcard_Var: { + s3[(*ci).var] += (*ci).coef; + break; + } + default: + if (cost == INT_MAX - 2) + cost = INT_MAX - 1; + else + cost = INT_MAX - 3; + break; + } + } + + if (cost == 0) { + for (std::map::iterator k = + s1.begin(); k != s1.end(); k++) + if ((*k).second != 0) + cost += 5; + for (std::map::iterator k = + s2.begin(); k != s2.end(); k++) + if ((*k).second != 0) + cost += 2; + for (std::map::iterator k = + s3.begin(); k != s3.end(); k++) + if ((*k).second != 0) + cost += 15; + } + + if (cost < best_cost) { + best_cost = cost; + simplest_lb = i; + simplest_ub = j; + } + } + } + + // prepare the new transformation relations + for (std::set::iterator i = same_tile_controlling_loop.begin(); + i != same_tile_controlling_loop.end(); i++) { + Relation r(stmt[*i].xform.n_out(), stmt[*i].xform.n_out() + 2); + F_And *f_root = r.add_and(); + for (int j = 0; j < outer_dim - 1; j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(r.output_var(j + 1), 1); + h.update_coef(r.input_var(j + 1), -1); + } + + for (int j = outer_dim - 1; j < stmt[*i].xform.n_out(); j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(r.output_var(j + 3), 1); + h.update_coef(r.input_var(j + 1), -1); + } + + EQ_Handle h = f_root->add_EQ(); + h.update_coef(r.output_var(outer_dim), 1); + h.update_const(-lex[outer_dim - 1]); + + stmt[*i].xform = Composition(r, stmt[*i].xform); + } + + // add tiling constraints. + for (std::set::iterator i = same_tile_controlling_loop.begin(); + i != same_tile_controlling_loop.end(); i++) { + F_And *f_super_root = stmt[*i].xform.and_with_and(); + F_Exists *f_exists = f_super_root->add_exists(); + F_And *f_root = f_exists->add_and(); + + // create a lower bound variable for easy formula creation later + Variable_ID aligned_lb; + { + Variable_ID lb = f_exists->declare(); + coef_t coef = lb_list[simplest_lb].get_coef( + bound.set_var(dim + 1)); + if (coef == 1) { // e.g. if i >= m+5, then LB = m+5 + EQ_Handle h = f_root->add_EQ(); + h.update_coef(lb, 1); + for (Constr_Vars_Iter ci(lb_list[simplest_lb]); ci; ci++) { + switch ((*ci).var->kind()) { + case Input_Var: { + int pos = (*ci).var->get_position(); + if (pos != dim + 1) + h.update_coef(stmt[*i].xform.output_var(pos), + (*ci).coef); + break; + } + case Global_Var: { + Global_Var_ID g = (*ci).var->get_global_var(); + Variable_ID v; + if (g->arity() == 0) + v = stmt[*i].xform.get_local(g); + else + v = stmt[*i].xform.get_local(g, + (*ci).var->function_of()); + h.update_coef(v, (*ci).coef); + break; + } + default: + throw loop_error("cannot handle tile bounds"); + } + } + h.update_const(lb_list[simplest_lb].get_const()); + } else { // e.g. if 2i >= m+5, then m+5 <= 2*LB < m+5+2 + GEQ_Handle h1 = f_root->add_GEQ(); + GEQ_Handle h2 = f_root->add_GEQ(); + for (Constr_Vars_Iter ci(lb_list[simplest_lb]); ci; ci++) { + switch ((*ci).var->kind()) { + case Input_Var: { + int pos = (*ci).var->get_position(); + if (pos == dim + 1) { + h1.update_coef(lb, (*ci).coef); + h2.update_coef(lb, -(*ci).coef); + } else { + h1.update_coef(stmt[*i].xform.output_var(pos), + (*ci).coef); + h2.update_coef(stmt[*i].xform.output_var(pos), + -(*ci).coef); + } + break; + } + case Global_Var: { + Global_Var_ID g = (*ci).var->get_global_var(); + Variable_ID v; + if (g->arity() == 0) + v = stmt[*i].xform.get_local(g); + else + v = stmt[*i].xform.get_local(g, + (*ci).var->function_of()); + h1.update_coef(v, (*ci).coef); + h2.update_coef(v, -(*ci).coef); + break; + } + default: + throw loop_error("cannot handle tile bounds"); + } + } + h1.update_const(lb_list[simplest_lb].get_const()); + h2.update_const(-lb_list[simplest_lb].get_const()); + h2.update_const(coef - 1); + } + + Variable_ID offset_lb; + if (alignment_offset == 0) + offset_lb = lb; + else { + EQ_Handle h = f_root->add_EQ(); + offset_lb = f_exists->declare(); + h.update_coef(offset_lb, 1); + h.update_coef(lb, -1); + h.update_const(alignment_offset); + } + + if (alignment_multiple == 1) { // trivial + aligned_lb = offset_lb; + } else { // e.g. to align at 4, aligned_lb = 4*alpha && LB-4 < 4*alpha <= LB + aligned_lb = f_exists->declare(); + Variable_ID e = f_exists->declare(); + + EQ_Handle h = f_root->add_EQ(); + h.update_coef(aligned_lb, 1); + h.update_coef(e, -alignment_multiple); + + GEQ_Handle h1 = f_root->add_GEQ(); + GEQ_Handle h2 = f_root->add_GEQ(); + h1.update_coef(e, alignment_multiple); + h2.update_coef(e, -alignment_multiple); + h1.update_coef(offset_lb, -1); + h2.update_coef(offset_lb, 1); + h1.update_const(alignment_multiple - 1); + } + } + + // create an upper bound variable for easy formula creation later + Variable_ID ub = f_exists->declare(); + { + coef_t coef = -ub_list[simplest_ub].get_coef( + bound.set_var(dim + 1)); + if (coef == 1) { // e.g. if i <= m+5, then UB = m+5 + EQ_Handle h = f_root->add_EQ(); + h.update_coef(ub, -1); + for (Constr_Vars_Iter ci(ub_list[simplest_ub]); ci; ci++) { + switch ((*ci).var->kind()) { + case Input_Var: { + int pos = (*ci).var->get_position(); + if (pos != dim + 1) + h.update_coef(stmt[*i].xform.output_var(pos), + (*ci).coef); + break; + } + case Global_Var: { + Global_Var_ID g = (*ci).var->get_global_var(); + Variable_ID v; + if (g->arity() == 0) + v = stmt[*i].xform.get_local(g); + else + v = stmt[*i].xform.get_local(g, + (*ci).var->function_of()); + h.update_coef(v, (*ci).coef); + break; + } + default: + throw loop_error("cannot handle tile bounds"); + } + } + h.update_const(ub_list[simplest_ub].get_const()); + } else { // e.g. if 2i <= m+5, then m+5-2 < 2*UB <= m+5 + GEQ_Handle h1 = f_root->add_GEQ(); + GEQ_Handle h2 = f_root->add_GEQ(); + for (Constr_Vars_Iter ci(ub_list[simplest_ub]); ci; ci++) { + switch ((*ci).var->kind()) { + case Input_Var: { + int pos = (*ci).var->get_position(); + if (pos == dim + 1) { + h1.update_coef(ub, -(*ci).coef); + h2.update_coef(ub, (*ci).coef); + } else { + h1.update_coef(stmt[*i].xform.output_var(pos), + -(*ci).coef); + h2.update_coef(stmt[*i].xform.output_var(pos), + (*ci).coef); + } + break; + } + case Global_Var: { + Global_Var_ID g = (*ci).var->get_global_var(); + Variable_ID v; + if (g->arity() == 0) + v = stmt[*i].xform.get_local(g); + else + v = stmt[*i].xform.get_local(g, + (*ci).var->function_of()); + h1.update_coef(v, -(*ci).coef); + h2.update_coef(v, (*ci).coef); + break; + } + default: + throw loop_error("cannot handle tile bounds"); + } + } + h1.update_const(-ub_list[simplest_ub].get_const()); + h2.update_const(ub_list[simplest_ub].get_const()); + h1.update_const(coef - 1); + } + } + + // insert tile controlling loop constraints + if (method == StridedTile) { // e.g. ii = LB + 32 * alpha && alpha >= 0 + Variable_ID e = f_exists->declare(); + GEQ_Handle h1 = f_root->add_GEQ(); + h1.update_coef(e, 1); + + EQ_Handle h2 = f_root->add_EQ(); + h2.update_coef(stmt[*i].xform.output_var(outer_dim + 1), 1); + h2.update_coef(e, -tile_size); + h2.update_coef(aligned_lb, -1); + } else if (method == CountedTile) { // e.g. 0 <= ii < ceiling((UB-LB+1)/32) + GEQ_Handle h1 = f_root->add_GEQ(); + h1.update_coef(stmt[*i].xform.output_var(outer_dim + 1), 1); + + GEQ_Handle h2 = f_root->add_GEQ(); + h2.update_coef(stmt[*i].xform.output_var(outer_dim + 1), + -tile_size); + h2.update_coef(aligned_lb, -1); + h2.update_coef(ub, 1); + } + + // special care for private statements like overflow assignment + if (private_stmt.find(*i) != private_stmt.end()) { // e.g. ii <= UB + GEQ_Handle h = f_root->add_GEQ(); + h.update_coef(stmt[*i].xform.output_var(outer_dim + 1), -1); + h.update_coef(ub, 1); + } + + // restrict original loop index inside the tile + else { + if (method == StridedTile) { // e.g. ii <= i < ii + tile_size + GEQ_Handle h1 = f_root->add_GEQ(); + h1.update_coef(stmt[*i].xform.output_var(dim + 3), 1); + h1.update_coef(stmt[*i].xform.output_var(outer_dim + 1), + -1); + + GEQ_Handle h2 = f_root->add_GEQ(); + h2.update_coef(stmt[*i].xform.output_var(dim + 3), -1); + h2.update_coef(stmt[*i].xform.output_var(outer_dim + 1), 1); + h2.update_const(tile_size - 1); + } else if (method == CountedTile) { // e.g. LB+32*ii <= i < LB+32*ii+tile_size + GEQ_Handle h1 = f_root->add_GEQ(); + h1.update_coef(stmt[*i].xform.output_var(outer_dim + 1), + -tile_size); + h1.update_coef(stmt[*i].xform.output_var(dim + 3), 1); + h1.update_coef(aligned_lb, -1); + + GEQ_Handle h2 = f_root->add_GEQ(); + h2.update_coef(stmt[*i].xform.output_var(outer_dim + 1), + tile_size); + h2.update_coef(stmt[*i].xform.output_var(dim + 3), -1); + h2.update_const(tile_size - 1); + h2.update_coef(aligned_lb, 1); + } + } + } + } + + // update loop level information + for (std::set::iterator i = same_tile_controlling_loop.begin(); + i != same_tile_controlling_loop.end(); i++) { + for (int j = 1; j <= stmt[*i].loop_level.size(); j++) + switch (stmt[*i].loop_level[j - 1].type) { + case LoopLevelOriginal: + break; + case LoopLevelTile: + if (stmt[*i].loop_level[j - 1].payload >= outer_level) + stmt[*i].loop_level[j - 1].payload++; + break; + default: + throw loop_error( + "unknown loop level type for statement " + + to_string(*i)); + } + + LoopLevel ll; + ll.type = LoopLevelTile; + ll.payload = level + 1; + ll.parallel_level = 0; + stmt[*i].loop_level.insert( + stmt[*i].loop_level.begin() + (outer_level - 1), ll); + } +} + diff --git a/src/transformations/loop_unroll.cc b/src/transformations/loop_unroll.cc new file mode 100644 index 0000000..86ffd84 --- /dev/null +++ b/src/transformations/loop_unroll.cc @@ -0,0 +1,1222 @@ +/* + * loop_unroll.cc + * + * Created on: Nov 12, 2012 + * Author: anand + */ + +#include +#include +#include "loop.hh" +#include "omegatools.hh" +#include "ir_code.hh" +#include "chill_error.hh" +#include + +using namespace omega; + + +std::set Loop::unroll(int stmt_num, int level, int unroll_amount, + std::vector > idxNames, + int cleanup_split_level) { + // check for sanity of parameters + // check for sanity of parameters + if (unroll_amount < 0) + throw std::invalid_argument( + "invalid unroll amount " + to_string(unroll_amount)); + if (stmt_num < 0 || stmt_num >= stmt.size()) + throw std::invalid_argument("invalid statement " + to_string(stmt_num)); + if (level <= 0 || level > stmt[stmt_num].loop_level.size()) + throw std::invalid_argument("invalid loop level " + to_string(level)); + + if (cleanup_split_level == 0) + cleanup_split_level = level; + if (cleanup_split_level > level) + throw std::invalid_argument( + "cleanup code must be split at or outside the unrolled loop level " + + to_string(level)); + if (cleanup_split_level <= 0) + throw std::invalid_argument( + "invalid split loop level " + to_string(cleanup_split_level)); + + // invalidate saved codegen computation + delete last_compute_cgr_; + last_compute_cgr_ = NULL; + delete last_compute_cg_; + last_compute_cg_ = NULL; + + int dim = 2 * level - 1; + std::vector lex = getLexicalOrder(stmt_num); + std::set same_loop = getStatements(lex, dim - 1); + + // nothing to do + if (unroll_amount == 1) + return std::set(); + + for (std::set::iterator i = same_loop.begin(); i != same_loop.end(); + i++) { + std::vector > D; + int n = stmt[*i].xform.n_out(); + for (DependenceGraph::EdgeList::iterator j = + dep.vertex[*i].second.begin(); j != dep.vertex[*i].second.end(); + j++) { + if (same_loop.find(j->first) != same_loop.end()) + for (int k = 0; k < j->second.size(); k++) { + DependenceVector dv = j->second[k]; + int dim2 = level - 1; + if (dv.type != DEP_CONTROL) { + + while (stmt[*i].loop_level[dim2].type == LoopLevelTile) { + dim2 = stmt[*i].loop_level[dim2].payload - 1; + } + dim2 = stmt[*i].loop_level[dim2].payload; + + /*if (dv.isCarried(dim2) + && (dv.hasNegative(dim2) && !dv.quasi)) + throw loop_error( + "loop error: Unrolling is illegal, dependence violation!"); + + if (dv.isCarried(dim2) + && (dv.hasPositive(dim2) && dv.quasi)) + throw loop_error( + "loop error: Unrolling is illegal, dependence violation!"); + */ + bool safe = false; + + if (dv.isCarried(dim2) && dv.hasPositive(dim2)) { + if (dv.quasi) + throw loop_error( + "loop error: a quasi dependence with a positive carried distance"); + if (!dv.quasi) { + if (dv.lbounds[dim2] != posInfinity) { + //if (dv.lbounds[dim2] != negInfinity) + if (dv.lbounds[dim2] > unroll_amount) + safe = true; + } else + safe = true; + }/* else { + if (dv.ubounds[dim2] != negInfinity) { + if (dv.ubounds[dim2] != posInfinity) + if ((-(dv.ubounds[dim2])) > unroll_amount) + safe = true; + } else + safe = true; + }*/ + + if (!safe) { + for (int l = level + 1; l <= (n - 1) / 2; l++) { + int dim3 = l - 1; + + if (stmt[*i].loop_level[dim3].type + != LoopLevelTile) + dim3 = + stmt[*i].loop_level[dim3].payload; + else { + while (stmt[*i].loop_level[dim3].type + == LoopLevelTile) { + dim3 = + stmt[*i].loop_level[dim3].payload + - 1; + } + dim3 = + stmt[*i].loop_level[dim3].payload; + } + + if (dim3 > dim2) { + + if (dv.hasPositive(dim3)) + break; + else if (dv.hasNegative(dim3)) + throw loop_error( + "loop error: Unrolling is illegal, dependence violation!"); + } + } + } + } + } + } + } + } + // extract the intersection of the iteration space to be considered + Relation hull = Relation::True(level); + apply_xform(same_loop); + for (std::set::iterator i = same_loop.begin(); i != same_loop.end(); + i++) { + if (stmt[*i].IS.is_upper_bound_satisfiable()) { + Relation mapping(stmt[*i].IS.n_set(), level); + F_And *f_root = mapping.add_and(); + for (int j = 1; j <= level; j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.input_var(j), 1); + h.update_coef(mapping.output_var(j), -1); + } + hull = Intersection(hull, + omega::Range(Restrict_Domain(mapping, copy(stmt[*i].IS)))); + hull.simplify(2, 4); + + } + } + for (int i = 1; i <= level; i++) { + std::string name = tmp_loop_var_name_prefix + to_string(i); + hull.name_set_var(i, name); + } + hull.setup_names(); + + // extract the exact loop bound of the dimension to be unrolled + if (is_single_loop_iteration(hull, level, this->known)) + return std::set(); + Relation bound = get_loop_bound(hull, level, this->known); + if (!bound.has_single_conjunct() || !bound.is_satisfiable() + || bound.is_tautology()) + throw loop_error("unable to extract loop bound for unrolling"); + + // extract the loop stride + coef_t stride; + std::pair result = find_simplest_stride(bound, + bound.set_var(level)); + if (result.second == NULL) + stride = 1; + else + stride = abs(result.first.get_coef(result.second)) + / gcd(abs(result.first.get_coef(result.second)), + abs(result.first.get_coef(bound.set_var(level)))); + + // separate lower and upper bounds + std::vector lb_list, ub_list; + { + Conjunct *c = bound.query_DNF()->single_conjunct(); + for (GEQ_Iterator gi(c->GEQs()); gi; gi++) { + int coef = (*gi).get_coef(bound.set_var(level)); + if (coef < 0) + ub_list.push_back(*gi); + else if (coef > 0) + lb_list.push_back(*gi); + } + } + + // simplify overflow expression for each pair of upper and lower bounds + std::vector > > overflow_table( + lb_list.size(), + std::vector >(ub_list.size(), + std::map())); + bool is_overflow_simplifiable = true; + for (int i = 0; i < lb_list.size(); i++) { + if (!is_overflow_simplifiable) + break; + + for (int j = 0; j < ub_list.size(); j++) { + // lower bound or upper bound has non-unit coefficient, can't simplify + if (ub_list[j].get_coef(bound.set_var(level)) != -1 + || lb_list[i].get_coef(bound.set_var(level)) != 1) { + is_overflow_simplifiable = false; + break; + } + + for (Constr_Vars_Iter ci(ub_list[j]); ci; ci++) { + switch ((*ci).var->kind()) { + case Input_Var: { + if ((*ci).var != bound.set_var(level)) + overflow_table[i][j][(*ci).var] += (*ci).coef; + + break; + } + case Global_Var: { + Global_Var_ID g = (*ci).var->get_global_var(); + Variable_ID v; + if (g->arity() == 0) + v = bound.get_local(g); + else + v = bound.get_local(g, (*ci).var->function_of()); + overflow_table[i][j][(*ci).var] += (*ci).coef; + break; + } + default: + throw loop_error("failed to calculate overflow amount"); + } + } + overflow_table[i][j][NULL] += ub_list[j].get_const(); + + for (Constr_Vars_Iter ci(lb_list[i]); ci; ci++) { + switch ((*ci).var->kind()) { + case Input_Var: { + if ((*ci).var != bound.set_var(level)) { + overflow_table[i][j][(*ci).var] += (*ci).coef; + if (overflow_table[i][j][(*ci).var] == 0) + overflow_table[i][j].erase( + overflow_table[i][j].find((*ci).var)); + } + break; + } + case Global_Var: { + Global_Var_ID g = (*ci).var->get_global_var(); + Variable_ID v; + if (g->arity() == 0) + v = bound.get_local(g); + else + v = bound.get_local(g, (*ci).var->function_of()); + overflow_table[i][j][(*ci).var] += (*ci).coef; + if (overflow_table[i][j][(*ci).var] == 0) + overflow_table[i][j].erase( + overflow_table[i][j].find((*ci).var)); + break; + } + default: + throw loop_error("failed to calculate overflow amount"); + } + } + overflow_table[i][j][NULL] += lb_list[i].get_const(); + + overflow_table[i][j][NULL] += stride; + if (unroll_amount == 0 + || (overflow_table[i][j].size() == 1 + && overflow_table[i][j][NULL] / stride + < unroll_amount)) + unroll_amount = overflow_table[i][j][NULL] / stride; + } + } + + // loop iteration count can't be determined, bail out gracefully + if (unroll_amount == 0) + return std::set(); + + // further simply overflow calculation using coefficients' modular + if (is_overflow_simplifiable) { + for (int i = 0; i < lb_list.size(); i++) + for (int j = 0; j < ub_list.size(); j++) + if (stride == 1) { + for (std::map::iterator k = + overflow_table[i][j].begin(); + k != overflow_table[i][j].end();) + if ((*k).first != NULL) { + int t = int_mod_hat((*k).second, unroll_amount); + if (t == 0) { + overflow_table[i][j].erase(k++); + } else { + int t2 = hull.query_variable_mod((*k).first, + unroll_amount); + if (t2 != INT_MAX) { + overflow_table[i][j][NULL] += t * t2; + overflow_table[i][j].erase(k++); + } else { + (*k).second = t; + k++; + } + } + } else + k++; + + overflow_table[i][j][NULL] = int_mod_hat( + overflow_table[i][j][NULL], unroll_amount); + + // Since we don't have MODULO instruction in SUIF yet (only MOD), + // make all coef positive in the final formula + for (std::map::iterator k = + overflow_table[i][j].begin(); + k != overflow_table[i][j].end(); k++) + if ((*k).second < 0) + (*k).second += unroll_amount; + } + } + + // build overflow statement + CG_outputBuilder *ocg = ir->builder(); + CG_outputRepr *overflow_code = NULL; + Relation cond_upper(level), cond_lower(level); + Relation overflow_constraint(0); + F_And *overflow_constraint_root = overflow_constraint.add_and(); + std::vector over_var_list; + if (is_overflow_simplifiable && lb_list.size() == 1) { + for (int i = 0; i < ub_list.size(); i++) { + if (overflow_table[0][i].size() == 1) { + // upper splitting condition + GEQ_Handle h = cond_upper.and_with_GEQ(ub_list[i]); + h.update_const( + ((overflow_table[0][i][NULL] / stride) % unroll_amount) + * -stride); + } else { + // upper splitting condition + std::string over_name = overflow_var_name_prefix + + to_string(overflow_var_name_counter++); + Free_Var_Decl *over_free_var = new Free_Var_Decl(over_name); + over_var_list.push_back(over_free_var); + GEQ_Handle h = cond_upper.and_with_GEQ(ub_list[i]); + h.update_coef(cond_upper.get_local(over_free_var), -stride); + + // insert constraint 0 <= overflow < unroll_amount + Variable_ID v = overflow_constraint.get_local(over_free_var); + GEQ_Handle h1 = overflow_constraint_root->add_GEQ(); + h1.update_coef(v, 1); + GEQ_Handle h2 = overflow_constraint_root->add_GEQ(); + h2.update_coef(v, -1); + h2.update_const(unroll_amount - 1); + + // create overflow assignment + bound.setup_names(); // hack to fix omega relation variable names issue + CG_outputRepr *rhs = NULL; + bool is_split_illegal = false; + for (std::map::iterator j = + overflow_table[0][i].begin(); + j != overflow_table[0][i].end(); j++) + if ((*j).first != NULL) { + if ((*j).first->kind() == Input_Var + && (*j).first->get_position() + >= cleanup_split_level) + is_split_illegal = true; + + CG_outputRepr *t = ocg->CreateIdent((*j).first->name()); + if ((*j).second != 1) + t = ocg->CreateTimes(ocg->CreateInt((*j).second), + t); + rhs = ocg->CreatePlus(rhs, t); + } else if ((*j).second != 0) + rhs = ocg->CreatePlus(rhs, ocg->CreateInt((*j).second)); + + if (is_split_illegal) { + rhs->clear(); + delete rhs; + throw loop_error( + "cannot split cleanup code at loop level " + + to_string(cleanup_split_level) + + " due to overflow variable data dependence"); + } + + if (stride != 1) + rhs = ocg->CreateIntegerCeil(rhs, ocg->CreateInt(stride)); + rhs = ocg->CreateIntegerMod(rhs, ocg->CreateInt(unroll_amount)); + + CG_outputRepr *lhs = ocg->CreateIdent(over_name); + init_code = ocg->StmtListAppend(init_code, + ocg->CreateAssignment(0, lhs, ocg->CreateInt(0))); + lhs = ocg->CreateIdent(over_name); + overflow_code = ocg->StmtListAppend(overflow_code, + ocg->CreateAssignment(0, lhs, rhs)); + } + } + + // lower splitting condition + GEQ_Handle h = cond_lower.and_with_GEQ(lb_list[0]); + } else if (is_overflow_simplifiable && ub_list.size() == 1) { + for (int i = 0; i < lb_list.size(); i++) { + + if (overflow_table[i][0].size() == 1) { + // lower splitting condition + GEQ_Handle h = cond_lower.and_with_GEQ(lb_list[i]); + h.update_const(overflow_table[i][0][NULL] * -stride); + } else { + // lower splitting condition + std::string over_name = overflow_var_name_prefix + + to_string(overflow_var_name_counter++); + Free_Var_Decl *over_free_var = new Free_Var_Decl(over_name); + over_var_list.push_back(over_free_var); + GEQ_Handle h = cond_lower.and_with_GEQ(lb_list[i]); + h.update_coef(cond_lower.get_local(over_free_var), -stride); + + // insert constraint 0 <= overflow < unroll_amount + Variable_ID v = overflow_constraint.get_local(over_free_var); + GEQ_Handle h1 = overflow_constraint_root->add_GEQ(); + h1.update_coef(v, 1); + GEQ_Handle h2 = overflow_constraint_root->add_GEQ(); + h2.update_coef(v, -1); + h2.update_const(unroll_amount - 1); + + // create overflow assignment + bound.setup_names(); // hack to fix omega relation variable names issue + CG_outputRepr *rhs = NULL; + for (std::map::iterator j = + overflow_table[0][i].begin(); + j != overflow_table[0][i].end(); j++) + if ((*j).first != NULL) { + CG_outputRepr *t = ocg->CreateIdent((*j).first->name()); + if ((*j).second != 1) + t = ocg->CreateTimes(ocg->CreateInt((*j).second), + t); + rhs = ocg->CreatePlus(rhs, t); + } else if ((*j).second != 0) + rhs = ocg->CreatePlus(rhs, ocg->CreateInt((*j).second)); + + if (stride != 1) + rhs = ocg->CreateIntegerCeil(rhs, ocg->CreateInt(stride)); + rhs = ocg->CreateIntegerMod(rhs, ocg->CreateInt(unroll_amount)); + + CG_outputRepr *lhs = ocg->CreateIdent(over_name); + init_code = ocg->StmtListAppend(init_code, + ocg->CreateAssignment(0, lhs, ocg->CreateInt(0))); + lhs = ocg->CreateIdent(over_name); + overflow_code = ocg->StmtListAppend(overflow_code, + ocg->CreateAssignment(0, lhs, rhs)); + } + } + + // upper splitting condition + GEQ_Handle h = cond_upper.and_with_GEQ(ub_list[0]); + } else { + std::string over_name = overflow_var_name_prefix + + to_string(overflow_var_name_counter++); + Free_Var_Decl *over_free_var = new Free_Var_Decl(over_name); + over_var_list.push_back(over_free_var); + + std::vector lb_repr_list, ub_repr_list; + for (int i = 0; i < lb_list.size(); i++) { + lb_repr_list.push_back( + output_lower_bound_repr(ocg, + lb_list[i], + bound.set_var(dim + 1), result.first, result.second, + bound, Relation::True(bound.n_set()), + std::vector >( + bound.n_set(), + std::make_pair( + static_cast(NULL), + 0)), + uninterpreted_symbols[stmt_num])); + GEQ_Handle h = cond_lower.and_with_GEQ(lb_list[i]); + } + for (int i = 0; i < ub_list.size(); i++) { + ub_repr_list.push_back( + output_upper_bound_repr(ocg, ub_list[i], + bound.set_var(dim + 1), bound, + std::vector >( + bound.n_set(), + std::make_pair( + static_cast(NULL), + 0)), + uninterpreted_symbols[stmt_num])); + GEQ_Handle h = cond_upper.and_with_GEQ(ub_list[i]); + h.update_coef(cond_upper.get_local(over_free_var), -stride); + } + + CG_outputRepr *lbRepr, *ubRepr; + if (lb_repr_list.size() > 1) { + //fprintf(stderr, "loop_unroll.cc createInvoke( max )\n"); + lbRepr = ocg->CreateInvoke("max", lb_repr_list); + } + else if (lb_repr_list.size() == 1) { + lbRepr = lb_repr_list[0]; + } + + if (ub_repr_list.size() > 1) { + //fprintf(stderr, "loop_unroll.cc createInvoke( min )\n"); + ubRepr = ocg->CreateInvoke("min", ub_repr_list); + } + else if (ub_repr_list.size() == 1) { + ubRepr = ub_repr_list[0]; + } + + // create overflow assignment + CG_outputRepr *rhs = ocg->CreatePlus(ocg->CreateMinus(ubRepr, lbRepr), + ocg->CreateInt(1)); + if (stride != 1) + rhs = ocg->CreateIntegerFloor(rhs, ocg->CreateInt(stride)); + rhs = ocg->CreateIntegerMod(rhs, ocg->CreateInt(unroll_amount)); + CG_outputRepr *lhs = ocg->CreateIdent(over_name); + init_code = ocg->StmtListAppend(init_code, + ocg->CreateAssignment(0, lhs, ocg->CreateInt(0))); + lhs = ocg->CreateIdent(over_name); + overflow_code = ocg->CreateAssignment(0, lhs, rhs); + + // insert constraint 0 <= overflow < unroll_amount + Variable_ID v = overflow_constraint.get_local(over_free_var); + GEQ_Handle h1 = overflow_constraint_root->add_GEQ(); + h1.update_coef(v, 1); + GEQ_Handle h2 = overflow_constraint_root->add_GEQ(); + h2.update_coef(v, -1); + h2.update_const(unroll_amount - 1); + } + + // insert overflow statement + int overflow_stmt_num = -1; + if (overflow_code != NULL) { + // build iteration space for overflow statement + Relation mapping(level, cleanup_split_level - 1); + F_And *f_root = mapping.add_and(); + for (int i = 1; i < cleanup_split_level; i++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.output_var(i), 1); + h.update_coef(mapping.input_var(i), -1); + } + Relation overflow_IS = omega::Range(Restrict_Domain(mapping, copy(hull))); + for (int i = 1; i < cleanup_split_level; i++) + overflow_IS.name_set_var(i, hull.set_var(i)->name()); + overflow_IS.setup_names(); + + // build dumb transformation relation for overflow statement + Relation overflow_xform(cleanup_split_level - 1, + 2 * (cleanup_split_level - 1) + 1); + f_root = overflow_xform.add_and(); + for (int i = 1; i <= cleanup_split_level - 1; i++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(overflow_xform.output_var(2 * i), 1); + h.update_coef(overflow_xform.input_var(i), -1); + + h = f_root->add_EQ(); + h.update_coef(overflow_xform.output_var(2 * i - 1), 1); + h.update_const(-lex[2 * i - 2]); + } + EQ_Handle h = f_root->add_EQ(); + h.update_coef( + overflow_xform.output_var(2 * (cleanup_split_level - 1) + 1), + 1); + h.update_const(-lex[2 * (cleanup_split_level - 1)]); + + shiftLexicalOrder(lex, 2 * cleanup_split_level - 2, 1); + Statement overflow_stmt; + + overflow_stmt.code = overflow_code; + overflow_stmt.IS = overflow_IS; + overflow_stmt.xform = overflow_xform; + overflow_stmt.loop_level = std::vector(level - 1); + overflow_stmt.ir_stmt_node = NULL; + for (int i = 0; i < level - 1; i++) { + overflow_stmt.loop_level[i].type = + stmt[stmt_num].loop_level[i].type; + if (stmt[stmt_num].loop_level[i].type == LoopLevelTile + && stmt[stmt_num].loop_level[i].payload >= level) + overflow_stmt.loop_level[i].payload = -1; + else + overflow_stmt.loop_level[i].payload = + stmt[stmt_num].loop_level[i].payload; + overflow_stmt.loop_level[i].parallel_level = + stmt[stmt_num].loop_level[i].parallel_level; + } + + fprintf(stderr, "loop_unroll.cc L581 adding stmt %d\n", stmt.size()); + stmt.push_back(overflow_stmt); + + uninterpreted_symbols.push_back(uninterpreted_symbols[stmt_num]); + uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[stmt_num]); + dep.insert(); + overflow_stmt_num = stmt.size() - 1; + overflow[overflow_stmt_num] = over_var_list; + + // update the global known information on overflow variable + this->known = Intersection(this->known, + Extend_Set(copy(overflow_constraint), + this->known.n_set() - overflow_constraint.n_set())); + + // update dependence graph + DependenceVector dv; + dv.type = DEP_CONTROL; + for (std::set::iterator i = same_loop.begin(); + i != same_loop.end(); i++) + dep.connect(overflow_stmt_num, *i, dv); + dv.type = DEP_W2W; + { + IR_ScalarSymbol *overflow_sym = NULL; + std::vector scalars = ir->FindScalarRef(overflow_code); + for (int i = scalars.size() - 1; i >= 0; i--) + if (scalars[i]->is_write()) { + overflow_sym = scalars[i]->symbol(); + break; + } + for (int i = scalars.size() - 1; i >= 0; i--) + delete scalars[i]; + dv.sym = overflow_sym; + } + dv.lbounds = std::vector(dep.num_dim(), 0); + dv.ubounds = std::vector(dep.num_dim(), 0); + int dep_dim = get_last_dep_dim_before(stmt_num, level); + for (int i = dep_dim + 1; i < dep.num_dim(); i++) { + dv.lbounds[i] = -posInfinity; + dv.ubounds[i] = posInfinity; + } + for (int i = 0; i <= dep_dim; i++) { + if (i != 0) { + dv.lbounds[i - 1] = 0; + dv.ubounds[i - 1] = 0; + } + dv.lbounds[i] = 1; + dv.ubounds[i] = posInfinity; + dep.connect(overflow_stmt_num, overflow_stmt_num, dv); + } + } + + // split the loop so it can be fully unrolled + std::set new_stmts = split(stmt_num, cleanup_split_level, cond_upper); + std::set new_stmts2 = split(stmt_num, cleanup_split_level, cond_lower); + new_stmts.insert(new_stmts2.begin(), new_stmts2.end()); + + // check if unrolled statements can be trivially lumped together as one statement + bool can_be_lumped = true; + if (can_be_lumped) { + for (std::set::iterator i = same_loop.begin(); + i != same_loop.end(); i++) + if (*i != stmt_num) { + if (stmt[*i].loop_level.size() + != stmt[stmt_num].loop_level.size()) { + can_be_lumped = false; + break; + } + for (int j = 0; j < stmt[stmt_num].loop_level.size(); j++) + if (!(stmt[*i].loop_level[j].type + == stmt[stmt_num].loop_level[j].type + && stmt[*i].loop_level[j].payload + == stmt[stmt_num].loop_level[j].payload)) { + can_be_lumped = false; + break; + } + if (!can_be_lumped) + break; + std::vector lex2 = getLexicalOrder(*i); + for (int j = 2 * level; j < lex.size() - 1; j += 2) + if (lex[j] != lex2[j]) { + can_be_lumped = false; + break; + } + if (!can_be_lumped) + break; + } + } + if (can_be_lumped) { + for (std::set::iterator i = same_loop.begin(); + i != same_loop.end(); i++) + if (is_inner_loop_depend_on_level(stmt[*i].IS, level, + this->known)) { + can_be_lumped = false; + break; + } + } + if (can_be_lumped) { + for (std::set::iterator i = same_loop.begin(); + i != same_loop.end(); i++) + if (*i != stmt_num) { + if (!(Must_Be_Subset(copy(stmt[*i].IS), copy(stmt[stmt_num].IS)) + && Must_Be_Subset(copy(stmt[stmt_num].IS), + copy(stmt[*i].IS)))) { + can_be_lumped = false; + break; + } + } + } + if (can_be_lumped) { + for (std::set::iterator i = same_loop.begin(); + i != same_loop.end(); i++) { + for (DependenceGraph::EdgeList::iterator j = + dep.vertex[*i].second.begin(); + j != dep.vertex[*i].second.end(); j++) + if (same_loop.find(j->first) != same_loop.end()) { + for (int k = 0; k < j->second.size(); k++) + if (j->second[k].type == DEP_CONTROL + || j->second[k].type == DEP_UNKNOWN) { + can_be_lumped = false; + break; + } + if (!can_be_lumped) + break; + } + if (!can_be_lumped) + break; + } + } + + // insert unrolled statements + int old_num_stmt = stmt.size(); + if (!can_be_lumped) { + std::map > what_stmt_num; + + for (int j = 1; j < unroll_amount; j++) { + for (std::set::iterator i = same_loop.begin(); + i != same_loop.end(); i++) { + Statement new_stmt; + + std::vector loop_vars; + std::vector subs; + loop_vars.push_back(stmt[*i].IS.set_var(level)->name()); + subs.push_back( + ocg->CreatePlus( + ocg->CreateIdent( + stmt[*i].IS.set_var(level)->name()), + ocg->CreateInt(j * stride))); + new_stmt.code = ocg->CreateSubstitutedStmt(0, + stmt[*i].code->clone(), loop_vars, subs); + + new_stmt.IS = adjust_loop_bound(stmt[*i].IS, level, j * stride); + add_loop_stride(new_stmt.IS, bound, level - 1, + unroll_amount * stride); + + new_stmt.xform = copy(stmt[*i].xform); + + new_stmt.loop_level = stmt[*i].loop_level; + new_stmt.ir_stmt_node = NULL; + + fprintf(stderr, "loop_unroll.cc L740 adding stmt %d\n", stmt.size()); + stmt.push_back(new_stmt); + + uninterpreted_symbols.push_back(uninterpreted_symbols[stmt_num]); + uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[stmt_num]); + dep.insert(); + what_stmt_num[*i].push_back(stmt.size() - 1); + } + } + for (std::set::iterator i = same_loop.begin(); + i != same_loop.end(); i++) + add_loop_stride(stmt[*i].IS, bound, level - 1, + unroll_amount * stride); + + // update dependence graph + if (stmt[stmt_num].loop_level[level - 1].type == LoopLevelOriginal) { + int dep_dim = stmt[stmt_num].loop_level[level - 1].payload; + int new_stride = unroll_amount * stride; + for (int i = 0; i < old_num_stmt; i++) { + std::vector > D; + + for (DependenceGraph::EdgeList::iterator j = + dep.vertex[i].second.begin(); + j != dep.vertex[i].second.end();) { + if (same_loop.find(i) != same_loop.end()) { + if (same_loop.find(j->first) != same_loop.end()) { + for (int k = 0; k < j->second.size(); k++) { + DependenceVector dv = j->second[k]; + if (dv.type == DEP_CONTROL + || dv.type == DEP_UNKNOWN) { + D.push_back(std::make_pair(j->first, dv)); + for (int kk = 0; kk < unroll_amount - 1; + kk++) + if (what_stmt_num[i][kk] != -1 + && what_stmt_num[j->first][kk] + != -1) + dep.connect(what_stmt_num[i][kk], + what_stmt_num[j->first][kk], + dv); + } else { + coef_t lb = dv.lbounds[dep_dim]; + coef_t ub = dv.ubounds[dep_dim]; + if (ub == lb + && int_mod(lb, + static_cast(new_stride)) + == 0) { + D.push_back( + std::make_pair(j->first, dv)); + for (int kk = 0; kk < unroll_amount - 1; + kk++) + if (what_stmt_num[i][kk] != -1 + && what_stmt_num[j->first][kk] + != -1) + dep.connect( + what_stmt_num[i][kk], + what_stmt_num[j->first][kk], + dv); + } else if (lb == -posInfinity + && ub == posInfinity) { + D.push_back( + std::make_pair(j->first, dv)); + for (int kk = 0; kk < unroll_amount; + kk++) + if (kk == 0) + D.push_back( + std::make_pair(j->first, + dv)); + else if (what_stmt_num[j->first][kk + - 1] != -1) + D.push_back( + std::make_pair( + what_stmt_num[j->first][kk + - 1], + dv)); + for (int t = 0; t < unroll_amount - 1; + t++) + if (what_stmt_num[i][t] != -1) + for (int kk = 0; + kk < unroll_amount; + kk++) + if (kk == 0) + dep.connect( + what_stmt_num[i][t], + j->first, dv); + else if (what_stmt_num[j->first][kk + - 1] != -1) + dep.connect( + what_stmt_num[i][t], + what_stmt_num[j->first][kk + - 1], + dv); + } else { + for (int kk = 0; kk < unroll_amount; + kk++) { + if (lb != -posInfinity) { + if (kk * stride + < int_mod(lb, + static_cast(new_stride))) + dv.lbounds[dep_dim] = + floor( + static_cast(lb) + / new_stride) + * new_stride + + new_stride; + else + dv.lbounds[dep_dim] = + floor( + static_cast(lb) + / new_stride) + * new_stride; + } + if (ub != posInfinity) { + if (kk * stride + > int_mod(ub, + static_cast(new_stride))) + dv.ubounds[dep_dim] = + floor( + static_cast(ub) + / new_stride) + * new_stride + - new_stride; + else + dv.ubounds[dep_dim] = + floor( + static_cast(ub) + / new_stride) + * new_stride; + } + if (dv.ubounds[dep_dim] + >= dv.lbounds[dep_dim]) { + if (kk == 0) + D.push_back( + std::make_pair( + j->first, + dv)); + else if (what_stmt_num[j->first][kk + - 1] != -1) + D.push_back( + std::make_pair( + what_stmt_num[j->first][kk + - 1], + dv)); + } + } + for (int t = 0; t < unroll_amount - 1; + t++) + if (what_stmt_num[i][t] != -1) + for (int kk = 0; + kk < unroll_amount; + kk++) { + if (lb != -posInfinity) { + if (kk * stride + < int_mod( + lb + t + + 1, + static_cast(new_stride))) + dv.lbounds[dep_dim] = + floor( + static_cast(lb + + (t + + 1) + * stride) + / new_stride) + * new_stride + + new_stride; + else + dv.lbounds[dep_dim] = + floor( + static_cast(lb + + (t + + 1) + * stride) + / new_stride) + * new_stride; + } + if (ub != posInfinity) { + if (kk * stride + > int_mod( + ub + t + + 1, + static_cast(new_stride))) + dv.ubounds[dep_dim] = + floor( + static_cast(ub + + (t + + 1) + * stride) + / new_stride) + * new_stride + - new_stride; + else + dv.ubounds[dep_dim] = + floor( + static_cast(ub + + (t + + 1) + * stride) + / new_stride) + * new_stride; + } + if (dv.ubounds[dep_dim] + >= dv.lbounds[dep_dim]) { + if (kk == 0) + dep.connect( + what_stmt_num[i][t], + j->first, + dv); + else if (what_stmt_num[j->first][kk + - 1] != -1) + dep.connect( + what_stmt_num[i][t], + what_stmt_num[j->first][kk + - 1], + dv); + } + } + } + } + } + + dep.vertex[i].second.erase(j++); + } else { + for (int kk = 0; kk < unroll_amount - 1; kk++) + if (what_stmt_num[i][kk] != -1) + dep.connect(what_stmt_num[i][kk], j->first, + j->second); + + j++; + } + } else { + if (same_loop.find(j->first) != same_loop.end()) + for (int k = 0; k < j->second.size(); k++) + for (int kk = 0; kk < unroll_amount - 1; kk++) + if (what_stmt_num[j->first][kk] != -1) + D.push_back( + std::make_pair( + what_stmt_num[j->first][kk], + j->second[k])); + j++; + } + } + + for (int j = 0; j < D.size(); j++) + dep.connect(i, D[j].first, D[j].second); + } + } + + // reset lexical order for the unrolled loop body + std::set new_same_loop; + + int count = 0; + + for (std::map >::iterator i = + what_stmt_num.begin(); i != what_stmt_num.end(); i++) { + + new_same_loop.insert(i->first); + for (int k = dim + 1; k < stmt[i->first].xform.n_out(); k += 2) + assign_const(stmt[i->first].xform, k, + get_const(stmt[(what_stmt_num.begin())->first].xform, k, + Output_Var) + count); + count++; + for (int j = 0; j < i->second.size(); j++) { + new_same_loop.insert(i->second[j]); + for (int k = dim + 1; k < stmt[i->second[j]].xform.n_out(); k += + 2) + assign_const(stmt[i->second[j]].xform, k, + get_const( + stmt[(what_stmt_num.begin())->first].xform, + k, Output_Var) + count); + count++; + } + } + setLexicalOrder(dim + 1, new_same_loop, 0, idxNames); + } else { + for (std::set::iterator i = same_loop.begin(); + i != same_loop.end(); i++) + add_loop_stride(stmt[*i].IS, bound, level - 1, + unroll_amount * stride); + + int max_level = stmt[stmt_num].loop_level.size(); + std::vector > stmt_order; + for (std::set::iterator i = same_loop.begin(); + i != same_loop.end(); i++) + stmt_order.push_back( + std::make_pair( + get_const(stmt[*i].xform, 2 * max_level, + Output_Var), *i)); + sort(stmt_order.begin(), stmt_order.end()); + + Statement new_stmt; + new_stmt.code = NULL; + for (int j = 1; j < unroll_amount; j++) { + for (int i = 0; i < stmt_order.size(); i++) { + std::vector loop_vars; + std::vector subs; + + //fprintf(stderr, "loop_unroll.cc, will replace '%s with '%s+%d' ??\n", + // stmt[stmt_order[i].second].IS.set_var(level)->name().c_str(), + // stmt[stmt_order[i].second].IS.set_var(level)->name().c_str(), j * stride); + + loop_vars.push_back( + stmt[stmt_order[i].second].IS.set_var(level)->name()); + subs.push_back( + ocg->CreatePlus(ocg->CreateIdent(stmt[stmt_order[i].second].IS.set_var(level)->name()), + ocg->CreateInt(j * stride))); // BUG HERE + //fprintf(stderr, "loop_unroll.cc subs now has %d parts\n", subs.size()); + //for (int k=0; k< subs.size(); k++) //fprintf(stderr, "subs[%d] = 0x%x\n", k, subs[k]); + + //fprintf(stderr, "ij %d %d ", i, j); + //fprintf(stderr, "old src was =\n"); + //stmt[stmt_order[i].second].code->dump(); fflush(stdout); //fprintf(stderr, "\n"); + + + + CG_outputRepr *code = ocg->CreateSubstitutedStmt(0, + stmt[stmt_order[i].second].code->clone(), + loop_vars, + subs); + + //fprintf(stderr, "old src is =\n"); + //stmt[stmt_order[i].second].code->dump(); fflush(stdout); //fprintf(stderr, "\n"); + + //fprintf(stderr, "substituted copy is =\n"); + //code->dump(); //fprintf(stderr, "\n\n"); + + + new_stmt.code = ocg->StmtListAppend(new_stmt.code, code); + //fprintf(stderr, "appended code =\n"); + //new_stmt.code->dump(); + + } + } + + + + //fprintf(stderr, "new_stmt.IS = \n"); + new_stmt.IS = copy(stmt[stmt_num].IS); + new_stmt.xform = copy(stmt[stmt_num].xform); + assign_const(new_stmt.xform, 2 * max_level, + stmt_order[stmt_order.size() - 1].first + 1); + new_stmt.loop_level = stmt[stmt_num].loop_level; + new_stmt.ir_stmt_node = NULL; + + new_stmt.has_inspector = false; // ?? or from copied stmt? + if (stmt[stmt_num].has_inspector) fprintf(stderr, "OLD STMT HAS INSPECTOR\n"); + else fprintf(stderr, "OLD STMT DOES NOT HAVE INSPECTOR\n"); + + fprintf(stderr, "loop_unroll.cc L1083 adding stmt %d\n", stmt.size()); + stmt.push_back(new_stmt); + + uninterpreted_symbols.push_back(uninterpreted_symbols[stmt_num]); + uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[stmt_num]); + dep.insert(); + + //fprintf(stderr, "update dependence graph\n"); + // update dependence graph + if (stmt[stmt_num].loop_level[level - 1].type == LoopLevelOriginal) { + int dep_dim = stmt[stmt_num].loop_level[level - 1].payload; + int new_stride = unroll_amount * stride; + for (int i = 0; i < old_num_stmt; i++) { + std::vector > > D; + + for (DependenceGraph::EdgeList::iterator j = + dep.vertex[i].second.begin(); + j != dep.vertex[i].second.end();) { + if (same_loop.find(i) != same_loop.end()) { + if (same_loop.find(j->first) != same_loop.end()) { + std::vector dvs11, dvs12, dvs22, + dvs21; + for (int k = 0; k < j->second.size(); k++) { + DependenceVector dv = j->second[k]; + if (dv.type == DEP_CONTROL + || dv.type == DEP_UNKNOWN) { + if (i == j->first) { + dvs11.push_back(dv); + dvs22.push_back(dv); + } else + throw loop_error( + "unrolled statements lumped together illegally"); + } else { + coef_t lb = dv.lbounds[dep_dim]; + coef_t ub = dv.ubounds[dep_dim]; + if (ub == lb + && int_mod(lb, + static_cast(new_stride)) + == 0) { + dvs11.push_back(dv); + dvs22.push_back(dv); + } else { + if (lb != -posInfinity) + dv.lbounds[dep_dim] = ceil( + static_cast(lb) + / new_stride) + * new_stride; + if (ub != posInfinity) + dv.ubounds[dep_dim] = floor( + static_cast(ub) + / new_stride) + * new_stride; + if (dv.ubounds[dep_dim] + >= dv.lbounds[dep_dim]) + dvs11.push_back(dv); + + if (lb != -posInfinity) + dv.lbounds[dep_dim] = ceil( + static_cast(lb) + / new_stride) + * new_stride; + if (ub != posInfinity) + dv.ubounds[dep_dim] = ceil( + static_cast(ub) + / new_stride) + * new_stride; + if (dv.ubounds[dep_dim] + >= dv.lbounds[dep_dim]) + dvs21.push_back(dv); + + if (lb != -posInfinity) + dv.lbounds[dep_dim] = floor( + static_cast(lb) + / new_stride) + * new_stride; + if (ub != posInfinity) + dv.ubounds[dep_dim] = floor( + static_cast(ub + - stride) + / new_stride) + * new_stride; + if (dv.ubounds[dep_dim] + >= dv.lbounds[dep_dim]) + dvs12.push_back(dv); + + if (lb != -posInfinity) + dv.lbounds[dep_dim] = floor( + static_cast(lb) + / new_stride) + * new_stride; + if (ub != posInfinity) + dv.ubounds[dep_dim] = ceil( + static_cast(ub + - stride) + / new_stride) + * new_stride; + if (dv.ubounds[dep_dim] + >= dv.lbounds[dep_dim]) + dvs22.push_back(dv); + } + } + } + if (dvs11.size() > 0) + D.push_back(std::make_pair(i, dvs11)); + if (dvs22.size() > 0) + dep.connect(old_num_stmt, old_num_stmt, dvs22); + if (dvs12.size() > 0) + D.push_back( + std::make_pair(old_num_stmt, dvs12)); + if (dvs21.size() > 0) + dep.connect(old_num_stmt, i, dvs21); + + dep.vertex[i].second.erase(j++); + } else { + dep.connect(old_num_stmt, j->first, j->second); + j++; + } + } else { + if (same_loop.find(j->first) != same_loop.end()) + D.push_back( + std::make_pair(old_num_stmt, j->second)); + j++; + } + } + + for (int j = 0; j < D.size(); j++) + dep.connect(i, D[j].first, D[j].second); + } + } + } + + //fprintf(stderr, " loop_unroll.cc returning new_stmts\n"); + return new_stmts; +} + + -- cgit v1.2.3-70-g09d2