Ejemplo n.º 1
0
  //! 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; 
  }  
Ejemplo n.º 2
0
 size_t array::bytes() const
 {
     dim_t nElements;
     AF_THROW(af_get_elements(&nElements, get()));
     return nElements * getSizeOf(type());
 }