//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()
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; }