//! Return an expression like 8*sizeof(int)+ 3*sizeof(float) + 5*sizeof(double) for a list of variables accessed (either read or write) // For array variable, we should only count a single element access, not the entire array size // Algorithm: // Iterate on each variable in the set // group them into buckets based on types, using a map<SgType*, int> to store this // Iterate the list of buckets to generate count*sizeof(type) + .. expression SgExpression* calculateBytes (std::set<SgInitializedName*>& name_set, SgScopeStatement* scope, bool isRead) { SgExpression* result = NULL; if (name_set.size()==0) return result; // the input is essentially the loop body, a scope statement ROSE_ASSERT (scope != NULL); // We need to record the associated loop info. SgStatement* loop= NULL; SgForStatement* forloop = isSgForStatement(scope->get_scope()); SgFortranDo* doloop = isSgFortranDo(scope->get_scope()); if (forloop) loop = forloop; else if (doloop) loop = doloop; else { cerr<<"Error in CountLoadStoreBytes (): input is not loop body type:"<< scope->class_name()<<endl; assert(false); } std::map<SgType* , int> type_based_counters; // get all processed variables by inner loops std::set<SgInitializedName*> processed_var_set; getVariablesProcessedByInnerLoops (scope, isRead, processed_var_set); // fill in the type-based counters std::set<SgInitializedName*>::iterator set_iter; for (set_iter = name_set.begin(); set_iter != name_set.end(); set_iter++) { SgInitializedName* init_name = *set_iter; // skip visited variable when processing inner loops // some global variables may be visited by another function // But we should count it when processing the current function! // // We group all references to a same variable into one reference for now // if a variable is considered when processing inner loops, the variable // will be skipped when processing outer loops. if (isRead) { // if inner loops already processed it, skip it if (processed_var_set.find(init_name) != processed_var_set.end()) continue; else LoopLoadVariables[loop].insert(init_name); } else { if (processed_var_set.find(init_name) != processed_var_set.end()) continue; else LoopStoreVariables[loop].insert(init_name); } // It is tricky here, TODO consider pointer, typedefs, reference, modifier types SgType* stripped_type = (*set_iter)->get_type()->stripTypedefsAndModifiers(); SgType* base_type = NULL; if (isScalarType(stripped_type)) base_type = stripped_type; else if (isSgArrayType(stripped_type)) { // we may have multi-dimensional arrays like int a[][][]; base_type = stripped_type; do { base_type = isSgArrayType(base_type)->get_base_type(); } while (isSgArrayType (base_type)); } else { cerr<<"Error in calculateBytes(). Unhandled stripped type:"<<stripped_type->class_name()<<endl; assert (false); } type_based_counters[base_type] ++; } // end for // use the type-based counters for byte calculation std::map<SgType* , int>::iterator citer; //It is possible now to have zero after filtering out redundant variables //assert (type_based_counters.size()>0); for (citer = type_based_counters.begin(); citer !=type_based_counters.end(); citer ++) { SgType* t = (*citer).first; // at this point, we should not have array types any more ROSE_ASSERT (isSgArrayType (t) == false); int count = (*citer).second; assert (t != NULL); assert (count>0); SgExpression* sizeof_exp = NULL; if (is_Fortran_language()) { #if 0 // this does not work. cannot find func symbol for sizeof() // In Fortran sizeof() is a function call, not SgSizeOfOp. // type name is a variable in the AST, // Too much trouble to build assert (scope !=NULL); // This does not work //SgFunctionSymbol* func_sym = lookupFunctionSymbolInParentScopes(SgName("sizeof"), scope); SgGlobal* gscope = getGlobalScope (scope); assert (gscope !=NULL); SgFunctionSymbol* func_sym = gscope->lookup_function_symbol(SgName("sizeof")); assert (func_sym!=NULL); SgVarRefExp* type_var = buildVarRefExp( t->unparseToString(), scope ); assert (type_var !=NULL); sizeof_exp = buildFunctionCallExp (func_sym, buildExprListExp(type_var)); #else // sizeof is not an operator in Fortran, there is no unparsing support for this // sizeof_exp = buildSizeOfOp(t); // Directly obtain an integer size value sizeof_exp = buildIntVal(getSizeOf(t)); #endif } else if (is_C_language() || is_C99_language() || is_Cxx_language()) { sizeof_exp = buildSizeOfOp(t); } else { cerr<<"Error in calculateBytes(). Unsupported programming language other than C/Cxx and Fortran. "<<endl; assert (false); } SgExpression* mop = buildMultiplyOp(buildIntVal(count), sizeof_exp); if (result == NULL) result = mop; else result = buildAddOp(result, mop); } return result; }
size_t array::bytes() const { dim_t nElements; AF_THROW(af_get_elements(&nElements, get())); return nElements * getSizeOf(type()); }