/* Inserts the loop before the expr statement for (_$dim = 0; _$dim < _length$dim; _$dim++) ; */ void insertLoop(SgExprStatement* exprStmt, int index) { string indexStr = StringUtility::numberToString(index); string indexName = "_" + indexStr; string lengthName = "_length" + indexStr; ROSE_ASSERT(exprStmt != NULL); SgScopeStatement* scope = exprStmt->get_scope(); SgVarRefExp* indexRefExp = buildVarRefExp(indexName, scope); SgVarRefExp* lengthRefExp = buildVarRefExp(lengthName, scope); // Init Statement SgStatement* init_stmt = buildAssignStatement(indexRefExp, buildIntVal(0)); // Cond Statement SgExprStatement* cond_stmt = buildExprStatement(buildLessThanOp(indexRefExp, lengthRefExp)); // Increment Expression SgExpression *incr_exp = buildPlusPlusOp(indexRefExp, SgUnaryOp::postfix); SgForStatement* loop = buildForStatement(init_stmt, cond_stmt, incr_exp, buildBasicBlock()); ROSE_ASSERT(loop != NULL); insertStatementBefore(exprStmt, loop); removeStatement(exprStmt); appendStatement(exprStmt, isSgBasicBlock(loop->get_loop_body())); }
//A generic function to check if a loop has a tag statement prepended to it, asking for instrumentation //If so, the loop will be instrumented and the tag statement will be returned. // This function supports both C/C++ for loops and Fortran Do loops SgStatement* instrumentLoopForCounting(SgStatement* loop) { //get scope of the loop assert (loop != NULL); SgForStatement* forloop = isSgForStatement(loop); SgFortranDo* doloop = isSgFortranDo(loop); SgScopeStatement* scope = NULL; if (forloop) scope = forloop->get_scope(); else if (doloop) scope = doloop->get_scope(); else { cerr<<"Error in instrumentLoopForCounting(): Unrecognized loop type:"<< loop->class_name()<<endl; assert(false); } ROSE_ASSERT(scope != NULL); // Only for a do-loop which immediately follows chiterations = .. SgVariableSymbol * chiterations_sym = lookupVariableSymbolInParentScopes(SgName("chiterations"), isSgScopeStatement(loop)); if (chiterations_sym==NULL) return NULL; SgStatement* prev_stmt = getPreviousStatement(loop,false); // backwards search, skipping pragma declaration etc. while (prev_stmt!=NULL && !isAssignmentStmtOf (prev_stmt, chiterations_sym->get_declaration())) prev_stmt = getPreviousStatement(prev_stmt,false); if (prev_stmt == NULL) return NULL; // To support nested loops, we need to use unique chiterations variable for each loop // otherwise the value stored in inner loop will overwrite the iteration count for the outerloop. loop_id ++; // increment loop ID // insert size_t chiterations_id ; // Find the enclosing function declaration, including its derived instances like //isSgProcedureHeaderStatement, isSgProgramHeaderStatement, and isSgMemberFunctionDeclaration. SgFunctionDeclaration* func_decl = getEnclosingFunctionDeclaration (loop); ROSE_ASSERT (func_decl !=NULL); SgFunctionDefinition* func_def = func_decl->get_definition(); ROSE_ASSERT (func_def !=NULL); SgBasicBlock* func_body = func_def->get_body(); // insert a new variable declaration std::string new_iter_var_name = std::string("chiterations_") + StringUtility::numberToString(loop_id); SgVariableDeclaration* new_iter_var_decl = buildVariableDeclaration(new_iter_var_name, chiterations_sym->get_type(), NULL, func_body); SgStatement* last_decl = findLastDeclarationStatement(func_body); if (last_decl!=NULL) insertStatementAfter (last_decl, new_iter_var_decl, false); else prependStatement(new_iter_var_decl, func_body); // rewrite the assignment stmt's left hand variable to be the new symbol SgExpression* lhs = NULL; bool rt = isAssignmentStatement (prev_stmt, &lhs); ROSE_ASSERT (rt == true); ROSE_ASSERT (lhs != NULL); SgVarRefExp* var_ref = isSgVarRefExp (lhs); ROSE_ASSERT (var_ref != NULL); var_ref->set_symbol(getFirstVarSym (new_iter_var_decl)); SgStatement* loop_body = NULL; if (forloop) loop_body = forloop->get_loop_body(); else if (doloop) loop_body = doloop->get_body(); assert (loop_body != NULL); // count FP operations for each loop CountFPOperations (loop_body); //chflops=chflops+chiterations*n FPCounters* current_result = getFPCounters (loop_body); if (current_result->getTotalCount() >0) { SgExprStatement* stmt = buildCounterAccumulationStmt("chflops", new_iter_var_name , buildIntVal(current_result->getTotalCount()),scope); insertStatementAfter (loop, stmt); attachComment(stmt," aitool generated FLOPS counting statement ..."); } // Obtain per-iteration load/store bytes calculation expressions // excluding scalar types to match the manual version //CountLoadStoreBytes (SgLocatedNode* input, bool includeScalars = true, bool includeIntType = true); std::pair <SgExpression*, SgExpression*> load_store_count_pair = CountLoadStoreBytes (loop_body, false, true); // chstores=chstores+chiterations*8 if (load_store_count_pair.second!= NULL) { SgExprStatement* store_byte_stmt = buildCounterAccumulationStmt("chstores", new_iter_var_name, load_store_count_pair.second, scope); insertStatementAfter (loop, store_byte_stmt); attachComment(store_byte_stmt," aitool generated Stores counting statement ..."); } // handle loads stmt 2nd so it can be inserted as the first after the loop // build chloads=chloads+chiterations*2*8 if (load_store_count_pair.first != NULL) { SgExprStatement* load_byte_stmt = buildCounterAccumulationStmt("chloads", new_iter_var_name, load_store_count_pair.first, scope); insertStatementAfter (loop, load_byte_stmt); attachComment(load_byte_stmt," aitool generated Loads counting statement ..."); } return prev_stmt; } // end instrumentLoopForCounting()
void createOneGlobalIndexExpForAllArrays(SgScopeStatement* kernel_body, MintInitNameMapExpList_t refList, SgDeclarationStatement* src_location) { //We declare one index variable for all arrays: one for 1D, one for 2D, one for 3D //Need a compiler flag for this //e.g. _gidx + _gidy * widthUnew in 2D //e.g. _gidx + _gidy * widthUnew + _gidz * sliceUnew in 3D ROSE_ASSERT(src_location); bool threeD = false; bool twoD = false; bool oneD = false; SgScopeStatement* indexScope= src_location->get_scope(); SgVariableSymbol* gidz_sym = MintArrayInterface::getSymbolFromName(isSgBasicBlock(kernel_body), GIDZ); SgVariableSymbol* gidy_sym = MintArrayInterface::getSymbolFromName(isSgBasicBlock(kernel_body), GIDY); SgVariableSymbol* gidx_sym = MintArrayInterface::getSymbolFromName(isSgBasicBlock(kernel_body), GIDX); MintInitNameMapExpList_t::iterator arr; //for each array, we don't create an index expression for(arr= refList.begin(); arr!= refList.end(); arr++) { SgInitializedName* iname = arr->first; int dim = MintArrayInterface::getDimension(iname); ROSE_ASSERT(dim <= 3); if(dim == 3 && (gidz_sym == NULL || threeD == true)) continue; //must be a boundary condition, we don't use index opt. optimization for those if(dim == 2 && (gidy_sym == NULL || twoD == true)) continue; //must be a boundary condition, we don't use index opt. optimization for those if(dim == 1 && (gidx_sym == NULL || oneD == true)) continue; //must be a boundary condition, we don't use index opt. optimization for those string arrStr = iname->get_name().str(); //_gidx + _gidy * widthUnew in 2D //_gidx + _gidy * widthUnew + _gidz * sliceUnew in 3D SgExpression* indexExp = NULL; indexExp = buildVarRefExp(GIDX, indexScope); string index_str = "index"; if(dim ==1){ index_str = "_" +index_str + "1D"; oneD = true; } else if(dim == 2){ index_str = "_" + index_str + "2D"; twoD = true; indexExp = buildAddOp(indexExp, buildMultiplyOp(buildVarRefExp(GIDY, indexScope), buildVarRefExp("_width", kernel_body))); } else if(dim == 3 ){ indexExp = buildAddOp(indexExp, buildMultiplyOp(buildVarRefExp(GIDY, indexScope), buildVarRefExp("_width", kernel_body))); indexExp = buildAddOp(indexExp, buildMultiplyOp(buildVarRefExp(GIDZ, indexScope), buildVarRefExp("_slice", kernel_body))); index_str = "_"+index_str + "3D"; threeD = true; } SgAssignInitializer* initIndex = buildAssignInitializer(indexExp); SgVariableDeclaration* index = buildVariableDeclaration(index_str, buildIntType(), initIndex, indexScope); //step 5 insert index expression in the kernel ROSE_ASSERT(index); insertStatementAfter(src_location, index ); //step 6 check if there is a loop, if there is we need to update the index //but we only update if the loop makes changes in the array reference std::vector<SgForStatement* > loopNest= SageInterface::querySubTree<SgForStatement>(kernel_body,V_SgForStatement); if(loopNest.size() > 0) { SgForStatement* loop = *(loopNest.begin()); SgBasicBlock* loop_body = isSgBasicBlock(loop->get_loop_body()); SgStatement* update_stmt = buildAssignStatement(buildVarRefExp(index),indexExp); ROSE_ASSERT(update_stmt); prependStatement(update_stmt, loop_body); } } }
void createGlobalIndexExpForAllArrays(SgScopeStatement* kernel_body, MintInitNameMapExpList_t refList, SgDeclarationStatement* src_location) { //we need to exclude the ones for shared memory //step 4 create an index expression for each distinct array //e.g. _gidx + _gidy * widthUnew in 2D //e.g. _gidx + _gidy * widthUnew + _gidz * sliceUnew in 3D ROSE_ASSERT(src_location); SgScopeStatement* indexScope= src_location->get_scope(); SgVariableSymbol* gidz_sym = MintArrayInterface::getSymbolFromName(isSgBasicBlock(kernel_body), GIDZ); SgVariableSymbol* gidy_sym = MintArrayInterface::getSymbolFromName(isSgBasicBlock(kernel_body), GIDY); MintInitNameMapExpList_t::iterator arr; //for each array, create an index expression for(arr= refList.begin(); arr!= refList.end(); arr++) { SgInitializedName* iname = arr->first; int dim = MintArrayInterface::getDimension(iname); ROSE_ASSERT(dim <= 3); if(dim == 3 && gidz_sym == NULL) continue; //must be a boundary condition, we don't use index opt. optimization for those if(dim == 2 && gidy_sym == NULL) continue; //must be a boundary condition, we don't use index opt. optimization for those string arrStr = iname->get_name().str(); //_gidx + _gidy * widthUnew in 2D //_gidx + _gidy * widthUnew + _gidz * sliceUnew in 3D SgExpression* indexExp = NULL; indexExp = buildVarRefExp(GIDX, indexScope); if(dim >= 2) indexExp = buildAddOp(indexExp, buildMultiplyOp(buildVarRefExp(GIDY, indexScope), buildVarRefExp("width"+arrStr, kernel_body))); if(dim == 3 ){ indexExp = buildAddOp(indexExp, buildMultiplyOp(buildVarRefExp(GIDZ, indexScope), buildVarRefExp("slice"+arrStr, kernel_body))); } SgAssignInitializer* initIndex = buildAssignInitializer(indexExp); SgVariableDeclaration* index = buildVariableDeclaration("index" + arrStr, buildIntType(), initIndex, indexScope); //step 5 insert index expression in the kernel ROSE_ASSERT(index); insertStatementAfter(src_location, index ); //step 6 check if there is a loop, if there is we need to update the index //but we only update if the loop makes changes in the array reference std::vector<SgForStatement* > loopNest= SageInterface::querySubTree<SgForStatement>(kernel_body,V_SgForStatement); if(loopNest.size() > 0) { SgForStatement* loop = *(loopNest.begin()); SgBasicBlock* loop_body = isSgBasicBlock(loop->get_loop_body()); SgStatement* update_stmt = buildAssignStatement(buildVarRefExp(index),indexExp); ROSE_ASSERT(update_stmt); prependStatement(update_stmt, loop_body); } } }
bool processStatements(SgNode* n) { ROSE_ASSERT (n!=NULL); // Skip compiler generated code, system headers, etc. if (isSgLocatedNode(n)) { if (isSgLocatedNode(n)->get_file_info()->isCompilerGenerated()) return false; } // For C/C++ loops if (isSgForStatement(n)!=NULL){ SgForStatement* loop = isSgForStatement(n); SgScopeStatement* scope = loop->get_scope(); ROSE_ASSERT(scope != NULL); if (running_mode == e_analysis_and_instrument) instrumentLoopForCounting (loop); else if (running_mode == e_static_counting) { CountFPOperations (loop->get_loop_body()); // verify the counting results are consistent with reference results from pragmas if (SgStatement* prev_stmt = getPreviousStatement(loop)) { if (isSgPragmaDeclaration(prev_stmt)) { FPCounters* ref_result = getFPCounters (prev_stmt); FPCounters* current_result = getFPCounters (loop->get_loop_body()); if (ref_result != NULL) { if (!current_result->consistentWithReference (ref_result)) { cerr<<"Error. Calculated FP operation counts differ from reference counts parsed from pragma!"<<endl; ref_result->printInfo("Reference counts are ...."); current_result->printInfo("Calculated counts are ...."); } assert (current_result->consistentWithReference (ref_result)); } else { // I believe ref_result should be available at this point assert (false); } } } // end verification } } // Get reference FP operation counting values from pragma, if available. // This is no longer useful since we use bottomup traversal!! // We should split this into another phase!! else if (isSgPragmaDeclaration(n)) { FPCounters* result = parse_aitool_pragma(isSgPragmaDeclaration(n)); if (result != NULL) { isSgPragmaDeclaration(n) -> setAttribute("FPCounters", result); if (debug) { FPCounters* result2 = getFPCounters (isSgLocatedNode(n)); result2->printInfo("After set and getFPCounters"); } } } // Now Fortran support else if (SgFortranDo* doloop = isSgFortranDo(n)) { instrumentLoopForCounting (doloop); } return true; }
POETCode* POETAstInterface::Ast2POET(const Ast& n) { static SgTemplateInstantiationFunctionDecl* tmp=0; SgNode* input = (SgNode*) n; if (input == 0) return EMPTY; POETCode* res = POETAstInterface::find_Ast2POET(input); if (res != 0) return res; { SgProject* sageProject=isSgProject(input); if (sageProject != 0) { int filenum = sageProject->numberOfFiles(); for (int i = 0; i < filenum; ++i) { SgSourceFile* sageFile = isSgSourceFile(sageProject->get_fileList()[i]); SgGlobal *root = sageFile->get_globalScope(); SgDeclarationStatementPtrList declList = root->get_declarations (); POETCode* curfile = ROSE_2_POET_list(declList, 0, tmp); curfile = new POETCode_ext(sageFile, curfile); POETAstInterface::set_Ast2POET(sageFile, curfile); res=LIST(curfile, res); } POETAstInterface::set_Ast2POET(sageProject,res); return res; } } { SgBasicBlock* block = isSgBasicBlock(input); if (block != 0) { res=ROSE_2_POET_list(block->get_statements(), res, tmp); POETAstInterface::set_Ast2POET(block, res); return res; } } { SgExprListExp* block = isSgExprListExp(input); if (block != 0) { res=ROSE_2_POET_list(block->get_expressions(), 0, tmp); POETAstInterface::set_Ast2POET(block, res); return res; } } { SgForStatement *f = isSgForStatement(input); if (f != 0) { POETCode* init = ROSE_2_POET_list(f->get_for_init_stmt()->get_init_stmt(),0, tmp); POETCode* ctrl = new POETCode_ext(f, TUPLE3(init,Ast2POET(f->get_test_expr()), Ast2POET(f->get_increment()))); res = CODE_ACC("Nest", PAIR(ctrl,Ast2POET(f->get_loop_body()))); POETAstInterface::set_Ast2POET(input, res); return res; } } { SgVarRefExp * v = isSgVarRefExp(input); if (v != 0) { res = STRING(v->get_symbol()->get_name().str()); POETAstInterface::set_Ast2POET(input, res); return res; } } { SgMemberFunctionRefExp * v = isSgMemberFunctionRefExp(input); if (v != 0) { res = STRING(v->get_symbol()->get_name().str()); POETAstInterface::set_Ast2POET(input, res); return res; } } { SgIntVal * v = isSgIntVal(input); if (v != 0) { res = ICONST(v->get_value()); POETAstInterface::set_Ast2POET(input, res); return res; } } { SgInitializedName* var = isSgInitializedName(input); if (var != 0) { POETCode* name = STRING(var->get_name().str()); POETCode* init = Ast2POET(var->get_initializer()); res = new POETCode_ext(var, PAIR(name,init)); POETAstInterface::set_Ast2POET(input, res); return res; } } /* { std::string fname; AstInterface::AstList params; AstNodeType returnType; AstNodePtr body; if (AstInterface :: IsFunctionDefinition( input, &fname, ¶ms, (AstInterface::AstList*)0, &body, (AstInterface::AstTypeList*)0, &returnType)) { if (body != AST_NULL) std::cerr << "body not empty:" << fname << "\n"; POETCode* c = TUPLE4(STRING(fname), ROSE_2_POET_list(0,params,0), STRING(AstInterface::GetTypeName(returnType)), Ast2POET(body.get_ptr())); res = new POETCode_ext(input, c); POETAstInterface::set_Ast2POET(input,res); return res; } } */ AstInterface::AstList c = AstInterface::GetChildrenList(input); switch (input->variantT()) { case V_SgCastExp: case V_SgAssignInitializer: res = Ast2POET(c[0]); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgDotExp: { POETCode* v1 = Ast2POET(c[1]); if (dynamic_cast<POETString*>(v1)->get_content() == "operator()") return Ast2POET(c[0]); res = CODE_ACC("Bop",TUPLE3(STRING("."), Ast2POET(c[0]), v1)); return res; } case V_SgLessThanOp: res = CODE_ACC("Bop",TUPLE3(STRING("<"),Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgSubtractOp: res = CODE_ACC("Bop",TUPLE3(STRING("-"),Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgAddOp: res = CODE_ACC("Bop",TUPLE3(STRING("+"),Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgMultiplyOp: res = CODE_ACC("Bop",TUPLE3(STRING("*"),Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgDivideOp: res = CODE_ACC("Bop",TUPLE3(STRING("/"),Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgAssignOp: res = CODE_ACC("Assign",PAIR(Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgFunctionCallExp: res = CODE_ACC("FunctionCall",PAIR(Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; } POETCode * c2 = 0; if (tmp == 0) tmp=isSgTemplateInstantiationFunctionDecl(input); switch (c.size()) { case 0: break; case 1: c2 = Ast2POET(c[0]); break; case 2: c2 = PAIR(Ast2POET(c[0]),Ast2POET(c[1])); break; case 3: c2 = TUPLE3(Ast2POET(c[0]),Ast2POET(c[1]),Ast2POET(c[2])); break; case 4: c2 = TUPLE4(Ast2POET(c[0]),Ast2POET(c[1]),Ast2POET(c[2]),Ast2POET(c[3])); break; default: //std::cerr << "too many children: " << c.size() << ":" << input->unparseToString() << "\n"; c2 = EMPTY; } if (tmp == input) tmp = 0; res = new POETCode_ext(input, c2); POETAstInterface::set_Ast2POET(input,res); return res; }
bool ClastToSage::insertPragmas(SgNode* root) { // 1- Collect the list of outer-parallel loop iterators specified // by pluto, as given by the .pragmas file. Grammar is: 1 line per // iterator, "ITER \SPACE PRAGMA STRING \ENDLNE" std::ifstream plutofile; plutofile.open(".pragmas"); std::vector<std::string> ompLoopIterators; if (plutofile) { std::string iter; char junk[256]; while (plutofile >> iter) { ompLoopIterators.push_back(iter); plutofile.getline(junk, 256); } plutofile.close(); } // 2- Collect the list of inner-parallel loop iterators specified // by pluto, as given by the .vectorize file. Grammar is: 1 line per // iterator, "ITER\ENDLINE" plutofile.open(".vectorize"); std::vector<std::string> simdLoopIterators; if (plutofile) { std::string iter; char junk[256]; while (plutofile >> iter) { simdLoopIterators.push_back(iter); plutofile.getline(junk, 256); } plutofile.close(); } // 3- Collect all for loops. std::vector<SgNode*> forLoops = NodeQuery::querySubTree(root, V_SgForStatement); std::set<std::string>::const_iterator i; std::set<std::string> allIterators; allIterators.insert(ompLoopIterators.begin(), ompLoopIterators.end()); allIterators.insert(simdLoopIterators.begin(), simdLoopIterators.end()); // 4- Iterate on all dimensions to parallelize. for (i = allIterators.begin(); i != allIterators.end(); ++i) { SgName iterName(*i); SgSymbol* iterSymb = isSgScopeStatement(root)->lookup_symbol(iterName); if (iterSymb == NULL) { // The loop iterator symbol does not exist. Typical case // where the tile size exceeds the iteration domain size: // there is only one parallel iteration, thus no loop, // thus no iterator. Safely proceed to the next loop iterator. continue; } std::vector<SgNode*>::const_iterator j; for (j = forLoops.begin(); j != forLoops.end(); ++j) { SgForStatement* fornode = isSgForStatement(*j); ROSE_ASSERT(fornode); // Get the loop iterator. SgVariableSymbol* forSymb = SageTools::getLoopIteratorSymbol(fornode); ROSE_ASSERT(forSymb); if (forSymb == iterSymb) { std::string pragmaClause; if (std::find(simdLoopIterators.begin(), simdLoopIterators.end(),*i) != simdLoopIterators.end()) { // This is a SIMDizable loop. // For a vectorizable and parallelizable dimension, // vectorization has precedence. pragmaClause = "#pragma ivdep\n#pragma vector always"; } else if (std::find(ompLoopIterators.begin(), ompLoopIterators.end(), *i) != ompLoopIterators.end()) { // This is an OpenMP parallelizable loop. // Collect all loop iterator names in the enclosed loops std::vector<SgNode*> innerLoops = NodeQuery::querySubTree(fornode->get_loop_body(), V_SgForStatement); // Create the pragma clause. pragmaClause = "#pragma omp parallel for"; bool first = true; std::vector<SgNode*>::const_iterator k; std::set<SgVariableSymbol*> loopSymbols; for (k = innerLoops.begin(); k != innerLoops.end(); ++k) loopSymbols.insert(SageTools::getLoopIteratorSymbol (isSgForStatement(*k))); if (loopSymbols.size() > 0) pragmaClause = pragmaClause + " private("; std::set<SgVariableSymbol*>::const_iterator l; for (l = loopSymbols.begin(); l != loopSymbols.end(); ++l) { std::string iterName = (*l)->get_name().getString(); if (first) { pragmaClause = pragmaClause + iterName; first = false; } else pragmaClause = pragmaClause + ", " + iterName; } if (loopSymbols.size() > 0) pragmaClause = pragmaClause + ")"; } else { // Should never occur. ROSE_ASSERT(0); } // Annotate the for node with the pragma clause. SageInterface::attachArbitraryText(fornode, pragmaClause, PreprocessingInfo::before); // Put loop lower bound and upper bound outside the loop // (OpenMp does not like complex loop bounds). /// LNP: FIXME: do it if it becomes needed. } } } return true; }
ExprSynAttr *examineStatement(SgStatement *stmt, ostream &out) { SgExpression *expr; SgExprStatement *expr_stmt; ExprSynAttr *expr_attr = NULL; ExprSynAttr *attr1 = NULL; stringstream fake; int i; if (NULL == stmt) return NULL; //out << "/* " << stmt->unparseToString() << " */" << endl; switch(stmt->variantT()) { case V_SgExprStatement: { expr_stmt = isSgExprStatement(stmt); expr_attr = examineExpr(expr_stmt->get_expression(), fake); //out << ";"; if (NULL != expr_attr) { expr_attr->output_comments(out); } break; } case V_SgVariableDeclaration: { SgVariableDeclaration *vardecl = isSgVariableDeclaration(stmt); expr_attr = examineVariableDeclaration(vardecl, out); break; } case V_SgBreakStmt: { out << "break;"; expr_attr->code << "break;"; break; } case V_SgContinueStmt: { out << "continue;"; expr_attr->code << "continue;"; break; } case V_SgReturnStmt: { SgReturnStmt *retstmt = isSgReturnStmt(stmt); expr_attr = new ExprSynAttr(); out << "return "; expr = retstmt->get_expression(); if (expr) { attr1 = examineExpr(expr, out); expr_attr->union_tmp_decls(attr1); expr_attr->code << attr1->code.str(); } out << ";"; expr_attr->code << "return "; if (attr1) { expr_attr->result_var = attr1->result_var; expr_attr->code << expr_attr->result_var; } expr_attr->code << ";"; break; } case V_SgForStatement: { stringstream head; head << "for ("; SgForStatement *forstmt = isSgForStatement(stmt); SgStatementPtrList &init_stmt_list = forstmt->get_init_stmt(); SgStatementPtrList::const_iterator init_stmt_iter; for (init_stmt_iter = init_stmt_list.begin(); init_stmt_iter != init_stmt_list.end(); init_stmt_iter++) { stmt = *init_stmt_iter; if (init_stmt_iter != init_stmt_list.begin()) head << ", "; expr_stmt = isSgExprStatement(stmt); if (expr_stmt) examineExpr(expr_stmt->get_expression(), head); } head << "; "; expr_stmt = isSgExprStatement(forstmt->get_test()); if (expr_stmt) examineExpr(expr_stmt->get_expression(), head); head << "; "; expr = forstmt->get_increment(); examineExpr(expr, head); head << ")" << endl; /* Loop body */ stmt = forstmt->get_loop_body(); expr_attr = examineStatement(stmt, fake); attr1 = new ExprSynAttr(); attr1->code << head.str(); if (!isSgScopeStatement(stmt)) { attr1->code << "{" << endl; } expr_attr->output_tmp_decls(attr1->code); attr1->code << expr_attr->code.str(); if (!isSgScopeStatement(stmt)) { attr1->code << "}" << endl; } delete expr_attr; expr_attr = attr1; attr1 = NULL; out << head.str(); out << fake.str(); break; } case V_SgBasicBlock: { SgScopeStatement *scope = isSgScopeStatement(stmt); expr_attr = examineScopeStatement(scope, "scope", out); break; } case V_SgIfStmt: { stringstream head; SgIfStmt *ifstmt = isSgIfStmt(stmt); head << "if ("; stmt = ifstmt->get_conditional(); expr_stmt = isSgExprStatement(stmt); if (expr_stmt) { attr1 = examineExpr(expr_stmt->get_expression(), head); if (attr1 != NULL) delete attr1; } head << ")" << endl; out << head.str(); /* True body */ stmt = ifstmt->get_true_body(); expr_attr = examineStatement(stmt, fake); attr1 = new ExprSynAttr(); attr1->code << head.str(); if (!isSgScopeStatement(stmt)) { attr1->code << "{" << endl; } expr_attr->output_tmp_decls(attr1->code); attr1->code << expr_attr->code.str(); if (!isSgScopeStatement(stmt)) { attr1->code << "}" << endl; } delete expr_attr; expr_attr = attr1; attr1 = NULL; out << head.str(); out << fake.str(); /* False body */ stmt = ifstmt->get_false_body(); if (stmt) { out << endl << "else" << endl; expr_attr->code << endl << "else" << endl; attr1 = examineStatement(stmt, out); if (!isSgScopeStatement(stmt)) { expr_attr->code << "{" << endl; } attr1->output_tmp_decls(expr_attr->code); expr_attr->code << attr1->code.str(); if (!isSgScopeStatement(stmt)) { expr_attr->code << "}" << endl; } } break; } case V_SgWhileStmt: { stringstream head; SgWhileStmt *whilestmt = isSgWhileStmt(stmt); expr_stmt = isSgExprStatement(whilestmt->get_condition()); head << "while ("; if (expr_stmt) { attr1 = examineExpr(expr_stmt->get_expression(), head); if (NULL != attr1) delete attr1; } out << head.str() << ")" << endl; head << ")" << endl; if (!isSgScopeStatement(stmt)) { head << "{" << endl; } expr_attr = new ExprSynAttr(); expr_attr->code << head.str(); /* Loop Body */ stmt = whilestmt->get_body(); attr1 = examineStatement(stmt, out); attr1->output_tmp_decls(expr_attr->code); expr_attr->code << attr1->code.str(); if (!isSgScopeStatement(stmt)) { expr_attr->code << "}" << endl; } delete attr1; break; } case V_SgDoWhileStmt: { stringstream head; SgDoWhileStmt *dowhilestmt = isSgDoWhileStmt(stmt); expr_stmt = isSgExprStatement(dowhilestmt->get_condition()); stmt = dowhilestmt->get_body(); out << "do"; head << "do" << endl; if (!isSgScopeStatement(stmt)) { head << "{" << endl; } expr_attr = new ExprSynAttr(); expr_attr->code << head.str(); attr1 = examineStatement(stmt, out); attr1->output_tmp_decls(expr_attr->code); expr_attr->code << attr1->code.str(); if (!isSgScopeStatement(stmt)) { expr_attr->code << "}" << endl; } expr_attr->code << " while ("; delete attr1; out << " while ("; head.str(""); if (expr_stmt) { attr1 = examineExpr(expr_stmt->get_expression(), head); delete attr1; out << head.str(); expr_attr->code << head.str(); } out << ");" << endl; expr_attr->code << ");" << endl; break; } } return expr_attr; }
MySynthesizedAttribute MyTraversal::evaluateRewriteSynthesizedAttribute ( SgNode* astNode, MyInheritedAttribute inheritedAttribute, SubTreeSynthesizedAttributes synthesizedAttributeList ) { MySynthesizedAttribute returnAttribute; switch(astNode->variantT()) { case V_SgForStatement: { SgForStatement *forStat = isSgForStatement(astNode); cout << " found V_SgForStatement " << printPosition(astNode) << "" << endl; for(size_t i=0; i<mAllFors.size(); i++) { if((mAllFors[i]->blocked)&&(astNode == mAllFors[i]->forStmt)) { ostringstream newFor; newFor << "for("; newFor << (*(forStat->get_init_stmt().begin()))->unparseToString(); newFor << forStat->get_test_expr()->unparseToString() << ";" ; newFor << mAllFors[i]->varName << "+=" << mAllFors[i]->blockSize << ")\n" ; newFor << forStat->get_loop_body()->unparseToString(); cout << " is blocked loop..." << endl; returnAttribute.replace( astNode, newFor.str() ); } } } break; case V_SgVarRefExp: { cout << " found V_SgVarRefExp " << printPosition(astNode) << astNode->unparseToString() << endl; forBlockVector fors = inheritedAttribute.getForScopes(); // replace variable occurrences in the loop kernel if(inheritedAttribute.getLoopKernel()) { for(size_t i=0;i<fors.size(); i++) { if( ( strcmp( astNode->unparseToString().c_str(), fors[i]->varName.c_str() )==0 ) && ( isSgVarRefExp(astNode)->get_type() == fors[i]->varType ) ) { string blockedVarName("blocked_"); blockedVarName += fors[i]->varName; AstRestructure::unparserReplace( isSgVarRefExp(astNode), blockedVarName ); cout << " replacing with '"<<blockedVarName<<"' " << endl; } } } } break; default: break; } // node type bool synth = false; for( SubTreeSynthesizedAttributes::iterator i=synthesizedAttributeList.begin(); i!= synthesizedAttributeList.end(); i++ ) { if( (*i).getVarRefFound() ) synth = true; } if( synth ) { returnAttribute.setVarRefFound( true ); if(isSgStatement( astNode )) { cout << " new statement " << printPosition(astNode) << " : '" << astNode->unparseToString() << "' " << endl; returnAttribute.setVarRefFound( false ); //if(!isSgReturnStmt( astNode )) { // DEBUG, this should work!??!? returnAttribute.replace( astNode, astNode->unparseToString(), HighLevelCollectionTypedefs::LocalScope ); //} } } if(isSgScopeStatement(astNode)) { // dont replace variable in higher scopes... if(mReplaceVariable > 0) { mReplaceVariable--; cerr << "end of scope " << mReplaceVariable << endl; } } //if(astNode == mpLoopBody) { // FIXME why doesnt replace basic block work? if( (astNode->get_parent() == mpLoopBody)&&(inheritedAttribute.getLoopKernel()) ) { // we're back at the loop kernel block, now replace and insert new loops... insertTransformedLoopBody( astNode, returnAttribute, inheritedAttribute.getForScopes() ); } return returnAttribute; }
// Functions required by the tree traversal mechanism MyInheritedAttribute MyTraversal::evaluateRewriteInheritedAttribute ( SgNode* astNode, MyInheritedAttribute inheritedAttribute ) { MyInheritedAttribute returnAttribute = inheritedAttribute; switch(astNode->variantT()) { case V_SgForStatement: { cout << " found V_SgForStatement " << printPosition(astNode) << "" << endl; SgForStatement *forStat = isSgForStatement(astNode); forBlockInfo *inf = new forBlockInfo; inf->forStmt = forStat; SgInitializedName *varin = isSgInitializedName( forStat->get_traversalSuccessorContainer()[0] //for init ->get_traversalSuccessorContainer()[0] // var decl ->get_traversalSuccessorContainer()[0] // initialized name ); assert( varin ); inf->varName = varin->get_name().str(); inf->varType = varin->get_type(); inf->blocked = false; inf->blockSize = 0; returnAttribute.addForStatement( inf ); mAllFors.push_back( inf ); list<SgNode*> forList = NodeQuery::querySubTree( astNode, forStatementNodeQuery ); if( (forList.size()==1) && // only the current loop? (returnAttribute.getForScopes().size()>1) ) { cerr << " it is the innermost for loop " << endl; mpLoopBody = forStat->get_loop_body(); } } break; default: break; } if(astNode == mpLoopBody) { bool loopsValid = true; // do some basic checks for validity forBlockVector fors = returnAttribute.getForScopes(); for(size_t i=0;i<fors.size(); i++) { SgExpression *testExpr = fors[i]->forStmt->get_test_expr(); SgExpression *incExpr = fors[i]->forStmt->get_increment_expr(); if(isSgPlusPlusOp(incExpr) ==NULL) loopsValid = false; if(isSgLessThanOp(testExpr) ==NULL) loopsValid = false; else { if(! isSgVarRefExp(isSgLessThanOp(testExpr)->get_lhs_operand()) ) loopsValid = false; } } // this is the basic block of the innermost loop // only do trafos, if more than two nested loop nests, and we found the inner one if(loopsValid) { returnAttribute.setLoopKernel( true ); } else { cout << " loop nest not valid, skipping transformation..." << endl; } } if(isSgScopeStatement(astNode)) { // dont replace variable in higher scopes... if(mReplaceVariable > 0) { mReplaceVariable++; cerr << "nested scope found, #" << mReplaceVariable << endl; } } return returnAttribute; }