void setupMPIInit(SgSourceFile* cur_file) { //#include "mpi.h" SageInterface::insertHeader (cur_file, "mpi.h", false,true); SageInterface::insertHeader (cur_file, "libxomp_mpi.h", false, true); SgFunctionDeclaration* main_decl = findMain(cur_file); // TODO: handle multiple files, some of them don't have main() ROSE_ASSERT (main_decl != NULL); SgFunctionDefinition* main_def = main_decl->get_definition(); ROSE_ASSERT (main_def != NULL); SgBasicBlock* func_body = main_def->get_body(); ROSE_ASSERT (func_body != NULL); // Setup MPI SgStatement* decl_rank = buildStatementFromString("int _xomp_rank;", func_body); prependStatement(decl_rank, func_body); SgStatement* decl_nprocs= buildStatementFromString("int _xomp_nprocs;", func_body); prependStatement(decl_nprocs, func_body); // xomp_init_mpi (&argc, &argv, &_xomp_rank, &_xomp_nprocs); SgExprListExp * para_list = buildExprListExp (buildAddressOfOp (buildVarRefExp("argc", func_body)), buildAddressOfOp (buildVarRefExp("argv", func_body)), buildAddressOfOp (buildVarRefExp("_xomp_rank", func_body)), buildAddressOfOp (buildVarRefExp("_xomp_nprocs", func_body)) ); SgExprStatement* mpi_init_stmt = buildFunctionCallStmt ("xomp_init_mpi", buildIntType(), para_list, func_body); // SgStatement* last_decl = findLastDeclarationStatement (func_body); insertStatementAfter (decl_rank, mpi_init_stmt); }
// handle OpenMP private variables // pSyms: private variable set // scope: the scope of a private variable's local declaration // private_remap: a map between the original variables and their private copies static void handlePrivateVariables( const ASTtools::VarSymSet_t& pSyms, SgScopeStatement* scope, VarSymRemap_t& private_remap) { // -------------------------------------------------- for (ASTtools::VarSymSet_t::const_reverse_iterator i = pSyms.rbegin (); i != pSyms.rend (); ++i) { const SgInitializedName* i_name = (*i)->get_declaration (); ROSE_ASSERT (i_name); string name_str = i_name->get_name ().str (); SgType * v_type = i_name->get_type(); SgVariableDeclaration* local_var_decl = buildVariableDeclaration(name_str, v_type, NULL, scope); prependStatement (local_var_decl,scope); recordSymRemap (*i, local_var_decl, scope, private_remap); } }
/** * @brief Adds @a var as a new local variable of @a func, possibly with an * initializer @a init. * * An advatage of using this function over manually adding @a var to @a func is * that this function also creates a VarDefStmt at the beginning of @a func, and * places it in a proper place so that all VarDefStmts at the beginning of @a * func are sorted alphabetically. * * If @a var is already a local function of @a func, this function does nothing. * * @par Preconditions * - @a func is a definition, not a declaration */ void addLocalVarToFunc(ShPtr<Variable> var, ShPtr<Function> func, ShPtr<Expression> init) { PRECONDITION(func->isDefinition(), "it has to be a definition"); if (func->hasLocalVar(var)) { return; } func->addLocalVar(var); // Insert a variable-defining statement to a proper position at the // beginning of the function's body. // First, we find a proper position... auto stmt = func->getBody(); while (auto varDefStmt = cast<VarDefStmt>(stmt)) { if (varDefStmt->getVar()->getName() > var->getName() || !stmt->getSuccessor()) { break; } stmt = stmt->getSuccessor(); } // ...then, we place a VarDefStmt of var into that position. stmt->prependStatement(VarDefStmt::create(var, init)); }
//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 CudaOutliner::functionParameterHandling(ASTtools::VarSymSet_t& syms, // regular (shared) parameters MintHostSymToDevInitMap_t hostToDevVars, const ASTtools::VarSymSet_t& pdSyms, // those must use pointer dereference const ASTtools::VarSymSet_t& pSyms, // private variables, handles dead variables (neither livein nor liveout) std::set<SgInitializedName*> & readOnlyVars, std::set<SgInitializedName*> & liveOutVars, SgFunctionDeclaration* func) // the outlined function { //ASTtools::VarSymSet_t syms; //std::copy(syms1.begin(), syms1.end(), std::inserter(syms,syms.begin())); VarSymRemap_t sym_remap; // variable remapping for regular(shared) variables VarSymRemap_t private_remap; // variable remapping for private/firstprivate/reduction variables ROSE_ASSERT (func); SgFunctionParameterList* params = func->get_parameterList (); ROSE_ASSERT (params); SgFunctionDefinition* def = func->get_definition (); ROSE_ASSERT (def); SgBasicBlock* body = def->get_body (); ROSE_ASSERT (body); // Place in which to put new outlined variable symbols. SgScopeStatement* args_scope = isSgScopeStatement (body); ROSE_ASSERT (args_scope); // For each variable symbol, create an equivalent function parameter. // Also create unpacking and repacking statements. int counter=0; // SgInitializedName* parameter1=NULL; // the wrapper parameter SgVariableDeclaration* local_var_decl = NULL; // handle OpenMP private variables/ or those which are neither live-in or live-out handlePrivateVariables(pSyms, body, private_remap); // -------------------------------------------------- // for each parameters passed to the outlined function // They include parameters for regular shared variables and // also the shared copies for firstprivate and reduction variables for (ASTtools::VarSymSet_t::reverse_iterator i = syms.rbegin ();i != syms.rend (); ++i) { // Basic information about the variable to be passed into the outlined function // Variable symbol name const SgInitializedName* i_name = (*i)->get_declaration (); ROSE_ASSERT (i_name); string name_str = i_name->get_name ().str (); SgName p_sg_name ( name_str); //SgType* i_type = i_name->get_type (); bool readOnly = false; if (readOnlyVars.find(const_cast<SgInitializedName*> (i_name)) != readOnlyVars.end()) readOnly = true; // step 1. Create parameters and insert it into the parameter list. // ---------------------------------------- SgInitializedName* p_init_name = NULL; SgVariableSymbol* host_sym= const_cast<SgVariableSymbol*> (*i); if(hostToDevVars.find(host_sym) != hostToDevVars.end() ){ //these are vector variables SgInitializedName* dev_name = hostToDevVars[host_sym]; p_init_name = createInitName (dev_name->get_name(), dev_name->get_type(), func, def); ROSE_ASSERT (p_init_name); prependArg(func->get_parameterList (),p_init_name); } else{ //scalar values p_init_name = createOneFunctionParameter(i_name, readOnly, func); } // step 2. Create unpacking/unwrapping statements, also record variables to be replaced // ---------------------------------------- // bool isPointerDeref = false; if (Outliner::enable_classic) { // classic methods use parameters directly, no unpacking is needed if (!readOnly) //read only variable should not have local variable declaration, using parameter directly // taking advantage of the same parameter names for readOnly variables // Let postprocessing to patch up symbols for them { // non-readonly variables need to be mapped to their parameters with different names (p__) // remapVarSyms() will use pointer dereferencing for all of them by default in C, // this is enough to mimic the classic outlining work //handleSharedVariables(*i, p_init_name, args_scope, sym_remap); //handleSharedVariables(*i, body, sym_remap); //Didem: I comment out this part because it uses pointer deferencing for all non-readonly variables. //recordSymRemap(*i,p_init_name, args_scope, sym_remap); } } else { local_var_decl = NULL; //createUnpackDecl (p_init_name, counter, isPointerDeref, i_name , NULL, body); ROSE_ASSERT (local_var_decl); prependStatement (local_var_decl,body); // regular and shared variables used the first local declaration recordSymRemap (*i, local_var_decl, args_scope, sym_remap); // transfer the value for firstprivate variables. } // step 3. Create and insert companion re-pack statement in the end of the function body // If necessary // ---------------------------------------- SgInitializedName* local_var_init = NULL; if (local_var_decl != NULL ) local_var_init = local_var_decl->get_decl_item (SgName (name_str.c_str ())); if (!SageInterface::is_Fortran_language() && !Outliner::enable_classic) ROSE_ASSERT(local_var_init!=NULL); SgExprStatement* pack_stmt = createPackStmt (local_var_init); if (pack_stmt) appendStatement (pack_stmt,body); counter ++; } //end for // variable substitution SgBasicBlock* func_body = func->get_definition()->get_body(); remapVarSyms (sym_remap, pdSyms, private_remap , func_body); }