void CudaOptimizer::applyRegisterOpt(SgFunctionDeclaration* kernel, std::set<SgInitializedName*> readOnlyVars, const MintArrFreqPairList_t& candidateVarsShared, const MintArrFreqPairList_t& candidateVarsReg, const bool optUnrollZ) { //perform register optimizations, go through each element in the candidate list //the list is in decending order based on the number of references bool optShared = MintOptions::GetInstance()->isSharedOpt(); MintArrFreqPairList_t::const_iterator it; for(it = candidateVarsReg.begin(); it != candidateVarsReg.end(); it++) { MintArrFreqPair_t apair = (*it); SgInitializedName* array = apair.first; ROSE_ASSERT(array); int freq = apair.second; MintArrFreqPairList_t::const_iterator it2; bool alsoShared = false; for(it2 = candidateVarsShared.begin(); it2 != candidateVarsShared.end(); it2++){ SgInitializedName* name = (*it2).first; if(name == array){ alsoShared = true; break; } } //if we slide the planes, we perform the register opt to that variable later //but if shared is ON, unroll is false, then we still perform register opt first //TODO: Check if that includes the shared memory opt only ? Yes, shared should be ON to skip this opt if( optShared && alsoShared && optUnrollZ ){ continue; } //TODO: should I put a limit about how many variables should be put into the registers? if(freq > 0 ) //should I set it to 1? { cout << " INFO:Mint: Candidate variable for register opt ("<< array->get_name().str() << ")"; cout << " with # of refs : "<< freq<< endl ; cout << " INFO:Mint: Applying register optimization to array ("<< array->get_name().str() << ")"<< endl; OnChipMemoryOpt::registerOptimizer(readOnlyVars, kernel, array); } //We want to put that variable in register, if we apply shared memory optimization else if(alsoShared && optShared ) { cout << " INFO:Mint: Candidate variable for register opt ("<< array->get_name().str() << ")"; cout << " with # of refs : "<< freq<< endl ; cout << " INFO:Mint: Applying register optimization to array ("<< array->get_name().str() << ")"<< endl; OnChipMemoryOpt::registerOptimizer(readOnlyVars, kernel, array, NULL, true); } }//end of for }
/** * Use visually distinct identifiers * * \note also checks DCL31-C */ bool DCL02_C( const SgNode *node ) { static std::map<const SgScopeStatement *, std::set<std::string> > scopeMap; static std::map<std::string, const SgInitializedName *> strVarMap; const SgScopeStatement *scope = isSgScopeStatement(node); if (!scope) return false; bool violation = false; if (isSgGlobal(scope)) { std::set<std::string> externNames; /** populate scopeMap */ FOREACH_SUBNODE(scope, nodes, i, V_SgInitializedName) { SgInitializedName *var = isSgInitializedName(*i); assert(var); if (isCompilerGeneratedNode(var) || !isSgDeclarationStatement(var->get_parent()) || findParentOfType(var, SgCtorInitializerList) || findParentOfType(var, SgClassDeclaration) // Might be too strong || var->get_name().getString().empty() || (var->get_name().getString().substr(0,2) == "__")) continue; /** Ignore function prototypes */ const SgFunctionDeclaration * fnDecl = findParentOfType(var, SgFunctionDeclaration); if (fnDecl && !fnDecl->get_definition()) continue; if (isExternVar(var)) { if (externNames.find(var->get_name().getString()) != externNames.end()) continue; externNames.insert(var->get_name().getString()); } const SgScopeStatement *varScope = var->get_scope(); std::string str (normalize_string(var->get_name().str(), isExternVar(var))); if (scopeMap[varScope].find(str) != scopeMap[varScope].end()) { DCL02_report_error(var); violation = true; } else { scopeMap[varScope].insert(str); strVarMap[str] = var; } } return false; }
void visitorTraversal::visit(SgNode* n) { // There are three types ir IR nodes that can be queried for scope: // - SgStatement, and // - SgInitializedName SgStatement* statement = isSgStatement(n); if (statement != NULL) { SgScopeStatement* scope = statement->get_scope(); ROSE_ASSERT(scope != NULL); printf ("SgStatement = %12p = %30s has scope = %12p = %s (total number = %d) \n", statement,statement->class_name().c_str(), scope,scope->class_name().c_str(),(int)scope->numberOfNodes()); } SgInitializedName* initializedName = isSgInitializedName(n); if (initializedName != NULL) { SgScopeStatement* scope = initializedName->get_scope(); ROSE_ASSERT(scope != NULL); printf ("SgInitializedName = %12p = %30s has scope = %12p = %s (total number = %d)\n", initializedName,initializedName->get_name().str(), scope,scope->class_name().c_str(),(int)scope->numberOfNodes()); } }
// Check if this is an A++ Array Reference bool isAPPArray(SgNode *astNode) { SgVarRefExp* varRefExp = isSgVarRefExp(astNode); if (varRefExp == NULL) return false; SgVariableSymbol* variableSymbol = varRefExp->get_symbol(); ROSE_ASSERT(variableSymbol != NULL); SgInitializedName* initializedName = variableSymbol->get_declaration(); ROSE_ASSERT(initializedName != NULL); SgName variableName = initializedName->get_name(); // Now compute the offset to the index objects (form a special query for this???) SgType* type = variableSymbol->get_type(); ROSE_ASSERT(type != NULL); string typeName = TransformationSupport::getTypeName(type); ROSE_ASSERT(typeName.c_str() != NULL); // Recognize only these types at present if (typeName == "intArray" || typeName == "floatArray" || typeName == "doubleArray") { return true; } return false; }
/* * Fix OP function calls and inject debug names */ void OPSource::fixOpStructs(SgNode *n) { SgInitializedName* initname = isSgInitializedName(n); if(initname) { string var_name = initname->get_name().getString(); SgConstructorInitializer *initer = isSgConstructorInitializer(initname->get_initializer()); if(initer) { string class_name = initer->get_class_decl()->get_name().getString(); if(class_name.find("op_dat") != string::npos || class_name.find("op_dat_gbl") != string::npos || class_name.compare("_op_ptr") == 0 || class_name.compare("_op_set") == 0 || class_name.compare("_op_dat_const") == 0) { cout << "---Injecting Debug Name: " << var_name << "---" << endl; SgExprListExp* list = initer->get_args(); SgExpressionPtrList &exprs = list->get_expressions(); if( isSgStringVal(exprs.back()) == NULL ) { list->append_expression(buildStringVal(var_name)); } } } } }
NameQuerySynthesizedAttributeType NameQuery::queryNameUnionFieldNames (SgNode * astNode) { ROSE_ASSERT (astNode != 0); NameQuerySynthesizedAttributeType returnNameList; // SgNode *sageReturnNode = NULL; SgClassDefinition *sageClassDefinition = isSgClassDefinition (astNode); if (sageClassDefinition != NULL) { ROSE_ASSERT (sageClassDefinition->get_declaration () != NULL); if (sageClassDefinition->get_declaration ()->get_class_type () == SgClassDeclaration::e_struct) { SgDeclarationStatementPtrList declarationStatementPtrList = sageClassDefinition->get_members (); typedef SgDeclarationStatementPtrList::iterator LI; for (LI i = declarationStatementPtrList.begin (); i != declarationStatementPtrList.end (); ++i) { SgNode *listElement = *i; SgVariableDeclaration *sageVariableDeclaration = isSgVariableDeclaration (listElement); if (sageVariableDeclaration != NULL) { typedef SgInitializedNamePtrList::iterator INITLI; SgInitializedNamePtrList sageInitializedNameList = sageVariableDeclaration->get_variables (); for (INITLI i = sageInitializedNameList.begin (); i != sageInitializedNameList.end (); ++i) { SgInitializedName* initializedListElement = *i; ROSE_ASSERT (isSgInitializedName (initializedListElement) != NULL); returnNameList.push_back (initializedListElement->get_name().str()); } /* End iteration over declarationStatementPtrList */ } /* End iteration over declarationStatementPtrList */ } } } return returnNameList; } /* End function queryUnionFieldNames() */
void BasicProgmemTransform::convertVarDeclToProgmemDecl(SgVariableDeclaration *varDecl) { printf("converting %s\n", varDecl->unparseToString().c_str()); std::string dec = "const char "; SgInitializedName *initName = varDecl->get_variables()[0]; std::string literal = isSgAssignInitializer(initName->get_initializer())->get_operand()->unparseToString(); dec += initName->get_name().getString() + "[] PROGMEM =" + literal + ";"; insertPreprocessingInfo(dec); SageInterface::removeStatement(varDecl, true); }
int main(int argc, char** argv) { SgProject* proj = frontend(argc, argv); // Set up the struct layout chain initUpcSizes(); CustomizedPrimitiveTypeLayoutGenerator gen1_upc(NULL,&upc_sizes); NonpackedTypeLayoutGenerator gen_upc(&gen1_upc); // Process every type used in a variable or parameter declaration vector<SgNode*> initNames = NodeQuery::querySubTree(proj, V_SgInitializedName); for (size_t i = 0; i < initNames.size(); ++i) { SgInitializedName* in = isSgInitializedName(initNames[i]); SgType* t = in->get_type(); if (isSgTypeEllipse(t)) continue; cout << in->get_name().getString() << " has type " << t->unparseToString() << ":\n"; cout << "For a customized UPC platform:\n"; cout << gen_upc.layoutType(t) << "\n"; size_t size = gen_upc.layoutType(t).size; size_t element_size=size; if (isSgArrayType(t)) element_size = gen_upc.layoutType( SageInterface::getArrayElementType(isSgArrayType(t))).size; #if 0 if (isSgArrayType(t)) { cout<<"Found an array, output its element type info."<<endl; cout<< gen_upc.layoutType(SageInterface::getArrayElementType(isSgArrayType(t)))<<endl; // Array of shared UPC elements } #endif if (isUpcSharedType(t)) { size_t block_bytes = SageInterface::getUpcSharedBlockSize(t); if (!isSgArrayType(t) || block_bytes == 0) { block_bytes = size; } else {block_bytes = min (block_bytes*element_size, size);} size_t num_blocks = (size % block_bytes==0)?(size/block_bytes):size/block_bytes +1; int hasThreads=0; if (isSgArrayType(t)) if (isUpcArrayWithThreads(isSgArrayType(t))) hasThreads =1; cout<<"Found a shared UPC type: block bytes="<<block_bytes <<" Number of block="<<num_blocks <<" Multiply by THREADS="<<hasThreads <<" Element size="<<element_size <<endl; } // UPC shared types } // end for return 0; }
/** * class: SgVarRefExp * term: var_ref_exp_annotation(tpe,name,static,scope) * arg tpe: type * arg name: name * arg static: wether the declaration was static * arg scope: scope name (either from a namespace, a class or "null") */ PrologCompTerm* RoseToTerm::getVarRefExpSpecific(SgVarRefExp* vr) { SgInitializedName* n = vr->get_symbol()->get_declaration(); /* type: in general, this can be taken "as is" from the ROSE AST. However, * ROSE (up to 0.9.4a-8xxx at least) gets a detail wrong: a declaration * like "int arr[]" as a function parameter declares a *pointer*, not an * array. Thus we check whether the variable might be of this sort, and if * yes, we must make a pointer type for it. */ PrologTerm* typeSpecific = NULL; SgInitializedName* vardecl = vr->get_symbol()->get_declaration(); SgType* t = vr->get_type()->stripType(SgType::STRIP_MODIFIER_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_TYPEDEF_TYPE); if (isSgFunctionParameterList(vardecl->get_parent()) && isSgArrayType(t)) { SgType* baseType = isSgArrayType(t)->get_base_type(); PrologTerm* baseTypeSpecific = getTypeSpecific(baseType); typeSpecific = new PrologCompTerm("pointer_type", /*1,*/ baseTypeSpecific); } else { typeSpecific = getTypeSpecific(n->get_typeptr()); } /* static? (relevant for unparsing if scope is a class)*/ PrologTerm *isStatic; SgDeclarationStatement* vdec = n->get_declaration(); if (vdec != NULL) { isStatic = getEnum(vdec->get_declarationModifier().get_storageModifier().isStatic(), re.static_flags); } else { isStatic = getEnum(0, re.static_flags); } PrologTerm* scope; if (vdec != NULL) { /* named scope or irrelevant?*/ if (SgNamespaceDefinitionStatement* scn = isSgNamespaceDefinitionStatement(vdec->get_parent())) { scope = getNamespaceScopeName(scn); } else if (SgClassDefinition* scn = isSgClassDefinition(vdec->get_parent())) { scope = getClassScopeName(scn); } else { scope = new PrologAtom("null"); } } else { scope = new PrologAtom("null"); } return new PrologCompTerm ("var_ref_exp_annotation", //5, typeSpecific, /* name*/ new PrologAtom(n->get_name().getString()), isStatic, scope, PPI(vr)); }
void CudaOptimizer::applyRegisterOpt(SgFunctionDeclaration* kernel, DefUseAnalysis* defuse, std::set<SgInitializedName*> readOnlyVars, MintInitNameMapExpList_t arrRefList, SgInitializedName* candidateVar4Shared, SgInitializedName* sec_candidateVar4Shared, bool optUnrollZ) { MintInitNameMapExpList_t::iterator it; //perform register optimizations for(it = arrRefList.begin(); it != arrRefList.end(); it++) { SgInitializedName* array = it->first; ROSE_ASSERT(array); std::vector<SgExpression*> expList = it->second; int countNonStencil = getNonStencilArrayRefCount(expList); //TODO: should I put a limit about how many variables //should be put into the registers? if(countNonStencil > 0 ) { string arrName = array->get_name().str (); string arrName_sh = (candidateVar4Shared != NULL) ? candidateVar4Shared->get_name().str() : " "; string arrName_sh_sec = (sec_candidateVar4Shared != NULL) ? sec_candidateVar4Shared->get_name().str() : " "; //if we slide the planes, we perform the register opt to that variable later //TODO: Check if that includes the shared memory opt only ? Yes, shared should be on to skip this opt if((arrName == arrName_sh || arrName == arrName_sh_sec) && optUnrollZ ){ continue; } else { cout << " INFO:Mint: Candidate variable for register opt ("<< array->get_name().str() << ")"; cout << " with # of refs : "<< countNonStencil<< endl ; cout << " INFO:Mint: Applying register optimization to array ("<< arrName << ")"<< endl; OnChipMemoryOpt::registerOptimizer(readOnlyVars, kernel, array); } } } }
void Traversal::processNode(SgNode* n, SynthesizedAttribute& synthesizedAttribute ) { // Look for names of functions SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(n); if (functionDeclaration != NULL) { string name = functionDeclaration->get_name().str(); #if DEBUG > 3 SgFunctionDefinition* functionDefinition = functionDeclaration->get_definition(); if (functionDefinition != NULL) printf ("SgFunctionDefinition: %s \n",name.c_str()); else printf ("SgFunctionDeclaration: %s \n",name.c_str()); #endif synthesizedAttribute.nameList.push_back( NameStructureType(name,n)); // nameSet.insert(name); } SgInitializedName* initializedName = isSgInitializedName(n); if (initializedName != NULL) { string name = initializedName->get_name().str(); #if DEBUG > 3 printf ("SgInitializedName: %s \n",name.c_str()); #endif synthesizedAttribute.nameList.push_back( NameStructureType(name,n)); // nameSet.insert(name); } SgNamespaceDeclarationStatement* namespaceDeclaration = isSgNamespaceDeclarationStatement(n); if (namespaceDeclaration != NULL) { string name = namespaceDeclaration->get_name().str(); #if DEBUG > 3 printf ("SgNamespaceDeclaration: %s \n",name.c_str()); #endif synthesizedAttribute.nameList.push_back( NameStructureType(name,n)); // nameSet.insert(name); } }
void CudaOptimizer::findCandidateVarForSharedMem(MintInitNameMapExpList_t arrRefList, SgInitializedName* &candidateVar, SgInitializedName* prevCandidate, int &countMaxStencilRef,int &countNonStencilRef ) { countMaxStencilRef = 0; countNonStencilRef = 0; MintInitNameMapExpList_t::iterator it; //find the candidate for shared memory //go through all the array list to find the candidates //arrRefList contains the (array, expList) //ex: A -> A[i][j], A[i+1][j], A[i][j-1] ... for(it = arrRefList.begin(); it != arrRefList.end(); it++) { SgInitializedName* array = it->first; ROSE_ASSERT(array); std::vector<SgExpression*> expList = it->second; //TODO: we need a better mechanism to find the count of stencil references //it is not enough to say that every non-[i][j] reference is stencil int countNonStencil = getNonStencilArrayRefCount(expList); int countStencilRef = expList.size() - countNonStencil; //need to check if candidate is the same as prevCandidate //because we may be looking for the second candidate if(prevCandidate == NULL || prevCandidate->get_name().str() != array->get_name().str()) { //TODO: we need to make more roboust function for isStencilArray if(MintArrayInterface::isStencilArray(expList)) { //these ones are canditates for shared memory if(countMaxStencilRef < countStencilRef) { candidateVar = array; countMaxStencilRef = countStencilRef; countNonStencilRef = countNonStencil ; //do we need this? } } } } if(candidateVar != NULL) cout << " INFO:Mint: Candidate variable for shared memory opt: ("<< candidateVar->get_name().str() << ")"<< endl; }
void BasicProgmemTransform::shiftVarDeclsToProgmem() { std::string flashHelper = "#define FS(x)(__FlashStringHelper*)(x)"; insertPreprocessingInfo(flashHelper); printf("shifting var decls...\n"); for(auto& varDecl : varDeclsToShift) { convertVarDeclToProgmemDecl(varDecl); } printf("shifting additional progmem strings...\n"); for(auto &item: additionalProgmemStrings) { SgInitializedName *initName = item.second->get_variables()[0]; std::string dec = "const char " + initName->get_name().getString() + "[] PROGMEM = \"" + item.first + "\";"; insertPreprocessingInfo(dec); // convertVarDeclToProgmemDecl(varDecl, false); } printf("ok here\n"); }
bool TaintAnalysis::magic_tainted(SgNode *node, FiniteVarsExprsProductLattice *prodLat) { if (isSgInitializedName(node)) { SgInitializedName *iname = isSgInitializedName(node); std::string vname = iname->get_name().getString(); TaintLattice *tlat = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(varID(iname))); if (tlat && 0==vname.compare(0, 7, "TAINTED")) { bool modified = tlat->set_vertex(TaintLattice::VERTEX_TAINTED); if (debug) { *debug <<"TaintAnalysis::magic_tainted: lattice is magically " <<tlat->to_string() <<(modified?" (modified)":" (not modified)") <<"\n"; } return modified; } } else if (isSgVarRefExp(node)) { SgVarRefExp *vref = isSgVarRefExp(node); std::string vname = vref->get_symbol()->get_name().getString(); TaintLattice *tlat = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(varID(vref))); if (tlat && 0==vname.compare(0, 7, "TAINTED")) { bool modified = tlat->set_vertex(TaintLattice::VERTEX_TAINTED); if (debug) { *debug <<"TaintAnalysis::magic_tainted: lattice is magically " <<tlat->to_string() <<(modified?" (modified)":" (not modified)") <<"\n"; } return modified; } } else if (isSgVariableDeclaration(node)) { SgVariableDeclaration *vdecl = isSgVariableDeclaration(node); const SgInitializedNamePtrList &inames = vdecl->get_variables(); for (size_t i=0; i<inames.size(); ++i) { std::string vname = inames[i]->get_name().getString(); TaintLattice *tlat = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(varID(inames[i]))); if (tlat && 0==vname.compare(0, 7, "TAINTED")) { bool modified = tlat->set_vertex(TaintLattice::VERTEX_TAINTED); if (debug) { *debug <<"TaintAnalysis::magic_tainted: lattice is magically " <<tlat->to_string() <<(modified?" (modified)":" (not modified)") <<"\n"; } return modified; } } } return false; }
void BasicProgmemTransform::transformCharArrayInitialization(SgFunctionDeclaration *func) { /* * * Translates statements of the form: * char arr[n] = "some string"; to: * char arr[n]; * strcpy_P(arr, <progmem placeholder>); * */ Rose_STL_Container<SgNode *> initNames = NodeQuery::querySubTree(func, V_SgInitializedName); for(auto &item: initNames) { SgInitializedName *initName = isSgInitializedName(item); if(initName->get_initializer() == NULL) { continue; } SgVariableDeclaration * varDecl = isSgVariableDeclaration(initName->get_declaration()); if(varDecl == NULL) { continue; } SgAssignInitializer *assignInit = isSgAssignInitializer(initName->get_initializer()); if(assignInit == NULL) { continue; } SgType *type = initName->get_type(); SgType *eleType = SageInterface::getElementType(type); if(isSgArrayType(type) && eleType != NULL && isSgTypeChar(eleType)) { SgStringVal* strVal = isSgStringVal(assignInit->get_operand()); std::string str = strVal->get_value(); int arrSize = getDeclaredArraySize(isSgArrayType(type)); if(arrSize == 0) { //char arr[] = "something"; int size = str.length() + 1; SgArrayType *type = SageBuilder::buildArrayType(SageBuilder::buildCharType(), SageBuilder::buildIntVal(size)); initName->set_type(type); } varDecl->reset_initializer(NULL); SgVariableDeclaration *placeholder = getVariableDeclPlaceholderForString(str); SgVarRefExp *ref = SageBuilder::buildVarRefExp(placeholder); std::stringstream instr; instr << "\n strcpy_P(" << initName->get_name().getString(); instr << ", " << ref->get_symbol()->get_name().getString() << ");\n"; SageInterface::attachComment(varDecl, instr.str(), PreprocessingInfo::after); printf("transformed %s\n", initName->unparseToString().c_str()); } } }
NameQuerySynthesizedAttributeType NameQuery::queryNameArgumentNames (SgNode * astNode) { ROSE_ASSERT (astNode != 0); NameQuerySynthesizedAttributeType returnNameList; SgFunctionDeclaration *sageFunctionDeclaration = isSgFunctionDeclaration (astNode); if (sageFunctionDeclaration != NULL) { typedef SgInitializedNamePtrList::iterator argumentIterator; SgInitializedNamePtrList sageNameList = sageFunctionDeclaration->get_args (); int countArguments = 0; for (argumentIterator i = sageNameList.begin(); i != sageNameList.end(); ++i) { SgInitializedName* elementNode = *i; ROSE_ASSERT (elementNode != NULL); string sageArgument(elementNode->get_name().str()); returnNameList.push_back(sageArgument.c_str()); countArguments += 1; } #if DEBUG_NAMEQUERY printf ("\nHere is a function declaration :Line = %d Columns = %d \n", ROSE::getLineNumber (isSgLocatedNode (astNode)), ROSE::getColumnNumber (isSgLocatedNode (astNode))); cout << "The filename is:" << ROSE:: getFileName (isSgLocatedNode (astNode)) << endl; cout << "The count of arguments is: " << countArguments << endl; #endif } return returnNameList; } /* End function queryNameArgumentNames() */
Rose_STL_Container<SgNode*> NodeQuery::queryNodeVariableDeclarationFromName(SgNode* astNode, SgNode* nameNode){ ROSE_ASSERT( nameNode != NULL ); ROSE_ASSERT( astNode != NULL ); Rose_STL_Container<SgNode*> returnList; if(astNode->variantT() == V_SgVariableDeclaration){ SgName* sageName = isSgName(nameNode); ROSE_ASSERT( sageName != NULL ); std::string nameToMatch = sageName->str(); ROSE_ASSERT( nameToMatch.length() > 0 ); SgVariableDeclaration* sageVariableDeclaration = isSgVariableDeclaration(astNode); ROSE_ASSERT(sageVariableDeclaration != NULL); ROSE_ASSERT( sageVariableDeclaration->get_definition() != NULL ); SgInitializedNamePtrList sageInitializedNameList = sageVariableDeclaration->get_variables (); //see if this variable declaration fits the criteria typedef SgInitializedNamePtrList::iterator variableIterator; for (variableIterator k = sageInitializedNameList.begin (); k != sageInitializedNameList.end(); ++k) { SgInitializedName* elmVar = *k; std::string name = elmVar->get_name().str(); if(name == nameToMatch) returnList.push_back(astNode); } } return returnList; }; /* End function: queryNodeVariableDeclarationFromName */
void testOMPForSensitiveInsertion() { annotateAllOmpFors(project); Rose_STL_Container<SgNode*> iteratorUses = NodeQuery::querySubTree(project, V_SgInitializedName); OMPcfgRWTransaction trans; //VirtualCFG::cfgRWTransaction trans; trans.beginTransaction(); for(Rose_STL_Container<SgNode*>::iterator it = iteratorUses.begin(); it!=iteratorUses.end(); it++) { SgInitializedName *initName = isSgInitializedName(*it); ROSE_ASSERT(initName); //printf("initialized Name <%s | %s>\n", initName->get_parent()->unparseToString().c_str(), initName->get_parent()->class_name().c_str()); if(initName->get_name().getString() == "iterator") { //printf(" inserting1 at spot <%s | %s>\n", initName->get_parent()->unparseToString().c_str(), initName->get_parent()->class_name().c_str()); trans.insertBefore(initName, fooCallCreate()); trans.insertAfter(initName, fooCallCreate()); } } iteratorUses = NodeQuery::querySubTree(project, V_SgVarRefExp); for(Rose_STL_Container<SgNode*>::iterator it = iteratorUses.begin(); it!=iteratorUses.end(); it++) { SgVarRefExp *varRef = isSgVarRefExp(*it); ROSE_ASSERT(varRef); if(varRef->get_symbol()->get_name().getString() == "iterator") { //printf(" inserting2 at spot <%s | %s>\n", varRef->get_parent()->unparseToString().c_str(), varRef->get_parent()->class_name().c_str()); trans.insertBefore(varRef->get_parent(), fooCallCreate()); trans.insertAfter(varRef->get_parent(), fooCallCreate()); } } trans.commitTransaction(); }
ForLoop::ForLoop( SgForStatement * l ) : BasicNode(LOOPHEAD), myLoop(l), myLoopType(UNDEFINED), start(NULL), end(NULL), body(NULL), back_edge(NULL), out(NULL), Iter(false) { /* STEP 1 : Get initialization expression and symbol */ SgStatementPtrList stmList = myLoop->get_init_stmt(); if ( stmList.size() != 1 ) { report_error("Too many init statements",l); } else if ( isSgVariableDeclaration(stmList[0]) ) { SgInitializedNamePtrList initList = isSgVariableDeclaration(stmList[0])->get_variables(); if ( initList.size() != 1 ) { report_error("To many induction variables",l); } else { SgInitializedName * initName = initList[0]; if ( isSgAssignInitializer(initName->get_initializer()) ) { symbol = initName->get_name().getString(); start = isSgAssignInitializer(initName->get_initializer())->get_operand(); } else { report_error("Loop initializer is too complecated",initName); } } } else if ( isSgExprStatement(stmList[0]) ) { SgExpression * exp = isSgExprStatement(stmList[0])->get_expression(); if ( isSgAssignOp(exp) ) { SgExpression * lhs = isSgAssignOp(exp)->get_lhs_operand(); SgExpression * rhs = isSgAssignOp(exp)->get_rhs_operand(); if ( isSgVarRefExp(lhs) ) { symbol = isSgVarRefExp(lhs)->get_symbol()->get_name().getString(); start = rhs; } else { report_error("LHS of expression must be a single variable",exp); } } else { report_error("Init expression must be an Assign operation",exp); } } else { report_error("Loop initialization is not recognized",l); } /* STEP 2 : Get the test expression */ SgExprStatement * expStm = isSgExprStatement(myLoop->get_test()); if ( expStm ) { SgExpression * exp = expStm->get_expression(); if ( isSgLessOrEqualOp(exp) ) { SgBinaryOp * binOp = isSgBinaryOp(exp); string name = isSgVarRefExp(isSgBinaryOp(exp)->get_lhs_operand())->get_symbol()->get_name().getString(); if ( name != symbol ) report_error("Loop init and test variable miss-match",exp); end = binOp->get_rhs_operand(); } else if ( isSgLessThanOp(exp) ) { SgBinaryOp * binOp = isSgBinaryOp(exp); string name = isSgVarRefExp(binOp->get_lhs_operand())->get_symbol()->get_name().getString(); if ( name != symbol ) report_error("Loop init and test variable miss-match",exp); SgExpression * tempExp = SageInterface::copyExpression(binOp->get_rhs_operand()); end = buildSubtractOp( tempExp, buildIntVal(1) ); end->set_need_paren(true); tempExp = buildLessOrEqualOp( SageInterface::copyExpression(binOp->get_lhs_operand()), end ); SageInterface::replaceExpression(exp, tempExp, false); } else { report_error("Test expression is not recognized. Re-write the loop or normilize it accordingly",exp); } } else { report_error("Test expression is not recognized. Sorry !", l); } /* STEP 3 : Check the stride */ if ( !isSgPlusPlusOp(l->get_increment()) ) report_error("Increment expression is not recognized. Re-write the loop or normilize it accordingly. Note: Only \"++\" operator supported.",l); /* STEP 4 : Link with Loop Tail node */ back_edge = new ForLoop(start,end,symbol,l,this,this,LOOPTAIL); body = back_edge; }
StencilEvaluation_SynthesizedAttribute StencilEvaluationTraversal::evaluateSynthesizedAttribute (SgNode* astNode, StencilEvaluation_InheritedAttribute inheritedAttribute, SubTreeSynthesizedAttributes synthesizedAttributeList ) { StencilEvaluation_SynthesizedAttribute return_synthesizedAttribute; #if 0 printf ("In StencilEvaluationTraversal::evaluateSynthesizedAttribute(): astNode = %p = %s \n",astNode,astNode->class_name().c_str()); #endif bool foundStencilOffsetFSM = false; SgConstructorInitializer* constructorInitializer = isSgConstructorInitializer(astNode); if (constructorInitializer != NULL && inheritedAttribute.stencilOffsetFSM != NULL) { #if 0 printf ("Found pair<Shift,double>(x,y): set then in the synthesizedAttribute: astNode = %p = %s \n",astNode,astNode->class_name().c_str()); #endif return_synthesizedAttribute.stencilOffsetFSM = inheritedAttribute.stencilOffsetFSM; return_synthesizedAttribute.stencilCoeficientValue = inheritedAttribute.stencilCoeficientValue; #if 0 printf ("return_synthesizedAttribute.stencilCoeficientValue = %f \n",return_synthesizedAttribute.stencilCoeficientValue); #endif foundStencilOffsetFSM = true; } // There should only be a single child set with a pair<Shift,double>(x,y) object. for (size_t i = 0; i < synthesizedAttributeList.size(); i++) { if (synthesizedAttributeList[i].stencilOffsetFSM != NULL) { // Check that the return_synthesizedAttribute.stencilOffsetFSM has not already been set. // This could happend if we allows nesting of pair<Shift,double>(x,y) within itself (not allowed). #if 0 printf ("synthesizedAttributeList[i].stencilOffsetFSM != NULL \n"); #endif // ROSE_ASSERT(foundStencilOffsetFSM == false); if (foundStencilOffsetFSM == false) { #if 0 printf ("foundStencilOffsetFSM == false \n"); #endif // ROSE_ASSERT(return_synthesizedAttribute.stencilOffsetFSM == NULL); if (return_synthesizedAttribute.stencilOffsetFSM == NULL) { #if 0 printf ("return_synthesizedAttribute.stencilOffsetFSM != NULL \n"); #endif return_synthesizedAttribute.stencilOffsetFSM = synthesizedAttributeList[i].stencilOffsetFSM; return_synthesizedAttribute.stencilCoeficientValue = synthesizedAttributeList[i].stencilCoeficientValue; } foundStencilOffsetFSM = true; } } } // This allows us to find the variables of type vector<Point> and vector<double> used as an alternative way // to specify a stencil (using the Stencil constructor that takes these variables as input arguments). // It relies upon a previous traversal to have identified the inputs to Stencil constructor. // This support is incomplete while I focus on the alternative approach to the specification of the stencil // using intremental union of a stencil with a pair<Shift,double>() template instantiation. SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(astNode); if (variableDeclaration != NULL) { // Get the SgInitializedName from the SgVariableDeclaration. SgInitializedName* initializedName = SageInterface::getFirstInitializedName(variableDeclaration); #if 0 printf ("In evaluateInheritedAttribute(): case SgInitializedName from variable declaration: initializedName = %p name = %s \n",initializedName,initializedName->get_name().str()); #endif bool foundStencilDeclaration = false; if (find(stencilInputInitializedNameList.begin(),stencilInputInitializedNameList.end(),initializedName) != stencilInputInitializedNameList.end()) { #if 0 printf ("Found declaration associated with stencil input: initializedName = %p = %s name = %s \n",initializedName,initializedName->class_name().c_str(),initializedName->get_name().str()); #endif // Build the finite state machine for the stencil and add it to the map using the name (in SgInitializedName) as a key. // For now we assume that the stencil specification is using the default construction. if (initializedName->get_initptr() != NULL) { printf ("FIXME: This declaration of a stencil appears to have constrcutor arguments (this not the default constuctor as interprest below). \n"); #if 0 ROSE_ASSERT(false); #endif } foundStencilDeclaration = true; } else { // Verify that this is a Stencil declaration. SgClassType* classType = isSgClassType(initializedName->get_type()); if (classType != NULL) { // Check if this is associated with a template instantiation. SgTemplateInstantiationDecl* templateInstantiationDecl = isSgTemplateInstantiationDecl(classType->get_declaration()); if (templateInstantiationDecl != NULL) { #if 0 printf ("case SgTemplateInstaiationDecl: class name = %s \n",classType->get_name().str()); printf ("case SgTemplateInstaiationDecl: templateInstantiationDecl->get_templateName() = %s \n",templateInstantiationDecl->get_templateName().str()); #endif if (templateInstantiationDecl->get_templateName() == "Stencil") { #if 0 printf ("This is verified to be associated with the Stencil template class \n"); #endif foundStencilDeclaration = true; } } } } if (foundStencilDeclaration == true) { string name = initializedName->get_name(); ROSE_ASSERT(stencilMap.find(name) == stencilMap.end()); // stencilMap[name] = new StencilFSM(); StencilFSM* stencilFSM = new StencilFSM(); ROSE_ASSERT(stencilFSM != NULL); stencilMap[name] = stencilFSM; ROSE_ASSERT(stencilMap.find(name) != stencilMap.end()); #if 0 printf ("Added StencilFSM to stencilMap using name = %s \n",name.c_str()); #endif #if 0 printf ("Trigger an event on the stencilFSM ========================== %p \n",stencilFSM); printf (" --- Use the return_synthesizedAttribute.stencilOffsetFSM = %p \n",return_synthesizedAttribute.stencilOffsetFSM); #endif if (return_synthesizedAttribute.stencilOffsetFSM != NULL) { // Trigger the event to add the stencil offset to the stencil. // Trigger the event on the finite state machine using the elements saved in the synthesized attribute. StencilFSM stencil_rhs (*(return_synthesizedAttribute.stencilOffsetFSM),return_synthesizedAttribute.stencilCoeficientValue); // This reproduces the same semantics in our finite state machine as the Stencil class's operator+() // in the stencil specification. but this permits use to accumulate the state at compile time. stencilFSM->operator+(stencil_rhs); // We have now used these values so avoid letting then be used again. return_synthesizedAttribute.stencilOffsetFSM = NULL; return_synthesizedAttribute.stencilCoeficientValue = 0.0; } #if 0 stencilFSM->display("after FSM stencil default construction plus union event: StencilEvaluationTraversal::evaluateSynthesizedAttribute()"); #endif #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } } // Recognize member function calls on "Stencil" objects so that we can trigger events on those associated finite state machines. bool isTemplateClass = true; bool isTemplateFunctionInstantiation = true; SgInitializedName* initializedNameUsedToCallMemberFunction = NULL; SgFunctionCallExp* functionCallExp = detectMemberFunctionOfSpecificClassType(astNode,initializedNameUsedToCallMemberFunction,"Stencil",isTemplateClass,"operator+",isTemplateFunctionInstantiation); if (return_synthesizedAttribute.stencilOffsetFSM != NULL && functionCallExp != NULL) { // This is the DSL specific part of the synthesized attribute evaluation. ROSE_ASSERT(initializedNameUsedToCallMemberFunction != NULL); string name = initializedNameUsedToCallMemberFunction->get_name(); #if 0 printf ("This is verified to be the operator+ member function of the Stencil templated class (so this corresponds to an event in the Stencil finite state machine) \n"); printf (" --- stencil object name = %s \n",name.c_str()); #endif // Lookup the stencil FSM in the map of stencil FSMs using the name as the key. ROSE_ASSERT(stencilMap.find(name) != stencilMap.end()); StencilFSM* stencilFSM = stencilMap[name]; ROSE_ASSERT(stencilFSM != NULL); #if 0 printf ("Trigger an event on the stencilFSM ========================== %p \n",stencilFSM); printf (" --- Use the return_synthesizedAttribute.stencilOffsetFSM = %p \n",return_synthesizedAttribute.stencilOffsetFSM); #endif // Make sure we have the input parameter for the stencil's finite state machine. ROSE_ASSERT(return_synthesizedAttribute.stencilOffsetFSM != NULL); // Trigger the event on the finite state machine using the elements saved in the synthesized attribute. StencilFSM stencil_rhs (*(return_synthesizedAttribute.stencilOffsetFSM),return_synthesizedAttribute.stencilCoeficientValue); // This reproduces the same semantics in our finite state machine as the Stencil class's operator+() // in the stencil specification. but this permits use to accumulate the state at compile time. stencilFSM->operator+(stencil_rhs); // We have now used these values so avoid letting then be used again. return_synthesizedAttribute.stencilOffsetFSM = NULL; return_synthesizedAttribute.stencilCoeficientValue = 0.0; #if 0 stencilFSM->display("after FSM stencil union event: StencilEvaluationTraversal::evaluateSynthesizedAttribute()"); #endif } #if 0 printf ("Leaving StencilEvaluationTraversal::evaluateSynthesizedAttribute(): return_synthesizedAttribute.stencilOffsetFSM = %p \n",return_synthesizedAttribute.stencilOffsetFSM); #endif #if 0 printf ("Leaving StencilEvaluationTraversal::evaluateSynthesizedAttribute(): return_synthesizedAttribute.stencilCoeficientValue = %f \n",return_synthesizedAttribute.stencilCoeficientValue); #endif return return_synthesizedAttribute; }
// Main inliner code. Accepts a function call as a parameter, and inlines // only that single function call. Returns true if it succeeded, and false // otherwise. The function call must be to a named function, static member // function, or non-virtual non-static member function, and the function // must be known (not through a function pointer or member function // pointer). Also, the body of the function must already be visible. // Recursive procedures are handled properly (when allowRecursion is set), by // inlining one copy of the procedure into itself. Any other restrictions on // what can be inlined are bugs in the inliner code. bool doInline(SgFunctionCallExp* funcall, bool allowRecursion) { #if 0 // DQ (4/6/2015): Adding code to check for consitancy of checking the isTransformed flag. ROSE_ASSERT(funcall != NULL); ROSE_ASSERT(funcall->get_parent() != NULL); SgGlobal* globalScope = TransformationSupport::getGlobalScope(funcall); ROSE_ASSERT(globalScope != NULL); // checkTransformedFlagsVisitor(funcall->get_parent()); checkTransformedFlagsVisitor(globalScope); #endif SgExpression* funname = funcall->get_function(); SgExpression* funname2 = isSgFunctionRefExp(funname); SgDotExp* dotexp = isSgDotExp(funname); SgArrowExp* arrowexp = isSgArrowExp(funname); SgExpression* thisptr = 0; if (dotexp || arrowexp) { funname2 = isSgBinaryOp(funname)->get_rhs_operand(); if (dotexp) { SgExpression* lhs = dotexp->get_lhs_operand(); // FIXME -- patch this into p_lvalue bool is_lvalue = lhs->get_lvalue(); if (isSgInitializer(lhs)) is_lvalue = false; if (!is_lvalue) { SgAssignInitializer* ai = SageInterface::splitExpression(lhs); ROSE_ASSERT (isSgInitializer(ai->get_operand())); #if 1 printf ("ai = %p ai->isTransformation() = %s \n",ai,ai->isTransformation() ? "true" : "false"); #endif SgInitializedName* in = isSgInitializedName(ai->get_parent()); ROSE_ASSERT (in); removeRedundantCopyInConstruction(in); lhs = dotexp->get_lhs_operand(); // Should be a var ref now } thisptr = new SgAddressOfOp(SgNULL_FILE, lhs); } else if (arrowexp) { thisptr = arrowexp->get_lhs_operand(); } else { assert (false); } } if (!funname2) { // std::cout << "Inline failed: not a call to a named function" << std::endl; return false; // Probably a call through a fun ptr } SgFunctionSymbol* funsym = 0; if (isSgFunctionRefExp(funname2)) funsym = isSgFunctionRefExp(funname2)->get_symbol(); else if (isSgMemberFunctionRefExp(funname2)) funsym = isSgMemberFunctionRefExp(funname2)->get_symbol(); else assert (false); assert (funsym); if (isSgMemberFunctionSymbol(funsym) && isSgMemberFunctionSymbol(funsym)->get_declaration()->get_functionModifier().isVirtual()) { // std::cout << "Inline failed: cannot inline virtual member functions" << std::endl; return false; } SgFunctionDeclaration* fundecl = funsym->get_declaration(); fundecl = fundecl ? isSgFunctionDeclaration(fundecl->get_definingDeclaration()) : NULL; SgFunctionDefinition* fundef = fundecl ? fundecl->get_definition() : NULL; if (!fundef) { // std::cout << "Inline failed: no definition is visible" << std::endl; return false; // No definition of the function is visible } if (!allowRecursion) { SgNode* my_fundef = funcall; while (my_fundef && !isSgFunctionDefinition(my_fundef)) { // printf ("Before reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str()); my_fundef = my_fundef->get_parent(); ROSE_ASSERT(my_fundef != NULL); // printf ("After reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str()); } // printf ("After reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str()); assert (isSgFunctionDefinition(my_fundef)); if (isSgFunctionDefinition(my_fundef) == fundef) { std::cout << "Inline failed: trying to inline a procedure into itself" << std::endl; return false; } } SgVariableDeclaration* thisdecl = 0; SgName thisname("this__"); thisname << ++gensym_counter; SgInitializedName* thisinitname = 0; if (isSgMemberFunctionSymbol(funsym) && !fundecl->get_declarationModifier().get_storageModifier().isStatic()) { assert (thisptr != NULL); SgType* thisptrtype = thisptr->get_type(); const SgSpecialFunctionModifier& specialMod = funsym->get_declaration()->get_specialFunctionModifier(); if (specialMod.isConstructor()) { SgFunctionType* ft = funsym->get_declaration()->get_type(); ROSE_ASSERT (ft); SgMemberFunctionType* mft = isSgMemberFunctionType(ft); ROSE_ASSERT (mft); SgType* ct = mft->get_class_type(); thisptrtype = new SgPointerType(ct); } SgConstVolatileModifier& thiscv = fundecl->get_declarationModifier().get_typeModifier().get_constVolatileModifier(); // if (thiscv.isConst() || thiscv.isVolatile()) { FIXME thisptrtype = new SgModifierType(thisptrtype); isSgModifierType(thisptrtype)->get_typeModifier().get_constVolatileModifier() = thiscv; // } // cout << thisptrtype->unparseToString() << " --- " << thiscv.isConst() << " " << thiscv.isVolatile() << endl; SgAssignInitializer* assignInitializer = new SgAssignInitializer(SgNULL_FILE, thisptr); assignInitializer->set_endOfConstruct(SgNULL_FILE); #if 1 printf ("before new SgVariableDeclaration(): assignInitializer = %p assignInitializer->isTransformation() = %s \n",assignInitializer,assignInitializer->isTransformation() ? "true" : "false"); #endif thisdecl = new SgVariableDeclaration(SgNULL_FILE, thisname, thisptrtype, assignInitializer); #if 1 printf ("(after new SgVariableDeclaration(): assignInitializer = %p assignInitializer->isTransformation() = %s \n",assignInitializer,assignInitializer->isTransformation() ? "true" : "false"); #endif thisdecl->set_endOfConstruct(SgNULL_FILE); thisdecl->get_definition()->set_endOfConstruct(SgNULL_FILE); thisdecl->set_definingDeclaration(thisdecl); thisinitname = (thisdecl->get_variables()).back(); //thisinitname = lastElementOfContainer(thisdecl->get_variables()); // thisinitname->set_endOfConstruct(SgNULL_FILE); assignInitializer->set_parent(thisinitname); markAsTransformation(assignInitializer); // printf ("Built new SgVariableDeclaration #1 = %p \n",thisdecl); // DQ (6/23/2006): New test ROSE_ASSERT(assignInitializer->get_parent() != NULL); } // Get the list of actual argument expressions from the function call, which we'll later use to initialize new local // variables in the inlined code. We need to detach the actual arguments from the AST here since we'll be reattaching // them below (otherwise we would violate the invariant that the AST is a tree). SgFunctionDefinition* targetFunction = PRE::getFunctionDefinition(funcall); SgExpressionPtrList funargs = funcall->get_args()->get_expressions(); funcall->get_args()->get_expressions().clear(); BOOST_FOREACH (SgExpression *actual, funargs) actual->set_parent(NULL); // Make a copy of the to-be-inlined function so we're not modifying and (re)inserting the original. SgBasicBlock* funbody_raw = fundef->get_body(); SgInitializedNamePtrList& params = fundecl->get_args(); std::vector<SgInitializedName*> inits; SgTreeCopy tc; SgFunctionDefinition* function_copy = isSgFunctionDefinition(fundef->copy(tc)); ROSE_ASSERT (function_copy); SgBasicBlock* funbody_copy = function_copy->get_body(); renameLabels(funbody_copy, targetFunction); ASSERT_require(funbody_raw->get_symbol_table()->size() == funbody_copy->get_symbol_table()->size()); // We don't need to keep the copied SgFunctionDefinition now that the labels in it have been moved to the target function // (having it in the memory pool confuses the AST tests), but we must not delete the formal argument list or the body // because we need them below. if (function_copy->get_declaration()) { ASSERT_require(function_copy->get_declaration()->get_parent() == function_copy); function_copy->get_declaration()->set_parent(NULL); function_copy->set_declaration(NULL); } if (function_copy->get_body()) { ASSERT_require(function_copy->get_body()->get_parent() == function_copy); function_copy->get_body()->set_parent(NULL); function_copy->set_body(NULL); } delete function_copy; function_copy = NULL; #if 0 SgPragma* pragmaBegin = new SgPragma("start_of_inline_function", SgNULL_FILE); SgPragmaDeclaration* pragmaBeginDecl = new SgPragmaDeclaration(SgNULL_FILE, pragmaBegin); pragmaBeginDecl->set_endOfConstruct(SgNULL_FILE); pragmaBegin->set_parent(pragmaBeginDecl); pragmaBeginDecl->set_definingDeclaration(pragmaBeginDecl); funbody_copy->prepend_statement(pragmaBeginDecl); pragmaBeginDecl->set_parent(funbody_copy); #endif // In the to-be-inserted function body, create new local variables with distinct non-conflicting names, one per formal // argument and having the same type as the formal argument. Initialize those new local variables with the actual // arguments. Also, build a paramMap that maps each formal argument (SgInitializedName) to its corresponding new local // variable (SgVariableSymbol). ReplaceParameterUseVisitor::paramMapType paramMap; SgInitializedNamePtrList::iterator formalIter = params.begin(); SgExpressionPtrList::iterator actualIter = funargs.begin(); for (size_t argNumber=0; formalIter != params.end() && actualIter != funargs.end(); ++argNumber, ++formalIter, ++actualIter) { SgInitializedName *formalArg = *formalIter; SgExpression *actualArg = *actualIter; // Build the new local variable. // FIXME[Robb P. Matzke 2014-12-12]: we need a better way to generate a non-conflicting local variable name SgAssignInitializer* initializer = new SgAssignInitializer(SgNULL_FILE, actualArg, formalArg->get_type()); ASSERT_not_null(initializer); initializer->set_endOfConstruct(SgNULL_FILE); #if 1 printf ("initializer = %p initializer->isTransformation() = %s \n",initializer,initializer->isTransformation() ? "true" : "false"); #endif SgName shadow_name(formalArg->get_name()); shadow_name << "__" << ++gensym_counter; SgVariableDeclaration* vardecl = new SgVariableDeclaration(SgNULL_FILE, shadow_name, formalArg->get_type(), initializer); vardecl->set_definingDeclaration(vardecl); vardecl->set_endOfConstruct(SgNULL_FILE); vardecl->get_definition()->set_endOfConstruct(SgNULL_FILE); vardecl->set_parent(funbody_copy); // Insert the new local variable into the (near) beginning of the to-be-inserted function body. We insert them in the // order their corresponding actuals/formals appear, although the C++ standard does not require this order of // evaluation. SgInitializedName* init = vardecl->get_variables().back(); inits.push_back(init); initializer->set_parent(init); init->set_scope(funbody_copy); funbody_copy->get_statements().insert(funbody_copy->get_statements().begin() + argNumber, vardecl); SgVariableSymbol* sym = new SgVariableSymbol(init); paramMap[formalArg] = sym; funbody_copy->insert_symbol(shadow_name, sym); sym->set_parent(funbody_copy->get_symbol_table()); } // Similarly for "this". We create a local variable in the to-be-inserted function body that will be initialized with the // caller's "this". if (thisdecl) { thisdecl->set_parent(funbody_copy); thisinitname->set_scope(funbody_copy); funbody_copy->get_statements().insert(funbody_copy->get_statements().begin(), thisdecl); SgVariableSymbol* thisSym = new SgVariableSymbol(thisinitname); funbody_copy->insert_symbol(thisname, thisSym); thisSym->set_parent(funbody_copy->get_symbol_table()); ReplaceThisWithRefVisitor(thisSym).traverse(funbody_copy, postorder); } ReplaceParameterUseVisitor(paramMap).traverse(funbody_copy, postorder); SgName end_of_inline_name = "rose_inline_end__"; end_of_inline_name << ++gensym_counter; SgLabelStatement* end_of_inline_label = new SgLabelStatement(SgNULL_FILE, end_of_inline_name); end_of_inline_label->set_endOfConstruct(SgNULL_FILE); #if 0 printf ("\n\nCalling AST copy mechanism on a SgBasicBlock \n"); // Need to set the parent of funbody_copy to avoid error. funbody_copy->set_parent(funbody_raw->get_parent()); printf ("This is a copy of funbody_raw = %p to build funbody_copy = %p \n",funbody_raw,funbody_copy); printf ("funbody_raw->get_statements().size() = %" PRIuPTR " \n",funbody_raw->get_statements().size()); printf ("funbody_copy->get_statements().size() = %" PRIuPTR " \n",funbody_copy->get_statements().size()); printf ("funbody_raw->get_symbol_table()->size() = %d \n",(int)funbody_raw->get_symbol_table()->size()); printf ("funbody_copy->get_symbol_table()->size() = %d \n",(int)funbody_copy->get_symbol_table()->size()); printf ("Output the symbol table for funbody_raw \n"); funbody_raw->get_symbol_table()->print("debugging copy problem"); // printf ("Output the symbol table for funbody_copy \n"); // funbody_copy->get_symbol_table()->print("debugging copy problem"); SgProject* project_copy = TransformationSupport::getProject(funbody_raw); ROSE_ASSERT(project_copy != NULL); const int MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH = 4000; generateAstGraph(project_copy,MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH); #endif funbody_copy->append_statement(end_of_inline_label); end_of_inline_label->set_scope(targetFunction); SgLabelSymbol* end_of_inline_label_sym = new SgLabelSymbol(end_of_inline_label); end_of_inline_label_sym->set_parent(targetFunction->get_symbol_table()); targetFunction->get_symbol_table()->insert(end_of_inline_label->get_name(), end_of_inline_label_sym); // To ensure that there is some statement after the label SgExprStatement* dummyStatement = SageBuilder::buildExprStatement(SageBuilder::buildNullExpression()); dummyStatement->set_endOfConstruct(SgNULL_FILE); funbody_copy->append_statement(dummyStatement); dummyStatement->set_parent(funbody_copy); #if 0 SgPragma* pragmaEnd = new SgPragma("end_of_inline_function", SgNULL_FILE); SgPragmaDeclaration* pragmaEndDecl = new SgPragmaDeclaration(SgNULL_FILE, pragmaEnd); pragmaEndDecl->set_endOfConstruct(SgNULL_FILE); pragmaEnd->set_parent(pragmaEndDecl); pragmaEndDecl->set_definingDeclaration(pragmaEndDecl); funbody_copy->append_statement(pragmaEndDecl); pragmaEndDecl->set_parent(funbody_copy); #endif ChangeReturnsToGotosPrevisitor previsitor = ChangeReturnsToGotosPrevisitor(end_of_inline_label, funbody_copy); replaceExpressionWithStatement(funcall, &previsitor); // Make sure the AST is consistent. To save time, we'll just fix things that we know can go wrong. For instance, the // SgAsmExpression.p_lvalue data member is required to be true for certain operators and is set to false in other // situations. Since we've introduced new expressions into the AST we need to adjust their p_lvalue according to the // operators where they were inserted. markLhsValues(targetFunction); #ifdef NDEBUG AstTests::runAllTests(SageInterface::getProject()); #endif #if 0 // DQ (4/6/2015): Adding code to check for consitancy of checking the isTransformed flag. ROSE_ASSERT(funcall != NULL); ROSE_ASSERT(funcall->get_parent() != NULL); ROSE_ASSERT(globalScope != NULL); // checkTransformedFlagsVisitor(funcall->get_parent()); checkTransformedFlagsVisitor(globalScope); #endif // DQ (4/7/2015): This fixes something I was required to fix over the weekend and which is fixed more directly, I think. // Mark the things we insert as being transformations so they get inserted into the output by backend() markAsTransformation(funbody_copy); return true; }
void generateStencilCode(StencilEvaluationTraversal & traversal, bool generateLowlevelCode) { // Read the stencil and generate the inner most loop AST for the stencil. // Note that generateLowlevelCode controls the generation of low level C code using a // base pointer to raw memory and linearized indexing off of that pointer. The // alternative is to use the operator[] member function in the RectMDArray class. // Example of code that we want to generate: // for (j=0; j < source.size(0); j++) // { // int axis_x_size = source.size(0); // for (i=0; i < source.size(0); i++) // { // destination[j*axis_x_size+i] = source[j*axis_x_size+i]; // } // } // This function genertes the loop nest only: // SgForStatement* buildLoopNest(int stencilDimension, SgBasicBlock* & innerLoopBody) // This function generates the statement in the inner most loop body: // SgExprStatement* assembleStencilSubTreeArray(vector<SgExpression*> & stencilSubTreeArray) // This function generates the AST representing the stencil points: // SgExpression* buildStencilPoint (StencilOffsetFSM* stencilOffsetFSM, double stencilCoeficient, int stencilDimension, SgVariableSymbol* destinationVariableSymbol, SgVariableSymbol* sourceVariableSymbol) // The generated code should be in terms of the operator[]() functions on the // RectMDArray objects. Likely we have to support a wider range of generated code later. // const RectMDArray<TDest>& a_LOfPhi, // const RectMDArray<TSrc>& a_phi, // std::vector<SgFunctionCallExp*> stencilOperatorFunctionCallList; std::vector<SgFunctionCallExp*> stencilOperatorFunctionCallList = traversal.get_stencilOperatorFunctionCallList(); for (size_t i = 0; i < stencilOperatorFunctionCallList.size(); i++) { SgFunctionCallExp* functionCallExp = stencilOperatorFunctionCallList[i]; ROSE_ASSERT(functionCallExp != NULL); printf ("processing functionCallExp = %p \n",functionCallExp); SgStatement* associatedStatement = TransformationSupport::getStatement(functionCallExp); ROSE_ASSERT(associatedStatement != NULL); string filename = associatedStatement->get_file_info()->get_filename(); int lineNumber = associatedStatement->get_file_info()->get_line(); printf ("Generating code for stencil operator used at file = %s at line = %d \n",filename.c_str(),lineNumber); SgExprListExp* argumentList = functionCallExp->get_args(); ROSE_ASSERT(argumentList != NULL); // There should be four elements to a stencil operator. ROSE_ASSERT(argumentList->get_expressions().size() == 4); // Stencil SgExpression* stencilExpression = argumentList->get_expressions()[0]; SgVarRefExp* stencilVarRefExp = isSgVarRefExp(stencilExpression); ROSE_ASSERT(stencilVarRefExp != NULL); // RectMDArray (destination) SgExpression* destinationArrayReferenceExpression = argumentList->get_expressions()[1]; SgVarRefExp* destinationArrayVarRefExp = isSgVarRefExp(destinationArrayReferenceExpression); ROSE_ASSERT(destinationArrayVarRefExp != NULL); // RectMDArray (source) SgExpression* sourceArrayReferenceExpression = argumentList->get_expressions()[2]; SgVarRefExp* sourceArrayVarRefExp = isSgVarRefExp(sourceArrayReferenceExpression); ROSE_ASSERT(sourceArrayVarRefExp != NULL); // Box SgExpression* boxReferenceExpression = argumentList->get_expressions()[3]; SgVarRefExp* boxVarRefExp = isSgVarRefExp(boxReferenceExpression); ROSE_ASSERT(boxVarRefExp != NULL); printf ("DONE: processing inputs to stencil operator \n"); ROSE_ASSERT(stencilVarRefExp->get_symbol() != NULL); SgInitializedName* stencilInitializedName = stencilVarRefExp->get_symbol()->get_declaration(); ROSE_ASSERT(stencilInitializedName != NULL); string stencilName = stencilInitializedName->get_name(); printf ("stencilName = %s \n",stencilName.c_str()); std::map<std::string,StencilFSM*> & stencilMap = traversal.get_stencilMap(); ROSE_ASSERT(stencilMap.find(stencilName) != stencilMap.end()); StencilFSM* stencilFSM = stencilMap[stencilName]; ROSE_ASSERT(stencilFSM != NULL); // DQ (2/8/2015): Moved out of loop. int stencilDimension = stencilFSM->stencilDimension(); ROSE_ASSERT(stencilDimension > 0); // These are computed values. printf ("Stencil dimension = %d \n",stencilDimension); printf ("Stencil width = %d \n",stencilFSM->stencilWidth()); std::vector<std::pair<StencilOffsetFSM,double> > & stencilPointList = stencilFSM->stencilPointList; // This is the scope where the stencil operator is evaluated. SgScopeStatement* outerScope = associatedStatement->get_scope(); ROSE_ASSERT(outerScope != NULL); SgVariableSymbol* indexVariableSymbol_X = NULL; SgVariableSymbol* indexVariableSymbol_Y = NULL; SgVariableSymbol* indexVariableSymbol_Z = NULL; SgVariableSymbol* arraySizeVariableSymbol_X = NULL; SgVariableSymbol* arraySizeVariableSymbol_Y = NULL; SgVariableSymbol* destinationVariableSymbol = destinationArrayVarRefExp->get_symbol(); ROSE_ASSERT(destinationVariableSymbol != NULL); SgVariableSymbol* sourceVariableSymbol = sourceArrayVarRefExp->get_symbol(); ROSE_ASSERT(sourceVariableSymbol != NULL); SgVariableSymbol* boxVariableSymbol = boxVarRefExp->get_symbol(); ROSE_ASSERT(boxVariableSymbol != NULL); // This can be important in handling of comments and CPP directives. bool autoMovePreprocessingInfo = true; SgStatement* lastStatement = associatedStatement; if (generateLowlevelCode == true) { #if 1 SgVariableDeclaration* sourceDataPointerVariableDeclaration = buildDataPointer("sourceDataPointer",sourceVariableSymbol,outerScope); #else // Optionally build a pointer variable so that we can optionally support a C style indexing for the DTEC DSL blocks. SgExpression* sourcePointerExp = buildMemberFunctionCall(sourceVariableSymbol,"getPointer",NULL,false); ROSE_ASSERT(sourcePointerExp != NULL); SgAssignInitializer* assignInitializer = SageBuilder::buildAssignInitializer_nfi(sourcePointerExp); ROSE_ASSERT(assignInitializer != NULL); // Build the variable declaration for the pointer to the data. string sourcePointerName = "sourceDataPointer"; SgVariableDeclaration* sourceDataPointerVariableDeclaration = SageBuilder::buildVariableDeclaration_nfi(sourcePointerName,SageBuilder::buildPointerType(SageBuilder::buildDoubleType()),assignInitializer,outerScope); ROSE_ASSERT(sourceDataPointerVariableDeclaration != NULL); #endif // SageInterface::insertStatementAfter(associatedStatement,forStatementScope,autoMovePreprocessingInfo); SageInterface::insertStatementAfter(associatedStatement,sourceDataPointerVariableDeclaration,autoMovePreprocessingInfo); SgVariableDeclaration* destinationDataPointerVariableDeclaration = buildDataPointer("destinationDataPointer",destinationVariableSymbol,outerScope); SageInterface::insertStatementAfter(sourceDataPointerVariableDeclaration,destinationDataPointerVariableDeclaration,autoMovePreprocessingInfo); // Reset the variable symbols we will use in the buildStencilPoint() function. sourceVariableSymbol = SageInterface::getFirstVarSym(sourceDataPointerVariableDeclaration); destinationVariableSymbol = SageInterface::getFirstVarSym(destinationDataPointerVariableDeclaration); lastStatement = destinationDataPointerVariableDeclaration; } SgBasicBlock* innerLoopBody = NULL; // SgForStatement* loopNest = buildLoopNest(stencilFSM->stencilDimension(),innerLoopBody,sourceVariableSymbol,indexVariableSymbol_X,indexVariableSymbol_Y,indexVariableSymbol_Z,arraySizeVariableSymbol_X,arraySizeVariableSymbol_Y); SgForStatement* loopNest = buildLoopNest(stencilFSM->stencilDimension(),innerLoopBody,boxVariableSymbol,indexVariableSymbol_X,indexVariableSymbol_Y,indexVariableSymbol_Z,arraySizeVariableSymbol_X,arraySizeVariableSymbol_Y); ROSE_ASSERT(innerLoopBody != NULL); ROSE_ASSERT(lastStatement != NULL); SageInterface::insertStatementAfter(lastStatement,loopNest,autoMovePreprocessingInfo); // Mark this as compiler generated so that it will not be unparsed. associatedStatement->get_file_info()->setCompilerGenerated(); // Form an array of AST subtrees to represent the different points in the stencil. // vector<SgFunctionCallExp*> stencilSubTreeArray; vector<SgExpression*> stencilSubTreeArray; for (size_t j = 0; j < stencilPointList.size(); j++) { #if 0 printf ("Forming stencil point subtree for offsetValues[0] = %3d [1] = %3d [2] = %3d \n",stencilPointList[j].first.offsetValues[0],stencilPointList[j].first.offsetValues[1],stencilPointList[j].first.offsetValues[2]); #endif StencilOffsetFSM* stencilOffsetFSM = &(stencilPointList[j].first); double stencilCoeficient = stencilPointList[j].second; // SgFunctionCallExp* stencilSubTree = buildStencilPoint(stencilOffsetFSM,stencilCoeficient,stencilFSM->stencilDimension()); SgExpression* stencilSubTree = buildStencilPoint(stencilOffsetFSM,stencilCoeficient,stencilDimension,sourceVariableSymbol, indexVariableSymbol_X,indexVariableSymbol_Y,indexVariableSymbol_Z,arraySizeVariableSymbol_X,arraySizeVariableSymbol_Y,generateLowlevelCode); ROSE_ASSERT(stencilSubTree != NULL); stencilSubTreeArray.push_back(stencilSubTree); } // Construct the lhs value for the stencil inner loop statement. StencilOffsetFSM* stencilOffsetFSM_lhs = new StencilOffsetFSM(0,0,0); double stencilCoeficient_lhs = 1.00; SgExpression* stencil_lhs = buildStencilPoint(stencilOffsetFSM_lhs,stencilCoeficient_lhs,stencilDimension,destinationVariableSymbol, indexVariableSymbol_X,indexVariableSymbol_Y,indexVariableSymbol_Z,arraySizeVariableSymbol_X,arraySizeVariableSymbol_Y,generateLowlevelCode); ROSE_ASSERT(stencil_lhs != NULL); // Assemble the stencilSubTreeArray into a single expression. SgExprStatement* stencilStatement = assembleStencilSubTreeArray(stencil_lhs,stencilSubTreeArray,stencilDimension,destinationVariableSymbol); SageInterface::appendStatement(stencilStatement,innerLoopBody); } }
DOTSynthesizedAttribute AstDOTGeneration::evaluateSynthesizedAttribute(SgNode* node, DOTInheritedAttribute ia, SubTreeSynthesizedAttributes l) { SubTreeSynthesizedAttributes::iterator iter; ROSE_ASSERT(node); // printf ("AstDOTGeneration::evaluateSynthesizedAttribute(): node = %s \n",node->class_name().c_str()); // DQ (5/3/2006): Skip this IR node if it is specified as such in the inherited attribute if (ia.skipSubTree == true) { // I am unclear if I should return NULL or node as a parameter to DOTSynthesizedAttribute // Figured this out: if we return a valid pointer then we get a node in the DOT graph // (with just the pointer value as a label), where as if we return a DOTSynthesizedAttribute // with a NUL pointer then the node will NOT appear in the DOT graph. // return DOTSynthesizedAttribute(node); return DOTSynthesizedAttribute(NULL); } string nodeoption; if(AstTests::isProblematic(node)) { // cout << "problematic node found." << endl; nodeoption="color=\"orange\" "; } string nodelabel=string("\\n")+node->class_name(); // DQ (1/24/2009): Added support for output of isForward flag in the dot graph. SgDeclarationStatement* genericDeclaration = isSgDeclarationStatement(node); if (genericDeclaration != NULL) { // At the moment the mnemonic name is stored, but it could be computed in the // future from the kind and the tostring() function. string name = (genericDeclaration->isForward() == true) ? "isForward" : "!isForward"; ROSE_ASSERT(name.empty() == false); // DQ (3/20/2011): Added class names to the generated dot file graphs of the AST. SgClassDeclaration* classDeclaration = isSgClassDeclaration(genericDeclaration); if (classDeclaration != NULL) { nodelabel += string("\\n") + classDeclaration->get_name(); } // DQ (3/20/2011): Added function names to the generated dot file graphs of the AST. SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(genericDeclaration); if (functionDeclaration != NULL) { nodelabel += string("\\n") + functionDeclaration->get_name(); } nodelabel += string("\\n") + name; } // DQ (4/6/2011): Added support for output of the name for SgInitializedName IR nodes. SgInitializedName* initializedName = isSgInitializedName(node); if (initializedName != NULL) { nodelabel += string("\\n") + initializedName->get_name(); } // DQ (4/6/2011): Added support for output of the name for SgInitializedName IR nodes. SgIntVal* intValue = isSgIntVal(node); if (intValue != NULL) { nodelabel += string("\\n value = ") + StringUtility::numberToString(intValue->get_value()); } // DQ (4/6/2011): Added support for output of the name for SgInitializedName IR nodes. SgVarRefExp* varRefExp = isSgVarRefExp(node); if (varRefExp != NULL) { SgVariableSymbol* variableSymbol = varRefExp->get_symbol(); ROSE_ASSERT(variableSymbol != NULL); string name = variableSymbol->get_name(); nodelabel += string("\\n name = ") + name; } // DQ (1/19/2009): Added support for output of what specific instrcution this is in the dot graph. SgAsmInstruction* genericInstruction = isSgAsmInstruction(node); if (genericInstruction != NULL) { #ifdef ROSE_BUILD_BINARY_ANALYSIS_SUPPORT // At the moment the mnemonic name is stored, but it could be computed in the // future from the kind and the tostring() function. #if 1 string unparsedInstruction = unparseInstruction(genericInstruction); string addressString = StringUtility::numberToString( (void*) genericInstruction->get_address() ); // string name = genericInstruction->get_mnemonic(); string name = unparsedInstruction + "\\n address: " + addressString; #else string name = unparsedInstruction + "\\n" + addressString; #endif ROSE_ASSERT(name.empty() == false); nodelabel += string("\\n") + name; #else printf ("Warning: In AstDOTGeneration.C ROSE_BUILD_BINARY_ANALYSIS_SUPPORT is not defined \n"); #endif } SgAsmExpression* genericExpression = isSgAsmExpression(node); if (genericExpression != NULL) { #ifdef ROSE_BUILD_BINARY_ANALYSIS_SUPPORT string name = unparseExpression(genericExpression, NULL, NULL); ROSE_ASSERT(name.empty() == false); nodelabel += string("\\n") + name; #else printf ("Warning: In AstDOTGeneration.C ROSE_BUILD_BINARY_ANALYSIS_SUPPORT is not defined \n"); #endif } // DQ (10/29/2008): Added some support for additional output of internal names for specific IR nodes. // In generall there are long list of these IR nodes in the binary and this helps make some sense of // the lists (sections, symbols, etc.). SgAsmExecutableFileFormat* binaryFileFormatNode = isSgAsmExecutableFileFormat(node); if (binaryFileFormatNode != NULL) { #ifdef ROSE_BUILD_BINARY_ANALYSIS_SUPPORT // The case of binary file format IR nodes can be especially confusing so we want the // default to output some more specific information for some IR nodes (e.g. sections). string name; SgAsmGenericSection* genericSection = isSgAsmGenericSection(node); if (genericSection != NULL) { SgAsmGenericString* genericString = genericSection->get_name(); ROSE_ASSERT(genericString != NULL); name = genericString->get_string(); } SgAsmGenericSymbol* genericSymbol = isSgAsmGenericSymbol(node); if (genericSymbol != NULL) { SgAsmGenericString* genericString = genericSymbol->get_name(); ROSE_ASSERT(genericString != NULL); name = genericString->get_string(); if (name.empty() == true) name = "no_name_for_symbol"; } SgAsmGenericDLL* genericDLL = isSgAsmGenericDLL(node); if (genericDLL != NULL) { SgAsmGenericString* genericString = genericDLL->get_name(); ROSE_ASSERT(genericString != NULL); name = genericString->get_string(); } SgAsmPEImportItem* peImportItem = isSgAsmPEImportItem(node); if (peImportItem != NULL) { SgAsmGenericString* genericString = peImportItem->get_name(); ROSE_ASSERT(genericString != NULL); name = genericString->get_string(); } SgAsmDwarfLine* asmDwarfLine = isSgAsmDwarfLine(node); if (asmDwarfLine != NULL) { char buffer[100]; // It does not work to embed the "\n" into the single sprintf parameter. // sprintf(buffer," Addr: 0x%08"PRIx64" \n line: %d col: %d ",asmDwarfLine->get_address(),asmDwarfLine->get_line(),asmDwarfLine->get_column()); sprintf(buffer,"Addr: 0x%08"PRIx64,asmDwarfLine->get_address()); name = buffer; sprintf(buffer,"line: %d col: %d",asmDwarfLine->get_line(),asmDwarfLine->get_column()); name += string("\\n") + buffer; } SgAsmDwarfConstruct* asmDwarfConstruct = isSgAsmDwarfConstruct(node); if (asmDwarfConstruct != NULL) { name = asmDwarfConstruct->get_name(); } #if 0 // This might not be the best way to implement this, since we want to detect common base classes of IR nodes. switch (node->variantT()) { case V_SgAsmElfSection: { SgAsmElfSection* n = isSgAsmElfSection(node); name = n->get_name(); break; } default: { // No additional information is suggested for the default case! } } #endif if (name.empty() == false) nodelabel += string("\\n") + name; #else printf ("Warning: In AstDOTGeneration.C ROSE_BUILD_BINARY_ANALYSIS_SUPPORT is not defined \n"); #endif } // DQ (11/29/2008): Output the directives in the label of the IR node. SgC_PreprocessorDirectiveStatement* preprocessorDirective = isSgC_PreprocessorDirectiveStatement(node); if (preprocessorDirective != NULL) { string s = preprocessorDirective->get_directiveString(); // Change any double quotes to single quotes so that DOT will not misunderstand the generated lables. while (s.find("\"") != string::npos) { s.replace(s.find("\""),1,"\'"); } if (s.empty() == false) nodelabel += string("\\n") + s; } nodelabel += additionalNodeInfo(node); // DQ (11/1/2003) added mechanism to add additional options (to add color, etc.) // nodeoption += additionalNodeOptions(node); string additionalOptions = additionalNodeOptions(node); // printf ("nodeoption = %s size() = %ld \n",nodeoption.c_str(),nodeoption.size()); // printf ("additionalOptions = %s size() = %ld \n",additionalOptions.c_str(),additionalOptions.size()); string x; string y; x += additionalOptions; nodeoption += additionalOptions; DOTSynthesizedAttribute d(0); // DQ (7/27/2008): Added mechanism to support pruning of AST bool commentoutNode = commentOutNodeInGraph(node); if (commentoutNode == true) { // DQ (11/10/2008): Fixed to only output message when (verbose_level > 0); command-line option. // DQ (7/27/2008): For now just return to test this mechanism, then we want to add comment "//" propoerly to generated DOT file. if (SgProject::get_verbose() > 0) { printf ("Skipping the use of this IR node in the DOT Graph \n"); } } else { // ************************** switch(traversal) { case TOPDOWNBOTTOMUP: dotrep.addNode(node,dotrep.traceFormat(ia.tdbuTracePos,tdbuTrace)+nodelabel,nodeoption); break; case PREORDER: case TOPDOWN: dotrep.addNode(node,dotrep.traceFormat(ia.tdTracePos)+nodelabel,nodeoption); break; case POSTORDER: case BOTTOMUP: dotrep.addNode(node,dotrep.traceFormat(buTrace)+nodelabel,nodeoption); break; default: assert(false); } ++tdbuTrace; ++buTrace; // add edges or null values int testnum=0; for (iter = l.begin(); iter != l.end(); iter++) { string edgelabel = string(node->get_traversalSuccessorNamesContainer()[testnum]); string toErasePrefix = "p_"; if (AstTests::isPrefix(toErasePrefix,edgelabel)) { edgelabel.erase(0, toErasePrefix.size()); } if ( iter->node == NULL) { // SgNode* snode=node->get_traversalSuccessorContainer()[testnum]; AstSuccessorsSelectors::SuccessorsContainer c; AstSuccessorsSelectors::selectDefaultSuccessors(node,c); SgNode* snode=c[testnum]; // isDefault shows that the default constructor for synth attribute was used if (l[testnum].isDefault() && snode && (visitedNodes.find(snode) != visitedNodes.end()) ) { // handle bugs in SAGE dotrep.addEdge(node,edgelabel,snode,"dir=forward arrowhead=\"odot\" color=red "); } else { if (snode == NULL) { dotrep.addNullValue(node,"",edgelabel,""); } } } else { // DQ (3/5/2007) added mechanism to add additional options (to add color, etc.) string edgeoption = additionalEdgeOptions(node,iter->node,edgelabel); switch(traversal) { case TOPDOWNBOTTOMUP: dotrep.addEdge(node,edgelabel,(*iter).node,edgeoption + "dir=both"); break; case PREORDER: case TOPDOWN: dotrep.addEdge(node,edgelabel,(*iter).node,edgeoption + "dir=forward"); break; case POSTORDER: case BOTTOMUP: dotrep.addEdge(node,edgelabel,(*iter).node,edgeoption + "dir=back"); break; default: assert(false); } } testnum++; } // ************************** } // DQ (7/4/2008): Support for edges specified in AST attributes AstAttributeMechanism* astAttributeContainer = node->get_attributeMechanism(); if (astAttributeContainer != NULL) { // Loop over all the attributes at this IR node for (AstAttributeMechanism::iterator i = astAttributeContainer->begin(); i != astAttributeContainer->end(); i++) { // std::string name = i->first; AstAttribute* attribute = i->second; ROSE_ASSERT(attribute != NULL); // This can return a non-empty list in user-defined attributes (derived from AstAttribute). // printf ("Calling attribute->additionalNodeInfo() \n"); std::vector<AstAttribute::AttributeNodeInfo> nodeList = attribute->additionalNodeInfo(); // printf ("nodeList.size() = %lu \n",nodeList.size()); for (std::vector<AstAttribute::AttributeNodeInfo>::iterator i_node = nodeList.begin(); i_node != nodeList.end(); i_node++) { SgNode* nodePtr = i_node->nodePtr; string nodelabel = i_node->label; string nodeoption = i_node->options; // printf ("In AstDOTGeneration::evaluateSynthesizedAttribute(): Adding a node nodelabel = %s nodeoption = %s \n",nodelabel.c_str(),nodeoption.c_str()); // dotrep.addNode(NULL,dotrep.traceFormat(ia.tdTracePos)+nodelabel,nodeoption); dotrep.addNode( nodePtr, dotrep.traceFormat(ia.tdTracePos) + nodelabel, nodeoption ); } // printf ("Calling attribute->additionalEdgeInfo() \n"); std::vector<AstAttribute::AttributeEdgeInfo> edgeList = attribute->additionalEdgeInfo(); // printf ("edgeList.size() = %lu \n",edgeList.size()); for (std::vector<AstAttribute::AttributeEdgeInfo>::iterator i_edge = edgeList.begin(); i_edge != edgeList.end(); i_edge++) { string edgelabel = i_edge->label; string edgeoption = i_edge->options; // printf ("In AstDOTGeneration::evaluateSynthesizedAttribute(): Adding an edge from i_edge->fromNode = %p to i_edge->toNode = %p edgelabel = %s edgeoption = %s \n",i_edge->fromNode,i_edge->toNode,edgelabel.c_str(),edgeoption.c_str()); dotrep.addEdge(i_edge->fromNode,edgelabel,i_edge->toNode,edgeoption + "dir=forward"); } } } switch(node->variantT()) { // DQ (9/1/2008): Added case for output of SgProject rooted DOT file. // This allows source code and binary files to be combined into the same DOT file. case V_SgProject: { SgProject* project = dynamic_cast<SgProject*>(node); ROSE_ASSERT(project != NULL); string generatedProjectName = SageInterface::generateProjectName( project ); // printf ("generatedProjectName (from SgProject) = %s \n",generatedProjectName.c_str()); if (generatedProjectName.length() > 40) { // printf ("Warning: generatedProjectName (from SgProject) = %s \n",generatedProjectName.c_str()); generatedProjectName = "aggregatedFileNameTooLong"; printf ("Proposed (generated) filename is too long, shortened to: %s \n",generatedProjectName.c_str()); } string filename = string("./") + generatedProjectName + ".dot"; // printf ("generated filename for dot file (from SgProject) = %s \n",filename.c_str()); if ( SgProject::get_verbose() >= 1 ) printf ("Output the DOT graph from the SgProject IR node (filename = %s) \n",filename.c_str()); dotrep.writeToFileAsGraph(filename); break; } // case V_SgFile: case V_SgSourceFile: case V_SgBinaryComposite: { SgFile* file = dynamic_cast<SgFile*>(node); ROSE_ASSERT(file != NULL); string original_filename = file->getFileName(); // DQ (7/4/2008): Fix filenamePostfix to go before the "." // string filename = string("./") + ROSE::stripPathFromFileName(original_filename) + "."+filenamePostfix+"dot"; string filename = string("./") + ROSE::stripPathFromFileName(original_filename) + filenamePostfix + ".dot"; // printf ("generated filename for dot file (from SgSourceFile or SgBinaryComposite) = %s file->get_parent() = %p \n",filename.c_str(),file->get_parent()); // printf ("file->get_parent() = %p \n",file->get_parent()); // cout << "generating DOT file (from SgSourceFile or SgBinaryComposite): " << filename2 << " ... "; // DQ (9/1/2008): this effects the output of DOT files when multiple files are specified // on the command line. A SgProject is still built even when a single file is specificed // on the command line, however there are cases where a SgFile can be built without a // SgProject and this case allows those SgFile rooted subtrees to be output as DOT files. // If there is a SgProject then output the dot file from there, else output as a SgFile. if (file->get_parent() == NULL) { // If there is no SgProject then output the file now! if ( SgProject::get_verbose() >= 1 ) printf ("Output the DOT graph from the SgFile IR node (no SgProject available) \n"); dotrep.writeToFileAsGraph(filename); } else { // There is a SgProject IR node, but if we will be traversing it we want to output the // graph then (so that the graph will include the SgProject IR nodes and connect multiple // files (SgSourceFile or SgBinaryComposite IR nodes). if ( visitedNodes.find(file->get_parent()) == visitedNodes.end() ) { // This SgProject node was not input as part of the traversal, // so we will not be traversing the SgProject IR nodes and we // have to output the graph now! if ( SgProject::get_verbose() >= 1 ) printf ("Output the DOT graph from the SgFile IR node (SgProject was not traversed) \n"); dotrep.writeToFileAsGraph(filename); } else { if ( SgProject::get_verbose() >= 1 ) printf ("Skip the output of the DOT graph from the SgFile IR node (SgProject will be traversed) \n"); } } // cout << "done." << endl; break; } // DQ (7/23/2005): Implemented default case to avoid g++ warnings // about enum values not handled by this switch default: { // nothing to do here break; } } d.node = node; return d; }
void CompassAnalyses::VariableNameEqualsDatabaseName::Traversal:: visit(SgNode* node) { if( isSgAssignInitializer(node) != NULL ) assignExp = node; if( isSgAssignOp(node) != NULL ) assignExp = node; SgFunctionCallExp* funcCall = isSgFunctionCallExp(node); // See if we have a dot expression or arrow expression which // accesses the desired member function in the class we are looking for. if ( funcCall != NULL ) { SgExpression* funcExp = funcCall->get_function(); if ( ( isSgDotExp(funcExp) != NULL ) | ( isSgArrowExp(funcExp) != NULL ) ) { SgBinaryOp* binOp = isSgBinaryOp(funcExp); SgExpression* rhsOp = binOp->get_rhs_operand(); // SgExpression* lhsOp = binOp->get_lhs_operand(); if ( SgMemberFunctionRefExp* funcRef = isSgMemberFunctionRefExp(rhsOp) ) { // std::cout << "c1\n" ; SgMemberFunctionSymbol* funcSymbol = funcRef->get_symbol(); ROSE_ASSERT(funcSymbol->get_declaration() != NULL); // DQ (1/16/2008): Note that the defining declaration need not exist (see test2001_11.C) // ROSE_ASSERT(funcSymbol->get_declaration()->get_definingDeclaration() != NULL); if (funcSymbol->get_declaration()->get_definingDeclaration() != NULL) { SgMemberFunctionDeclaration* funcDecl = isSgMemberFunctionDeclaration(funcSymbol->get_declaration()->get_definingDeclaration()); ROSE_ASSERT( funcDecl != NULL ); SgClassDefinition* clDef = isSgClassDefinition(funcDecl->get_scope()); SgClassDeclaration* clDecl = isSgClassDeclaration(clDef->get_declaration()); // SgClassDeclaration* clDecl = funcDecl->get_associatedClassDeclaration(); ROSE_ASSERT( clDecl != NULL ); std::string className = clDecl->get_name().getString(); ROSE_ASSERT(funcDecl != NULL); std::string functionName = funcDecl->get_name().getString(); // If the class is the class we are looking for see if the member function // access is to the member function we are interested in. // std::cout << "className = " << className << std::endl; // std::cout << "functionName = " << functionName << std::endl; if ( (className == classToLookFor) && ( functionName == memberFunctionToLookFor ) ) { SgExprListExp* actualArgs = funcCall->get_args(); SgExpressionPtrList& actualExpArgs = actualArgs->get_expressions (); ROSE_ASSERT(actualExpArgs.size() == 1); Rose_STL_Container<SgNode*> nodeLst = NodeQuery::querySubTree(*actualExpArgs.begin(), V_SgStringVal); ROSE_ASSERT( nodeLst.size() > 0); SgStringVal* actualArg = isSgStringVal(*nodeLst.begin()); ROSE_ASSERT(actualArg != NULL); std::string stringArg = actualArg->get_value(); std::cout << "arg:" << stringArg << std::endl; std::string varName; // SgInitializedName* initName = NULL; if ( SgAssignInitializer* assignInit = isSgAssignInitializer(assignExp) ) { SgInitializedName* initName = isSgInitializedName(assignInit->get_parent()); ROSE_ASSERT(initName != NULL); varName = initName->get_name().getString(); } else { if ( SgAssignOp* assignOp = isSgAssignOp(assignExp) ) { SgExpression* lhsOp = assignOp->get_lhs_operand(); SgVarRefExp* varRef = isSgVarRefExp(lhsOp); ROSE_ASSERT(varRef!=NULL); SgVariableSymbol* varSymbol = varRef->get_symbol(); ROSE_ASSERT(varSymbol != NULL); SgInitializedName* initName = varSymbol->get_declaration(); varName = initName->get_name().getString(); } } if (varName != "") { // we are only interested in the part of the argument after the last ":" // Database scopes in ALE3D are separated by ":" size_t posCol = stringArg.find_last_of(':'); if (posCol != std::string::npos) stringArg = stringArg.substr(posCol+1); //Find violations to the rule if ( stringArg != varName) { output->addOutput(new CheckerOutput(assignExp)); std::cout << "violation" << varName << std::endl; } else { std::cout << "non=violation" << varName << std::endl; } } } } } } } } // End of the visit function.
int main( int argc, char *argv[] ) { if( argc < 2 ) { cout << "./amos: no input files " << endl; cout << " " << endl; cout << "Hi, this is Amos! " << endl; cout << "It's my pleasure to serve you. " << endl; cout << " " << endl; cout << "Please type option '--help' to see guide " << endl; cout << " " << endl; return 0; } cout << "*************************************************************" << endl; cout << "** **" << endl; cout << "** Welcome to use OpenMP task validation system! **" << endl; cout << "** **" << endl; cout << "** editor: Amos Wang **" << endl; cout << "*************************************************************\n" << endl; vector<string> argvList( argv, argv+argc ); vector<string> argvList0( argv, argv+argc ); // keep original argv and argc command_processing( argvList ); if( !parse_OmpTask( argvList ) ) { cout << "\nAmos says: I am sorry that I could not find any OpenMP task !" << endl << endl; return 0; } // for time counter long t_start; long t_end; double time_program = 0.0; t_start = usecs(); // for time counter transform_Task2Loop( argvList ); SgProject *project = frontend(argvList); ROSE_ASSERT( project != NULL ); #if 1 VariantVector vv( V_SgForStatement ); Rose_STL_Container<SgNode*> loops = NodeQuery::queryMemoryPool(vv); for( Rose_STL_Container<SgNode*>::iterator iter = loops.begin(); iter!= loops.end(); iter++ ) { SgForStatement* cur_loop = isSgForStatement(*iter); ROSE_ASSERT(cur_loop); SageInterface::normalizeForLoopInitDeclaration(cur_loop); } #endif //initialize_analysis( project, false ); initialize_analysis( project, false ); //For each source file in the project SgFilePtrList &ptr_list = project->get_fileList(); cout << "\n**** Amos' validation system running ****\n" << endl; for( SgFilePtrList::iterator iter = ptr_list.begin(); iter != ptr_list.end(); iter++ ) { cout << "temp source code: " << (*iter)->get_file_info()->get_filename() << endl << endl; SgFile *sageFile = (*iter); SgSourceFile *sfile = isSgSourceFile(sageFile); ROSE_ASSERT(sfile); SgGlobal *root = sfile->get_globalScope(); SgDeclarationStatementPtrList& declList = root->get_declarations (); //cout << "Check point 2" << endl; //For each function body in the scope for( SgDeclarationStatementPtrList::iterator p = declList.begin(); p != declList.end(); ++p ) { SgFunctionDeclaration *func = isSgFunctionDeclaration(*p); if ( func == 0 ) continue; SgFunctionDefinition *defn = func->get_definition(); if ( defn == 0 ) continue; //ignore functions in system headers, Can keep them to test robustness if ( defn->get_file_info()->get_filename() != sageFile->get_file_info()->get_filename() ) continue; SgBasicBlock *body = defn->get_body(); // For each loop Rose_STL_Container<SgNode*> loops = NodeQuery::querySubTree( defn, V_SgForStatement ); if( loops.size() == 0 ) continue; // X. Replace operators with their equivalent counterparts defined // in "inline" annotations AstInterfaceImpl faImpl_1( body ); CPPAstInterface fa_body( &faImpl_1 ); OperatorInlineRewrite()( fa_body, AstNodePtrImpl(body) ); // Pass annotations to arrayInterface and use them to collect // alias info. function info etc. ArrayAnnotation* annot = ArrayAnnotation::get_inst(); ArrayInterface array_interface( *annot ); array_interface.initialize( fa_body, AstNodePtrImpl(defn) ); array_interface.observe( fa_body ); // X. Loop normalization for all loops within body NormalizeForLoop(fa_body, AstNodePtrImpl(body)); //cout << "Check point 3" << endl; for ( Rose_STL_Container<SgNode*>::iterator iter = loops.begin(); iter!= loops.end(); iter++ ) { SgNode* current_loop = *iter; SgInitializedName* invarname = getLoopInvariant( current_loop ); if( invarname != NULL ) { if( invarname->get_name().getString().compare("__Amos_Wang__") == 0 ) { //cout << "It's __Amos_Wang__." << endl; //replace "for(__Amos_Wang__ = 0;__Amos_Wang__ <= 1 - 1;__Amos_Wang__ += 1)" //to "#pragma omp task" std::string strtemp = current_loop->unparseToString(); strtemp.replace( 0, 64, "#pragma omp task" ); cout << "task position at: " << current_loop->get_file_info()->get_line() << ", " << current_loop->get_file_info()->get_col() << endl; cout << "context: " << strtemp.c_str() << endl; TaskValidation( current_loop ); cout << "TaskValidation done...\n" << endl; } else continue; } }// end for loops }//end loop for each function body cout << "--------------------------------------------" << endl; }//end loop for each source file release_analysis(); //generateDOT( *project ); backend( project ); //generate final file with correct directive amos_filter( argvList0 ); // for time counter t_end = usecs(); time_program = ((double)(t_end - t_start))/1000000; cout << "analysis time: " << time_program << " sec" << endl; // cout << endl << "***** Thank you for using Amos' compiler ! *****\n" << endl; return 0; }
void CudaOptimizer::applyLoopAggregationOpt(SgFunctionDeclaration* kernel, const std::set<SgInitializedName*> readOnlyVars, const MintArrFreqPairList_t& candidateVarsShared, const MintArrFreqPairList_t& candidateVarsReg, const MintForClauses_t& clauseList) { //perform shared memory optimizations, go through each element in the candidate list //the list is in decending order based on the number of references //the list contains array name and how many planes it needs SgBasicBlock* kernel_body = kernel->get_definition()->get_body(); int common_order =0 ; //find the common order otherwise, we need to declare separate idx and idy, that's not good. MintArrFreqPairList_t::const_iterator it; for(it = candidateVarsShared.begin(); it != candidateVarsShared.end(); it++) { MintArrFreqPair_t apair = (*it); SgInitializedName* candidate = apair.first; ROSE_ASSERT(candidate); //we already computed, how many planes we will need int num_planes = apair.second; int dimension = MintArrayInterface::getDimension(candidate); if(dimension > 3 || dimension < 2) continue; int order = StencilAnalysis::performHigherOrderAnalysis(kernel_body, candidate, num_planes); //TODO: should we return if the order is 0 or too high ? //what do you think? Yes, we should use registers if the order is 0, because there is no sharing. if(order == 0){ cout << " INFO:Mint: Order of this array is " << order ; cout << ". No sharing, no need to use shared memory " << endl; continue ; } common_order = order > common_order ? order : common_order ; } common_order = common_order > MAX_ORDER ? MAX_ORDER : common_order ; cout << " INFO:Mint: Common order of this kernel " << common_order << endl ; bool first = true; for(it = candidateVarsShared.begin(); it != candidateVarsShared.end(); it++) { MintArrFreqPair_t apair = (*it); SgInitializedName* candidate = apair.first; ROSE_ASSERT(candidate); //we already computed, how many planes we will need int num_planes = apair.second; int dimension = MintArrayInterface::getDimension(candidate); if(dimension > 3 || dimension < 2) continue; //TODO <--check this if it should be true or false? when only -opt:shared is set (not register) //bool regSharedSame = true; //refCountMaxRg > 0 ? true : false; we already inserted the register cout << " INFO:Mint: Applying Loop Aggregation optimization to array ("<<candidate->get_name().str(); cout << " using " << num_planes << " planes )" << endl; slidingRowOptimizer(kernel, readOnlyVars, candidate, clauseList, num_planes, common_order, first); first = false; }//end of for if(candidateVarsShared.size () > 0) OnChipMemoryOpt::insertSynchPoints(kernel); }
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); } } }
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); } } }
bool checkIfNodeMaps(token_type tok, SgNode* node) { bool nodeMaps = false; using namespace boost::wave; //By definition a compiler generated node can //not map to the token stream SgLocatedNode* compilerGeneratedNode = isSgLocatedNode(node); if( compilerGeneratedNode != NULL ) if(compilerGeneratedNode->get_file_info()->isCompilerGenerated() == true) return false; // std::cout << get_token_name(tok) << " " << std::string(tok.get_value().c_str()) << " " << node->class_name() << " " << node->get_file_info()->get_line() << std::endl; //Mapping literal token id's switch(token_id(tok)){ case T_PP_NUMBER:{ if(isSgValueExp(node)!=NULL) nodeMaps=true; break; } case T_CHARLIT:{ if( ( isSgCharVal(node) != NULL ) | ( isSgUnsignedCharVal(node) != NULL ) ) nodeMaps = true; break; } case T_FLOATLIT:{ if( isSgFloatVal(node) != NULL ) nodeMaps = true; break; } case T_INTLIT:{ if( ( isSgIntVal(node) != NULL ) || ( isSgUnsignedIntVal(node) != NULL ) ) nodeMaps = true; break; } case T_LONGINTLIT: { if( ( isSgLongIntVal(node) != NULL ) | ( isSgLongLongIntVal(node) != NULL ) | ( isSgUnsignedLongLongIntVal(node) != NULL ) ) nodeMaps = true; break; } case T_STRINGLIT: { if( isSgStringVal(node) != NULL ) nodeMaps = true; break; } case T_QUESTION_MARK: { if( isSgConditionalExp(node) != NULL ) nodeMaps = true; break; } case T_FALSE: case T_TRUE: if( isSgBoolValExp(node) != NULL ) nodeMaps = true; break; default: break; } //map keyword token id's switch(token_id(tok)){ case T_ASM: if( isSgAsmStmt(node) != NULL ) nodeMaps = true; break; case T_AUTO: //auto //dont know break; /*case T_BOOL: //dont think this can be mapped break;*/ case T_BREAK: if( isSgBreakStmt(node) != NULL ) nodeMaps = true; break; case T_CASE: if( isSgCaseOptionStmt(node) != NULL ) nodeMaps = true; break; case T_CATCH: if( isSgCatchOptionStmt(node) != NULL ) nodeMaps = true; break; /* case T_CHAR: //dont know break; */ case boost::wave::T_CLASS: if( isSgClassDeclaration(node) != NULL ) nodeMaps = true; break; case T_CONST: // is it SgConstVolatileModifier? //dont know break; case T_CONTINUE: if( isSgContinueStmt(node) != NULL ) nodeMaps = true; break; //case T_DEFAULT: //Dont know // break; case T_DELETE: if( isSgDeleteExp(node) != NULL ) nodeMaps = true; break; case T_DO: if( isSgDoWhileStmt(node) != NULL ) nodeMaps = true; break; case T_ELSE: //dont know break; case T_EXPLICIT: //dont know break; case T_EXPORT: case T_EXTERN: break; case T_FOR: if( isSgForStatement(node) != NULL ) nodeMaps = true; break; case T_FRIEND: //dont know break; case T_GOTO: if( isSgGotoStatement(node) != NULL ) nodeMaps = true; break; case T_IF: //dont know how to handle this because if if-else break; case T_INLINE: //dont know break; case T_MUTABLE: //dont know break; case T_NAMESPACE: if( ( isSgNamespaceAliasDeclarationStatement(node) != NULL ) | (isSgNamespaceDeclarationStatement(node) != NULL ) ) nodeMaps = true; break; case T_NEW: if( isSgNewExp(node) != NULL ) nodeMaps = true; break; case T_OPERATOR: case T_PRIVATE: case T_PROTECTED: case T_PUBLIC: case T_REGISTER: case T_REINTERPRETCAST: //dont know break; case T_RETURN: if( isSgReturnStmt(node) != NULL ) nodeMaps = true; break; case T_SIZEOF: if( isSgSizeOfOp(node) != NULL ) nodeMaps = true; break; case T_STATIC: case T_STATICCAST: //dont know break; case T_STRUCT: if( isSgClassDeclaration(node) != NULL ) nodeMaps = true; break; case T_SWITCH: if( isSgSwitchStatement(node) != NULL ) nodeMaps = true; break; //case T_TEMPLATE: //dont know // break; case T_THIS: if( isSgThisExp(node) != NULL ) nodeMaps = true; break; case T_THROW: if( isSgThrowOp(node) != NULL ) nodeMaps = true; break; case T_TRY: if( isSgTryStmt(node) != NULL ) nodeMaps = true; break; case boost::wave::T_TYPEDEF: if( isSgTypedefDeclaration(node) != NULL ) nodeMaps = true; break; case T_TYPEID: if( isSgTypeIdOp(node) != NULL ) nodeMaps = true; break; case T_TYPENAME: //dont know break; case T_UNION: if( isSgClassDeclaration(node) != NULL ) nodeMaps = true; break; case T_USING: if( isSgUsingDeclarationStatement(node) != NULL ) nodeMaps = true; break; case T_VIRTUAL: //dont know break; case T_VOLATILE: //is it SgConstVolatileModifier ? break; case T_WHILE: if( isSgWhileStmt(node) != NULL ) nodeMaps = true; break; default: break; } //map operator token id's switch(token_id(tok)){ case T_AND: case T_ANDAND: if( isSgAndOp(node) != NULL | isSgBitAndOp(node) != NULL ) nodeMaps = true; break; case T_ASSIGN: if ( isSgAssignOp(node) != NULL | isSgAssignInitializer(node) != NULL ) nodeMaps = true; break; case T_ANDASSIGN: //do not know break; case T_OR: if ( isSgBitOrOp(node) != NULL || isSgOrOp(node) != NULL ) nodeMaps = true; break; case T_ORASSIGN: //do not know break; case T_XOR: if ( isSgBitXorOp(node) != NULL ) nodeMaps = true; break; case T_XORASSIGN: if ( isSgXorAssignOp(node) != NULL ) nodeMaps = true; break; case T_COMMA: if ( isSgCommaOpExp(node) != NULL ) nodeMaps = true; break; case T_COLON: //dont know break; case T_DIVIDE: if ( isSgDivideOp(node) != NULL ) nodeMaps = true; break; case T_DIVIDEASSIGN: if ( isSgDivAssignOp(node) != NULL ) nodeMaps = true; break; case T_DOT: if ( isSgDotExp(node) != NULL ) nodeMaps = true; break; case T_DOTSTAR: if ( isSgDotExp(node) != NULL ) nodeMaps = true; break; case T_ELLIPSIS: //Dont know break; case T_EQUAL: if ( isSgEqualityOp(node) != NULL ) nodeMaps = true; break; case T_GREATER: if ( isSgGreaterThanOp(node) != NULL ) nodeMaps = true; break; case T_GREATEREQUAL: if ( isSgGreaterOrEqualOp(node) != NULL ) nodeMaps = true; break; case T_LEFTBRACE: //Dont know break; case T_LESS: if ( isSgLessThanOp(node) != NULL ) nodeMaps = true; break; case T_LESSEQUAL: if ( isSgLessOrEqualOp(node) != NULL ) nodeMaps = true; break; case T_LEFTPAREN: //Dont know break; case T_LEFTBRACKET: case T_RIGHTBRACKET: if ( isSgPntrArrRefExp(node) != NULL ) nodeMaps = true; break; case T_MINUS: if ( ( isSgSubtractOp(node) != NULL ) | ( isSgMinusOp(node) != NULL ) ) nodeMaps = true; break; case T_MINUSASSIGN: if ( isSgMinusAssignOp(node) != NULL ) nodeMaps = true; break; case T_MINUSMINUS: if ( isSgMinusMinusOp(node) != NULL ) nodeMaps = true; break; case T_PERCENT: if ( isSgModOp(node) != NULL ) nodeMaps = true; break; case T_PERCENTASSIGN: if ( isSgModAssignOp(node) != NULL ) nodeMaps = true; break; case T_NOT: if ( isSgNotOp(node) != NULL ) nodeMaps = true; break; case T_NOTEQUAL: if ( isSgNotEqualOp(node) != NULL ) nodeMaps = true; break; case T_OROR: if ( isSgOrOp(node) != NULL ) nodeMaps = true; break; case T_PLUS: if ( isSgAddOp(node) != NULL ) nodeMaps = true; break; case T_PLUSASSIGN: if ( isSgPlusAssignOp(node) != NULL ) nodeMaps = true; break; case T_PLUSPLUS: if ( isSgPlusPlusOp(node) != NULL ) nodeMaps = true; break; case T_ARROW: if ( isSgArrowExp(node) != NULL ) nodeMaps = true; break; case T_ARROWSTAR: if ( isSgArrowStarOp(node) != NULL ) nodeMaps = true; break; case T_QUESTION_MARK: //dont know break; case T_RIGHTBRACE: case T_RIGHTPAREN: case T_COLON_COLON: case T_SEMICOLON: //dont know break; case T_SHIFTLEFT: if ( isSgLshiftOp(node) != NULL ) nodeMaps = true; break; case T_SHIFTLEFTASSIGN: if ( isSgLshiftAssignOp(node) != NULL ) nodeMaps = true; break; case T_SHIFTRIGHT: if ( isSgRshiftOp(node) != NULL ) nodeMaps = true; break; case T_SHIFTRIGHTASSIGN: if ( isSgRshiftAssignOp(node) != NULL ) nodeMaps = true; break; case T_STAR: //dont know if ( isSgMultiplyOp(node) != NULL || isSgPointerType(node) ) nodeMaps = true; break; case T_COMPL://~ if( isSgBitComplementOp(node) != NULL ) nodeMaps = true; //Dont know break; case T_STARASSIGN: if ( isSgMultAssignOp(node) != NULL ) nodeMaps = true; break; case T_POUND_POUND: case T_POUND: //dont know break; case T_AND_ALT: case T_ANDASSIGN_ALT: case T_OR_ALT: case T_ORASSIGN_ALT: case T_XOR_ALT: case T_XORASSIGN_ALT: case T_LEFTBRACE_ALT: case T_LEFTBRACKET_ALT: case T_NOT_ALT: case T_NOTEQUAL_ALT: case T_RIGHTBRACE_ALT: case T_RIGHTBRACKET_ALT: case T_COMPL_ALT: case T_POUND_POUND_ALT: case T_POUND_ALT: case T_OR_TRIGRAPH: case T_XOR_TRIGRAPH: case T_LEFTBRACE_TRIGRAPH: case T_LEFTBRACKET_TRIGRAPH: case T_RIGHTBRACE_TRIGRAPH: case T_RIGHTBRACKET_TRIGRAPH: case T_COMPL_TRIGRAPH: case T_POUND_POUND_TRIGRAPH: case T_POUND_TRIGRAPH: //dont know break; default: break; } switch(token_id(tok)){ case T_FALSE: case T_TRUE: break; case T_CHARLIT: if(SgProject::get_verbose() >= 1) std::cout << "char " << std::string(tok.get_value().c_str()) << std::endl; if( isSgCharVal(node) != NULL ){ SgCharVal* charVal = isSgCharVal(node); if(SgProject::get_verbose() >= 1) std::cout << std::string(tok.get_value().c_str()) << std::endl; char tmp = charVal->get_value(); if(SgProject::get_verbose() >= 1) std::cout << "From charlit: " << tmp << std::endl; if(("\""+std::string(&tmp)+"\"") == std::string(tok.get_value().c_str()) ) nodeMaps = true; } break; case T_STRINGLIT: { if(SgProject::get_verbose() >= 1) std::cout << "string " <<std::string(tok.get_value().c_str()) << std::endl; if( isSgStringVal(node) != NULL ){ SgStringVal* stringVal = isSgStringVal(node); if(SgProject::get_verbose() >= 1){ std::cout << std::string(tok.get_value().c_str()) << std::endl; std::cout << "stringlit: " << stringVal->get_value() << std::endl; } if(("\""+stringVal->get_value()+"\"") == std::string(tok.get_value().c_str()) ) nodeMaps = true; } break; } /*case V_SgWcharVal: if( isSgWcharVal(node) != NULL ) if( std::string(isSgWcharVal(node)->get_value()) == std::string(tok.get_value().c_str()) ) nodeMaps = true; break;*/ default: break; } if( token_id(tok) == T_IDENTIFIER ){ if( isSgInitializedName(node) != NULL ){ std::cout << "Identifier" << std::endl; SgInitializedName* initName = isSgInitializedName(node); std::cout << initName->get_name().getString() << " " << std::string(tok.get_value().c_str()) << std::endl; if( initName->get_name().getString() == std::string(tok.get_value().c_str()) ){ nodeMaps = true; } }else if( isSgVarRefExp(node) != NULL ){ SgVariableSymbol* varSymbol = isSgVarRefExp(node)->get_symbol(); SgInitializedName* initName = varSymbol->get_declaration(); if( initName->get_name().getString() == std::string(tok.get_value().c_str()) ){ nodeMaps = true; std::cout << "Maps:" << initName->get_name().getString() << " " << std::string(tok.get_value().c_str()) << std::endl; }else std::cout << "DONT Map:" << initName->get_name().getString() << " " << std::string(tok.get_value().c_str()) << std::endl; }else if( isSgFunctionRefExp(node) != NULL){ SgFunctionRefExp* funcRef = isSgFunctionRefExp(node); SgFunctionSymbol* funcSymbol = funcRef->get_symbol_i(); if( funcSymbol->get_declaration()->get_name().getString() == std::string(tok.get_value().c_str()) ) nodeMaps = true; }else if( isSgMemberFunctionRefExp(node) != NULL){ SgMemberFunctionRefExp* funcRef = isSgMemberFunctionRefExp(node); SgMemberFunctionSymbol* funcSymbol = funcRef->get_symbol(); if( funcSymbol->get_declaration()->get_name().getString() == std::string(tok.get_value().c_str()) ) nodeMaps = true; } } //Exceptions to the general rule switch(token_id(tok)){ case T_CHARLIT: { switch(node->variantT()) { case V_SgCharVal: case V_SgComplexVal: case V_SgDoubleVal: case V_SgEnumVal: case V_SgFloatVal: case V_SgIntVal: case V_SgLongDoubleVal: case V_SgLongIntVal: case V_SgLongLongIntVal: case V_SgShortVal: case V_SgStringVal: case V_SgUnsignedCharVal: case V_SgUnsignedIntVal: case V_SgUnsignedLongLongIntVal: case V_SgUnsignedLongVal: case V_SgUnsignedShortVal: case V_SgWcharVal: { nodeMaps=true; break; } default: break; }; break; }; } switch(boost::wave::token_id(tok)){ case boost::wave::T_CHAR: { if(isSgTypeChar(node) != NULL) nodeMaps=true; break; } case boost::wave::T_CONST: break; case boost::wave::T_DOUBLE: if(isSgTypeDouble(node) != NULL) nodeMaps=true; break; case boost::wave::T_INT: if(isSgTypeInt(node) != NULL) nodeMaps=true; break; case boost::wave::T_LONG: if(isSgTypeLong(node) != NULL) nodeMaps=true; break; case boost::wave::T_SHORT: if(isSgTypeShort(node) != NULL) nodeMaps=true; break; case boost::wave::T_SIGNED: case boost::wave::T_UNSIGNED: case boost::wave::T_VOID: if(isSgTypeVoid(node) != NULL) nodeMaps=true; break; default: break; }; return nodeMaps; }
// Count the load and store bytes for the // I think we can only return expressions to calculate the value, not the actual values, // since sizeof(type) is machine dependent // Consider both scalar and array accesses by default. Consider both floating point and integer types by default. // return a pair of expressions: // load_byte_exp, and // store_byte_exp // Algorithm: // 1. Call side effect analysis to find read/write variables, some reference may trigger both read and write accesses // Accesses to the same array/scalar variable are grouped into one read (or write) access // e.g. array[i][j], array[i][j+1], array[i][j-1], etc are counted a single access // 2. Group accesses based on the types (same type? increment the same counter to shorten expression length) // 4. Iterate on the results to generate expression like 2*sizeof(float) + 5* sizeof(double) // As an approximate, we use simple analysis here assuming no function calls. std::pair <SgExpression*, SgExpression*> CountLoadStoreBytes (SgLocatedNode* input, bool includeScalars /* = true */, bool includeIntType /* = true */) { std::pair <SgExpression*, SgExpression*> result; assert (input != NULL); // the input is essentially the loop body, a scope statement SgScopeStatement* scope = isSgScopeStatement(input); // 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:"<< input->class_name()<<endl; assert(false); } //Plan A: use and extend Qing's side effect analysis std::set<SgInitializedName*> readVars; std::set<SgInitializedName*> writeVars; bool success = SageInterface::collectReadWriteVariables (isSgStatement(input), readVars, writeVars); if (success!= true) { cout<<"Warning: CountLoadStoreBytes(): failed to collect load/store, mostly due to existence of function calls inside of loop body @ "<<input->get_file_info()->get_line()<<endl; } std::set<SgInitializedName*>::iterator it; if (debug) cout<<"debug: found read variables (SgInitializedName) count = "<<readVars.size()<<endl; for (it=readVars.begin(); it!=readVars.end(); it++) { SgInitializedName* iname = (*it); if (debug) cout<<scalar_or_array (iname->get_type()) <<" "<<iname->get_name()<<"@"<<iname->get_file_info()->get_line()<<endl; } if (!includeScalars ) readVars = filterVariables (readVars); if (debug) cout<<"debug: found write variables (SgInitializedName) count = "<<writeVars.size()<<endl; for (it=writeVars.begin(); it!=writeVars.end(); it++) { SgInitializedName* iname = (*it); if (debug) cout<<scalar_or_array(iname->get_type()) <<" "<<iname->get_name()<<"@"<<iname->get_file_info()->get_line()<<endl; } if (!includeScalars ) writeVars = filterVariables (writeVars); result.first = calculateBytes (readVars, scope, true); result.second = calculateBytes (writeVars, scope, false); return result; }