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 --- CMakeLists.txt | 14 +- include/chillAST.h | 12 + include/chillAST/chillAST_def.hh | 161 + include/chillAST/chillAST_node.hh | 504 +++ include/chillAST/chillASTs.hh | 1666 +++++++ include/chill_ast.hh | 2365 ---------- include/chilldebug.h | 21 +- include/dep.hh | 4 - include/ir_clang.hh | 11 +- include/ir_code.hh | 2 +- include/irtools.hh | 1 - include/stencil.hh | 2 +- lib/chillcg/include/code_gen/CG_chillRepr.h | 2 +- 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 +++++ 30 files changed, 18662 insertions(+), 18686 deletions(-) create mode 100644 include/chillAST.h create mode 100644 include/chillAST/chillAST_def.hh create mode 100644 include/chillAST/chillAST_node.hh create mode 100644 include/chillAST/chillASTs.hh delete mode 100644 include/chill_ast.hh 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 diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c6e2dd..c668668 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,18 +15,18 @@ set(CORE_LIBS set(CORE_SRC src/dep.cc src/irtools.cc - src/loop.cc - src/loop_basic.cc - src/loop_datacopy.cc - src/loop_extra.cc - src/loop_tile.cc - src/loop_unroll.cc + src/transformations/loop.cc + src/transformations/loop_basic.cc + src/transformations/loop_datacopy.cc + src/transformations/loop_extra.cc + src/transformations/loop_tile.cc + src/transformations/loop_unroll.cc src/omegatools.cc ) set(IR_CHILL_SRC src/ir_clang.cc - src/chill_ast.cc + src/chillASTs.cc ) set(PYTHON_SRC diff --git a/include/chillAST.h b/include/chillAST.h new file mode 100644 index 0000000..dba4ed2 --- /dev/null +++ b/include/chillAST.h @@ -0,0 +1,12 @@ +// +// Created by ztuowen on 9/22/16. +// + +#ifndef CHILL_CHILLAST_H +#define CHILL_CHILLAST_H + +#include "chillAST/chillAST_def.hh" +#include "chillAST/chillAST_node.hh" +#include "chillAST/chillASTs.hh" + +#endif //CHILL_CHILLAST_H diff --git a/include/chillAST/chillAST_def.hh b/include/chillAST/chillAST_def.hh new file mode 100644 index 0000000..318b51b --- /dev/null +++ b/include/chillAST/chillAST_def.hh @@ -0,0 +1,161 @@ + + +#ifndef _CHILLAST_DEF_H_ +#define _CHILLAST_DEF_H_ + + +#define CHILL_INDENT_AMOUNT 2 + +#include +#include +#include +#include +#include +#include // std::vector + +#include // for IR_CONDITION_* + +#define CHILLAST_NODETYPE_FORSTMT CHILLAST_NODETYPE_LOOP +#define CHILLAST_NODETYPE_TRANSLATIONUNIT CHILLAST_NODETYPE_SOURCEFILE + +enum CHILL_ASTNODE_TYPE { + CHILLAST_NODETYPE_UNKNOWN=0, + CHILLAST_NODETYPE_SOURCEFILE, + CHILLAST_NODETYPE_TYPEDEFDECL, + CHILLAST_NODETYPE_VARDECL, + // CHILLAST_NODETYPE_PARMVARDECL, not used any more + CHILLAST_NODETYPE_FUNCTIONDECL, + CHILLAST_NODETYPE_RECORDDECL, // struct or union (or class) + CHILLAST_NODETYPE_MACRODEFINITION, + CHILLAST_NODETYPE_COMPOUNDSTMT, + CHILLAST_NODETYPE_LOOP, // AKA ForStmt + CHILLAST_NODETYPE_TERNARYOPERATOR, + CHILLAST_NODETYPE_BINARYOPERATOR, + CHILLAST_NODETYPE_UNARYOPERATOR, + CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR, + CHILLAST_NODETYPE_MEMBEREXPR, // structs/unions + CHILLAST_NODETYPE_DECLREFEXPR, + CHILLAST_NODETYPE_INTEGERLITERAL, + CHILLAST_NODETYPE_FLOATINGLITERAL, + CHILLAST_NODETYPE_IMPLICITCASTEXPR, + CHILLAST_NODETYPE_RETURNSTMT, + CHILLAST_NODETYPE_CALLEXPR, + CHILLAST_NODETYPE_DECLSTMT, + CHILLAST_NODETYPE_PARENEXPR, + CHILLAST_NODETYPE_CSTYLECASTEXPR, + CHILLAST_NODETYPE_CSTYLEADDRESSOF, + CHILLAST_NODETYPE_IFSTMT, + CHILLAST_NODETYPE_SIZEOF, + CHILLAST_NODETYPE_MALLOC, + CHILLAST_NODETYPE_FREE, + CHILLAST_NODETYPE_PREPROCESSING, // comments, #define, #include, whatever else works + CHILLAST_NODETYPE_NOOP, // NO OP + // CUDA specific + CHILLAST_NODETYPE_CUDAMALLOC, + CHILLAST_NODETYPE_CUDAFREE, + CHILLAST_NODETYPE_CUDAMEMCPY, + CHILLAST_NODETYPE_CUDAKERNELCALL, + CHILLAST_NODETYPE_CUDASYNCTHREADS, + CHILLAST_NODETYPE_NULL // explicit non-statement + // TODO + +} ; + +enum CHILL_FUNCTION_TYPE { + CHILL_FUNCTION_CPU = 0, + CHILL_FUNCTION_GPU +}; + +enum CHILL_MEMBER_EXP_TYPE { + CHILL_MEMBER_EXP_DOT = 0, + CHILL_MEMBER_EXP_ARROW +}; + +enum CHILL_PREPROCESSING_TYPE { + CHILL_PREPROCESSING_TYPEUNKNOWN = 0, + CHILL_PREPROCESSING_COMMENT, + CHILL_PREPROCESSING_POUNDDEFINE, + CHILL_PREPROCESSING_POUNDINCLUDE, + CHILL_PREPROCESSING_PRAGMA // unused so far +}; + +enum CHILL_PREPROCESSING_POSITION { // when tied to another statement + CHILL_PREPROCESSING_POSITIONUNKNOWN = 0, + CHILL_PREPROCESSING_LINEBEFORE, // previous line + CHILL_PREPROCESSING_LINEAFTER, // next line + CHILL_PREPROCESSING_TOTHERIGHT, // for this kind of comment, on same line + CHILL_PREPROCESSING_IMMEDIATELYBEFORE // on same line +}; + +char *parseUnderlyingType( char *sometype ); +char *parseArrayParts( char *sometype ); +bool isRestrict( const char *sometype ); +char *splitTypeInfo( char *underlyingtype ); +char *ulhack( char *brackets ); // change "1024UL" to "1024" +char *restricthack( char *typeinfo ); // remove __restrict__ , MODIFIES the argument! + +extern const char* Chill_AST_Node_Names[]; // WARNING MUST BE KEPT IN SYNC WITH BELOW LIST + +// fwd declarations +class chillAST_node; // the generic node. specific types derive from this +class chillAST_NULL; // empty +class chillAST_SourceFile; // ast for an entire source file (translationunit) + +class chillAST_TypedefDecl; +class chillAST_VarDecl; +//class chillAST_ParmVarDecl; +class chillAST_FunctionDecl; +class chillAST_RecordDecl; // structs and unions (and classes?) +class chillAST_MacroDefinition; +class chillAST_CompoundStmt; // just a bunch of other statements +class chillAST_ForStmt; // AKA a LOOP +class chillAST_TernaryOperator; +class chillAST_BinaryOperator; +class chillAST_ArraySubscriptExpr; +class chillAST_MemberExpr; +class chillAST_DeclRefExpr; +class chillAST_IntegerLiteral; +class chillAST_FloatingLiteral; +class chillAST_UnaryOperator; +class chillAST_ImplicitCastExpr; +class chillAST_CStyleCastExpr; +class chillAST_CStyleAddressOf; +class chillAST_ReturnStmt; +class chillAST_CallExpr; +class chillAST_ParenExpr; +class chillAST_Sizeof; +class chillAST_Malloc; +class chillAST_Free; +class chillAST_NoOp; +class chillAST_CudaMalloc; +class chillAST_CudaFree; +class chillAST_CudaMemcpy; +class chillAST_CudaKernelCall; +class chillAST_CudaSyncthreads; +class chillAST_Preprocessing; + +typedef std::vector chillAST_SymbolTable; // typedef +typedef std::vector chillAST_TypedefTable; // typedef + +bool symbolTableHasVariableNamed( chillAST_SymbolTable *table, const char *name ); // fwd decl +chillAST_VarDecl *symbolTableFindVariableNamed( chillAST_SymbolTable *table, const char *name ); // fwd decl TODO too many similar named functions + +void printSymbolTable( chillAST_SymbolTable *st ); // fwd decl +void printSymbolTableMoreInfo( chillAST_SymbolTable *st ); // fwd decl + + +chillAST_node *lessthanmacro( chillAST_node *left, chillAST_node *right); // fwd declaration +chillAST_SymbolTable *addSymbolToTable( chillAST_SymbolTable *st, chillAST_VarDecl *vd ); // fwd decl +chillAST_TypedefTable *addTypedefToTable( chillAST_TypedefTable *tt, chillAST_TypedefDecl *td ); // fwd decl + + +bool streq( const char *a, const char *b); // fwd decl +void chillindent( int i, FILE *fp ); // fwd declaration +void insertNewDeclAtLocationOfOldIfNeeded( chillAST_VarDecl *newdecl, chillAST_VarDecl *olddecl); + +chillAST_DeclRefExpr *buildDeclRefExpr( chillAST_VarDecl *); + +chillAST_FunctionDecl *findFunctionDecl( chillAST_node *node, const char *procname); + +#endif + diff --git a/include/chillAST/chillAST_node.hh b/include/chillAST/chillAST_node.hh new file mode 100644 index 0000000..70660c5 --- /dev/null +++ b/include/chillAST/chillAST_node.hh @@ -0,0 +1,504 @@ + + +#ifndef _CHILLAST_NODE_H_ +#define _CHILLAST_NODE_H_ + +#include "chillAST_def.hh" + +// an actual chill ast. +// nodes based on clang AST which are in turn based on C++ + +class chillAST_node { // generic node. a tree of these is the AST. this is virtual (can't instantiate) +public: + + static int chill_scalar_counter; // for manufactured scalars + static int chill_array_counter ; // for manufactured arrays + static int chill_pointer_counter ; // for manufactured arrays + + + CHILL_ASTNODE_TYPE asttype; + + bool isSourceFile() { return (asttype == CHILLAST_NODETYPE_SOURCEFILE); }; + bool isTypeDefDecl() { return (asttype == CHILLAST_NODETYPE_TYPEDEFDECL); }; + bool isVarDecl() { return (asttype == CHILLAST_NODETYPE_VARDECL); }; + bool isFunctionDecl() { return (asttype == CHILLAST_NODETYPE_FUNCTIONDECL); }; + bool isRecordDecl() { return (asttype == CHILLAST_NODETYPE_RECORDDECL); }; + bool isMacroDefinition() { return (asttype == CHILLAST_NODETYPE_MACRODEFINITION); }; + bool isCompoundStmt() { return (asttype == CHILLAST_NODETYPE_COMPOUNDSTMT); }; + bool isLoop() { return (asttype == CHILLAST_NODETYPE_LOOP); }; // AKA ForStmt + bool isForStmt() { return (asttype == CHILLAST_NODETYPE_LOOP); }; // AKA Loop + bool isIfStmt() { return (asttype == CHILLAST_NODETYPE_IFSTMT); }; + bool isTernaryOperator() { return (asttype == CHILLAST_NODETYPE_TERNARYOPERATOR);}; + bool isBinaryOperator() { return (asttype == CHILLAST_NODETYPE_BINARYOPERATOR); }; + bool isUnaryOperator() { return (asttype == CHILLAST_NODETYPE_UNARYOPERATOR); }; + bool isArraySubscriptExpr() { return (asttype == CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR); }; + bool isMemberExpr() { return (asttype == CHILLAST_NODETYPE_MEMBEREXPR); }; + bool isDeclRefExpr() { return (asttype == CHILLAST_NODETYPE_DECLREFEXPR); }; + bool isIntegerLiteral() { return (asttype == CHILLAST_NODETYPE_INTEGERLITERAL); }; + bool isFloatingLiteral() { return (asttype == CHILLAST_NODETYPE_FLOATINGLITERAL); }; + bool isImplicitCastExpr() { return (asttype == CHILLAST_NODETYPE_IMPLICITCASTEXPR); }; + bool isReturnStmt() { return (asttype == CHILLAST_NODETYPE_RETURNSTMT); }; + bool isCallExpr() { return (asttype == CHILLAST_NODETYPE_CALLEXPR); }; + bool isParenExpr() { return (asttype == CHILLAST_NODETYPE_PARENEXPR); }; + bool isSizeof() { return (asttype == CHILLAST_NODETYPE_SIZEOF); }; + bool isMalloc() { return (asttype == CHILLAST_NODETYPE_MALLOC); }; + bool isFree() { return (asttype == CHILLAST_NODETYPE_FREE); }; + bool isPreprocessing() { return (asttype == CHILLAST_NODETYPE_PREPROCESSING); }; + bool isNoOp() { return (asttype == CHILLAST_NODETYPE_NOOP); }; + bool isNull() { return (asttype == CHILLAST_NODETYPE_NULL); }; + bool isCStyleCastExpr() { return (asttype == CHILLAST_NODETYPE_CSTYLECASTEXPR); }; + bool isCStyleAddressOf() { return (asttype == CHILLAST_NODETYPE_CSTYLEADDRESSOF); }; + bool isCudaMalloc() { return (asttype == CHILLAST_NODETYPE_CUDAMALLOC); }; + bool isCudaFree() { return (asttype == CHILLAST_NODETYPE_CUDAFREE); }; + bool isCudaMemcpy() { return (asttype == CHILLAST_NODETYPE_CUDAMEMCPY); }; + bool isCudaKERNELCALL() { return (asttype == CHILLAST_NODETYPE_CUDAKERNELCALL); }; + bool isCudaSYNCTHREADS() { return (asttype == CHILLAST_NODETYPE_CUDASYNCTHREADS); }; + + bool isDeclStmt() { return (asttype == CHILLAST_NODETYPE_DECLSTMT); }; // doesn't exist + + bool isConstant() { return (asttype == CHILLAST_NODETYPE_INTEGERLITERAL) || (asttype == CHILLAST_NODETYPE_FLOATINGLITERAL); } + + + virtual bool isAssignmentOp() { return false; }; + virtual bool isComparisonOp() { return false; }; + virtual bool isNotLeaf() { return false; }; + virtual bool isLeaf() { return true; }; + virtual bool isParmVarDecl() { return false; }; + + virtual bool isPlusOp() { return false; }; + virtual bool isMinusOp() { return false; }; + virtual bool isPlusMinusOp() { return false; }; + virtual bool isMultDivOp() { return false; }; + + virtual bool isAStruct() { return false; }; + virtual bool isAUnion() { return false; }; + + virtual bool hasSymbolTable() { return false; } ; // most nodes do NOT have a symbol table + virtual bool hasTypedefTable() { return false; } ; // most nodes do NOT have a typedef table + virtual chillAST_SymbolTable *getSymbolTable() { return NULL; } // most nodes do NOT have a symbol table + + virtual chillAST_VarDecl *findVariableNamed( const char *name ); // recursive + + chillAST_RecordDecl *findRecordDeclNamed( const char *name ); // recursive + + // void addDecl( chillAST_VarDecl *vd); // recursive, adds to first symbol table it can find + + // TODO decide how to hide some data + chillAST_node *parent; + bool isFromSourceFile; // false = #included + char *filename; // file this node is from + + void segfault() { fprintf(stderr, "segfaulting on purpose\n"); int *i=0; int j = i[0]; }; // seg fault + int getNumChildren() { return children.size(); }; + std::vector children; + std::vector getChildren() { return children; } ; // not usually useful + void setChildren( std::vector&c ) { children = c; } ; // does not set parent. probably should + chillAST_node *getChild( int which) { return children[which]; }; + void setChild( int which, chillAST_node *n ) { children[which] = n; children[which]->parent = this; } ; + + char *metacomment; // for compiler internals, formerly a comment + void setMetaComment( char *c ) { metacomment = strdup(c); }; + + std::vector preprocessinginfo; + + virtual void addChild( chillAST_node* c) { + //if (c->isFunctionDecl()) fprintf(stderr, "addchild FunctionDecl\n"); + c->parent = this; + // check to see if it's already there + for (int i=0; igetTypeString(), i); + node->parent = this; + children.insert( children.begin()+i, node ); + }; + + virtual void removeChild(int i) { + children.erase( children.begin()+i ); + }; + + int findChild( chillAST_node *c ) { + for (int i=0; isetParent( this ); + return; + } + } + fprintf(stderr, "%s %p generic replaceChild called with oldchild that was not a child\n", + getTypeString(), this) ; + fprintf(stderr, "printing\n"); + print(); fprintf(stderr, "\nchild: "); + if (!old) fprintf(stderr, "oldchild NULL!\n"); + old->print(); fprintf(stderr, "\nnew: "); + newchild->print(); fprintf(stderr, "\n"); + segfault(); // make easier for gdb + }; + + virtual void loseLoopWithLoopVar( char *var ) { + // walk tree. If a loop has this loop variable, replace the loop with the loop body, + // removing the loop. The loop will be spread across a bunch of cores that will each + // calculate their own loop variable. + + // things that can not have loops as substatements can have a null version of this method + // things that have more complicated sets of "children" will have specialized versions + + // this is the generic version of the method. It just recurses among its children. + // ForStmt is the only one that can actually remove itself. When it does, it will + // potentially change the children vector, which is not the simple array it might appear. + // so you have to make a copy of the vector to traverse + + std::vector dupe = children; // simple enough? + //fprintf(stderr, "node XXX has %d children\n", dupe.size()); + //fprintf(stderr, "generic node %s has %d children\n", getTypeString(), dupe.size()); + for (int i=0; iloseLoopWithLoopVar( var ); + } + } + + virtual int evalAsInt() { + fprintf(stderr,"(%s) can't be evaluated as an integer??\n", Chill_AST_Node_Names[asttype]); + print(); fprintf(stderr, "\n"); + segfault(); + } + + virtual const char* getUnderlyingType() { + fprintf(stderr,"(%s) forgot to implement getUnderlyingType()\n", Chill_AST_Node_Names[asttype]); + dump(); + print(); + fprintf(stderr, "\n\n"); + segfault(); + }; + + virtual chillAST_VarDecl* getUnderlyingVarDecl() { + fprintf(stderr,"(%s) forgot to implement getUnderlyingVarDecl()\n", Chill_AST_Node_Names[asttype]); + dump(); + print(); + fprintf(stderr, "\n\n"); + segfault(); + }; + + + virtual chillAST_node *findref(){// find the SINGLE constant or data reference at this node or below + fprintf(stderr,"(%s) forgot to implement findref()\n" ,Chill_AST_Node_Names[asttype]); + dump(); + print(); + fprintf(stderr, "\n\n"); + segfault(); + }; + + virtual void gatherArrayRefs( std::vector &refs, bool writtento ) { + fprintf(stderr,"(%s) forgot to implement gatherArrayRefs()\n" ,Chill_AST_Node_Names[asttype]); + dump(); + print(); + fprintf(stderr, "\n\n"); + }; + + // TODO we MIGHT want the VarDecl // NOTHING IMPLEMENTS THIS? ??? + virtual void gatherScalarRefs( std::vector &refs, bool writtento ) { + fprintf(stderr,"(%s) forgot to implement gatherScalarRefs()\n" ,Chill_AST_Node_Names[asttype]); + dump(); + print(); + fprintf(stderr, "\n\n"); + }; + + virtual void gatherLoopIndeces( std::vector &indeces ) { // recursive walk parent links, looking for loops, and grabbing the declRefExpr in the loop init and cond. + // you can quit when you get to certain nodes + + //fprintf(stderr, "%s::gatherLoopIndeces()\n", getTypeString()); + + if (isSourceFile() || isFunctionDecl() ) return; // end of the line + + // just for debugging + //if (parent) { + // fprintf(stderr, "%s has parent of type %s\n", getTypeString(), parent->getTypeString()); + //} + //else fprintf(stderr, "this %s %p has no parent???\n", getTypeString(), this); + + + if (!parent) return; // should not happen, but be careful + + // for most nodes, this just recurses upwards + //fprintf(stderr, "%s::gatherLoopIndeces() %p recursing up\n", this); + parent->gatherLoopIndeces( indeces ); + } + + + chillAST_ForStmt* findContainingLoop() { // recursive walk parent links, looking for loops + //fprintf(stderr, "%s::findContainingLoop() ", getTypeString()); + //if (parent) fprintf(stderr, "parents is a %s\n", parent->getTypeString()); + //else fprintf(stderr, "no parent\n"); + // do not check SELF type, as we may want to find the loop containing a loop + if (!parent) return NULL; + if (parent->isForStmt()) return (chillAST_ForStmt*)parent; + return parent->findContainingLoop(); // recurse upwards + } + + chillAST_node* findContainingNonLoop() { // recursive walk parent links, avoiding loops + fprintf(stderr, "%s::findContainingNonLoop() ", getTypeString()); + //if (parent) fprintf(stderr, "parent is a %s\n", parent->getTypeString()); + //else fprintf(stderr, "no parent\n"); + // do not check SELF type, as we may want to find the loop containing a loop + if (!parent) return NULL; + if (parent->isCompoundStmt() && parent->getParent()->isForStmt()) return parent->getParent()->findContainingNonLoop(); // keep recursing + if (parent->isForStmt()) return parent->findContainingNonLoop(); // keep recursing + return (chillAST_node*)parent; // return non-loop + } + + // TODO gather loop init and cond (and if cond) like gatherloopindeces + + virtual void gatherDeclRefExprs( std::vector&refs ){ // both scalar and arrays + fprintf(stderr,"(%s) forgot to implement gatherDeclRefExpr()\n" ,Chill_AST_Node_Names[asttype]); + }; + + + + virtual void gatherVarUsage( std::vector &decls ) { + fprintf(stderr,"(%s) forgot to implement gatherVarUsage()\n" ,Chill_AST_Node_Names[asttype]); + }; + + virtual void gatherVarLHSUsage( std::vector &decls ) { + fprintf(stderr,"(%s) forgot to implement gatherVarLHSUsage()\n" ,Chill_AST_Node_Names[asttype]); + }; + + + virtual void gatherVarDecls( std::vector &decls ) { // ACTUAL Declaration + fprintf(stderr,"(%s) forgot to implement gatherVarDecls()\n" ,Chill_AST_Node_Names[asttype]); + }; + + + virtual void gatherVarDeclsMore( std::vector &decls ) { // even if the decl itself is not in the ast. + fprintf(stderr,"(%s) forgot to implement gatherVarDeclsMore()\n" ,Chill_AST_Node_Names[asttype]); + }; + + virtual void gatherScalarVarDecls( std::vector &decls ) { // ACTUAL Declaration + fprintf(stderr,"(%s) forgot to implement gatherScalarVarDecls()\n" ,Chill_AST_Node_Names[asttype]); + }; + + virtual void gatherArrayVarDecls( std::vector &decls ) { // ACTUAL Declaration + fprintf(stderr,"(%s) forgot to implement gatherArrayVarDecls()\n" ,Chill_AST_Node_Names[asttype]); + }; + + virtual chillAST_VarDecl *findArrayDecl( const char *name ) { // scoping TODO + if (!hasSymbolTable()) return parent->findArrayDecl( name ); // most things + else + fprintf(stderr,"(%s) forgot to implement gatherArrayVarDecls()\n" ,Chill_AST_Node_Names[asttype]); + } + + + virtual void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) { + fprintf(stderr,"(%s) forgot to implement replaceVarDecls()\n" ,Chill_AST_Node_Names[asttype]); + }; + + virtual bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ) { + // this just looks for ForStmts with preferred index metacomment attached + fprintf(stderr,"(%s) forgot to implement findLoopIndexesToReplace()\n" ,Chill_AST_Node_Names[asttype]); + return false; + } + + + virtual chillAST_node* constantFold() { // hacky. TODO. make nice + fprintf(stderr,"(%s) forgot to implement constantFold()\n" ,Chill_AST_Node_Names[asttype]); + exit(-1); ; + }; + + virtual chillAST_node* clone() { // makes a deep COPY (?) + fprintf(stderr,"(%s) forgot to implement clone()\n" ,Chill_AST_Node_Names[asttype]); + exit(-1); ; + }; + virtual void dump( int indent=0, FILE *fp = stderr ) { + fflush(fp); + fprintf(fp,"(%s) forgot to implement dump()\n" ,Chill_AST_Node_Names[asttype]); };// print ast + + virtual void print( int indent=0, FILE *fp = stderr ) { + fflush(fp); + //fprintf(stderr, "generic chillAST_node::print() called!\n"); + //fprintf(stderr, "asttype is %d\n", asttype); + fprintf(fp, "\n"); + chillindent(indent, fp); + fprintf(fp,"(%s) forgot to implement print()\n" ,Chill_AST_Node_Names[asttype]); + };// print CODE + + virtual void printName( int indent=0, FILE *fp = stderr ) { + fflush(fp); + //fprintf(stderr, "generic chillAST_node::printName() called!\n"); + //fprintf(stderr, "asttype is %d\n", asttype); + fprintf(fp, "\n"); + chillindent(indent, fp); + fprintf(fp,"(%s) forgot to implement printName()\n" ,Chill_AST_Node_Names[asttype]); + };// print CODE + + virtual char *stringRep(int indent=0 ) { // the ast's print version + fflush(stdout); + // chillindent(indent, fp); TODO + fprintf(stderr,"(%s) forgot to implement stringRep()\n" ,Chill_AST_Node_Names[asttype]); + segfault(); + } + + + virtual void printonly( int indent=0, FILE *fp = stderr ) { print( indent, fp); }; + + //virtual void printString( std::string &s ) { + // fprintf(stderr,"(%s) forgot to implement printString()\n" ,Chill_AST_Node_Names[asttype]); + //} + + + virtual void get_top_level_loops( std::vector &loops) { + int n = children.size(); + //fprintf(stderr, "get_top_level_loops of a %s with %d children\n", getTypeString(), n); + for (int i=0; igetTypeString()); + if (children[i]->isForStmt()) { + loops.push_back( ((chillAST_ForStmt *)(children[i])) ); + } + } + //fprintf(stderr, "found %d top level loops\n", loops.size()); + } + + + virtual void repairParentChild() { // for nodes where all subnodes are children + int n = children.size(); + for (int i=0; iparent != this) { + fprintf(stderr, "fixing child %s that didn't know its parent\n", children[i]->getTypeString()); + children[i]->parent = this; + } + } + } + + + + virtual void get_deep_loops( std::vector &loops) { // this is probably broken - returns ALL loops under it + int n = children.size(); + //fprintf(stderr, "get_deep_loops of a %s with %d children\n", getTypeString(), n); + for (int i=0; igetTypeString()); + children[i]->get_deep_loops( loops ); + } + //fprintf(stderr, "found %d deep loops\n", loops.size()); + } + + + // generic for chillAST_node with children + virtual void find_deepest_loops( std::vector &loops) { // returns DEEPEST nesting of loops + std::vectordeepest; // deepest below here + + int n = children.size(); + //fprintf(stderr, "find_deepest_loops of a %s with %d children\n", getTypeString(), n); + for (int i=0; i subloops; // loops below here among a child of mine + + //fprintf(stderr, "child %d is a %s\n", i, children[i]->getTypeString()); + children[i]->find_deepest_loops( subloops ); + + if (subloops.size() > deepest.size()) { + deepest = subloops; + } + } + + // append deepest we see at this level to loops + for ( int i=0; igetSourceFile(); + fprintf(stderr, "UHOH, getSourceFile() called on node %p %s that does not have a parent and is not a source file\n", this, this->getTypeString()); + this->print(); printf("\n\n"); fflush(stdout); + exit(-1); + } + + virtual chillAST_node *findDatatype( char *t ) { + fprintf(stderr, "%s looking for datatype %s\n", getTypeString(), t); + if (parent != NULL) return parent->findDatatype(t); // most nodes do this + return NULL; + } + + + virtual chillAST_SymbolTable *addVariableToSymbolTable( chillAST_VarDecl *vd ) { + if (!parent) { + fprintf(stderr, "%s with no parent addVariableToSymbolTable()\n", getTypeString()); + exit(-1); + } + //fprintf(stderr, "%s::addVariableToSymbolTable() (default) headed up\n", getTypeString()); + return parent->addVariableToSymbolTable( vd ); // default, defer to parent + } + + virtual void addTypedefToTypedefTable( chillAST_TypedefDecl *tdd ) { + parent->addTypedefToTypedefTable( tdd ); // default, defer to parent + } + + void walk_parents() { + fprintf(stderr, "wp: (%s) ", getTypeString()); + print(); printf("\n"); fflush(stdout); + if (isSourceFile()) { fprintf(stderr, "(top sourcefile)\n\n"); return;} + + if (parent) parent->walk_parents(); + else fprintf(stderr, "UHOH, %s has no parent??\n", getTypeString()); + return; + } + + virtual chillAST_node *getEnclosingStatement( int level = 0 ); + virtual chillAST_VarDecl *multibase() { + fprintf(stderr,"(%s) forgot to implement multibase()\n", Chill_AST_Node_Names[asttype]); + exit(-1); + } + virtual chillAST_node *multibase2() { + fprintf(stderr,"(%s) forgot to implement multibase2()\n", Chill_AST_Node_Names[asttype]); + exit(-1); + } + + + virtual void gatherStatements( std::vector &statements ) { + fprintf(stderr,"(%s) forgot to implement gatherStatements()\n" ,Chill_AST_Node_Names[asttype]); + dump();fflush(stdout); + print(); + fprintf(stderr, "\n\n"); + } + + + virtual bool isSameAs( chillAST_node *other ){ // for tree comparison + fprintf(stderr,"(%s) forgot to implement isSameAs()\n" ,Chill_AST_Node_Names[asttype]); + dump(); fflush(stdout); + print(); + fprintf(stderr, "\n\n"); } + + void printPreprocBEFORE( int indent, FILE *fp ); + void printPreprocAFTER( int indent, FILE *fp ); + + + +}; + + +#endif + diff --git a/include/chillAST/chillASTs.hh b/include/chillAST/chillASTs.hh new file mode 100644 index 0000000..228cf3f --- /dev/null +++ b/include/chillAST/chillASTs.hh @@ -0,0 +1,1666 @@ + + +#ifndef _CHILLAST_ASTs_H_ +#define _CHILLAST_ASTs_H_ + +#include "chillAST_def.hh" +#include "chillAST_node.hh" + +class chillAST_NULL: public chillAST_node { // NOOP? +public: + chillAST_NULL(chillAST_node *p = NULL) { parent = p; asttype = CHILLAST_NODETYPE_NULL; }; + void print( int indent=0, FILE *fp = stderr ) { + chillindent( indent, fp ); + fprintf(fp, "/* (NULL statement); */ "); + fflush(fp); + } + void dump( int indent=0, FILE *fp = stderr ) { + chillindent( indent, fp ); + fprintf(fp, "(NULL statement) "); fflush(fp); + } +}; + + +class chillAST_Preprocessing: public chillAST_node { +public: + // variables that are special for this type of node + CHILL_PREPROCESSING_POSITION position; + CHILL_PREPROCESSING_TYPE pptype; + char *blurb; + + // constructors + chillAST_Preprocessing(); // not sure what this is good for + chillAST_Preprocessing( CHILL_PREPROCESSING_POSITION pos, CHILL_PREPROCESSING_TYPE t, char *text ); + + // other methods particular to this type of node + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + //void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc +}; + + +//typedef is a keyword in the C and C++ programming languages. The purpose of typedef is to assign alternative names to existing types, most often those whose standard declaration is cumbersome, potentially confusing, or likely to vary from one implementation to another. +class chillAST_TypedefDecl: public chillAST_node { +private: + bool isStruct; + bool isUnion; + char *structname; // get rid of this? + +public: + char *newtype; // the new type name ?? + char *underlyingtype; // float, int, "struct bubba" ? + char *arraypart; // string like "[1234][56]" ?? + + chillAST_RecordDecl *rd; // if it's a struct, point to the recorddecl ?? + // TODO what if "typedef int[10] tenints; " ?? + void setStructInfo( chillAST_RecordDecl *arrdee ) { rd = arrdee; }; + chillAST_RecordDecl * getStructDef(); + + + bool isAStruct() { return isStruct; }; + bool isAUnion() { return isUnion; }; + void setStruct(bool tf) { isStruct = tf; fprintf(stderr, "%s isStruct %d\n", structname, isStruct); }; + void setUnion( bool tf) { isUnion = tf; }; + void setStructName( const char *newname) { structname = strdup(newname); }; + char *getStructName( ) { return structname; }; + bool nameis( const char *n ) { return !strcmp(n, structname); }; + + // special for struct/unions rethink TODO + std::vector subparts; + chillAST_VarDecl *findSubpart( const char *name ); + + //TODO hide data, set/get type and alias + chillAST_TypedefDecl(); + chillAST_TypedefDecl(char *t, const char *nt, chillAST_node *p); + chillAST_TypedefDecl(char *t, const char *nt, char *a, chillAST_node *par); + + const char* getUnderlyingType() { fprintf(stderr, "TypedefDecl getUnderLyingType()\n"); return underlyingtype; }; + //virtual chillAST_VarDecl* getUnderlyingVarDecl() { return this; }; // ?? + + void dump( int indent=0, FILE *fp = stderr ) { + fprintf(fp, "(TypedefDecl %s %s %s)\n", underlyingtype, newtype, arraypart); }; + void print( int indent=0, FILE *fp = stderr ) ; + //void printString( std::string &s ); + +}; + + +class chillAST_VarDecl: public chillAST_node { +public: + char *vartype; // should probably be an enum, except it's used for unnamed structs too + + chillAST_RecordDecl *vardef;// the thing that says what the struct looks like + chillAST_TypedefDecl *typedefinition; // NULL for float, int, etc. + chillAST_RecordDecl * getStructDef(); // TODO make vardef private? + + //bool insideAStruct; // this variable is itself part of a struct + + char *underlyingtype; + char *varname; + char *arraypart; // [ 12 ] [ 34 ] if that is how it was defined + char *arraypointerpart; + char *arraysetpart; + void splitarraypart(); + + int numdimensions; + int *arraysizes; // TODO + bool knownArraySizes; // if this float *a or float a[128] ? true means we know ALL dimensions + int cudamallocsize; // usually specified in lua/python transformation file + + bool isRestrict; // C++ __restrict__ + bool isShared; // CUDA __shared__ + bool isDevice; // CUDA __device__ + bool isStruct; + + int isAParameter; + bool byreference; + void setByReference( bool tf ) { byreference = tf; fprintf(stderr, "byref %d\n", tf); }; + + bool isABuiltin; // if variable is builtin, we don't need to declare it + void *uniquePtr; // DO NOT REFERENCE THROUGH THIS! just used to differentiate declarations + bool isArray() { return (numdimensions != 0); }; + bool isAStruct() { return (isStruct || (typedefinition && typedefinition->isAStruct())); } + void setStruct( bool b ) {isStruct = b;/*fprintf(stderr,"vardecl %s IS A STRUCT\n",varname);*/ }; + bool isPointer() { return isArray() && !knownArraySizes; } // + + bool knowAllDimensions() { return knownArraySizes; } ; + + chillAST_node *init; + void setInit( chillAST_node *i ) { init = i; i->setParent(this); }; + bool hasInit() { return init != NULL; }; + chillAST_node *getInit() { return init; }; + + chillAST_VarDecl(); + chillAST_VarDecl( const char *t, const char *n, const char *a, chillAST_node *p); + chillAST_VarDecl( const char *t, const char *n, const char *a, void *ptr, chillAST_node *p); + chillAST_VarDecl( chillAST_TypedefDecl *tdd, const char *n, const char *arraypart, chillAST_node *par); + chillAST_VarDecl( chillAST_RecordDecl *astruct, const char *n, const char *arraypart, chillAST_node *par); + + void dump( int indent=0, FILE *fp = stderr ); + void print( int indent=0, FILE *fp = stderr ); + void printName( int indent=0, FILE *fp = stderr ); + bool isParmVarDecl() { return( isAParameter == 1 ); }; + bool isBuiltin() { return( isABuiltin == 1 ); }; // designate variable as a builtin + void setLocation( void *ptr ) { uniquePtr = ptr; } ; + + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + + void gatherVarUsage( std::vector &decls ) {}; // does nothing + void gatherDeclRefExprs( std::vector&refs ) {}; // does nothing + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) {}; + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + const char* getUnderlyingType() { /* fprintf(stderr, "VarDecl getUnderLyingType()\n"); */return underlyingtype; }; + virtual chillAST_VarDecl* getUnderlyingVarDecl() { return this; }; + + chillAST_node* constantFold(); + chillAST_node* clone(); + +}; + + +class chillAST_DeclRefExpr: public chillAST_node { +public: + // variables that are special for this type of node + char *declarationType; + char *declarationName; + chillAST_node *decl; // the declaration of this variable or function ... uhoh + //char *functionparameters; // TODO probably should split this node into 2 types, one for variables, one for functions + + // constructors + chillAST_DeclRefExpr(); + chillAST_DeclRefExpr( const char *variablename, chillAST_node *p); + chillAST_DeclRefExpr( const char *vartype, const char *variablename, chillAST_node *p); + chillAST_DeclRefExpr( const char *vartype, const char *variablename, chillAST_node *dec, chillAST_node *p); + chillAST_DeclRefExpr( chillAST_VarDecl *vd, chillAST_node *p=NULL); + chillAST_DeclRefExpr( chillAST_FunctionDecl *fd, chillAST_node *p=NULL); + + // other methods particular to this type of node + bool operator!=( chillAST_DeclRefExpr &other ) { return decl != other.decl ; }; + bool operator==( chillAST_DeclRefExpr &other ) { return decl == other.decl ; }; // EXACT SAME VARECL BY ADDRESS + + chillAST_node *getDecl() { return decl; }; + + chillAST_VarDecl *getVarDecl() { + if (!decl) return NULL; // should never happen + if (decl->isVarDecl()) return (chillAST_VarDecl *)decl; + return NULL; + }; + + chillAST_FunctionDecl *getFunctionDecl() { + if (!decl) return NULL; // should never happen + if (decl->isFunctionDecl()) return (chillAST_FunctionDecl *)decl; + return NULL; + }; + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE + void dump( int indent=0, FILE *fp = stderr ); // print ast + char *stringRep(int indent=0 ); + + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector &refs, bool writtento ) {}; // do nothing + void gatherScalarRefs( std::vector &refs, bool writtento ); + + // this is the AST node where these 2 differ + void gatherVarDecls ( std::vector &decls ) {}; // does nothing, to get the cvardecl using this method, the actual vardecl must be in the AST + void gatherVarDeclsMore ( std::vector &decls ); // returns the decl this declrefexpr references, even if the decl is not in the AST + + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + + void gatherVarUsage( std::vector &decls ); + void gatherDeclRefExprs( std::vector&refs ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + chillAST_node *findref(){return this;}// find the SINGLE constant or data reference at this node or below + + const char* getUnderlyingType() {fprintf(stderr, "DeclRefExpr getUnderLyingType()\n"); return decl->getUnderlyingType();}; + + virtual chillAST_VarDecl* getUnderlyingVarDecl() { return decl->getUnderlyingVarDecl(); } // functions?? TODO + + chillAST_VarDecl* multibase(); + chillAST_node *multibase2() { return (chillAST_node *)multibase(); } +}; + + + + + +class chillAST_CompoundStmt: public chillAST_node { +public: + // variables that are special for this type of node + chillAST_SymbolTable *symbol_table; // symbols defined inside this compound statement + chillAST_TypedefTable *typedef_table; + + bool hasSymbolTable() { return true; } ; + bool hasTypeDefTable() { return true; } ; + chillAST_node *findDatatype( char *t ) { + fprintf(stderr, "chillAST_CompoundStmt::findDatatype( %s )\n", t); + if (typedef_table) { + for (int i=0; i< typedef_table->size(); i++) { + chillAST_TypedefDecl *tdd = (*typedef_table)[i]; + if (tdd->nameis( t )) return tdd; + } + } + if (parent) return parent->findDatatype(t); + return NULL; // should not happen + } + + chillAST_SymbolTable *getSymbolTable() { return symbol_table; } + + chillAST_SymbolTable* addVariableToSymbolTable( chillAST_VarDecl *vd ) { // chillAST_CompoundStmt method + //fprintf(stderr, "\nchillAST_CompoundStmt addVariableToSymbolTable( %s )\n", vd->varname); + symbol_table = addSymbolToTable( symbol_table, vd ); + //printSymbolTable( symbol_table ); + return symbol_table; + } + + void addTypedefToTypedefTable( chillAST_TypedefDecl *tdd ) { + typedef_table = addTypedefToTable( typedef_table, tdd ); + } + + // constructors + chillAST_CompoundStmt(); // never has any args ??? + + // other methods particular to this type of node + + + // required methods + void replaceChild( chillAST_node *old, chillAST_node *newchild ); + void dump( int indent=0, FILE *fp = stderr ); + void print( int indent=0, FILE *fp = stderr ); + chillAST_node* constantFold(); + chillAST_node* clone(); + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + void gatherArrayRefs( std::vector &refs, bool writtento ); + void gatherScalarRefs( std::vector &refs, bool writtento ) ; + + void gatherVarUsage( std::vector &decls ); + void gatherDeclRefExprs( std::vector&refs ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ); + void loseLoopWithLoopVar( char *var ); // special case this for not for debugging + + void gatherStatements( std::vector &statements ); +}; + + + + +class chillAST_RecordDecl: public chillAST_node { // declaration of the shape of a struct or union +private: + char *name; // could be NULL? for unnamed structs? + char *originalname; + bool isStruct; + + bool isUnion; + std::vector subparts; + +public: + chillAST_RecordDecl(); + chillAST_RecordDecl( const char *nam, chillAST_node *p ); + chillAST_RecordDecl( const char *nam, const char *orig, chillAST_node *p ); + + void setName( const char *newname) { name = strdup(newname); }; + char *getName( ) { return name; }; + + bool isAUnion() { return isUnion; }; + bool isAStruct() { return isStruct; }; + bool isUnnamed; + void setUnnamed( bool b ) { isUnnamed = b; }; + + + void setStruct(bool tf) { isStruct = tf; }; + //fprintf(stderr, "%s isStruct %d\n", structname, isStruct); }; + void setUnion( bool tf) { isUnion = tf; }; + + chillAST_SymbolTable *addVariableToSymbolTable( chillAST_VarDecl *vd ); // RecordDecl does NOTHING + + int numSubparts() { return subparts.size(); }; + void addSubpart( chillAST_VarDecl *s ) { subparts.push_back(s); }; + chillAST_VarDecl *findSubpart( const char *name ); + chillAST_VarDecl *findSubpartByType( const char *typ ); + + void dump( int indent=0, FILE *fp = stderr ); + void print( int indent=0, FILE *fp = stderr ) ; + void printStructure( int indent=0, FILE *fp = stderr ) ; +}; + + + + +class chillAST_FunctionDecl: public chillAST_node { +private: + chillAST_CompoundStmt *body; // always a compound statement? + CHILL_FUNCTION_TYPE function_type; // CHILL_FUNCTION_CPU or CHILL_FUNCTION_GPU + bool externfunc; // function is external + bool builtin; // function is a builtin + bool forwarddecl; + +public: + char *returnType; + char *functionName; + + // parameters + int numParameters() { return parameters.size(); } ; + chillAST_SymbolTable parameters; + + // this is probably a mistake, but symbol_table here is pointing to BODY'S symbol table + //chillAST_SymbolTable *symbol_table; // symbols defined inside this function. REALLY the body's symbol table? + + chillAST_TypedefTable *typedef_table; // function typedef table + + + bool hasSymbolTable() { return true; } ; // COULD HAVE + bool hasTypeDefTable(){ return true; } ; // COULD HAVE + + + //char *parametertypes; // a single string?? + void printParameterTypes( FILE *fp ); + void setName( char *n ) { functionName = strdup(n); /* probable memory leak */ }; + + void setBuiltin() { builtin = true; } ; // designate function as a builtin + bool isBuiltin() { return builtin; } ; // report whether is a builtin + + void setExtern() { externfunc = true; }; // designate function as external + bool isExtern() { return externfunc; }; // report whether function is external + + void setForward() { forwarddecl = true; }; // designate function as fwd declaration + bool isForward() { return forwarddecl; }; // report whether function is external + + bool isFunctionCPU() { return( function_type == CHILL_FUNCTION_CPU ); }; + bool isFunctionGPU() { return( function_type == CHILL_FUNCTION_GPU ); }; + void setFunctionCPU() { function_type = CHILL_FUNCTION_CPU; }; + void setFunctionGPU() { function_type = CHILL_FUNCTION_GPU; }; + + void *uniquePtr; // DO NOT REFERENCE THROUGH THIS! USED AS A UNIQUE ID + + + + + chillAST_FunctionDecl(); // { asttype = CHILLAST_NODETYPE_FUNCTIONDECL; numparameters = 0;}; + chillAST_FunctionDecl(const char *rt, const char *fname, chillAST_node *p=NULL ) ; + chillAST_FunctionDecl(const char *rt, const char *fname, chillAST_node *p, void *unique ) ; + + void addParameter( chillAST_VarDecl *p); + chillAST_VarDecl *hasParameterNamed( const char *name ); + chillAST_VarDecl *findParameterNamed( const char *name ) { return hasParameterNamed( name ); }; + + void addDecl( chillAST_VarDecl *vd); // just adds to symbol table?? TODO + + chillAST_VarDecl *funcHasVariableNamed( const char *name ); // functiondecl::hasVariableNamed + //chillAST_VarDecl *findVariableNamed( const char *name ) { return hasVariableNamed( name ); }; + + void addChild(chillAST_node* node); // special because inserts into BODY + void insertChild(int i, chillAST_node* node); // special because inserts into BODY + + void setBody( chillAST_node * bod ); + chillAST_CompoundStmt *getBody() { return( body); } + + void print( int indent=0, FILE *fp = stderr ); // in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // in chill_ast.cc + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + chillAST_VarDecl *findArrayDecl( const char *name ); + //void gatherArrayRefs( std::vector &refs, bool writtento ); + //void gatherScalarRefs( std::vector &refs, bool writtento ) + + void gatherVarUsage( std::vector &decls ); + void gatherDeclRefExprs( std::vector&refs ); + void cleanUpVarDecls(); + + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ); + + chillAST_node* constantFold(); + + chillAST_node *findDatatype( char *t ) { + fprintf(stderr, "%s looking for datatype %s\n", getTypeString(), t); + if (!typedef_table) { // not here + if (parent) return parent->findDatatype(t); // not here, check parents + else return NULL; // not defined here and no parent + } + + //fprintf(stderr, "%d typedefs\n", typedef_table->size()); + for (int i=0; i< typedef_table->size(); i++) { + chillAST_TypedefDecl *tdd = (*typedef_table)[i]; + if ( tdd->nameis( t )) return tdd; + } + if (parent) return parent->findDatatype(t); + return NULL; // should not happen + } + + chillAST_SymbolTable *getParameterSymbolTable() { return ¶meters; } + chillAST_SymbolTable *getSymbolTable() { return body->getSymbolTable(); } //symbol_table; } // + void setSymbolTable( chillAST_SymbolTable *tab ) { + // no longer keeping a local ?? symbol_table = tab; + if (!body) { // can never happen now + body = new chillAST_CompoundStmt(); + } // only if func is empty! + body->symbol_table = tab; + } + + chillAST_SymbolTable* addVariableToSymbolTable( chillAST_VarDecl *vd ) { // chillAST_FunctionDecl method + //fprintf(stderr, "\nchillAST_FunctionDecl addVariableToSymbolTable( %s )\n", vd->varname); + + // this is all dealing with the body's symbol table + // the function has a symbol table called "parameters" but that is a special case + + addSymbolToTable( getSymbolTable(), vd ); + if (!vd->parent) { + //fprintf(stderr, "setting parent of vardecl to be the function whose symbol table it is going into\n"); // ?? + vd->setParent( this ); + insertChild(0,vd); + } + //printSymbolTable( getSymbolTable() ); + return getSymbolTable(); + } + + + void addTypedefToTypedefTable( chillAST_TypedefDecl *tdd ) { + typedef_table = addTypedefToTable( typedef_table, tdd ); + } + + void replaceChild( chillAST_node *old, chillAST_node *newchild ) { + body->replaceChild( old, newchild ); + } +}; // end FunctionDecl + + + + +class chillAST_SourceFile: public chillAST_node { +public: + + // constructors + chillAST_SourceFile(); // defined in chill_ast.cc + chillAST_SourceFile(const char *filename ); // defined in chill_ast.cc + + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void printToFile( char *filename = NULL ); + + char *SourceFileName; // where this originated + char *FileToWrite; + char *frontend; + + void setFileToWrite( char *f ) { FileToWrite = strdup( f ); }; + + void setFrontend( const char *compiler ) { if (frontend) free(frontend); frontend = strdup(compiler); } + // get, set filename ? + + chillAST_SymbolTable *global_symbol_table; // (global) symbols defined inside this source file + chillAST_TypedefTable *global_typedef_table; // source file + chillAST_VarDecl *findVariableNamed( const char *name ); // looks in global_symbol_table; + + bool hasSymbolTable() { return true; } ; // "has" vs "can have" TODO + bool hasTypeDefTable() { return true; } ; + + chillAST_SymbolTable* addVariableToSymbolTable( chillAST_VarDecl *vd ) { // chillAST_SourceFile method + fprintf(stderr, "\nchillAST_SourceFile addVariableToSymbolTable( %s )\n", vd->varname); + global_symbol_table = addSymbolToTable( global_symbol_table, vd ); + //addChild( vd ); // ?? + //printSymbolTable( global_symbol_table ); + return global_symbol_table; + } + + void addTypedefToTypedefTable( chillAST_TypedefDecl *tdd ) { + //fprintf(stderr, "SOURCEFILE adding typedef %s to typedeftable\n", tdd->getStructName()); + global_typedef_table = addTypedefToTable( global_typedef_table, tdd ); + //fprintf(stderr, "now global typedef table has %d entries\n", global_typedef_table->size()); + } + + chillAST_node *findDatatype( char *t ) { + fprintf(stderr, "%s looking for datatype %s\n", getTypeString(), t); + fprintf(stderr, "%d global typedefs\n", global_typedef_table->size()); + for (int i=0; i< global_typedef_table->size(); i++) { + + chillAST_TypedefDecl *tdd = (*global_typedef_table)[i]; + //fprintf(stderr, "comparing to %s\n", tdd->getStructName()); + if (tdd->nameis( t )) { + //fprintf(stderr, "found it\n"); + return (chillAST_node *)tdd; + } + } + return NULL; + } + + std::vector< chillAST_FunctionDecl *> functions; // at top level, or anywhere? + std::vector< chillAST_MacroDefinition *> macrodefinitions; + + chillAST_MacroDefinition* findMacro( const char *name ); // TODO ignores arguments + chillAST_FunctionDecl *findFunction( const char *name ); // TODO ignores arguments + chillAST_node *findCall( const char *name ); + void addMacro(chillAST_MacroDefinition* md) { + macrodefinitions.push_back(md); + //fprintf(stderr, "addMacro(), now %d macros\n", macrodefinitions.size()); + } + void addFunc(chillAST_FunctionDecl* fd) { + //fprintf(stderr, "chillAST_SourceFile::addFunc( %s %p)\n", fd->functionName, fd); + + bool already = false; + for (int i=0; ifunctionName, functions[i]); + if (functions[i] == fd) { + //fprintf(stderr, "function %s was already in source functions\n", fd->functionName); + already = true; + } + } + if (!already) functions.push_back(fd); + + // PROBABLY fd was created with sourcefile as its parent. Don't add it twice + addChild( (chillAST_node *)fd); } + +}; + +class chillAST_MacroDefinition: public chillAST_node { +private: + chillAST_node *body; // rhs always a compound statement? + chillAST_SymbolTable *symbol_table; +public: + char *macroName; + char *rhsString; + + // parameters - these will be odd, in that they HAVE NO TYPE + int numParameters() { return parameters.size(); } ; + std::vectorparameters; + + void setName( char *n ) { macroName = strdup(n); /* probable memory leak */ }; + void setRhsString( char *n ) { rhsString = strdup(n); /* probable memory leak */ }; + char *getRhsString() { return rhsString; } + + chillAST_MacroDefinition(); + chillAST_MacroDefinition( const char *name, chillAST_node *par); + chillAST_MacroDefinition( const char *name, const char *rhs, chillAST_node *par); + + void addParameter( chillAST_VarDecl *p); // parameters have no TYPE ?? + chillAST_VarDecl *hasParameterNamed( const char *name ); + chillAST_VarDecl *findParameterNamed( const char *name ) { return hasParameterNamed( name ); }; + void addChild(chillAST_node* node); // special because inserts into BODY + void insertChild(int i, chillAST_node* node); // special because inserts into BODY + + void setBody( chillAST_node * bod ); + chillAST_node *getBody() { return( body); } + + void print( int indent=0, FILE *fp = stderr ); // in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // in chill_ast.cc + + bool hasSymbolTable() { return true; } ; + + //const std::vector getSymbolTable() { return symbol_table; } + chillAST_SymbolTable *getSymbolTable() { return symbol_table; } + chillAST_SymbolTable* addVariableToSymbolTable( chillAST_VarDecl *vd ) { // chillAST_MacroDefinition method ?? + //fprintf(stderr, "\nchillAST_MacroDefinition addVariableToSymbolTable( %s )\n", vd->varname); + symbol_table = addSymbolToTable( symbol_table, vd ); + //printSymbolTable( symbol_table ); + return symbol_table; + } + + + chillAST_node* clone(); + + // none of these make sense for macros + void gatherVarDecls ( std::vector &decls ){}; + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ){}; + void gatherArrayVarDecls ( std::vector &decls ){}; + chillAST_VarDecl *findArrayDecl( const char *name ){}; + void gatherVarUsage( std::vector &decls ){}; + void gatherDeclRefExprs( std::vector&refs ){}; + void cleanUpVarDecls(); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){}; + chillAST_node* constantFold(){}; +}; + +class chillAST_ForStmt: public chillAST_node { +public: + // variables that are special for this type of node + chillAST_node *init; + chillAST_node *cond; + chillAST_node *incr; + chillAST_node *body; // always a compoundstmt? + IR_CONDITION_TYPE conditionoperator; // from ir_code.hh + + chillAST_SymbolTable *symbol_table; // symbols defined inside this forstmt (in init but not body?) body is compound stmt + bool hasSymbolTable() { return true; } ; + + // constructors + chillAST_ForStmt(); + chillAST_ForStmt( chillAST_node *ini, chillAST_node *con, chillAST_node *inc, chillAST_node *bod, chillAST_node *p); + + // other methods particular to this type of node + void addSyncs(); + void removeSyncComment(); + chillAST_node *getInit() { return init; }; + chillAST_node *getCond() { return cond; }; + chillAST_node *getInc() { return incr; }; + chillAST_node *getBody() { //fprintf(stderr, "chillAST_ForStmt::getBody(), returning a chillAST_node of type %s\n", body->getTypeString()); + return body; }; + void setBody( chillAST_node *b ) { body = b; b->parent = this; }; + + bool isNotLeaf() { return true; }; + bool isLeaf() { return false; }; + + + // required methods that I can't seem to get to inherit + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void printControl( int indent=0, FILE *fp = stderr ); // print just for ( ... ) but not body + + chillAST_node* constantFold(); + chillAST_node* clone(); + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + void gatherArrayRefs( std::vector &refs, bool writtento ); + void gatherScalarRefs( std::vector &refs, bool writtento ) ; + + void gatherVarUsage( std::vector &decls ); + void gatherDeclRefExprs( std::vector&refs ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); // will get called on inner loops + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ); + + void gatherLoopIndeces( std::vector &indeces ); + void gatherLoopVars( std::vector &loopvars ); // gather as strings ?? + + void get_deep_loops( std::vector &loops) { // chillAST_ForStmt version + // ADD MYSELF! + loops.push_back( this ); + + int n = body->children.size(); + //fprintf(stderr, "get_deep_loops of a %s with %d children\n", getTypeString(), n); + for (int i=0; ichildren[i]->getTypeString()); + body->children[i]->get_deep_loops( loops ); + } + //fprintf(stderr, "found %d deep loops\n", loops.size()); + } + + + void find_deepest_loops( std::vector &loops) { + std::vector b; // deepest loops below me + + int n = body->children.size(); + for (int i=0; i l; // deepest loops below one child + body->children[i]->find_deepest_loops( l ); + if ( l.size() > b.size() ) { // a deeper nesting than we've seen + b = l; + } + } + + loops.push_back( this ); // add myself + for (int i=0; ivarname); + symbol_table = addSymbolToTable( symbol_table, vd ); + //printSymbolTable( symbol_table ); + return symbol_table; + } + + void gatherStatements( std::vector &statements ); + bool lowerBound( int &l ); + bool upperBound( int &u ); + +}; + + + +class chillAST_TernaryOperator: public chillAST_node { +public: + // variables that are special for this type of node + char *op; // TODO need enum so far, only "?" conditional operator + chillAST_node *condition; + chillAST_node *lhs; // keep name from binary + chillAST_node *rhs; + + + // constructors + chillAST_TernaryOperator(); + chillAST_TernaryOperator(const char *op, chillAST_node *cond, chillAST_node *lhs, chillAST_node *rhs, chillAST_node *p=NULL); + + // other methods particular to this type of node + bool isNotLeaf() { return true; }; + bool isLeaf() { return false; }; + + + char *getOp() { return op; }; // dangerous. could get changed! + chillAST_node *getCond() { return condition; }; + chillAST_node *getRHS() { return rhs; }; + chillAST_node *getLHS() { return lhs; }; + + void setCond( chillAST_node *newc ) { condition = newc; newc->setParent( this ); } + void setLHS( chillAST_node *newlhs ) { lhs = newlhs; newlhs->setParent( this ); } + void setRHS( chillAST_node *newrhs ) { rhs = newrhs; newrhs->setParent( this ); } + + + + + // required methods that I can't seem to get to inherit + void dump( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void printonly( int indent=0, FILE *fp = stderr ); + + chillAST_node* constantFold(); + chillAST_node* clone(); + void replaceChild( chillAST_node *old, chillAST_node *newchild ) ; + void gatherArrayRefs( std::vector &refs, bool writtento ); + void gatherScalarRefs( std::vector &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + + void gatherVarUsage( std::vector &decls ); + void gatherDeclRefExprs( std::vector&refs ); + void gatherVarLHSUsage( std::vector &decls ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + void loseLoopWithLoopVar( char *var ){}; // ternop can't have loop as child? +}; + + + +class chillAST_BinaryOperator: public chillAST_node { +public: + // variables that are special for this type of node + char *op; // TODO need enum + chillAST_node *lhs; + chillAST_node *rhs; + + + // constructors + chillAST_BinaryOperator(); + chillAST_BinaryOperator(chillAST_node *lhs, const char *op, chillAST_node *rhs, chillAST_node *p=NULL); + + // other methods particular to this type of node + int evalAsInt(); + chillAST_IntegerLiteral *evalAsIntegerLiteral(); + + bool isNotLeaf() { return true; }; + bool isLeaf() { return false; }; + + chillAST_node *getRHS() { return rhs; }; + chillAST_node *getLHS() { return lhs; }; + void setLHS( chillAST_node *newlhs ) { lhs = newlhs; newlhs->setParent( this ); } + void setRHS( chillAST_node *newrhs ) { rhs = newrhs; newrhs->setParent( this ); } + + char *getOp() { return op; }; // dangerous. could get changed! + bool isAugmentedAssignmentOp() { + return + (!strcmp(op, "*=")) || // BO_MulAssign, + (!strcmp(op, "/=")) || // BO_DivAssign + (!strcmp(op, "%=")) || // BO_RemAssign + (!strcmp(op, "+=")) || // BO_AddAssign + (!strcmp(op, "-=")) || // BO_SubAssign + + (!strcmp(op, "<<=")) || // BO_ShlAssign + (!strcmp(op, ">>=")) || // BO_ShrAssign + (!strcmp(op, "&&=")) || // BO_AndAssign + (!strcmp(op, "||=")) || // BO_OrAssign + + (!strcmp(op, "^=")) // BO_XorAssign + ; + } + bool isAssignmentOp() { + return( (!strcmp(op, "=")) || // BO_Assign, + isAugmentedAssignmentOp() ); + }; + bool isComparisonOp() { return (!strcmp(op,"<")) || (!strcmp(op,">")) || (!strcmp(op,"<=")) || (!strcmp(op,">=")); }; + + bool isPlusOp() { return (!strcmp(op,"+")); }; + bool isMinusOp() { return (!strcmp(op,"-")); }; + bool isPlusMinusOp() { return (!strcmp(op,"+")) || (!strcmp(op,"-")); }; + bool isMultDivOp() { return (!strcmp(op,"*")) || (!strcmp(op,"/")); }; + + bool isStructOp() { return (!strcmp(op,".")) || (!strcmp(op,"->")); }; + + + // required methods that I can't seem to get to inherit + void dump( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void printonly( int indent=0, FILE *fp = stderr ); + char *stringRep(int indent=0 ); + + chillAST_node* constantFold(); + chillAST_node* clone(); + void replaceChild( chillAST_node *old, chillAST_node *newchild ) ; + void gatherArrayRefs( std::vector &refs, bool writtento ); // chillAST_BinaryOperator + void gatherScalarRefs( std::vector &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + + void gatherVarUsage( std::vector &decls ); + void gatherDeclRefExprs( std::vector&refs ); + void gatherVarLHSUsage( std::vector &decls ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + void loseLoopWithLoopVar( char *var ){}; // binop can't have loop as child? + + void gatherStatements( std::vector &statements ); // + + bool isSameAs( chillAST_node *other ); + +}; + + + + + + + + +class chillAST_ArraySubscriptExpr: public chillAST_node { +public: + // variables that are special for this type of node + chillAST_node *base; // always a decl ref expr? No, for multidimensional array, is another ASE + chillAST_node *index; + bool imwrittento; + bool imreadfrom; // WARNING: ONLY used when both writtento and readfrom are true x += 1 and so on + chillAST_VarDecl *basedecl; // the vardecl that this refers to + void *uniquePtr; // DO NOT REFERENCE THROUGH THIS! + + // constructors + chillAST_ArraySubscriptExpr(); + chillAST_ArraySubscriptExpr( chillAST_node *bas, chillAST_node *indx, chillAST_node *p, void *unique); + chillAST_ArraySubscriptExpr( chillAST_node *bas, chillAST_node *indx, bool writtento, chillAST_node *p, void *unique); + + chillAST_ArraySubscriptExpr( chillAST_VarDecl *v, std::vector indeces, chillAST_node *p); + + // other methods particular to this type of node + bool operator!=( const chillAST_ArraySubscriptExpr& ) ; + bool operator==( const chillAST_ArraySubscriptExpr& ) ; + chillAST_VarDecl *multibase(); // method for finding the basedecl + chillAST_node *multibase2() { return base->multibase2(); } + + chillAST_node *getIndex(int dim); + void gatherIndeces( std::vector< chillAST_node * > &ind ); + + void replaceChild( chillAST_node *old, chillAST_node *newchild ); // will examine index + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void printonly( int indent=0, FILE *fp = stderr ); + void print( int indent=0, FILE *fp = stderr ) const; // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + char *stringRep(int indent=0 ); + + chillAST_node* constantFold(); + chillAST_node* clone(); + chillAST_node *findref(){return this;}// find the SINGLE constant or data reference at this node or below + void gatherArrayRefs( std::vector &refs, bool writtento ); + void gatherScalarRefs( std::vector &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + + void gatherVarUsage( std::vector &decls ); + void gatherDeclRefExprs( std::vector&refs ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + + const char* getUnderlyingType() { + //fprintf(stderr, "ASE getUnderlyingType() base of type %s\n", base->getTypeString()); base->print(); printf("\n"); fflush(stderr); + return base->getUnderlyingType(); }; + + virtual chillAST_VarDecl* getUnderlyingVarDecl() { return base->getUnderlyingVarDecl(); }; + +}; + + + +class chillAST_MemberExpr: public chillAST_node { +public: + // variables that are special for this type of node + chillAST_node *base; // always a decl ref expr? No, can be Array Subscript Expr + char *member; + char *printstring; + + chillAST_VarDecl *basedecl; // the vardecl that this refers to + void *uniquePtr; // DO NOT REFERENCE THROUGH THIS! + + CHILL_MEMBER_EXP_TYPE exptype; + + + // constructors + chillAST_MemberExpr(); + chillAST_MemberExpr( chillAST_node *bas, const char *mem, chillAST_node *p, void *unique, CHILL_MEMBER_EXP_TYPE t=CHILL_MEMBER_EXP_DOT); + + // other methods particular to this type of node + bool operator!=( const chillAST_MemberExpr& ) ; + bool operator==( const chillAST_MemberExpr& ) ; + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void printonly( int indent=0, FILE *fp = stderr ); + void print( int indent=0, FILE *fp = stderr ) const; // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + char *stringRep( int indent = 0); + + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector &refs, bool writtento ); + void gatherScalarRefs( std::vector &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + + void gatherVarUsage( std::vector &decls ); + void gatherDeclRefExprs( std::vector&refs ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + + chillAST_VarDecl* getUnderlyingVarDecl(); + + void replaceChild( chillAST_node *old, chillAST_node *newchild ); + + void setType( CHILL_MEMBER_EXP_TYPE t ) { exptype = t; }; + CHILL_MEMBER_EXP_TYPE getType( CHILL_MEMBER_EXP_TYPE t ) { return exptype; }; + + chillAST_VarDecl* multibase(); // this one will return the member decl + chillAST_node* multibase2(); // this one will return the member expression +}; + + + + +class chillAST_IntegerLiteral: public chillAST_node { +public: + // variables that are special for this type of node + int value; + + // constructors + chillAST_IntegerLiteral(int val, chillAST_node *p = NULL); + + // other methods particular to this type of node + int evalAsInt() { return value; } + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector &refs, bool w ){}; // does nothing + void gatherScalarRefs( std::vector &refs, bool writtento ){}; // does nothing + + void gatherVarDecls ( std::vector &decls ){}; // does nothing + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ){}; // does nothing + void gatherArrayVarDecls ( std::vector &decls ){}; // does nothing + + void gatherVarUsage( std::vector &decls ) {}; // does nothing + void gatherDeclRefExprs( std::vector&refs ) {}; // does nothing + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) {}; + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + + chillAST_node *findref(){return this;}// find the SINGLE constant or data reference at this node or below +}; + + +class chillAST_FloatingLiteral: public chillAST_node { +public: + // variables that are special for this type of node + float value; + double doublevalue; + int float0double1; + + char *allthedigits; // if not NULL, use this as printable representation + int precision; // float == 1, double == 2, ??? + + // constructors + chillAST_FloatingLiteral( float val, chillAST_node *p); + chillAST_FloatingLiteral( double val, chillAST_node *p); + chillAST_FloatingLiteral( float val, int pre, chillAST_node *p); + chillAST_FloatingLiteral( double val, int pre, chillAST_node *p); + chillAST_FloatingLiteral( float val, const char *printable, chillAST_node *p); + chillAST_FloatingLiteral( float val, int pre, const char *printable, chillAST_node *p); + chillAST_FloatingLiteral( chillAST_FloatingLiteral *old ); + + // other methods particular to this type of node + void setPrecision( int precis ) { precision = precis; }; + int getPrecision() { return precision; } + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector &refs, bool w ){}; // does nothing + void gatherScalarRefs( std::vector &refs, bool writtento ){}; // does nothing + + void gatherVarDecls ( std::vector &decls ){}; // does nothing + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ){}; // does nothing ; + void gatherArrayVarDecls ( std::vector &decls ){}; // does nothing ; + + void gatherVarUsage( std::vector &decls ) {}; // does nothing + void gatherDeclRefExprs( std::vector&refs ){}; // does nothing + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){}; + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + chillAST_node *findref(){return this;};// find the SINGLE constant or data reference at this node or below + + bool isSameAs( chillAST_node *other ); +}; + + + + +class chillAST_UnaryOperator: public chillAST_node { +public: + // variables that are special for this type of node + char *op; // TODO enum + bool prefix; // or post + chillAST_node *subexpr; + + // constructors + chillAST_UnaryOperator( const char *oper, bool pre, chillAST_node *sub, chillAST_node *p ); + + // other methods particular to this type of node + bool isAssignmentOp() { + return( (!strcmp(op, "++")) || + (!strcmp(op, "--")) ); // are there more ??? TODO + } + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + void gatherArrayRefs( std::vector &refs, bool writtento ); // chillAST_UnaryOperator + + void gatherVarLHSUsage( std::vector &decls ); + + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + void gatherVarUsage( std::vector &decls ); + void gatherDeclRefExprs( std::vector&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + + int evalAsInt(); + bool isSameAs( chillAST_node *other ); + +}; + + + + + +class chillAST_ImplicitCastExpr: public chillAST_node { +public: + // variables that are special for this type of node + chillAST_node *subexpr; + + // constructors + chillAST_ImplicitCastExpr(chillAST_node *sub, chillAST_node *p); + + // other methods particular to this type of node + bool isNotLeaf() { return true; }; + bool isLeaf() { return false; }; + + // required methods that I can't seem to get to inherit + void replaceChild( chillAST_node *old, chillAST_node *newchild ); + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void printonly( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ) { print( indent, fp); }; // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector &refs, bool writtento ); + void gatherScalarRefs( std::vector &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + + void gatherVarUsage( std::vector &decls ); + void gatherDeclRefExprs( std::vector&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + chillAST_VarDecl *multibase(); // just recurse on subexpr + +}; + + + +class chillAST_CStyleCastExpr: public chillAST_node { +public: + // variables that are special for this type of node + char * towhat; + chillAST_node *subexpr; + // constructors + chillAST_CStyleCastExpr(const char *to, chillAST_node *sub, chillAST_node *p=NULL); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void replaceChild( chillAST_node *old, chillAST_node *newchild ); + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector &refs, bool writtento ); + void gatherScalarRefs( std::vector &refs, bool writtento ) ; + + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + + void gatherVarUsage( std::vector &decls ); + void gatherDeclRefExprs( std::vector&refs ); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + chillAST_node *findref(){return subexpr;};// find the SINGLE constant or data reference at this node or below + +}; + + +class chillAST_CStyleAddressOf: public chillAST_node { +public: + // variables that are special for this type of node + chillAST_node *subexpr; + // constructors + chillAST_CStyleAddressOf(chillAST_node *sub, chillAST_node *p=NULL); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector &refs, bool writtento ); + void gatherScalarRefs( std::vector &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + + void gatherVarUsage( std::vector &decls ); + void gatherDeclRefExprs( std::vector&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + + +}; + + +class chillAST_CudaMalloc:public chillAST_node { +public: + // variables that are special for this type of node + chillAST_node *devPtr; // Pointer to allocated device memory + chillAST_node *sizeinbytes; + + // constructors + chillAST_CudaMalloc(chillAST_node *devmemptr, chillAST_node *size, chillAST_node *p=NULL); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector &refs, bool writtento ); + void gatherScalarRefs( std::vector &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + + void gatherVarUsage( std::vector &decls ); + //void gatherDeclRefExprs( std::vector&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + +}; + + +class chillAST_CudaFree:public chillAST_node { +public: + // variables that are special for this type of node + chillAST_VarDecl *variable; + + // constructors + chillAST_CudaFree(chillAST_VarDecl *var, chillAST_node *p=NULL); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector &refs, bool writtento ); + void gatherScalarRefs( std::vector &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + + void gatherVarUsage( std::vector &decls ); + //void gatherDeclRefExprs( std::vector&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + +}; + + + + + +class chillAST_Malloc:public chillAST_node { // malloc( sizeof(int) * 2048 ); +public: + // variables that are special for this type of node + char *thing; // to void if this is null , sizeof(thing) if it is not + chillAST_node *sizeexpr; // bytes + + // constructors + chillAST_Malloc(chillAST_node *size, chillAST_node *p=NULL); + chillAST_Malloc(char *thething, chillAST_node *numthings, chillAST_node *p=NULL); // malloc (sizeof(int) *1024) + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector &refs, bool writtento ); + void gatherScalarRefs( std::vector &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + + void gatherVarUsage( std::vector &decls ); + //void gatherDeclRefExprs( std::vector&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + +}; + + + + +class chillAST_Free:public chillAST_node { +public: + + + + +}; + + + + +class chillAST_CudaMemcpy:public chillAST_node { +public: + // variables that are special for this type of node + chillAST_VarDecl *dest; // Pointer to allocated device memory + chillAST_VarDecl *src; + chillAST_node *size; + char *cudaMemcpyKind; // could use the actual enum + + // constructors + chillAST_CudaMemcpy(chillAST_VarDecl *d, chillAST_VarDecl *s, chillAST_node *size, char *kind, chillAST_node *p=NULL); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector &refs, bool writtento ); + void gatherScalarRefs( std::vector &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + + void gatherVarUsage( std::vector &decls ); + //void gatherDeclRefExprs( std::vector&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + +}; + + +class chillAST_CudaSyncthreads:public chillAST_node { +public: + // variables that are special for this type of node + + // constructors + chillAST_CudaSyncthreads(chillAST_node *p=NULL); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + //chillAST_node* constantFold() {}; + //chillAST_node* clone(); + //void gatherArrayRefs( std::vector &refs, bool writtento ){}; + //void gatherScalarRefs( std::vector &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector &decls ) {}; // does nothing + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ) {}; // does nothing + void gatherArrayVarDecls ( std::vector &decls ) {}; // does nothing + + void gatherVarUsage( std::vector &decls ) {}; // does nothing + //void gatherDeclRefExprs( std::vector&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + //bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; + +}; + + + +class chillAST_ReturnStmt: public chillAST_node { +public: + // variables that are special for this type of node + chillAST_node *returnvalue; + + // constructors + chillAST_ReturnStmt( chillAST_node *retval, chillAST_node *p ); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + + void gatherVarUsage( std::vector &decls ); + void gatherDeclRefExprs( std::vector&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + +}; + + + +class chillAST_CallExpr: public chillAST_node { // a function call +public: + // variables that are special for this type of node + chillAST_node *callee; // the function declaration (what about builtins?) + int numargs; + std::vector args; + chillAST_VarDecl *grid; + chillAST_VarDecl *block; + + // constructors + chillAST_CallExpr(chillAST_node *function, chillAST_node *p ); + void addArg( chillAST_node *newarg ); + + // other methods particular to this type of node + // TODO get/set grid, block + + // required methods that I can't seem to get to inherit + chillAST_node* constantFold(); + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + void gatherArrayRefs( std::vector &refs, bool writtento ); + void gatherScalarRefs( std::vector &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + + void gatherVarUsage( std::vector &decls ); + void gatherDeclRefExprs( std::vector&refs ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + chillAST_node* clone(); +}; + + + +class chillAST_ParenExpr: public chillAST_node { +public: + // variables that are special for this type of node + chillAST_node *subexpr; + + // constructors + chillAST_ParenExpr( chillAST_node *sub, chillAST_node *p=NULL ); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector &refs, bool writtento ); + void gatherScalarRefs( std::vector &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + + void gatherVarUsage( std::vector &decls ); + void gatherDeclRefExprs( std::vector&refs ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + +}; + + +class chillAST_Sizeof: public chillAST_node { +public: + // variables that are special for this type of node + char *thing; + + // constructors + chillAST_Sizeof( char *t, chillAST_node *p = NULL ); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector &refs, bool writtento ); + void gatherScalarRefs( std::vector &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + + void gatherVarUsage( std::vector &decls ); + void gatherDeclRefExprs( std::vector&refs ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){}; + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + +}; + + + +class chillAST_NoOp: public chillAST_node { +public: + chillAST_NoOp( chillAST_node *p = NULL ); // { parent = p; }; + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ) {}; // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ) {}; // print ast in chill_ast.cc + chillAST_node* constantFold() {}; + chillAST_node* clone() { return new chillAST_NoOp( parent ); }; // ?? + + void gatherArrayRefs( std::vector &refs, bool writtento ) {}; + void gatherScalarRefs( std::vector &refs, bool writtento ) {}; + + void gatherVarDecls ( std::vector &decls ){}; + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ){}; + void gatherArrayVarDecls ( std::vector &decls ){}; + + void gatherVarUsage( std::vector &decls ){}; + void gatherDeclRefExprs( std::vector&refs ){}; + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){}; + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; };//no loops under here +}; + + + +class chillAST_IfStmt: public chillAST_node { +public: + // variables that are special for this type of node + chillAST_node *cond; + chillAST_node *thenpart; + chillAST_node *elsepart; + IR_CONDITION_TYPE conditionoperator; // from ir_code.hh + + // constructors + chillAST_IfStmt(); + chillAST_IfStmt( chillAST_node *c, chillAST_node *t, chillAST_node *e, chillAST_node *p); + + // other methods particular to this type of node + chillAST_node *getCond() { return cond; }; + chillAST_node *getThen() { return thenpart; }; + chillAST_node *getElse() { return elsepart; }; + + void setCond( chillAST_node *b ) { cond = b; if (cond) cond->parent = this; }; + void setThen( chillAST_node *b ) { thenpart = b; if (thenpart) thenpart->parent = this; }; + void setElse( chillAST_node *b ) { elsepart = b; if (elsepart) elsepart->parent = this; }; + + // required methods that I can't seem to get to inherit + void dump( int indent=0, FILE *fp = stderr ); + void print( int indent=0, FILE *fp = stderr ); + + chillAST_node* constantFold(); + chillAST_node* clone(); + + void gatherVarDecls ( std::vector &decls ); + void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector &decls ); + void gatherArrayVarDecls ( std::vector &decls ); + void gatherArrayRefs( std::vector &refs, bool writtento ); + void gatherScalarRefs( std::vector &refs, bool writtento ) ; + + void gatherVarUsage( std::vector &decls ); + void gatherDeclRefExprs( std::vector&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ); + + void gatherStatements( std::vector &statements ); + +}; + + + + + + + + +class chillAST_something: public chillAST_node { +public: + // variables that are special for this type of node + + // constructors + chillAST_something(); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + //void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc +}; + + + + + + + +#endif + diff --git a/include/chill_ast.hh b/include/chill_ast.hh deleted file mode 100644 index 43eb106..0000000 --- a/include/chill_ast.hh +++ /dev/null @@ -1,2365 +0,0 @@ - - -#ifndef _CHILL_AST_H_ -#define _CHILL_AST_H_ - - -#define CHILL_INDENT_AMOUNT 2 - -#include -#include -#include -#include -#include -#include // std::vector - -#include // for IR_CONDITION_* - -char *parseUnderlyingType( char *sometype ); -char *parseArrayParts( char *sometype ); -bool isRestrict( const char *sometype ); -char *splitTypeInfo( char *underlyingtype ); -char *ulhack( char *brackets ); // change "1024UL" to "1024" -char *restricthack( char *typeinfo ); // remove __restrict__ , MODIFIES the argument! - - -enum CHILL_ASTNODE_TYPE { - CHILLAST_NODETYPE_UNKNOWN=0, - CHILLAST_NODETYPE_SOURCEFILE, - CHILLAST_NODETYPE_TYPEDEFDECL, - CHILLAST_NODETYPE_VARDECL, - // CHILLAST_NODETYPE_PARMVARDECL, not used any more - CHILLAST_NODETYPE_FUNCTIONDECL, - CHILLAST_NODETYPE_RECORDDECL, // struct or union (or class) - CHILLAST_NODETYPE_MACRODEFINITION, - CHILLAST_NODETYPE_COMPOUNDSTMT, - CHILLAST_NODETYPE_LOOP, // AKA ForStmt - CHILLAST_NODETYPE_TERNARYOPERATOR, - CHILLAST_NODETYPE_BINARYOPERATOR, - CHILLAST_NODETYPE_UNARYOPERATOR, - CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR, - CHILLAST_NODETYPE_MEMBEREXPR, // structs/unions - CHILLAST_NODETYPE_DECLREFEXPR, - CHILLAST_NODETYPE_INTEGERLITERAL, - CHILLAST_NODETYPE_FLOATINGLITERAL, - CHILLAST_NODETYPE_IMPLICITCASTEXPR, - CHILLAST_NODETYPE_RETURNSTMT, - CHILLAST_NODETYPE_CALLEXPR, - CHILLAST_NODETYPE_DECLSTMT, - CHILLAST_NODETYPE_PARENEXPR, - CHILLAST_NODETYPE_CSTYLECASTEXPR, - CHILLAST_NODETYPE_CSTYLEADDRESSOF, - CHILLAST_NODETYPE_IFSTMT, - CHILLAST_NODETYPE_SIZEOF, - CHILLAST_NODETYPE_MALLOC, - CHILLAST_NODETYPE_FREE, - CHILLAST_NODETYPE_PREPROCESSING, // comments, #define, #include, whatever else works - CHILLAST_NODETYPE_NOOP, // NO OP - // CUDA specific - CHILLAST_NODETYPE_CUDAMALLOC, - CHILLAST_NODETYPE_CUDAFREE, - CHILLAST_NODETYPE_CUDAMEMCPY, - CHILLAST_NODETYPE_CUDAKERNELCALL, - CHILLAST_NODETYPE_CUDASYNCTHREADS, - CHILLAST_NODETYPE_NULL // explicit non-statement - // TODO - -} ; - -#define CHILLAST_NODETYPE_FORSTMT CHILLAST_NODETYPE_LOOP -#define CHILLAST_NODETYPE_TRANSLATIONUNIT CHILLAST_NODETYPE_SOURCEFILE - -enum CHILL_FUNCTION_TYPE { - CHILL_FUNCTION_CPU = 0, - CHILL_FUNCTION_GPU -}; - -enum CHILL_MEMBER_EXP_TYPE { - CHILL_MEMBER_EXP_DOT = 0, - CHILL_MEMBER_EXP_ARROW -}; - -enum CHILL_PREPROCESSING_TYPE { - CHILL_PREPROCESSING_TYPEUNKNOWN = 0, - CHILL_PREPROCESSING_COMMENT, - CHILL_PREPROCESSING_POUNDDEFINE, - CHILL_PREPROCESSING_POUNDINCLUDE, - CHILL_PREPROCESSING_PRAGMA // unused so far -}; - -enum CHILL_PREPROCESSING_POSITION { // when tied to another statement - CHILL_PREPROCESSING_POSITIONUNKNOWN = 0, - CHILL_PREPROCESSING_LINEBEFORE, // previous line - CHILL_PREPROCESSING_LINEAFTER, // next line - CHILL_PREPROCESSING_TOTHERIGHT, // for this kind of comment, on same line - CHILL_PREPROCESSING_IMMEDIATELYBEFORE // on same line -}; - - - - - -extern const char* Chill_AST_Node_Names[]; // WARNING MUST BE KEPT IN SYNC WITH BELOW LIST - - -// fwd declarations -class chillAST_node; // the generic node. specific types derive from this -class chillAST_NULL; // empty -class chillAST_SourceFile; // ast for an entire source file (translationunit) - -class chillAST_TypedefDecl; -class chillAST_VarDecl; -//class chillAST_ParmVarDecl; -class chillAST_FunctionDecl; -class chillAST_RecordDecl; // structs and unions (and classes?) -class chillAST_MacroDefinition; -class chillAST_CompoundStmt; // just a bunch of other statements -class chillAST_ForStmt; // AKA a LOOP -class chillAST_TernaryOperator; -class chillAST_BinaryOperator; -class chillAST_ArraySubscriptExpr; -class chillAST_MemberExpr; -class chillAST_DeclRefExpr; -class chillAST_IntegerLiteral; -class chillAST_FloatingLiteral; -class chillAST_UnaryOperator; -class chillAST_ImplicitCastExpr; -class chillAST_CStyleCastExpr; -class chillAST_CStyleAddressOf; -class chillAST_ReturnStmt; -class chillAST_CallExpr; -class chillAST_ParenExpr; -class chillAST_Sizeof; -class chillAST_Malloc; -class chillAST_Free; -class chillAST_NoOp; -class chillAST_CudaMalloc; -class chillAST_CudaFree; -class chillAST_CudaMemcpy; -class chillAST_CudaKernelCall; -class chillAST_CudaSyncthreads; -class chillAST_Preprocessing; - -typedef std::vector chillAST_SymbolTable; // typedef -typedef std::vector chillAST_TypedefTable; // typedef - -bool symbolTableHasVariableNamed( chillAST_SymbolTable *table, const char *name ); // fwd decl -chillAST_VarDecl *symbolTableFindVariableNamed( chillAST_SymbolTable *table, const char *name ); // fwd decl TODO too many similar named functions - -void printSymbolTable( chillAST_SymbolTable *st ); // fwd decl -void printSymbolTableMoreInfo( chillAST_SymbolTable *st ); // fwd decl - - -chillAST_node *lessthanmacro( chillAST_node *left, chillAST_node *right); // fwd declaration -chillAST_SymbolTable *addSymbolToTable( chillAST_SymbolTable *st, chillAST_VarDecl *vd ); // fwd decl -chillAST_TypedefTable *addTypedefToTable( chillAST_TypedefTable *tt, chillAST_TypedefDecl *td ); // fwd decl - - -bool streq( const char *a, const char *b); // fwd decl -void chillindent( int i, FILE *fp ); // fwd declaration -void insertNewDeclAtLocationOfOldIfNeeded( chillAST_VarDecl *newdecl, chillAST_VarDecl *olddecl); - -chillAST_DeclRefExpr *buildDeclRefExpr( chillAST_VarDecl *); - - - - - - -// an actual chill ast. -// nodes based on clang AST which are in turn based on C++ - -class chillAST_node { // generic node. a tree of these is the AST. this is virtual (can't instantiate) -public: - - static int chill_scalar_counter; // for manufactured scalars - static int chill_array_counter ; // for manufactured arrays - static int chill_pointer_counter ; // for manufactured arrays - - - CHILL_ASTNODE_TYPE asttype; - - bool isSourceFile() { return (asttype == CHILLAST_NODETYPE_SOURCEFILE); }; - bool isTypeDefDecl() { return (asttype == CHILLAST_NODETYPE_TYPEDEFDECL); }; - bool isVarDecl() { return (asttype == CHILLAST_NODETYPE_VARDECL); }; - bool isFunctionDecl() { return (asttype == CHILLAST_NODETYPE_FUNCTIONDECL); }; - bool isRecordDecl() { return (asttype == CHILLAST_NODETYPE_RECORDDECL); }; - bool isMacroDefinition() { return (asttype == CHILLAST_NODETYPE_MACRODEFINITION); }; - bool isCompoundStmt() { return (asttype == CHILLAST_NODETYPE_COMPOUNDSTMT); }; - bool isLoop() { return (asttype == CHILLAST_NODETYPE_LOOP); }; // AKA ForStmt - bool isForStmt() { return (asttype == CHILLAST_NODETYPE_LOOP); }; // AKA Loop - bool isIfStmt() { return (asttype == CHILLAST_NODETYPE_IFSTMT); }; - bool isTernaryOperator() { return (asttype == CHILLAST_NODETYPE_TERNARYOPERATOR);}; - bool isBinaryOperator() { return (asttype == CHILLAST_NODETYPE_BINARYOPERATOR); }; - bool isUnaryOperator() { return (asttype == CHILLAST_NODETYPE_UNARYOPERATOR); }; - bool isArraySubscriptExpr() { return (asttype == CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR); }; - bool isMemberExpr() { return (asttype == CHILLAST_NODETYPE_MEMBEREXPR); }; - bool isDeclRefExpr() { return (asttype == CHILLAST_NODETYPE_DECLREFEXPR); }; - bool isIntegerLiteral() { return (asttype == CHILLAST_NODETYPE_INTEGERLITERAL); }; - bool isFloatingLiteral() { return (asttype == CHILLAST_NODETYPE_FLOATINGLITERAL); }; - bool isImplicitCastExpr() { return (asttype == CHILLAST_NODETYPE_IMPLICITCASTEXPR); }; - bool isReturnStmt() { return (asttype == CHILLAST_NODETYPE_RETURNSTMT); }; - bool isCallExpr() { return (asttype == CHILLAST_NODETYPE_CALLEXPR); }; - bool isParenExpr() { return (asttype == CHILLAST_NODETYPE_PARENEXPR); }; - bool isSizeof() { return (asttype == CHILLAST_NODETYPE_SIZEOF); }; - bool isMalloc() { return (asttype == CHILLAST_NODETYPE_MALLOC); }; - bool isFree() { return (asttype == CHILLAST_NODETYPE_FREE); }; - bool isPreprocessing() { return (asttype == CHILLAST_NODETYPE_PREPROCESSING); }; - bool isNoOp() { return (asttype == CHILLAST_NODETYPE_NOOP); }; - bool isNull() { return (asttype == CHILLAST_NODETYPE_NULL); }; - bool isCStyleCastExpr() { return (asttype == CHILLAST_NODETYPE_CSTYLECASTEXPR); }; - bool isCStyleAddressOf() { return (asttype == CHILLAST_NODETYPE_CSTYLEADDRESSOF); }; - bool isCudaMalloc() { return (asttype == CHILLAST_NODETYPE_CUDAMALLOC); }; - bool isCudaFree() { return (asttype == CHILLAST_NODETYPE_CUDAFREE); }; - bool isCudaMemcpy() { return (asttype == CHILLAST_NODETYPE_CUDAMEMCPY); }; - bool isCudaKERNELCALL() { return (asttype == CHILLAST_NODETYPE_CUDAKERNELCALL); }; - bool isCudaSYNCTHREADS() { return (asttype == CHILLAST_NODETYPE_CUDASYNCTHREADS); }; - - bool isDeclStmt() { return (asttype == CHILLAST_NODETYPE_DECLSTMT); }; // doesn't exist - - bool isConstant() { return (asttype == CHILLAST_NODETYPE_INTEGERLITERAL) || (asttype == CHILLAST_NODETYPE_FLOATINGLITERAL); } - - - virtual bool isAssignmentOp() { return false; }; - virtual bool isComparisonOp() { return false; }; - virtual bool isNotLeaf() { return false; }; - virtual bool isLeaf() { return true; }; - virtual bool isParmVarDecl() { return false; }; - - virtual bool isPlusOp() { return false; }; - virtual bool isMinusOp() { return false; }; - virtual bool isPlusMinusOp() { return false; }; - virtual bool isMultDivOp() { return false; }; - - virtual bool isAStruct() { return false; }; - virtual bool isAUnion() { return false; }; - - virtual bool hasSymbolTable() { return false; } ; // most nodes do NOT have a symbol table - virtual bool hasTypedefTable() { return false; } ; // most nodes do NOT have a typedef table - virtual chillAST_SymbolTable *getSymbolTable() { return NULL; } // most nodes do NOT have a symbol table - - virtual chillAST_VarDecl *findVariableNamed( const char *name ); // recursive - - chillAST_RecordDecl *findRecordDeclNamed( const char *name ); // recursive - - // void addDecl( chillAST_VarDecl *vd); // recursive, adds to first symbol table it can find - - // TODO decide how to hide some data - chillAST_node *parent; - bool isFromSourceFile; // false = #included - char *filename; // file this node is from - - void segfault() { fprintf(stderr, "segfaulting on purpose\n"); int *i=0; int j = i[0]; }; // seg fault - int getNumChildren() { return children.size(); }; - std::vector children; - std::vector getChildren() { return children; } ; // not usually useful - void setChildren( std::vector&c ) { children = c; } ; // does not set parent. probably should - chillAST_node *getChild( int which) { return children[which]; }; - void setChild( int which, chillAST_node *n ) { children[which] = n; children[which]->parent = this; } ; - - char *metacomment; // for compiler internals, formerly a comment - void setMetaComment( char *c ) { metacomment = strdup(c); }; - - std::vector preprocessinginfo; - - virtual void addChild( chillAST_node* c) { - //if (c->isFunctionDecl()) fprintf(stderr, "addchild FunctionDecl\n"); - c->parent = this; - // check to see if it's already there - for (int i=0; igetTypeString(), i); - node->parent = this; - children.insert( children.begin()+i, node ); - }; - - virtual void removeChild(int i) { - children.erase( children.begin()+i ); - }; - - int findChild( chillAST_node *c ) { - for (int i=0; isetParent( this ); - return; - } - } - fprintf(stderr, "%s %p generic replaceChild called with oldchild that was not a child\n", - getTypeString(), this) ; - fprintf(stderr, "printing\n"); - print(); fprintf(stderr, "\nchild: "); - if (!old) fprintf(stderr, "oldchild NULL!\n"); - old->print(); fprintf(stderr, "\nnew: "); - newchild->print(); fprintf(stderr, "\n"); - segfault(); // make easier for gdb - }; - - virtual void loseLoopWithLoopVar( char *var ) { - // walk tree. If a loop has this loop variable, replace the loop with the loop body, - // removing the loop. The loop will be spread across a bunch of cores that will each - // calculate their own loop variable. - - // things that can not have loops as substatements can have a null version of this method - // things that have more complicated sets of "children" will have specialized versions - - // this is the generic version of the method. It just recurses among its children. - // ForStmt is the only one that can actually remove itself. When it does, it will - // potentially change the children vector, which is not the simple array it might appear. - // so you have to make a copy of the vector to traverse - - std::vector dupe = children; // simple enough? - //fprintf(stderr, "node XXX has %d children\n", dupe.size()); - //fprintf(stderr, "generic node %s has %d children\n", getTypeString(), dupe.size()); - for (int i=0; iloseLoopWithLoopVar( var ); - } - } - - virtual int evalAsInt() { - fprintf(stderr,"(%s) can't be evaluated as an integer??\n", Chill_AST_Node_Names[asttype]); - print(); fprintf(stderr, "\n"); - segfault(); - } - - virtual const char* getUnderlyingType() { - fprintf(stderr,"(%s) forgot to implement getUnderlyingType()\n", Chill_AST_Node_Names[asttype]); - dump(); - print(); - fprintf(stderr, "\n\n"); - segfault(); - }; - - virtual chillAST_VarDecl* getUnderlyingVarDecl() { - fprintf(stderr,"(%s) forgot to implement getUnderlyingVarDecl()\n", Chill_AST_Node_Names[asttype]); - dump(); - print(); - fprintf(stderr, "\n\n"); - segfault(); - }; - - - virtual chillAST_node *findref(){// find the SINGLE constant or data reference at this node or below - fprintf(stderr,"(%s) forgot to implement findref()\n" ,Chill_AST_Node_Names[asttype]); - dump(); - print(); - fprintf(stderr, "\n\n"); - segfault(); - }; - - virtual void gatherArrayRefs( std::vector &refs, bool writtento ) { - fprintf(stderr,"(%s) forgot to implement gatherArrayRefs()\n" ,Chill_AST_Node_Names[asttype]); - dump(); - print(); - fprintf(stderr, "\n\n"); - }; - - // TODO we MIGHT want the VarDecl // NOTHING IMPLEMENTS THIS? ??? - virtual void gatherScalarRefs( std::vector &refs, bool writtento ) { - fprintf(stderr,"(%s) forgot to implement gatherScalarRefs()\n" ,Chill_AST_Node_Names[asttype]); - dump(); - print(); - fprintf(stderr, "\n\n"); - }; - - virtual void gatherLoopIndeces( std::vector &indeces ) { // recursive walk parent links, looking for loops, and grabbing the declRefExpr in the loop init and cond. - // you can quit when you get to certain nodes - - //fprintf(stderr, "%s::gatherLoopIndeces()\n", getTypeString()); - - if (isSourceFile() || isFunctionDecl() ) return; // end of the line - - // just for debugging - //if (parent) { - // fprintf(stderr, "%s has parent of type %s\n", getTypeString(), parent->getTypeString()); - //} - //else fprintf(stderr, "this %s %p has no parent???\n", getTypeString(), this); - - - if (!parent) return; // should not happen, but be careful - - // for most nodes, this just recurses upwards - //fprintf(stderr, "%s::gatherLoopIndeces() %p recursing up\n", this); - parent->gatherLoopIndeces( indeces ); - } - - - chillAST_ForStmt* findContainingLoop() { // recursive walk parent links, looking for loops - //fprintf(stderr, "%s::findContainingLoop() ", getTypeString()); - //if (parent) fprintf(stderr, "parents is a %s\n", parent->getTypeString()); - //else fprintf(stderr, "no parent\n"); - // do not check SELF type, as we may want to find the loop containing a loop - if (!parent) return NULL; - if (parent->isForStmt()) return (chillAST_ForStmt*)parent; - return parent->findContainingLoop(); // recurse upwards - } - - chillAST_node* findContainingNonLoop() { // recursive walk parent links, avoiding loops - fprintf(stderr, "%s::findContainingNonLoop() ", getTypeString()); - //if (parent) fprintf(stderr, "parent is a %s\n", parent->getTypeString()); - //else fprintf(stderr, "no parent\n"); - // do not check SELF type, as we may want to find the loop containing a loop - if (!parent) return NULL; - if (parent->isCompoundStmt() && parent->getParent()->isForStmt()) return parent->getParent()->findContainingNonLoop(); // keep recursing - if (parent->isForStmt()) return parent->findContainingNonLoop(); // keep recursing - return (chillAST_node*)parent; // return non-loop - } - - // TODO gather loop init and cond (and if cond) like gatherloopindeces - - virtual void gatherDeclRefExprs( std::vector&refs ){ // both scalar and arrays - fprintf(stderr,"(%s) forgot to implement gatherDeclRefExpr()\n" ,Chill_AST_Node_Names[asttype]); - }; - - - - virtual void gatherVarUsage( std::vector &decls ) { - fprintf(stderr,"(%s) forgot to implement gatherVarUsage()\n" ,Chill_AST_Node_Names[asttype]); - }; - - virtual void gatherVarLHSUsage( std::vector &decls ) { - fprintf(stderr,"(%s) forgot to implement gatherVarLHSUsage()\n" ,Chill_AST_Node_Names[asttype]); - }; - - - virtual void gatherVarDecls( std::vector &decls ) { // ACTUAL Declaration - fprintf(stderr,"(%s) forgot to implement gatherVarDecls()\n" ,Chill_AST_Node_Names[asttype]); - }; - - - virtual void gatherVarDeclsMore( std::vector &decls ) { // even if the decl itself is not in the ast. - fprintf(stderr,"(%s) forgot to implement gatherVarDeclsMore()\n" ,Chill_AST_Node_Names[asttype]); - }; - - virtual void gatherScalarVarDecls( std::vector &decls ) { // ACTUAL Declaration - fprintf(stderr,"(%s) forgot to implement gatherScalarVarDecls()\n" ,Chill_AST_Node_Names[asttype]); - }; - - virtual void gatherArrayVarDecls( std::vector &decls ) { // ACTUAL Declaration - fprintf(stderr,"(%s) forgot to implement gatherArrayVarDecls()\n" ,Chill_AST_Node_Names[asttype]); - }; - - virtual chillAST_VarDecl *findArrayDecl( const char *name ) { // scoping TODO - if (!hasSymbolTable()) return parent->findArrayDecl( name ); // most things - else - fprintf(stderr,"(%s) forgot to implement gatherArrayVarDecls()\n" ,Chill_AST_Node_Names[asttype]); - } - - - virtual void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) { - fprintf(stderr,"(%s) forgot to implement replaceVarDecls()\n" ,Chill_AST_Node_Names[asttype]); - }; - - virtual bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ) { - // this just looks for ForStmts with preferred index metacomment attached - fprintf(stderr,"(%s) forgot to implement findLoopIndexesToReplace()\n" ,Chill_AST_Node_Names[asttype]); - return false; - } - - - virtual chillAST_node* constantFold() { // hacky. TODO. make nice - fprintf(stderr,"(%s) forgot to implement constantFold()\n" ,Chill_AST_Node_Names[asttype]); - exit(-1); ; - }; - - virtual chillAST_node* clone() { // makes a deep COPY (?) - fprintf(stderr,"(%s) forgot to implement clone()\n" ,Chill_AST_Node_Names[asttype]); - exit(-1); ; - }; - virtual void dump( int indent=0, FILE *fp = stderr ) { - fflush(fp); - fprintf(fp,"(%s) forgot to implement dump()\n" ,Chill_AST_Node_Names[asttype]); };// print ast - - virtual void print( int indent=0, FILE *fp = stderr ) { - fflush(fp); - //fprintf(stderr, "generic chillAST_node::print() called!\n"); - //fprintf(stderr, "asttype is %d\n", asttype); - fprintf(fp, "\n"); - chillindent(indent, fp); - fprintf(fp,"(%s) forgot to implement print()\n" ,Chill_AST_Node_Names[asttype]); - };// print CODE - - virtual void printName( int indent=0, FILE *fp = stderr ) { - fflush(fp); - //fprintf(stderr, "generic chillAST_node::printName() called!\n"); - //fprintf(stderr, "asttype is %d\n", asttype); - fprintf(fp, "\n"); - chillindent(indent, fp); - fprintf(fp,"(%s) forgot to implement printName()\n" ,Chill_AST_Node_Names[asttype]); - };// print CODE - - virtual char *stringRep(int indent=0 ) { // the ast's print version - fflush(stdout); - // chillindent(indent, fp); TODO - fprintf(stderr,"(%s) forgot to implement stringRep()\n" ,Chill_AST_Node_Names[asttype]); - segfault(); - } - - - virtual void printonly( int indent=0, FILE *fp = stderr ) { print( indent, fp); }; - - //virtual void printString( std::string &s ) { - // fprintf(stderr,"(%s) forgot to implement printString()\n" ,Chill_AST_Node_Names[asttype]); - //} - - - virtual void get_top_level_loops( std::vector &loops) { - int n = children.size(); - //fprintf(stderr, "get_top_level_loops of a %s with %d children\n", getTypeString(), n); - for (int i=0; igetTypeString()); - if (children[i]->isForStmt()) { - loops.push_back( ((chillAST_ForStmt *)(children[i])) ); - } - } - //fprintf(stderr, "found %d top level loops\n", loops.size()); - } - - - virtual void repairParentChild() { // for nodes where all subnodes are children - int n = children.size(); - for (int i=0; iparent != this) { - fprintf(stderr, "fixing child %s that didn't know its parent\n", children[i]->getTypeString()); - children[i]->parent = this; - } - } - } - - - - virtual void get_deep_loops( std::vector &loops) { // this is probably broken - returns ALL loops under it - int n = children.size(); - //fprintf(stderr, "get_deep_loops of a %s with %d children\n", getTypeString(), n); - for (int i=0; igetTypeString()); - children[i]->get_deep_loops( loops ); - } - //fprintf(stderr, "found %d deep loops\n", loops.size()); - } - - - // generic for chillAST_node with children - virtual void find_deepest_loops( std::vector &loops) { // returns DEEPEST nesting of loops - std::vectordeepest; // deepest below here - - int n = children.size(); - //fprintf(stderr, "find_deepest_loops of a %s with %d children\n", getTypeString(), n); - for (int i=0; i subloops; // loops below here among a child of mine - - //fprintf(stderr, "child %d is a %s\n", i, children[i]->getTypeString()); - children[i]->find_deepest_loops( subloops ); - - if (subloops.size() > deepest.size()) { - deepest = subloops; - } - } - - // append deepest we see at this level to loops - for ( int i=0; igetSourceFile(); - fprintf(stderr, "UHOH, getSourceFile() called on node %p %s that does not have a parent and is not a source file\n", this, this->getTypeString()); - this->print(); printf("\n\n"); fflush(stdout); - exit(-1); - } - - virtual chillAST_node *findDatatype( char *t ) { - fprintf(stderr, "%s looking for datatype %s\n", getTypeString(), t); - if (parent != NULL) return parent->findDatatype(t); // most nodes do this - return NULL; - } - - - virtual chillAST_SymbolTable *addVariableToSymbolTable( chillAST_VarDecl *vd ) { - if (!parent) { - fprintf(stderr, "%s with no parent addVariableToSymbolTable()\n", getTypeString()); - exit(-1); - } - //fprintf(stderr, "%s::addVariableToSymbolTable() (default) headed up\n", getTypeString()); - return parent->addVariableToSymbolTable( vd ); // default, defer to parent - } - - virtual void addTypedefToTypedefTable( chillAST_TypedefDecl *tdd ) { - parent->addTypedefToTypedefTable( tdd ); // default, defer to parent - } - - void walk_parents() { - fprintf(stderr, "wp: (%s) ", getTypeString()); - print(); printf("\n"); fflush(stdout); - if (isSourceFile()) { fprintf(stderr, "(top sourcefile)\n\n"); return;} - - if (parent) parent->walk_parents(); - else fprintf(stderr, "UHOH, %s has no parent??\n", getTypeString()); - return; - } - - virtual chillAST_node *getEnclosingStatement( int level = 0 ); - virtual chillAST_VarDecl *multibase() { - fprintf(stderr,"(%s) forgot to implement multibase()\n", Chill_AST_Node_Names[asttype]); - exit(-1); - } - virtual chillAST_node *multibase2() { - fprintf(stderr,"(%s) forgot to implement multibase2()\n", Chill_AST_Node_Names[asttype]); - exit(-1); - } - - - virtual void gatherStatements( std::vector &statements ) { - fprintf(stderr,"(%s) forgot to implement gatherStatements()\n" ,Chill_AST_Node_Names[asttype]); - dump();fflush(stdout); - print(); - fprintf(stderr, "\n\n"); - } - - - virtual bool isSameAs( chillAST_node *other ){ // for tree comparison - fprintf(stderr,"(%s) forgot to implement isSameAs()\n" ,Chill_AST_Node_Names[asttype]); - dump(); fflush(stdout); - print(); - fprintf(stderr, "\n\n"); } - - void printPreprocBEFORE( int indent, FILE *fp ); - void printPreprocAFTER( int indent, FILE *fp ); - - - -}; - -class chillAST_NULL: public chillAST_node { // NOOP? -public: - chillAST_NULL(chillAST_node *p = NULL) { parent = p; asttype = CHILLAST_NODETYPE_NULL; }; - void print( int indent=0, FILE *fp = stderr ) { - chillindent( indent, fp ); - fprintf(fp, "/* (NULL statement); */ "); - fflush(fp); - } - void dump( int indent=0, FILE *fp = stderr ) { - chillindent( indent, fp ); - fprintf(fp, "(NULL statement) "); fflush(fp); - } -}; - - -class chillAST_Preprocessing: public chillAST_node { -public: - // variables that are special for this type of node - CHILL_PREPROCESSING_POSITION position; - CHILL_PREPROCESSING_TYPE pptype; - char *blurb; - - // constructors - chillAST_Preprocessing(); // not sure what this is good for - chillAST_Preprocessing( CHILL_PREPROCESSING_POSITION pos, CHILL_PREPROCESSING_TYPE t, char *text ); - - // other methods particular to this type of node - - // required methods that I can't seem to get to inherit - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - //void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc -}; - - -//typedef is a keyword in the C and C++ programming languages. The purpose of typedef is to assign alternative names to existing types, most often those whose standard declaration is cumbersome, potentially confusing, or likely to vary from one implementation to another. -class chillAST_TypedefDecl: public chillAST_node { -private: - bool isStruct; - bool isUnion; - char *structname; // get rid of this? - -public: - char *newtype; // the new type name ?? - char *underlyingtype; // float, int, "struct bubba" ? - char *arraypart; // string like "[1234][56]" ?? - - chillAST_RecordDecl *rd; // if it's a struct, point to the recorddecl ?? - // TODO what if "typedef int[10] tenints; " ?? - void setStructInfo( chillAST_RecordDecl *arrdee ) { rd = arrdee; }; - chillAST_RecordDecl * getStructDef(); - - - bool isAStruct() { return isStruct; }; - bool isAUnion() { return isUnion; }; - void setStruct(bool tf) { isStruct = tf; fprintf(stderr, "%s isStruct %d\n", structname, isStruct); }; - void setUnion( bool tf) { isUnion = tf; }; - void setStructName( const char *newname) { structname = strdup(newname); }; - char *getStructName( ) { return structname; }; - bool nameis( const char *n ) { return !strcmp(n, structname); }; - - // special for struct/unions rethink TODO - std::vector subparts; - chillAST_VarDecl *findSubpart( const char *name ); - - //TODO hide data, set/get type and alias - chillAST_TypedefDecl(); - chillAST_TypedefDecl(char *t, const char *nt, chillAST_node *p); - chillAST_TypedefDecl(char *t, const char *nt, char *a, chillAST_node *par); - - const char* getUnderlyingType() { fprintf(stderr, "TypedefDecl getUnderLyingType()\n"); return underlyingtype; }; - //virtual chillAST_VarDecl* getUnderlyingVarDecl() { return this; }; // ?? - - void dump( int indent=0, FILE *fp = stderr ) { - fprintf(fp, "(TypedefDecl %s %s %s)\n", underlyingtype, newtype, arraypart); }; - void print( int indent=0, FILE *fp = stderr ) ; - //void printString( std::string &s ); - -}; - - -class chillAST_VarDecl: public chillAST_node { -public: - char *vartype; // should probably be an enum, except it's used for unnamed structs too - - chillAST_RecordDecl *vardef;// the thing that says what the struct looks like - chillAST_TypedefDecl *typedefinition; // NULL for float, int, etc. - chillAST_RecordDecl * getStructDef(); // TODO make vardef private? - - //bool insideAStruct; // this variable is itself part of a struct - - char *underlyingtype; - char *varname; - char *arraypart; // [ 12 ] [ 34 ] if that is how it was defined - char *arraypointerpart; - char *arraysetpart; - void splitarraypart(); - - int numdimensions; - int *arraysizes; // TODO - bool knownArraySizes; // if this float *a or float a[128] ? true means we know ALL dimensions - int cudamallocsize; // usually specified in lua/python transformation file - - bool isRestrict; // C++ __restrict__ - bool isShared; // CUDA __shared__ - bool isDevice; // CUDA __device__ - bool isStruct; - - int isAParameter; - bool byreference; - void setByReference( bool tf ) { byreference = tf; fprintf(stderr, "byref %d\n", tf); }; - - bool isABuiltin; // if variable is builtin, we don't need to declare it - void *uniquePtr; // DO NOT REFERENCE THROUGH THIS! just used to differentiate declarations - bool isArray() { return (numdimensions != 0); }; - bool isAStruct() { return (isStruct || (typedefinition && typedefinition->isAStruct())); } - void setStruct( bool b ) {isStruct = b;/*fprintf(stderr,"vardecl %s IS A STRUCT\n",varname);*/ }; - bool isPointer() { return isArray() && !knownArraySizes; } // - - bool knowAllDimensions() { return knownArraySizes; } ; - - chillAST_node *init; - void setInit( chillAST_node *i ) { init = i; i->setParent(this); }; - bool hasInit() { return init != NULL; }; - chillAST_node *getInit() { return init; }; - - chillAST_VarDecl(); - chillAST_VarDecl( const char *t, const char *n, const char *a, chillAST_node *p); - chillAST_VarDecl( const char *t, const char *n, const char *a, void *ptr, chillAST_node *p); - chillAST_VarDecl( chillAST_TypedefDecl *tdd, const char *n, const char *arraypart, chillAST_node *par); - chillAST_VarDecl( chillAST_RecordDecl *astruct, const char *n, const char *arraypart, chillAST_node *par); - - void dump( int indent=0, FILE *fp = stderr ); - void print( int indent=0, FILE *fp = stderr ); - void printName( int indent=0, FILE *fp = stderr ); - bool isParmVarDecl() { return( isAParameter == 1 ); }; - bool isBuiltin() { return( isABuiltin == 1 ); }; // designate variable as a builtin - void setLocation( void *ptr ) { uniquePtr = ptr; } ; - - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - - void gatherVarUsage( std::vector &decls ) {}; // does nothing - void gatherDeclRefExprs( std::vector&refs ) {}; // does nothing - void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) {}; - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - const char* getUnderlyingType() { /* fprintf(stderr, "VarDecl getUnderLyingType()\n"); */return underlyingtype; }; - virtual chillAST_VarDecl* getUnderlyingVarDecl() { return this; }; - - chillAST_node* constantFold(); - chillAST_node* clone(); - -}; - - -class chillAST_DeclRefExpr: public chillAST_node { -public: - // variables that are special for this type of node - char *declarationType; - char *declarationName; - chillAST_node *decl; // the declaration of this variable or function ... uhoh - //char *functionparameters; // TODO probably should split this node into 2 types, one for variables, one for functions - - // constructors - chillAST_DeclRefExpr(); - chillAST_DeclRefExpr( const char *variablename, chillAST_node *p); - chillAST_DeclRefExpr( const char *vartype, const char *variablename, chillAST_node *p); - chillAST_DeclRefExpr( const char *vartype, const char *variablename, chillAST_node *dec, chillAST_node *p); - chillAST_DeclRefExpr( chillAST_VarDecl *vd, chillAST_node *p=NULL); - chillAST_DeclRefExpr( chillAST_FunctionDecl *fd, chillAST_node *p=NULL); - - // other methods particular to this type of node - bool operator!=( chillAST_DeclRefExpr &other ) { return decl != other.decl ; }; - bool operator==( chillAST_DeclRefExpr &other ) { return decl == other.decl ; }; // EXACT SAME VARECL BY ADDRESS - - chillAST_node *getDecl() { return decl; }; - - chillAST_VarDecl *getVarDecl() { - if (!decl) return NULL; // should never happen - if (decl->isVarDecl()) return (chillAST_VarDecl *)decl; - return NULL; - }; - - chillAST_FunctionDecl *getFunctionDecl() { - if (!decl) return NULL; // should never happen - if (decl->isFunctionDecl()) return (chillAST_FunctionDecl *)decl; - return NULL; - }; - - // required methods that I can't seem to get to inherit - void print( int indent=0, FILE *fp = stderr ); // print CODE - void dump( int indent=0, FILE *fp = stderr ); // print ast - char *stringRep(int indent=0 ); - - chillAST_node* constantFold(); - chillAST_node* clone(); - void gatherArrayRefs( std::vector &refs, bool writtento ) {}; // do nothing - void gatherScalarRefs( std::vector &refs, bool writtento ); - - // this is the AST node where these 2 differ - void gatherVarDecls ( std::vector &decls ) {}; // does nothing, to get the cvardecl using this method, the actual vardecl must be in the AST - void gatherVarDeclsMore ( std::vector &decls ); // returns the decl this declrefexpr references, even if the decl is not in the AST - - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - - void gatherVarUsage( std::vector &decls ); - void gatherDeclRefExprs( std::vector&refs ); - void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - chillAST_node *findref(){return this;}// find the SINGLE constant or data reference at this node or below - - const char* getUnderlyingType() {fprintf(stderr, "DeclRefExpr getUnderLyingType()\n"); return decl->getUnderlyingType();}; - - virtual chillAST_VarDecl* getUnderlyingVarDecl() { return decl->getUnderlyingVarDecl(); } // functions?? TODO - - chillAST_VarDecl* multibase(); - chillAST_node *multibase2() { return (chillAST_node *)multibase(); } -}; - - - - - -class chillAST_CompoundStmt: public chillAST_node { -public: - // variables that are special for this type of node - chillAST_SymbolTable *symbol_table; // symbols defined inside this compound statement - chillAST_TypedefTable *typedef_table; - - bool hasSymbolTable() { return true; } ; - bool hasTypeDefTable() { return true; } ; - chillAST_node *findDatatype( char *t ) { - fprintf(stderr, "chillAST_CompoundStmt::findDatatype( %s )\n", t); - if (typedef_table) { - for (int i=0; i< typedef_table->size(); i++) { - chillAST_TypedefDecl *tdd = (*typedef_table)[i]; - if (tdd->nameis( t )) return tdd; - } - } - if (parent) return parent->findDatatype(t); - return NULL; // should not happen - } - - chillAST_SymbolTable *getSymbolTable() { return symbol_table; } - - chillAST_SymbolTable* addVariableToSymbolTable( chillAST_VarDecl *vd ) { // chillAST_CompoundStmt method - //fprintf(stderr, "\nchillAST_CompoundStmt addVariableToSymbolTable( %s )\n", vd->varname); - symbol_table = addSymbolToTable( symbol_table, vd ); - //printSymbolTable( symbol_table ); - return symbol_table; - } - - void addTypedefToTypedefTable( chillAST_TypedefDecl *tdd ) { - typedef_table = addTypedefToTable( typedef_table, tdd ); - } - - // constructors - chillAST_CompoundStmt(); // never has any args ??? - - // other methods particular to this type of node - - - // required methods - void replaceChild( chillAST_node *old, chillAST_node *newchild ); - void dump( int indent=0, FILE *fp = stderr ); - void print( int indent=0, FILE *fp = stderr ); - chillAST_node* constantFold(); - chillAST_node* clone(); - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - void gatherArrayRefs( std::vector &refs, bool writtento ); - void gatherScalarRefs( std::vector &refs, bool writtento ) ; - - void gatherVarUsage( std::vector &decls ); - void gatherDeclRefExprs( std::vector&refs ); - void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ); - void loseLoopWithLoopVar( char *var ); // special case this for not for debugging - - void gatherStatements( std::vector &statements ); -}; - - - - -class chillAST_RecordDecl: public chillAST_node { // declaration of the shape of a struct or union -private: - char *name; // could be NULL? for unnamed structs? - char *originalname; - bool isStruct; - - bool isUnion; - std::vector subparts; - -public: - chillAST_RecordDecl(); - chillAST_RecordDecl( const char *nam, chillAST_node *p ); - chillAST_RecordDecl( const char *nam, const char *orig, chillAST_node *p ); - - void setName( const char *newname) { name = strdup(newname); }; - char *getName( ) { return name; }; - - bool isAUnion() { return isUnion; }; - bool isAStruct() { return isStruct; }; - bool isUnnamed; - void setUnnamed( bool b ) { isUnnamed = b; }; - - - void setStruct(bool tf) { isStruct = tf; }; - //fprintf(stderr, "%s isStruct %d\n", structname, isStruct); }; - void setUnion( bool tf) { isUnion = tf; }; - - chillAST_SymbolTable *addVariableToSymbolTable( chillAST_VarDecl *vd ); // RecordDecl does NOTHING - - int numSubparts() { return subparts.size(); }; - void addSubpart( chillAST_VarDecl *s ) { subparts.push_back(s); }; - chillAST_VarDecl *findSubpart( const char *name ); - chillAST_VarDecl *findSubpartByType( const char *typ ); - - void dump( int indent=0, FILE *fp = stderr ); - void print( int indent=0, FILE *fp = stderr ) ; - void printStructure( int indent=0, FILE *fp = stderr ) ; -}; - - - - -class chillAST_FunctionDecl: public chillAST_node { -private: - chillAST_CompoundStmt *body; // always a compound statement? - CHILL_FUNCTION_TYPE function_type; // CHILL_FUNCTION_CPU or CHILL_FUNCTION_GPU - bool externfunc; // function is external - bool builtin; // function is a builtin - bool forwarddecl; - -public: - char *returnType; - char *functionName; - - // parameters - int numParameters() { return parameters.size(); } ; - chillAST_SymbolTable parameters; - - // this is probably a mistake, but symbol_table here is pointing to BODY'S symbol table - //chillAST_SymbolTable *symbol_table; // symbols defined inside this function. REALLY the body's symbol table? - - chillAST_TypedefTable *typedef_table; // function typedef table - - - bool hasSymbolTable() { return true; } ; // COULD HAVE - bool hasTypeDefTable(){ return true; } ; // COULD HAVE - - - //char *parametertypes; // a single string?? - void printParameterTypes( FILE *fp ); - void setName( char *n ) { functionName = strdup(n); /* probable memory leak */ }; - - void setBuiltin() { builtin = true; } ; // designate function as a builtin - bool isBuiltin() { return builtin; } ; // report whether is a builtin - - void setExtern() { externfunc = true; }; // designate function as external - bool isExtern() { return externfunc; }; // report whether function is external - - void setForward() { forwarddecl = true; }; // designate function as fwd declaration - bool isForward() { return forwarddecl; }; // report whether function is external - - bool isFunctionCPU() { return( function_type == CHILL_FUNCTION_CPU ); }; - bool isFunctionGPU() { return( function_type == CHILL_FUNCTION_GPU ); }; - void setFunctionCPU() { function_type = CHILL_FUNCTION_CPU; }; - void setFunctionGPU() { function_type = CHILL_FUNCTION_GPU; }; - - void *uniquePtr; // DO NOT REFERENCE THROUGH THIS! USED AS A UNIQUE ID - - - - - chillAST_FunctionDecl(); // { asttype = CHILLAST_NODETYPE_FUNCTIONDECL; numparameters = 0;}; - chillAST_FunctionDecl(const char *rt, const char *fname, chillAST_node *p=NULL ) ; - chillAST_FunctionDecl(const char *rt, const char *fname, chillAST_node *p, void *unique ) ; - - void addParameter( chillAST_VarDecl *p); - chillAST_VarDecl *hasParameterNamed( const char *name ); - chillAST_VarDecl *findParameterNamed( const char *name ) { return hasParameterNamed( name ); }; - - void addDecl( chillAST_VarDecl *vd); // just adds to symbol table?? TODO - - chillAST_VarDecl *funcHasVariableNamed( const char *name ); // functiondecl::hasVariableNamed - //chillAST_VarDecl *findVariableNamed( const char *name ) { return hasVariableNamed( name ); }; - - void addChild(chillAST_node* node); // special because inserts into BODY - void insertChild(int i, chillAST_node* node); // special because inserts into BODY - - void setBody( chillAST_node * bod ); - chillAST_CompoundStmt *getBody() { return( body); } - - void print( int indent=0, FILE *fp = stderr ); // in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ); // in chill_ast.cc - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - chillAST_VarDecl *findArrayDecl( const char *name ); - //void gatherArrayRefs( std::vector &refs, bool writtento ); - //void gatherScalarRefs( std::vector &refs, bool writtento ) - - void gatherVarUsage( std::vector &decls ); - void gatherDeclRefExprs( std::vector&refs ); - void cleanUpVarDecls(); - - //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ); - - chillAST_node* constantFold(); - - chillAST_node *findDatatype( char *t ) { - fprintf(stderr, "%s looking for datatype %s\n", getTypeString(), t); - if (!typedef_table) { // not here - if (parent) return parent->findDatatype(t); // not here, check parents - else return NULL; // not defined here and no parent - } - - //fprintf(stderr, "%d typedefs\n", typedef_table->size()); - for (int i=0; i< typedef_table->size(); i++) { - chillAST_TypedefDecl *tdd = (*typedef_table)[i]; - if ( tdd->nameis( t )) return tdd; - } - if (parent) return parent->findDatatype(t); - return NULL; // should not happen - } - - chillAST_SymbolTable *getParameterSymbolTable() { return ¶meters; } - chillAST_SymbolTable *getSymbolTable() { return body->getSymbolTable(); } //symbol_table; } // - void setSymbolTable( chillAST_SymbolTable *tab ) { - // no longer keeping a local ?? symbol_table = tab; - if (!body) { // can never happen now - body = new chillAST_CompoundStmt(); - } // only if func is empty! - body->symbol_table = tab; - } - - chillAST_SymbolTable* addVariableToSymbolTable( chillAST_VarDecl *vd ) { // chillAST_FunctionDecl method - //fprintf(stderr, "\nchillAST_FunctionDecl addVariableToSymbolTable( %s )\n", vd->varname); - - // this is all dealing with the body's symbol table - // the function has a symbol table called "parameters" but that is a special case - - addSymbolToTable( getSymbolTable(), vd ); - if (!vd->parent) { - //fprintf(stderr, "setting parent of vardecl to be the function whose symbol table it is going into\n"); // ?? - vd->setParent( this ); - insertChild(0,vd); - } - //printSymbolTable( getSymbolTable() ); - return getSymbolTable(); - } - - - void addTypedefToTypedefTable( chillAST_TypedefDecl *tdd ) { - typedef_table = addTypedefToTable( typedef_table, tdd ); - } - - void replaceChild( chillAST_node *old, chillAST_node *newchild ) { - body->replaceChild( old, newchild ); - } -}; // end FunctionDecl - - - - -class chillAST_SourceFile: public chillAST_node { -public: - - // constructors - chillAST_SourceFile(); // defined in chill_ast.cc - chillAST_SourceFile(const char *filename ); // defined in chill_ast.cc - - void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void printToFile( char *filename = NULL ); - - char *SourceFileName; // where this originated - char *FileToWrite; - char *frontend; - - void setFileToWrite( char *f ) { FileToWrite = strdup( f ); }; - - void setFrontend( const char *compiler ) { if (frontend) free(frontend); frontend = strdup(compiler); } - // get, set filename ? - - chillAST_SymbolTable *global_symbol_table; // (global) symbols defined inside this source file - chillAST_TypedefTable *global_typedef_table; // source file - chillAST_VarDecl *findVariableNamed( const char *name ); // looks in global_symbol_table; - - bool hasSymbolTable() { return true; } ; // "has" vs "can have" TODO - bool hasTypeDefTable() { return true; } ; - - chillAST_SymbolTable* addVariableToSymbolTable( chillAST_VarDecl *vd ) { // chillAST_SourceFile method - fprintf(stderr, "\nchillAST_SourceFile addVariableToSymbolTable( %s )\n", vd->varname); - global_symbol_table = addSymbolToTable( global_symbol_table, vd ); - //addChild( vd ); // ?? - //printSymbolTable( global_symbol_table ); - return global_symbol_table; - } - - void addTypedefToTypedefTable( chillAST_TypedefDecl *tdd ) { - //fprintf(stderr, "SOURCEFILE adding typedef %s to typedeftable\n", tdd->getStructName()); - global_typedef_table = addTypedefToTable( global_typedef_table, tdd ); - //fprintf(stderr, "now global typedef table has %d entries\n", global_typedef_table->size()); - } - - chillAST_node *findDatatype( char *t ) { - fprintf(stderr, "%s looking for datatype %s\n", getTypeString(), t); - fprintf(stderr, "%d global typedefs\n", global_typedef_table->size()); - for (int i=0; i< global_typedef_table->size(); i++) { - - chillAST_TypedefDecl *tdd = (*global_typedef_table)[i]; - //fprintf(stderr, "comparing to %s\n", tdd->getStructName()); - if (tdd->nameis( t )) { - //fprintf(stderr, "found it\n"); - return (chillAST_node *)tdd; - } - } - return NULL; - } - - std::vector< chillAST_FunctionDecl *> functions; // at top level, or anywhere? - std::vector< chillAST_MacroDefinition *> macrodefinitions; - - chillAST_MacroDefinition* findMacro( const char *name ); // TODO ignores arguments - chillAST_FunctionDecl *findFunction( const char *name ); // TODO ignores arguments - chillAST_node *findCall( const char *name ); - void addMacro(chillAST_MacroDefinition* md) { - macrodefinitions.push_back(md); - //fprintf(stderr, "addMacro(), now %d macros\n", macrodefinitions.size()); - } - void addFunc(chillAST_FunctionDecl* fd) { - //fprintf(stderr, "chillAST_SourceFile::addFunc( %s %p)\n", fd->functionName, fd); - - bool already = false; - for (int i=0; ifunctionName, functions[i]); - if (functions[i] == fd) { - //fprintf(stderr, "function %s was already in source functions\n", fd->functionName); - already = true; - } - } - if (!already) functions.push_back(fd); - - // PROBABLY fd was created with sourcefile as its parent. Don't add it twice - addChild( (chillAST_node *)fd); } - -}; - - -/* - class chillAST_VarDecl: public chillAST_node { // now a SINGLE DECL. multiples in - public: - int howmany; // usually 1 but sometimes multiple declarations in a decl; - std::vector decls; - - chillAST_VarDecl(); - chillAST_VarDecl( char *t, char *n, char *a); - void addDecl( char *t, char *n, char *a); - - void dump( int indent=0, FILE *fp = stderr ); - void print( int indent=0, FILE *fp = stderr ); - }; -*/ - - -/* -class chillAST_ParmVarDecl: public chillAST_node { // no longer used? -public: - char *vartype; // should probably be an enum - char *varname; - char *arraypart; - int numdimensions; // TODO - int *arraysizes; // TODO - // hasDefaultArg - // getDefaultArg - - chillAST_ParmVarDecl(); - chillAST_ParmVarDecl( const char *type, const char *name, const char *ap, chillAST_node *p ); - - void dump( int indent=0, FILE *fp = stderr ) { - fprintf(fp, "(2VarDecl'%s' '%s' '%s')", vartype, varname, arraypart); }; - void print( int indent=0, FILE *fp = stderr ); -}; -*/ - - - -class chillAST_MacroDefinition: public chillAST_node { -private: - chillAST_node *body; // rhs always a compound statement? - chillAST_SymbolTable *symbol_table; -public: - char *macroName; - char *rhsString; - - // parameters - these will be odd, in that they HAVE NO TYPE - int numParameters() { return parameters.size(); } ; - std::vectorparameters; - - void setName( char *n ) { macroName = strdup(n); /* probable memory leak */ }; - void setRhsString( char *n ) { rhsString = strdup(n); /* probable memory leak */ }; - char *getRhsString() { return rhsString; } - - chillAST_MacroDefinition(); - chillAST_MacroDefinition( const char *name, chillAST_node *par); - chillAST_MacroDefinition( const char *name, const char *rhs, chillAST_node *par); - - void addParameter( chillAST_VarDecl *p); // parameters have no TYPE ?? - chillAST_VarDecl *hasParameterNamed( const char *name ); - chillAST_VarDecl *findParameterNamed( const char *name ) { return hasParameterNamed( name ); }; - void addChild(chillAST_node* node); // special because inserts into BODY - void insertChild(int i, chillAST_node* node); // special because inserts into BODY - - void setBody( chillAST_node * bod ); - chillAST_node *getBody() { return( body); } - - void print( int indent=0, FILE *fp = stderr ); // in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ); // in chill_ast.cc - - bool hasSymbolTable() { return true; } ; - - //const std::vector getSymbolTable() { return symbol_table; } - chillAST_SymbolTable *getSymbolTable() { return symbol_table; } - chillAST_SymbolTable* addVariableToSymbolTable( chillAST_VarDecl *vd ) { // chillAST_MacroDefinition method ?? - //fprintf(stderr, "\nchillAST_MacroDefinition addVariableToSymbolTable( %s )\n", vd->varname); - symbol_table = addSymbolToTable( symbol_table, vd ); - //printSymbolTable( symbol_table ); - return symbol_table; - } - - - chillAST_node* clone(); - - // none of these make sense for macros - void gatherVarDecls ( std::vector &decls ){}; - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ){}; - void gatherArrayVarDecls ( std::vector &decls ){}; - chillAST_VarDecl *findArrayDecl( const char *name ){}; - void gatherVarUsage( std::vector &decls ){}; - void gatherDeclRefExprs( std::vector&refs ){}; - void cleanUpVarDecls(); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){}; - chillAST_node* constantFold(){}; -}; - - - - - - -class chillAST_ForStmt: public chillAST_node { -public: - // variables that are special for this type of node - chillAST_node *init; - chillAST_node *cond; - chillAST_node *incr; - chillAST_node *body; // always a compoundstmt? - IR_CONDITION_TYPE conditionoperator; // from ir_code.hh - - chillAST_SymbolTable *symbol_table; // symbols defined inside this forstmt (in init but not body?) body is compound stmt - bool hasSymbolTable() { return true; } ; - - // constructors - chillAST_ForStmt(); - chillAST_ForStmt( chillAST_node *ini, chillAST_node *con, chillAST_node *inc, chillAST_node *bod, chillAST_node *p); - - // other methods particular to this type of node - void addSyncs(); - void removeSyncComment(); - chillAST_node *getInit() { return init; }; - chillAST_node *getCond() { return cond; }; - chillAST_node *getInc() { return incr; }; - chillAST_node *getBody() { //fprintf(stderr, "chillAST_ForStmt::getBody(), returning a chillAST_node of type %s\n", body->getTypeString()); - return body; }; - void setBody( chillAST_node *b ) { body = b; b->parent = this; }; - - bool isNotLeaf() { return true; }; - bool isLeaf() { return false; }; - - - // required methods that I can't seem to get to inherit - void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void printControl( int indent=0, FILE *fp = stderr ); // print just for ( ... ) but not body - - chillAST_node* constantFold(); - chillAST_node* clone(); - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - void gatherArrayRefs( std::vector &refs, bool writtento ); - void gatherScalarRefs( std::vector &refs, bool writtento ) ; - - void gatherVarUsage( std::vector &decls ); - void gatherDeclRefExprs( std::vector&refs ); - void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); // will get called on inner loops - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ); - - void gatherLoopIndeces( std::vector &indeces ); - void gatherLoopVars( std::vector &loopvars ); // gather as strings ?? - - void get_deep_loops( std::vector &loops) { // chillAST_ForStmt version - // ADD MYSELF! - loops.push_back( this ); - - int n = body->children.size(); - //fprintf(stderr, "get_deep_loops of a %s with %d children\n", getTypeString(), n); - for (int i=0; ichildren[i]->getTypeString()); - body->children[i]->get_deep_loops( loops ); - } - //fprintf(stderr, "found %d deep loops\n", loops.size()); - } - - - void find_deepest_loops( std::vector &loops) { - std::vector b; // deepest loops below me - - int n = body->children.size(); - for (int i=0; i l; // deepest loops below one child - body->children[i]->find_deepest_loops( l ); - if ( l.size() > b.size() ) { // a deeper nesting than we've seen - b = l; - } - } - - loops.push_back( this ); // add myself - for (int i=0; ivarname); - symbol_table = addSymbolToTable( symbol_table, vd ); - //printSymbolTable( symbol_table ); - return symbol_table; - } - - void gatherStatements( std::vector &statements ); - bool lowerBound( int &l ); - bool upperBound( int &u ); - -}; - - - -class chillAST_TernaryOperator: public chillAST_node { -public: - // variables that are special for this type of node - char *op; // TODO need enum so far, only "?" conditional operator - chillAST_node *condition; - chillAST_node *lhs; // keep name from binary - chillAST_node *rhs; - - - // constructors - chillAST_TernaryOperator(); - chillAST_TernaryOperator(const char *op, chillAST_node *cond, chillAST_node *lhs, chillAST_node *rhs, chillAST_node *p=NULL); - - // other methods particular to this type of node - bool isNotLeaf() { return true; }; - bool isLeaf() { return false; }; - - - char *getOp() { return op; }; // dangerous. could get changed! - chillAST_node *getCond() { return condition; }; - chillAST_node *getRHS() { return rhs; }; - chillAST_node *getLHS() { return lhs; }; - - void setCond( chillAST_node *newc ) { condition = newc; newc->setParent( this ); } - void setLHS( chillAST_node *newlhs ) { lhs = newlhs; newlhs->setParent( this ); } - void setRHS( chillAST_node *newrhs ) { rhs = newrhs; newrhs->setParent( this ); } - - - - - // required methods that I can't seem to get to inherit - void dump( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void printonly( int indent=0, FILE *fp = stderr ); - - chillAST_node* constantFold(); - chillAST_node* clone(); - void replaceChild( chillAST_node *old, chillAST_node *newchild ) ; - void gatherArrayRefs( std::vector &refs, bool writtento ); - void gatherScalarRefs( std::vector &refs, bool writtento ) ; - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - - void gatherVarUsage( std::vector &decls ); - void gatherDeclRefExprs( std::vector&refs ); - void gatherVarLHSUsage( std::vector &decls ); - void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - void loseLoopWithLoopVar( char *var ){}; // ternop can't have loop as child? -}; - - - -class chillAST_BinaryOperator: public chillAST_node { -public: - // variables that are special for this type of node - char *op; // TODO need enum - chillAST_node *lhs; - chillAST_node *rhs; - - - // constructors - chillAST_BinaryOperator(); - chillAST_BinaryOperator(chillAST_node *lhs, const char *op, chillAST_node *rhs, chillAST_node *p=NULL); - - // other methods particular to this type of node - int evalAsInt(); - chillAST_IntegerLiteral *evalAsIntegerLiteral(); - - bool isNotLeaf() { return true; }; - bool isLeaf() { return false; }; - - chillAST_node *getRHS() { return rhs; }; - chillAST_node *getLHS() { return lhs; }; - void setLHS( chillAST_node *newlhs ) { lhs = newlhs; newlhs->setParent( this ); } - void setRHS( chillAST_node *newrhs ) { rhs = newrhs; newrhs->setParent( this ); } - - char *getOp() { return op; }; // dangerous. could get changed! - bool isAugmentedAssignmentOp() { - return - (!strcmp(op, "*=")) || // BO_MulAssign, - (!strcmp(op, "/=")) || // BO_DivAssign - (!strcmp(op, "%=")) || // BO_RemAssign - (!strcmp(op, "+=")) || // BO_AddAssign - (!strcmp(op, "-=")) || // BO_SubAssign - - (!strcmp(op, "<<=")) || // BO_ShlAssign - (!strcmp(op, ">>=")) || // BO_ShrAssign - (!strcmp(op, "&&=")) || // BO_AndAssign - (!strcmp(op, "||=")) || // BO_OrAssign - - (!strcmp(op, "^=")) // BO_XorAssign - ; - } - bool isAssignmentOp() { - return( (!strcmp(op, "=")) || // BO_Assign, - isAugmentedAssignmentOp() ); - }; - bool isComparisonOp() { return (!strcmp(op,"<")) || (!strcmp(op,">")) || (!strcmp(op,"<=")) || (!strcmp(op,">=")); }; - - bool isPlusOp() { return (!strcmp(op,"+")); }; - bool isMinusOp() { return (!strcmp(op,"-")); }; - bool isPlusMinusOp() { return (!strcmp(op,"+")) || (!strcmp(op,"-")); }; - bool isMultDivOp() { return (!strcmp(op,"*")) || (!strcmp(op,"/")); }; - - bool isStructOp() { return (!strcmp(op,".")) || (!strcmp(op,"->")); }; - - - // required methods that I can't seem to get to inherit - void dump( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void printonly( int indent=0, FILE *fp = stderr ); - char *stringRep(int indent=0 ); - - chillAST_node* constantFold(); - chillAST_node* clone(); - void replaceChild( chillAST_node *old, chillAST_node *newchild ) ; - void gatherArrayRefs( std::vector &refs, bool writtento ); // chillAST_BinaryOperator - void gatherScalarRefs( std::vector &refs, bool writtento ) ; - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - - void gatherVarUsage( std::vector &decls ); - void gatherDeclRefExprs( std::vector&refs ); - void gatherVarLHSUsage( std::vector &decls ); - void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - void loseLoopWithLoopVar( char *var ){}; // binop can't have loop as child? - - void gatherStatements( std::vector &statements ); // - - bool isSameAs( chillAST_node *other ); - -}; - - - - - - - - -class chillAST_ArraySubscriptExpr: public chillAST_node { -public: - // variables that are special for this type of node - chillAST_node *base; // always a decl ref expr? No, for multidimensional array, is another ASE - chillAST_node *index; - bool imwrittento; - bool imreadfrom; // WARNING: ONLY used when both writtento and readfrom are true x += 1 and so on - chillAST_VarDecl *basedecl; // the vardecl that this refers to - void *uniquePtr; // DO NOT REFERENCE THROUGH THIS! - - // constructors - chillAST_ArraySubscriptExpr(); - chillAST_ArraySubscriptExpr( chillAST_node *bas, chillAST_node *indx, chillAST_node *p, void *unique); - chillAST_ArraySubscriptExpr( chillAST_node *bas, chillAST_node *indx, bool writtento, chillAST_node *p, void *unique); - - chillAST_ArraySubscriptExpr( chillAST_VarDecl *v, std::vector indeces, chillAST_node *p); - - // other methods particular to this type of node - bool operator!=( const chillAST_ArraySubscriptExpr& ) ; - bool operator==( const chillAST_ArraySubscriptExpr& ) ; - chillAST_VarDecl *multibase(); // method for finding the basedecl - chillAST_node *multibase2() { return base->multibase2(); } - - chillAST_node *getIndex(int dim); - void gatherIndeces( std::vector< chillAST_node * > &ind ); - - void replaceChild( chillAST_node *old, chillAST_node *newchild ); // will examine index - - // required methods that I can't seem to get to inherit - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void printonly( int indent=0, FILE *fp = stderr ); - void print( int indent=0, FILE *fp = stderr ) const; // print CODE in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc - char *stringRep(int indent=0 ); - - chillAST_node* constantFold(); - chillAST_node* clone(); - chillAST_node *findref(){return this;}// find the SINGLE constant or data reference at this node or below - void gatherArrayRefs( std::vector &refs, bool writtento ); - void gatherScalarRefs( std::vector &refs, bool writtento ) ; - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - - void gatherVarUsage( std::vector &decls ); - void gatherDeclRefExprs( std::vector&refs ); - void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - - const char* getUnderlyingType() { - //fprintf(stderr, "ASE getUnderlyingType() base of type %s\n", base->getTypeString()); base->print(); printf("\n"); fflush(stderr); - return base->getUnderlyingType(); }; - - virtual chillAST_VarDecl* getUnderlyingVarDecl() { return base->getUnderlyingVarDecl(); }; - -}; - - - -class chillAST_MemberExpr: public chillAST_node { -public: - // variables that are special for this type of node - chillAST_node *base; // always a decl ref expr? No, can be Array Subscript Expr - char *member; - char *printstring; - - chillAST_VarDecl *basedecl; // the vardecl that this refers to - void *uniquePtr; // DO NOT REFERENCE THROUGH THIS! - - CHILL_MEMBER_EXP_TYPE exptype; - - - // constructors - chillAST_MemberExpr(); - chillAST_MemberExpr( chillAST_node *bas, const char *mem, chillAST_node *p, void *unique, CHILL_MEMBER_EXP_TYPE t=CHILL_MEMBER_EXP_DOT); - - // other methods particular to this type of node - bool operator!=( const chillAST_MemberExpr& ) ; - bool operator==( const chillAST_MemberExpr& ) ; - - // required methods that I can't seem to get to inherit - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void printonly( int indent=0, FILE *fp = stderr ); - void print( int indent=0, FILE *fp = stderr ) const; // print CODE in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc - char *stringRep( int indent = 0); - - chillAST_node* constantFold(); - chillAST_node* clone(); - void gatherArrayRefs( std::vector &refs, bool writtento ); - void gatherScalarRefs( std::vector &refs, bool writtento ) ; - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - - void gatherVarUsage( std::vector &decls ); - void gatherDeclRefExprs( std::vector&refs ); - void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - - chillAST_VarDecl* getUnderlyingVarDecl(); - - void replaceChild( chillAST_node *old, chillAST_node *newchild ); - - void setType( CHILL_MEMBER_EXP_TYPE t ) { exptype = t; }; - CHILL_MEMBER_EXP_TYPE getType( CHILL_MEMBER_EXP_TYPE t ) { return exptype; }; - - chillAST_VarDecl* multibase(); // this one will return the member decl - chillAST_node* multibase2(); // this one will return the member expression -}; - - - - -class chillAST_IntegerLiteral: public chillAST_node { -public: - // variables that are special for this type of node - int value; - - // constructors - chillAST_IntegerLiteral(int val, chillAST_node *p = NULL); - - // other methods particular to this type of node - int evalAsInt() { return value; } - - // required methods that I can't seem to get to inherit - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc - chillAST_node* constantFold(); - chillAST_node* clone(); - void gatherArrayRefs( std::vector &refs, bool w ){}; // does nothing - void gatherScalarRefs( std::vector &refs, bool writtento ){}; // does nothing - - void gatherVarDecls ( std::vector &decls ){}; // does nothing - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ){}; // does nothing - void gatherArrayVarDecls ( std::vector &decls ){}; // does nothing - - void gatherVarUsage( std::vector &decls ) {}; // does nothing - void gatherDeclRefExprs( std::vector&refs ) {}; // does nothing - void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) {}; - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - - chillAST_node *findref(){return this;}// find the SINGLE constant or data reference at this node or below -}; - - -class chillAST_FloatingLiteral: public chillAST_node { -public: - // variables that are special for this type of node - float value; - double doublevalue; - int float0double1; - - char *allthedigits; // if not NULL, use this as printable representation - int precision; // float == 1, double == 2, ??? - - // constructors - chillAST_FloatingLiteral( float val, chillAST_node *p); - chillAST_FloatingLiteral( double val, chillAST_node *p); - chillAST_FloatingLiteral( float val, int pre, chillAST_node *p); - chillAST_FloatingLiteral( double val, int pre, chillAST_node *p); - chillAST_FloatingLiteral( float val, const char *printable, chillAST_node *p); - chillAST_FloatingLiteral( float val, int pre, const char *printable, chillAST_node *p); - chillAST_FloatingLiteral( chillAST_FloatingLiteral *old ); - - // other methods particular to this type of node - void setPrecision( int precis ) { precision = precis; }; - int getPrecision() { return precision; } - - // required methods that I can't seem to get to inherit - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc - chillAST_node* constantFold(); - chillAST_node* clone(); - void gatherArrayRefs( std::vector &refs, bool w ){}; // does nothing - void gatherScalarRefs( std::vector &refs, bool writtento ){}; // does nothing - - void gatherVarDecls ( std::vector &decls ){}; // does nothing - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ){}; // does nothing ; - void gatherArrayVarDecls ( std::vector &decls ){}; // does nothing ; - - void gatherVarUsage( std::vector &decls ) {}; // does nothing - void gatherDeclRefExprs( std::vector&refs ){}; // does nothing - void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){}; - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - chillAST_node *findref(){return this;};// find the SINGLE constant or data reference at this node or below - - bool isSameAs( chillAST_node *other ); -}; - - - - -class chillAST_UnaryOperator: public chillAST_node { -public: - // variables that are special for this type of node - char *op; // TODO enum - bool prefix; // or post - chillAST_node *subexpr; - - // constructors - chillAST_UnaryOperator( const char *oper, bool pre, chillAST_node *sub, chillAST_node *p ); - - // other methods particular to this type of node - bool isAssignmentOp() { - return( (!strcmp(op, "++")) || - (!strcmp(op, "--")) ); // are there more ??? TODO - } - - // required methods that I can't seem to get to inherit - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc - chillAST_node* constantFold(); - chillAST_node* clone(); - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - void gatherArrayRefs( std::vector &refs, bool writtento ); // chillAST_UnaryOperator - - void gatherVarLHSUsage( std::vector &decls ); - - void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - void gatherVarUsage( std::vector &decls ); - void gatherDeclRefExprs( std::vector&refs ); - //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - - int evalAsInt(); - bool isSameAs( chillAST_node *other ); - -}; - - - - - -class chillAST_ImplicitCastExpr: public chillAST_node { -public: - // variables that are special for this type of node - chillAST_node *subexpr; - - // constructors - chillAST_ImplicitCastExpr(chillAST_node *sub, chillAST_node *p); - - // other methods particular to this type of node - bool isNotLeaf() { return true; }; - bool isLeaf() { return false; }; - - // required methods that I can't seem to get to inherit - void replaceChild( chillAST_node *old, chillAST_node *newchild ); - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void printonly( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ) { print( indent, fp); }; // print ast in chill_ast.cc - chillAST_node* constantFold(); - chillAST_node* clone(); - void gatherArrayRefs( std::vector &refs, bool writtento ); - void gatherScalarRefs( std::vector &refs, bool writtento ) ; - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - - void gatherVarUsage( std::vector &decls ); - void gatherDeclRefExprs( std::vector&refs ); - //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - chillAST_VarDecl *multibase(); // just recurse on subexpr - -}; - - - -class chillAST_CStyleCastExpr: public chillAST_node { -public: - // variables that are special for this type of node - char * towhat; - chillAST_node *subexpr; - // constructors - chillAST_CStyleCastExpr(const char *to, chillAST_node *sub, chillAST_node *p=NULL); - - // other methods particular to this type of node - - - // required methods that I can't seem to get to inherit - void replaceChild( chillAST_node *old, chillAST_node *newchild ); - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc - chillAST_node* constantFold(); - chillAST_node* clone(); - void gatherArrayRefs( std::vector &refs, bool writtento ); - void gatherScalarRefs( std::vector &refs, bool writtento ) ; - - void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - - void gatherVarUsage( std::vector &decls ); - void gatherDeclRefExprs( std::vector&refs ); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - chillAST_node *findref(){return subexpr;};// find the SINGLE constant or data reference at this node or below - -}; - - -class chillAST_CStyleAddressOf: public chillAST_node { -public: - // variables that are special for this type of node - chillAST_node *subexpr; - // constructors - chillAST_CStyleAddressOf(chillAST_node *sub, chillAST_node *p=NULL); - - // other methods particular to this type of node - - - // required methods that I can't seem to get to inherit - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc - chillAST_node* constantFold(); - chillAST_node* clone(); - void gatherArrayRefs( std::vector &refs, bool writtento ); - void gatherScalarRefs( std::vector &refs, bool writtento ) ; - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - - void gatherVarUsage( std::vector &decls ); - void gatherDeclRefExprs( std::vector&refs ); - //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - - -}; - - -class chillAST_CudaMalloc:public chillAST_node { -public: - // variables that are special for this type of node - chillAST_node *devPtr; // Pointer to allocated device memory - chillAST_node *sizeinbytes; - - // constructors - chillAST_CudaMalloc(chillAST_node *devmemptr, chillAST_node *size, chillAST_node *p=NULL); - - // other methods particular to this type of node - - - // required methods that I can't seem to get to inherit - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc - chillAST_node* constantFold(); - chillAST_node* clone(); - void gatherArrayRefs( std::vector &refs, bool writtento ); - void gatherScalarRefs( std::vector &refs, bool writtento ) ; - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - - void gatherVarUsage( std::vector &decls ); - //void gatherDeclRefExprs( std::vector&refs ); - //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - -}; - - -class chillAST_CudaFree:public chillAST_node { -public: - // variables that are special for this type of node - chillAST_VarDecl *variable; - - // constructors - chillAST_CudaFree(chillAST_VarDecl *var, chillAST_node *p=NULL); - - // other methods particular to this type of node - - - // required methods that I can't seem to get to inherit - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc - chillAST_node* constantFold(); - chillAST_node* clone(); - void gatherArrayRefs( std::vector &refs, bool writtento ); - void gatherScalarRefs( std::vector &refs, bool writtento ) ; - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - - void gatherVarUsage( std::vector &decls ); - //void gatherDeclRefExprs( std::vector&refs ); - //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - -}; - - - - - -class chillAST_Malloc:public chillAST_node { // malloc( sizeof(int) * 2048 ); -public: - // variables that are special for this type of node - char *thing; // to void if this is null , sizeof(thing) if it is not - chillAST_node *sizeexpr; // bytes - - // constructors - chillAST_Malloc(chillAST_node *size, chillAST_node *p=NULL); - chillAST_Malloc(char *thething, chillAST_node *numthings, chillAST_node *p=NULL); // malloc (sizeof(int) *1024) - - // other methods particular to this type of node - - - // required methods that I can't seem to get to inherit - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc - chillAST_node* constantFold(); - chillAST_node* clone(); - void gatherArrayRefs( std::vector &refs, bool writtento ); - void gatherScalarRefs( std::vector &refs, bool writtento ) ; - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - - void gatherVarUsage( std::vector &decls ); - //void gatherDeclRefExprs( std::vector&refs ); - //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - -}; - - - - -class chillAST_Free:public chillAST_node { -public: - - - - -}; - - - - -class chillAST_CudaMemcpy:public chillAST_node { -public: - // variables that are special for this type of node - chillAST_VarDecl *dest; // Pointer to allocated device memory - chillAST_VarDecl *src; - chillAST_node *size; - char *cudaMemcpyKind; // could use the actual enum - - // constructors - chillAST_CudaMemcpy(chillAST_VarDecl *d, chillAST_VarDecl *s, chillAST_node *size, char *kind, chillAST_node *p=NULL); - - // other methods particular to this type of node - - - // required methods that I can't seem to get to inherit - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc - chillAST_node* constantFold(); - chillAST_node* clone(); - void gatherArrayRefs( std::vector &refs, bool writtento ); - void gatherScalarRefs( std::vector &refs, bool writtento ) ; - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - - void gatherVarUsage( std::vector &decls ); - //void gatherDeclRefExprs( std::vector&refs ); - //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - -}; - - -class chillAST_CudaSyncthreads:public chillAST_node { -public: - // variables that are special for this type of node - - // constructors - chillAST_CudaSyncthreads(chillAST_node *p=NULL); - - // other methods particular to this type of node - - - // required methods that I can't seem to get to inherit - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc - //chillAST_node* constantFold() {}; - //chillAST_node* clone(); - //void gatherArrayRefs( std::vector &refs, bool writtento ){}; - //void gatherScalarRefs( std::vector &refs, bool writtento ) ; - - void gatherVarDecls ( std::vector &decls ) {}; // does nothing - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ) {}; // does nothing - void gatherArrayVarDecls ( std::vector &decls ) {}; // does nothing - - void gatherVarUsage( std::vector &decls ) {}; // does nothing - //void gatherDeclRefExprs( std::vector&refs ); - //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - //bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; - -}; - - - -class chillAST_ReturnStmt: public chillAST_node { -public: - // variables that are special for this type of node - chillAST_node *returnvalue; - - // constructors - chillAST_ReturnStmt( chillAST_node *retval, chillAST_node *p ); - - // other methods particular to this type of node - - - // required methods that I can't seem to get to inherit - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc - chillAST_node* constantFold(); - chillAST_node* clone(); - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - - void gatherVarUsage( std::vector &decls ); - void gatherDeclRefExprs( std::vector&refs ); - //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - -}; - - - -class chillAST_CallExpr: public chillAST_node { // a function call -public: - // variables that are special for this type of node - chillAST_node *callee; // the function declaration (what about builtins?) - int numargs; - std::vector args; - chillAST_VarDecl *grid; - chillAST_VarDecl *block; - - // constructors - chillAST_CallExpr(chillAST_node *function, chillAST_node *p ); - void addArg( chillAST_node *newarg ); - - // other methods particular to this type of node - // TODO get/set grid, block - - // required methods that I can't seem to get to inherit - chillAST_node* constantFold(); - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc - void gatherArrayRefs( std::vector &refs, bool writtento ); - void gatherScalarRefs( std::vector &refs, bool writtento ) ; - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - - void gatherVarUsage( std::vector &decls ); - void gatherDeclRefExprs( std::vector&refs ); - void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - chillAST_node* clone(); -}; - - - -class chillAST_ParenExpr: public chillAST_node { -public: - // variables that are special for this type of node - chillAST_node *subexpr; - - // constructors - chillAST_ParenExpr( chillAST_node *sub, chillAST_node *p=NULL ); - - // other methods particular to this type of node - - - // required methods that I can't seem to get to inherit - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc - chillAST_node* constantFold(); - chillAST_node* clone(); - void gatherArrayRefs( std::vector &refs, bool writtento ); - void gatherScalarRefs( std::vector &refs, bool writtento ) ; - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - - void gatherVarUsage( std::vector &decls ); - void gatherDeclRefExprs( std::vector&refs ); - void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - -}; - - -class chillAST_Sizeof: public chillAST_node { -public: - // variables that are special for this type of node - char *thing; - - // constructors - chillAST_Sizeof( char *t, chillAST_node *p = NULL ); - - // other methods particular to this type of node - - - // required methods that I can't seem to get to inherit - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc - chillAST_node* constantFold(); - chillAST_node* clone(); - void gatherArrayRefs( std::vector &refs, bool writtento ); - void gatherScalarRefs( std::vector &refs, bool writtento ) ; - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - - void gatherVarUsage( std::vector &decls ); - void gatherDeclRefExprs( std::vector&refs ); - void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){}; - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here - -}; - - - -class chillAST_NoOp: public chillAST_node { -public: - chillAST_NoOp( chillAST_node *p = NULL ); // { parent = p; }; - - // required methods that I can't seem to get to inherit - void print( int indent=0, FILE *fp = stderr ) {}; // print CODE in chill_ast.cc - void dump( int indent=0, FILE *fp = stderr ) {}; // print ast in chill_ast.cc - chillAST_node* constantFold() {}; - chillAST_node* clone() { return new chillAST_NoOp( parent ); }; // ?? - - void gatherArrayRefs( std::vector &refs, bool writtento ) {}; - void gatherScalarRefs( std::vector &refs, bool writtento ) {}; - - void gatherVarDecls ( std::vector &decls ){}; - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ){}; - void gatherArrayVarDecls ( std::vector &decls ){}; - - void gatherVarUsage( std::vector &decls ){}; - void gatherDeclRefExprs( std::vector&refs ){}; - void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){}; - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; };//no loops under here -}; - - - -class chillAST_IfStmt: public chillAST_node { -public: - // variables that are special for this type of node - chillAST_node *cond; - chillAST_node *thenpart; - chillAST_node *elsepart; - IR_CONDITION_TYPE conditionoperator; // from ir_code.hh - - // constructors - chillAST_IfStmt(); - chillAST_IfStmt( chillAST_node *c, chillAST_node *t, chillAST_node *e, chillAST_node *p); - - // other methods particular to this type of node - chillAST_node *getCond() { return cond; }; - chillAST_node *getThen() { return thenpart; }; - chillAST_node *getElse() { return elsepart; }; - - void setCond( chillAST_node *b ) { cond = b; if (cond) cond->parent = this; }; - void setThen( chillAST_node *b ) { thenpart = b; if (thenpart) thenpart->parent = this; }; - void setElse( chillAST_node *b ) { elsepart = b; if (elsepart) elsepart->parent = this; }; - - // required methods that I can't seem to get to inherit - void dump( int indent=0, FILE *fp = stderr ); - void print( int indent=0, FILE *fp = stderr ); - - chillAST_node* constantFold(); - chillAST_node* clone(); - - void gatherVarDecls ( std::vector &decls ); - void gatherVarDeclsMore ( std::vector &decls ) { gatherVarDecls(decls); } ; - - void gatherScalarVarDecls( std::vector &decls ); - void gatherArrayVarDecls ( std::vector &decls ); - void gatherArrayRefs( std::vector &refs, bool writtento ); - void gatherScalarRefs( std::vector &refs, bool writtento ) ; - - void gatherVarUsage( std::vector &decls ); - void gatherDeclRefExprs( std::vector&refs ); - //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); - bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ); - - void gatherStatements( std::vector &statements ); - -}; - - - - - - - - -class chillAST_something: public chillAST_node { -public: - // variables that are special for this type of node - - // constructors - chillAST_something(); - - // other methods particular to this type of node - - - // required methods that I can't seem to get to inherit - void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc - //void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc -}; - - - - -chillAST_FunctionDecl *findFunctionDecl( chillAST_node *node, const char *procname); - - - -#endif - diff --git a/include/chilldebug.h b/include/chilldebug.h index f187955..c09aa59 100644 --- a/include/chilldebug.h +++ b/include/chilldebug.h @@ -1,20 +1,31 @@ #ifndef DEBUGCHILL_H #define DEBUGCHILL_H +#include +#include +#include + #ifndef NDEBUG // means that CMAKE_BUILD_TYPE=Debug #define DEBUGCHILL #endif +// This thing below potentially create leaks +#define FILENAME basename(strdup(__FILE__)) #ifdef DEBUGCHILL -#define CHILL_DEBUG_PRINT(format,args...) fprintf(stderr,"%s,%s,LN%d:\n\t" format,__FILE__,__FUNCTION__,__LINE__, ##args ) +#define CHILL_DEBUG_PRINT(format,args...) fprintf(stderr,"%s, %s, LN%d:\t" format,FILENAME,__FUNCTION__, \ + __LINE__, ##args ) #define CHILL_DEBUG_BEGIN { \ - fprintf(stderr,"%s,%s,LN%d:\n",__FILE__,__FUNCTION__,__LINE__); -#define CHILL_DEBUG_END } + fprintf(stderr,"=========\t%s, %s, LN%d\t=========\n",FILENAME,__FUNCTION__,__LINE__); +#define CHILL_DEBUG_END fprintf(stderr,"===========================\n");} #else #define CHILL_DEBUG_PRINT(format,args...) do {} while(0) /* Don't do anything */ -#define CHILL_DEBUG_BEGIN do { -#define CHILL_DEBUG_END } while (0); +#define CHILL_DEBUG_BEGIN while(0) { +#define CHILL_DEBUG_END } #endif +// TODO below should be substituted by some error throwing? to be more consistent with cpp style +#define CHILL_ERROR(format,args...) fprintf(stderr,"ERROR:\t%s, %s, LN%d:\t" format,FILENAME,__FUNCTION__, \ + __LINE__, ##args ) + #endif diff --git a/include/dep.hh b/include/dep.hh index ed5a83d..73c662c 100644 --- a/include/dep.hh +++ b/include/dep.hh @@ -34,7 +34,6 @@ struct DependenceVector { quasi = false; is_scalar_dependence = false; } - // DependenceVector(int size); DependenceVector(const DependenceVector &that); ~DependenceVector() { delete sym; } // is this legal? TODO DependenceVector &operator=(const DependenceVector &that); @@ -60,7 +59,6 @@ struct DependenceVector { std::vector normalize() const; std::vector permute(const std::vector &pi) const; DependenceVector reverse() const; - // std::vector matrix(const std::vector > &M) const; DependenceType getType() const; friend std::ostream& operator<<(std::ostream &os, const DependenceVector &d); }; @@ -77,10 +75,8 @@ public: DependenceGraph() { num_dim_ = 0; } ~DependenceGraph() {} int num_dim() const { return num_dim_; } -// DependenceGraph permute(const std::vector &pi) const; DependenceGraph permute(const std::vector &pi, const std::set &active = std::set()) const; - // DependenceGraph matrix(const std::vector > &M) const; DependenceGraph subspace(int dim) const; bool isPositive() const; bool hasPositive(int dim) const; diff --git a/include/ir_clang.hh b/include/ir_clang.hh index b283359..e637016 100755 --- a/include/ir_clang.hh +++ b/include/ir_clang.hh @@ -3,7 +3,6 @@ #include #include "ir_code.hh" -//#include #include "chill_error.hh" #define __STDC_CONSTANT_MACROS @@ -29,7 +28,7 @@ #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Basic/DiagnosticOptions.h" -#include "chill_ast.hh" +#include "chillAST.h" extern std::vector VariableDeclarations; // a global. TODO @@ -282,14 +281,6 @@ public: std::vectorstatements; chillAST_node *chillAST; // how about for now we say if there are statements, which is presumably the top level of statements from ... somewhere, otherwise the code is in chillAST - //IR_chillBlock(const IR_Code *ir, const StmtList& bDecl) : bDecl_(bDecl), cs_(NULL) { - // fprintf(stderr, "MISTAKE IR_chillBlock bdecl\n"); exit(-1); - // ir_ = ir; - //} - //IR_chillBlock(const IR_Code *ir, clang::CompoundStmt *cs) : cs_(cs) { - // fprintf(stderr, "MISTAKE IR_chillBlock cs\n"); exit(-1); - // ir_ = ir; - //} IR_chillBlock( const IR_chillBlock *CB ) { // clone existing IR_chillBlock ir_ = CB->ir_; for (int i=0; istatements.size(); i++) statements.push_back( CB->statements[i] ); diff --git a/include/ir_code.hh b/include/ir_code.hh index f52d147..e3fd8ea 100644 --- a/include/ir_code.hh +++ b/include/ir_code.hh @@ -24,7 +24,7 @@ #include -#include +#include #include diff --git a/include/irtools.hh b/include/irtools.hh index d85b76b..a743fa5 100644 --- a/include/irtools.hh +++ b/include/irtools.hh @@ -47,7 +47,6 @@ typedef std::map, std::vector, std::vector > DVPair; // Manu:: this function is required for reduction operation -//omega::CG_outputRepr * from_same_statement(IR_Code *ir, IR_ArrayRef *a, IR_ArrayRef *b); bool from_same_statement(IR_Code *ir, IR_ArrayRef *a, IR_ArrayRef *b); int stmtType(IR_Code *ir, const omega::CG_outputRepr *repr); IR_OPERATION_TYPE getReductionOperator(IR_Code *ir, const omega::CG_outputRepr *repr); diff --git a/include/stencil.hh b/include/stencil.hh index 69eec42..799e3b9 100644 --- a/include/stencil.hh +++ b/include/stencil.hh @@ -2,7 +2,7 @@ #pragma once #include "ir_clang.hh" -#include "chill_ast.hh" +#include "chillAST/chillASTs.hh" //#include #include diff --git a/lib/chillcg/include/code_gen/CG_chillRepr.h b/lib/chillcg/include/code_gen/CG_chillRepr.h index 3d19de7..36b2fa4 100755 --- a/lib/chillcg/include/code_gen/CG_chillRepr.h +++ b/lib/chillcg/include/code_gen/CG_chillRepr.h @@ -12,7 +12,7 @@ #endif -#include "chill_ast.hh" +#include "chillAST/chillASTs.hh" namespace omega { 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