SgType* Fortran_to_C::translateType(SgType* oldType) { switch(oldType->variantT()) { case V_SgTypeString: { SgExpression* stringLength = deepCopy(isSgTypeString(oldType)->get_lengthExpression()); SgArrayType* newType = buildArrayType(buildCharType(),NULL); newType->set_rank(1); newType->set_dim_info(buildExprListExp(stringLength)); return newType; } case V_SgTypeFloat: { SgIntVal* typeKind = isSgIntVal(oldType->get_type_kind()); if(typeKind == NULL) { // TODO: we just return original type. Might need to fix this in the future return oldType; } switch(typeKind->get_value()) { case 4: return buildFloatType(); case 8: return buildDoubleType(); default: ROSE_ASSERT(false); } } case V_SgTypeInt: { SgIntVal* typeKind = isSgIntVal(oldType->get_type_kind()); if(typeKind == NULL) { // TODO: we just return original type. Might need to fix this in the future return oldType; } switch(typeKind->get_value()) { case 2: return buildShortType(); case 4: return buildIntType(); case 8: return buildLongType(); default: ROSE_ASSERT(false); } } default: return oldType; } }
DeterminismState getExpectation(SgNode *ast, const char *varName) { SgName name(varName); Rose_STL_Container<SgNode*> sdNodes = NodeQuery::querySubTree(ast, &name, NodeQuery::VariableDeclarationFromName); if (sdNodes.size() != 1) { cerr << "Didn't find target variable " << varName << " in list of size " << sdNodes.size() << endl; for (Rose_STL_Container<SgNode*>::iterator i = sdNodes.begin(); i != sdNodes.end(); ++i) cerr << "\t" << (*(isSgVariableDeclaration(*i)->get_variables().begin()))->get_name().str() << endl; return QUESTIONABLE; } SgNode *nSd = *(sdNodes.begin()); SgVariableDeclaration *vdSd = dynamic_cast<SgVariableDeclaration *>(nSd); if (!vdSd) { cerr << "Node wasn't a variable declaration" << endl; return QUESTIONABLE; } SgInitializedName *inSd = vdSd->get_decl_item(name); SgAssignInitializer *aiSd = dynamic_cast<SgAssignInitializer*>(inSd->get_initializer()); if (!aiSd) { cerr << "Couldn't pull an assignment initializer out" << endl; return QUESTIONABLE; } SgIntVal *ivSd = dynamic_cast<SgIntVal*>(aiSd->get_operand()); if (!ivSd) { cerr << "Assignment wasn't an intval" << endl; return QUESTIONABLE; } int value = ivSd->get_value(); return value ? DETERMINISTIC : NONDETERMINISTIC; }
SgExpression* Fortran_to_C::foldBinaryOp(SgExpression* inputExpression) { SgExpression* foldedExp; if(isSgBinaryOp(inputExpression)) { SgBinaryOp* binOp = isSgBinaryOp(inputExpression); SgIntVal* rhs = isSgIntVal(binOp->get_rhs_operand()); if(!rhs) return inputExpression; SgIntVal* lhs = isSgIntVal(binOp->get_lhs_operand()); if(!lhs) return inputExpression; int foldedVal; switch(binOp->variantT()) { case V_SgAddOp: { foldedVal = lhs->get_value() + rhs->get_value(); break; } case V_SgSubtractOp: { foldedVal = lhs->get_value() - rhs->get_value(); break; } case V_SgMultiplyOp: { foldedVal = lhs->get_value() * rhs->get_value(); break; } default: { cerr<<"warning: calculuate - unhandled operator type:"<<binOp->class_name() << endl; return inputExpression; } } foldedExp = buildIntVal(foldedVal); } else return inputExpression; return foldedExp; }
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; }
SgExpression* MintArrayInterface::linearizeThisArrayRefs(SgNode* arrayNode, SgBasicBlock* kernel_body, SgScopeStatement* indexScope, SgInitializedName* arr_iname, bool useSameIndex) { //an instance of an array reference E[k][j+1][i] SgExpression* arrRefWithIndices = isSgExpression(arrayNode); SgExpression* arrayName; //index list are from right to left //first index is i if E[j][i] vector<SgExpression*> subscripts; //get each subscripts of an array reference bool yes = MintArrayInterface::isArrayReference(arrRefWithIndices, &arrayName, &subscripts); ROSE_ASSERT(yes); if(subscripts.size() <= 1) return NULL; //no need to flatten //step 7 //simplfy means that we can simplfy the index expression (subexpression elimination) //by rewriting it in terms of index + some offset instead of computing the offset from address 0. //if simplfy is false, then we cannot figure out the offset. We need to use offset from the address zero. bool simplfy = canWeSimplfyIndexExpression(subscripts); string arr_str = arr_iname -> get_name().str(); string index_str = "index" + arr_str; string width_str = "width" + arr_str; string slice_str = "slice" + arr_str; if(useSameIndex) { width_str = "_width"; slice_str = "_slice"; if(subscripts.size() == 3){ index_str = "_index3D"; } else if(subscripts.size() == 2){ index_str = "_index2D"; } else if(subscripts.size() == 1){ index_str = "_index1D"; } } //base offset, we need to find the relative offset //index expression can be [k +|- c] SgExpression* indexExp = buildVarRefExp(index_str, indexScope); if(simplfy) //continue step 7 { int indexNo=0; vector<SgExpression*>::iterator index_itr = subscripts.begin(); for(index_itr = subscripts.begin(); index_itr != subscripts.end(); index_itr++) { //We assume that if there is binary operation, then it has to be //plus/minus i,j,k with a constant //Otherwise it is just i,j,k SgExpression* index = *index_itr; ROSE_ASSERT(index); //looking for minus, plus 1s: i-1, j+1 or just i,j,k Rose_STL_Container<SgNode*> constExp = NodeQuery::querySubTree(index, V_SgIntVal); Rose_STL_Container<SgNode*> indexVarExp = NodeQuery::querySubTree(index, V_SgVarRefExp); Rose_STL_Container<SgNode*> subtractExp = NodeQuery::querySubTree(index, V_SgSubtractOp); Rose_STL_Container<SgNode*> addExp = NodeQuery::querySubTree(index, V_SgAddOp); indexNo++; if(subtractExp.size() == 1 || addExp.size() == 1) // it is addOp or subtractOp { //e.g. [k][j-1][i+1] becomes [index - 1* width + 1] //optimize it further if the constant is 1 or 0. if(indexVarExp.size() == 1) { ROSE_ASSERT(constExp.size() == 1); SgIntVal* constVal = isSgIntVal(*(constExp.begin())); int constIntVal = constVal->get_value(); SgExpression* offset = NULL; if(indexNo == 1) //gidx { offset = buildIntVal(constIntVal); } else if (indexNo==2) //idy { offset = buildVarRefExp(width_str, kernel_body) ; if(constIntVal != 1) offset = buildMultiplyOp(offset, buildIntVal(constIntVal)); } else if(indexNo==3) //idz { offset = buildVarRefExp(slice_str, kernel_body) ; if(constIntVal != 1) offset = buildMultiplyOp(offset, buildIntVal(constIntVal)); } if(constIntVal != 0 ) { ROSE_ASSERT(offset); if(subtractExp.size() == 1) indexExp = buildSubtractOp(indexExp, offset); else if (addExp.size() == 1) indexExp = buildAddOp(indexExp, offset); } } else if (indexVarExp.size() == 2) { //Added in (3 March 2011) to handle boundary loads //they are typically A[z][y][x + borderOffset] so it is worth to optimize them Rose_STL_Container<SgNode*>::iterator it = indexVarExp.begin(); SgVarRefExp* first = isSgVarRefExp(*it); SgVarRefExp* second = isSgVarRefExp(*(++it)); ROSE_ASSERT(first); ROSE_ASSERT(second); string secondRef = second->unparseToString(); SgExpression* offset =copyExpression(first); if(secondRef.find(GIDX) == string::npos && secondRef.find(GIDY) && string::npos && secondRef.find(GIDZ) == string::npos) {//borderOffset is the second var offset = copyExpression(second); } if (indexNo==2) //idy { offset = buildMultiplyOp(offset,buildVarRefExp(width_str, kernel_body)) ; } if(indexNo==3) //idz { offset = buildMultiplyOp(offset, buildVarRefExp(slice_str, kernel_body)) ; } ROSE_ASSERT(offset); if(subtractExp.size() == 1) indexExp = buildSubtractOp(indexExp, offset); else if (addExp.size() == 1) indexExp = buildAddOp(indexExp, offset); } else { ROSE_ABORT(); } } else { ROSE_ASSERT(constExp.size() == 0); //do nothing because it is in the base index } } //end of subscript loop }//end of simplfy = true else //step 8 { //index expression cannot be simplfied //e.g A[0][n-1][i-j+1][0+3-i] //output: //e.g. _gidx + _gidy * widthUnew in 2D //e.g. _gidx + _gidy * widthUnew + _gidz * sliceUnew in 3D vector<SgExpression*>::iterator index_itr = subscripts.begin(); //first index is i if E[j][i] ROSE_ASSERT(*index_itr); //first index indexExp = deepCopy(*index_itr); if(subscripts.size() >= 2) //second index { index_itr++; ROSE_ASSERT(*index_itr); SgVarRefExp* sizeExp = buildVarRefExp(width_str, kernel_body); ROSE_ASSERT(sizeExp); indexExp = buildAddOp(indexExp, buildMultiplyOp( deepCopy(*index_itr), sizeExp)); } if (subscripts.size() == 3) //third index { index_itr++; ROSE_ASSERT(*index_itr); SgVarRefExp* sizeExp2 = buildVarRefExp(slice_str, kernel_body); ROSE_ASSERT(sizeExp2); indexExp = buildAddOp(indexExp, buildMultiplyOp( deepCopy(*index_itr), sizeExp2)); } ROSE_ASSERT(subscripts.size() <= 3); }//end of !simplfy return indexExp; }//end of indexList of one array
StencilEvaluation_InheritedAttribute StencilEvaluationTraversal::evaluateInheritedAttribute (SgNode* astNode, StencilEvaluation_InheritedAttribute inheritedAttribute ) { #if 0 printf ("In evaluateInheritedAttribute(): astNode = %p = %s \n",astNode,astNode->class_name().c_str()); #endif bool foundPairShiftDoubleConstructor = false; // This is for stencil specifications using vectors of points to represent offsets (not finished). // bool foundVariableDeclarationForStencilInput = false; double stencilCoeficientValue = 0.0; // StencilOffsetFSM offset; StencilOffsetFSM* stencilOffsetFSM = NULL; // We want to interogate the SgAssignInitializer, but we need to generality in the refactored function to use any SgInitializer (e.g. SgConstructorInitializer, etc.). SgInitializedName* initializedName = detectVariableDeclarationOfSpecificType (astNode,"Point"); if (initializedName != NULL) { // This is the code that is specific to the DSL (e.g. the semantics of getZeros() and getUnitv() functions). // So this may be the limit of what can be refactored to common DSL support code. // Or I can maybe do a second pass at atempting to refactor more code later. string name = initializedName->get_name(); SgInitializer* initializer = initializedName->get_initptr(); SgAssignInitializer* assignInitializer = isSgAssignInitializer(initializer); if (assignInitializer != NULL) { SgExpression* exp = assignInitializer->get_operand(); ROSE_ASSERT(exp != NULL); SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(exp); if (functionCallExp != NULL) { SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(functionCallExp->get_function()); if (functionRefExp != NULL) { SgFunctionSymbol* functionSymbol = functionRefExp->get_symbol(); ROSE_ASSERT(functionSymbol != NULL); string functionName = functionSymbol->get_name(); #if 0 printf ("functionName = %s \n",functionName.c_str()); #endif if (functionName == "getZeros") { // We leverage the semantics of known functions used to initialize "Point" objects ("getZeros" initialized the Point object to be all zeros). // In a stencil this will be the center point from which all other points will have non-zero offsets. // For a common centered difference discretization this will be the center point of the stencil. #if 0 printf ("Identified and interpreting the semantics of getZeros() function \n"); #endif stencilOffsetFSM = new StencilOffsetFSM(0,0,0); ROSE_ASSERT(stencilOffsetFSM != NULL); } if (functionName == "getUnitv") { // We leverage the semantics of known functions used to initialize "Point" objects // ("getUnitv" initializes the Point object to be a unit vector for a specific input dimention). // In a stencil this will be an ofset from the center point. #if 0 printf ("Identified and interpreting the semantics of getUnitv() function \n"); #endif // Need to get the dimention argument. SgExprListExp* argumentList = functionCallExp->get_args(); ROSE_ASSERT(argumentList != NULL); // This function has a single argument. ROSE_ASSERT(argumentList->get_expressions().size() == 1); SgExpression* functionArg = argumentList->get_expressions()[0]; ROSE_ASSERT(functionArg != NULL); SgIntVal* intVal = isSgIntVal(functionArg); // ROSE_ASSERT(intVal != NULL); if (intVal != NULL) { int value = intVal->get_value(); #if 0 printf ("value = %d \n",value); #endif switch(value) { case 0: stencilOffsetFSM = new StencilOffsetFSM(1,0,0); break; case 1: stencilOffsetFSM = new StencilOffsetFSM(0,1,0); break; case 2: stencilOffsetFSM = new StencilOffsetFSM(0,0,1); break; default: { printf ("Error: default reached in switch: value = %d (for be value of 0, 1, or 2) \n",value); ROSE_ASSERT(false); } } ROSE_ASSERT(stencilOffsetFSM != NULL); // End of test for intVal != NULL } else { #if 0 printf ("functionArg = %p = %s \n",functionArg,functionArg->class_name().c_str()); #endif } } // ROSE_ASSERT(stencilOffsetFSM != NULL); } } } if (stencilOffsetFSM != NULL) { // Put the FSM into the map. #if 0 printf ("Put the stencilOffsetFSM = %p into the StencilOffsetMap using key = %s \n",stencilOffsetFSM,name.c_str()); #endif ROSE_ASSERT(StencilOffsetMap.find(name) == StencilOffsetMap.end()); // We have a choice of syntax to add the element to the map. // StencilOffsetMap.insert(pair<string,StencilOffsetFSM*>(name,stencilOffsetFSM)); StencilOffsetMap[name] = stencilOffsetFSM; } // new StencilOffsetFSM(); #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } // Recognize member function calls on "Point" objects so that we can trigger events on those associated finite state machines. bool isTemplateClass = false; bool isTemplateFunctionInstantiation = false; SgInitializedName* initializedNameUsedToCallMemberFunction = NULL; SgFunctionCallExp* functionCallExp = detectMemberFunctionOfSpecificClassType(astNode,initializedNameUsedToCallMemberFunction,"Point",isTemplateClass,"operator*=",isTemplateFunctionInstantiation); if (functionCallExp != NULL) { // This is the DSL specific part (capturing the semantics of operator*= with specific integer values). // The name of the variable off of which the member function is called (variable has type "Point"). ROSE_ASSERT(initializedNameUsedToCallMemberFunction != NULL); string name = initializedNameUsedToCallMemberFunction->get_name(); // Need to get the dimention argument. SgExprListExp* argumentList = functionCallExp->get_args(); ROSE_ASSERT(argumentList != NULL); // This function has a single argument. ROSE_ASSERT(argumentList->get_expressions().size() == 1); SgExpression* functionArg = argumentList->get_expressions()[0]; ROSE_ASSERT(functionArg != NULL); SgIntVal* intVal = isSgIntVal(functionArg); bool usingUnaryMinus = false; if (intVal == NULL) { SgMinusOp* minusOp = isSgMinusOp(functionArg); if (minusOp != NULL) { #if 0 printf ("Using SgMinusOp on stencil constant \n"); #endif usingUnaryMinus = true; intVal = isSgIntVal(minusOp->get_operand()); } } ROSE_ASSERT(intVal != NULL); int value = intVal->get_value(); if (usingUnaryMinus == true) { value *= -1; } #if 0 printf ("value = %d \n",value); #endif // Look up the stencil offset finite state machine ROSE_ASSERT(StencilOffsetMap.find(name) != StencilOffsetMap.end()); StencilOffsetFSM* stencilOffsetFSM = StencilOffsetMap[name]; ROSE_ASSERT(stencilOffsetFSM != NULL); #if 0 printf ("We have found the StencilOffsetFSM associated with the StencilOffset named %s \n",name.c_str()); #endif #if 0 stencilOffsetFSM->display("before multiply event"); #endif if (value == -1) { // Execute the event on the finte state machine to accumulate the state. stencilOffsetFSM->operator*=(-1); } else { printf ("Error: constant value other than -1 are not supported \n"); ROSE_ASSERT(false); } #if 0 stencilOffsetFSM->display("after multiply event"); #endif } // Detection of "pair<Shift,double>(xdir,ident)" defined as an event in the stencil finite machine model. // Actually, it is the Stencil that is create using the "pair<Shift,double>(xdir,ident)" that should be the // event so we first detect the SgConstructorInitializer. There is not other code similar to this which // has to test for the template arguments, so this has not yet refactored into the dslSupport.C file. // I will do this later since this is general support that could be resused in other DSL compilers. SgConstructorInitializer* constructorInitializer = isSgConstructorInitializer(astNode); if (constructorInitializer != NULL) { // DQ (10/20/2014): This can sometimes be NULL. // ROSE_ASSERT(constructorInitializer->get_class_decl() != NULL); SgClassDeclaration* classDeclaration = constructorInitializer->get_class_decl(); // ROSE_ASSERT(classDeclaration != NULL); if (classDeclaration != NULL) { #if 0 printf ("constructorInitializer = %p class name = %s \n",constructorInitializer,classDeclaration->get_name().str()); #endif SgTemplateInstantiationDecl* templateInstantiationDecl = isSgTemplateInstantiationDecl(classDeclaration); // ROSE_ASSERT(templateInstantiationDecl != NULL); #if 0 if (templateInstantiationDecl != NULL) { printf ("constructorInitializer = %p name = %s template name = %s \n",constructorInitializer,templateInstantiationDecl->get_name().str(),templateInstantiationDecl->get_templateName().str()); } #endif // if (classDeclaration->get_name() == "pair") if (templateInstantiationDecl != NULL && templateInstantiationDecl->get_templateName() == "pair") { // Look at the template parameters. #if 0 printf ("Found template instantiation for pair \n"); #endif SgTemplateArgumentPtrList & templateArgs = templateInstantiationDecl->get_templateArguments(); if (templateArgs.size() == 2) { // Now look at the template arguments and check that they represent the pattern that we are looking for in the AST. // It is not clear now flexible we should be, at present shift/coeficent pairs must be specified exactly one way. SgType* type_0 = templateArgs[0]->get_type(); SgType* type_1 = templateArgs[1]->get_type(); if ( type_0 != NULL && type_1 != NULL) { SgClassType* classType_0 = isSgClassType(type_0); // ROSE_ASSERT(classType_0 != NULL); if (classType_0 != NULL) { SgClassDeclaration* classDeclarationType_0 = isSgClassDeclaration(classType_0->get_declaration()); ROSE_ASSERT(classDeclarationType_0 != NULL); #if 0 printf ("templateArgs[0]->get_name() = %s \n",classDeclarationType_0->get_name().str()); printf ("templateArgs[1]->get_type()->class_name() = %s \n",type_1->class_name().c_str()); #endif bool foundShiftExpression = false; bool foundStencilCoeficient = false; // We might want to be more flexiable about the type of the 2nd parameter (allow SgTypeFloat, SgTypeComplex, etc.). if (classDeclarationType_0->get_name() == "Shift" && type_1->variant() == V_SgTypeDouble) { // Found a pair<Shift,double> input for a stencil. #if 0 printf ("##### Found a pair<Shift,double>() input for a stencil input \n"); #endif // ***************************************************************************************************** // Look at the first parameter to the pair<Shift,double>() constructor. // ***************************************************************************************************** SgExpression* stencilOffset = constructorInitializer->get_args()->get_expressions()[0]; ROSE_ASSERT(stencilOffset != NULL); #if 0 printf ("stencilOffset = %p = %s \n",stencilOffset,stencilOffset->class_name().c_str()); #endif SgConstructorInitializer* stencilOffsetConstructorInitializer = isSgConstructorInitializer(stencilOffset); if (stencilOffsetConstructorInitializer != NULL) { // This is the case of a Shift being constructed implicitly from a Point (doing so more directly would be easier to make sense of in the AST). #if 0 printf ("!!!!! Looking for the stencil offset \n"); #endif ROSE_ASSERT(stencilOffsetConstructorInitializer->get_class_decl() != NULL); SgClassDeclaration* stencilOffsetClassDeclaration = stencilOffsetConstructorInitializer->get_class_decl(); ROSE_ASSERT(stencilOffsetClassDeclaration != NULL); #if 0 printf ("stencilOffsetConstructorInitializer = %p class name = %s \n",stencilOffsetConstructorInitializer,stencilOffsetClassDeclaration->get_name().str()); printf ("stencilOffsetConstructorInitializer = %p class = %p = %s \n",stencilOffsetConstructorInitializer,stencilOffsetClassDeclaration,stencilOffsetClassDeclaration->class_name().c_str()); #endif // This should not be a template instantiation (the Shift is defined to be a noo-template class declaration, not a template class declaration). SgTemplateInstantiationDecl* stencilOffsetTemplateInstantiationDecl = isSgTemplateInstantiationDecl(stencilOffsetClassDeclaration); ROSE_ASSERT(stencilOffsetTemplateInstantiationDecl == NULL); if (stencilOffsetClassDeclaration != NULL && stencilOffsetClassDeclaration->get_name() == "Shift") { // Now we know that the type associated with the first template parameter is associated with the class "Shift". // But we need so also now what the first parametr is associate with the constructor initializer, since it will // be the name of the variable used to interprete the stencil offset (and the name of the variable will be the // key into the map of finite machine models used to accumulate the state of the stencil offsets that we accumulate // to build the stencil. // Now we need the value of the input (computed using it's fine state machine). SgExpression* inputToShiftConstructor = stencilOffsetConstructorInitializer->get_args()->get_expressions()[0]; ROSE_ASSERT(inputToShiftConstructor != NULL); SgConstructorInitializer* inputToShiftConstructorInitializer = isSgConstructorInitializer(inputToShiftConstructor); if (stencilOffsetConstructorInitializer != NULL) { SgExpression* inputToPointConstructor = inputToShiftConstructorInitializer->get_args()->get_expressions()[0]; ROSE_ASSERT(inputToPointConstructor != NULL); // This should be a SgVarRefExp (if we strictly follow the stencil specification rules (which are not written down yet). SgVarRefExp* inputToPointVarRefExp = isSgVarRefExp(inputToPointConstructor); if (inputToPointVarRefExp != NULL) { #if 0 printf ("Found varRefExp in bottom of chain of constructors \n"); #endif SgVariableSymbol* variableSymbolForOffset = isSgVariableSymbol(inputToPointVarRefExp->get_symbol()); ROSE_ASSERT(variableSymbolForOffset != NULL); SgInitializedName* initializedNameForOffset = variableSymbolForOffset->get_declaration(); ROSE_ASSERT(initializedNameForOffset != NULL); SgInitializer* initializer = initializedNameForOffset->get_initptr(); ROSE_ASSERT(initializer != NULL); #if 0 printf ("Found initializedName: name = %s in bottom of chain of constructors: initializer = %p = %s \n",initializedNameForOffset->get_name().str(),initializer,initializer->class_name().c_str()); #endif // Record the name to be used as a key into the map of "StencilOffset" finite state machines. SgAssignInitializer* assignInitializer = isSgAssignInitializer(initializer); ROSE_ASSERT(assignInitializer != NULL); string name = initializedNameForOffset->get_name(); // Look up the current state in the finite state machine for the "Point". // Check that this is a previously defined stencil offset. ROSE_ASSERT(StencilOffsetMap.find(name) != StencilOffsetMap.end()); // StencilOffsetFSM* stencilOffsetFSM = StencilOffsetMap[name]; stencilOffsetFSM = StencilOffsetMap[name]; ROSE_ASSERT(stencilOffsetFSM != NULL); #if 0 printf ("We have found the StencilOffsetFSM associated with the StencilOffset named %s \n",name.c_str()); #endif #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } else { printf ("What is this expression: inputToPointConstructor = %p = %s \n",inputToPointConstructor,inputToPointConstructor->class_name().c_str()); ROSE_ASSERT(false); } } #if 0 printf ("Found Shift type \n"); #endif foundShiftExpression = true; } #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } else { // This case for the specification of a Shift in the first argument is not yet supported (need an example of this). printf ("This case of using a shift is not a part of what is supported \n"); } // ***************************************************************************************************** // Look at the second parameter to the pair<Shift,double>(first_parameter,second_parameter) constructor. // ***************************************************************************************************** SgExpression* stencilCoeficent = constructorInitializer->get_args()->get_expressions()[1]; ROSE_ASSERT(stencilCoeficent != NULL); SgVarRefExp* stencilCoeficentVarRefExp = isSgVarRefExp(stencilCoeficent); if (stencilCoeficentVarRefExp != NULL) { // Handle the case where this is a constant SgVarRefExp and the value is available in the declaration. SgVariableSymbol* variableSymbolForConstant = isSgVariableSymbol(stencilCoeficentVarRefExp->get_symbol()); ROSE_ASSERT(variableSymbolForConstant != NULL); SgInitializedName* initializedNameForConstant = variableSymbolForConstant->get_declaration(); ROSE_ASSERT(initializedNameForConstant != NULL); SgInitializer* initializer = initializedNameForConstant->get_initptr(); ROSE_ASSERT(initializer != NULL); SgAssignInitializer* assignInitializer = isSgAssignInitializer(initializer); ROSE_ASSERT(assignInitializer != NULL); SgValueExp* valueExp = isSgValueExp(assignInitializer->get_operand()); bool usingUnaryMinus = false; // ROSE_ASSERT(valueExp != NULL); if (valueExp == NULL) { SgExpression* operand = assignInitializer->get_operand(); SgMinusOp* minusOp = isSgMinusOp(operand); if (minusOp != NULL) { #if 0 printf ("Using SgMinusOp on stencil constant \n"); #endif usingUnaryMinus = true; valueExp = isSgValueExp(minusOp->get_operand()); } } SgDoubleVal* doubleVal = isSgDoubleVal(valueExp); // ROSE_ASSERT(doubleVal != NULL); double value = 0.0; if (doubleVal == NULL) { // Call JP's function to evaluate the constant expression. ROSE_ASSERT(valueExp == NULL); ROSE_ASSERT(stencilCoeficent != NULL); DSL_Support::const_numeric_expr_t const_expression = DSL_Support::evaluateConstNumericExpression(stencilCoeficent); if (const_expression.hasValue_ == true) { ROSE_ASSERT(const_expression.isIntOnly_ == false); value = const_expression.value_; printf ("const expression evaluated to value = %4.2f \n",value); } else { printf ("constnat value expression could not be evaluated to a constant \n"); ROSE_ASSERT(false); } } else { #if 1 printf ("SgDoubleVal value = %f \n",doubleVal->get_value()); #endif value = (usingUnaryMinus == false) ? doubleVal->get_value() : -(doubleVal->get_value()); } #if 1 printf ("Stencil coeficient = %f \n",value); #endif foundStencilCoeficient = true; stencilCoeficientValue = value; } else { // When we turn on constant folding in the frontend we eveluate directly to a SgDoubleVal. SgDoubleVal* doubleVal = isSgDoubleVal(stencilCoeficent); if (doubleVal != NULL) { ROSE_ASSERT(doubleVal != NULL); #if 0 printf ("SgDoubleVal value = %f \n",doubleVal->get_value()); #endif double value = doubleVal->get_value(); #if 0 printf ("Stencil coeficient = %f \n",value); #endif foundStencilCoeficient = true; stencilCoeficientValue = value; } else { printf ("Error: second parameter in pair for stencil is not a SgVarRefExp (might be explicit value not yet supported) \n"); printf (" --- stencilCoeficent = %p = %s \n",stencilCoeficent,stencilCoeficent->class_name().c_str()); ROSE_ASSERT(false); } } } #if 0 printf ("foundShiftExpression = %s \n",foundShiftExpression ? "true" : "false"); printf ("foundStencilCoeficient = %s \n",foundStencilCoeficient ? "true" : "false"); #endif if (foundShiftExpression == true && foundStencilCoeficient == true) { #if 0 printf ("Found pair<Shift,double>() constructor expression! \n"); #endif foundPairShiftDoubleConstructor = true; } // End of test for classType_0 != NULL } } } } else { #if 0 printf ("This is not a SgConstructorInitializer for the pair templated class \n"); #endif } // End of test for classDeclaration != NULL } } #if 0 printf ("foundPairShiftDoubleConstructor = %s \n",foundPairShiftDoubleConstructor ? "true" : "false"); #endif if (foundPairShiftDoubleConstructor == true) { // This is the recognition of an event for one of the finite state machines we implement to evaluate the stencil at compile time. #if 0 printf ("In evaluateInheritedAttribute(): found pair<Shift,double>() constructor expression! \n"); printf (" --- stencilOffsetFSM = %p \n",stencilOffsetFSM); printf (" --- stencilCoeficientValue = %f \n",stencilCoeficientValue); #endif ROSE_ASSERT(stencilOffsetFSM != NULL); inheritedAttribute.stencilOffsetFSM = stencilOffsetFSM; inheritedAttribute.stencilCoeficientValue = stencilCoeficientValue; #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } // Construct the return attribute from the modified input attribute. return StencilEvaluation_InheritedAttribute(inheritedAttribute); }
void FortranProgramDeclarationsAndDefinitions::analyseParallelLoopArguments ( FortranParallelLoop * parallelLoop, SgExprListExp * actualArguments, int numberOfOpArgs) { using boost::iequals; using boost::lexical_cast; using std::find; using std::string; using std::vector; using std::map; Debug::getInstance ()->debugMessage ( "Analysing OP_PAR_LOOP actual arguments", Debug::FUNCTION_LEVEL, __FILE__, __LINE__); unsigned int OP_DAT_ArgumentGroup = 1; /* * ====================================================== * Loops over the arguments to populate the parallel loop object * Each object in the actualArguments array is a function call * We analyse the arguments of each call * \warning: the args start from position 2 (the first two args are * the user kernel reference and the iteration set * ====================================================== */ for ( int i = 2; i < numberOfOpArgs + 2; i++ ) { /* * ====================================================== * Distinguish between op_dat and global variable by * checking the function name * ====================================================== */ SgFunctionCallExp * functionExpression = isSgFunctionCallExp ( actualArguments->get_expressions ()[i]); ROSE_ASSERT (functionExpression != NULL); string functionName = functionExpression ->getAssociatedFunctionSymbol ()-> get_name ().getString (); SgExprListExp * opArgArguments = functionExpression ->get_args (); ROSE_ASSERT (opArgArguments ); /* * ====================================================== * Assume that this is not an op_mat, possibly amend later * ====================================================== */ parallelLoop->setIsOpMatArg (OP_DAT_ArgumentGroup, false); if ( functionName == "op_arg_dat" ) { /* * ====================================================== * Obtain the op_dat reference and its name * ====================================================== */ SgVarRefExp * opDatReference = NULL; opDatReference = getOpDatReferenceFromOpArg (opArgArguments); ROSE_ASSERT (opDatReference != NULL); string const opDatName = opDatReference->get_symbol ()->get_name ().getString (); /* * ====================================================== * Obtain the map reference and name, and select access * type (direct or indirect) * ====================================================== */ SgVarRefExp * opMapReference; opMapReference = getOpMapReferenceFromOpArg (opArgArguments); ROSE_ASSERT (opMapReference != NULL); string const mappingValue = opMapReference->get_symbol ()->get_name ().getString (); if (iequals (mappingValue, OP2::OP_ID)) { /* * ====================================================== * OP_ID signals identity mapping and therefore direct * access to the data * ====================================================== */ Debug::getInstance ()->debugMessage ("...DIRECT mapping descriptor", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); parallelLoop->setOpMapValue (OP_DAT_ArgumentGroup, DIRECT); } else { Debug::getInstance ()->debugMessage ("...INDIRECT mapping descriptor", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); parallelLoop->setOpMapValue (OP_DAT_ArgumentGroup, INDIRECT); } setOpDatProperties (parallelLoop, opDatName, OP_DAT_ArgumentGroup); setParallelLoopAccessDescriptor (parallelLoop, opArgArguments, OP_DAT_ArgumentGroup, DAT_ACC_POSITION); } else if ( functionName == "op_arg_gbl" ) { Debug::getInstance ()->debugMessage ("...GLOBAL mapping descriptor", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); /* * ====================================================== * Get the OP_GBL variable reference and name * ====================================================== */ SgVarRefExp * opDatReference; if (isSgDotExp (opArgArguments->get_expressions ()[DAT_POSITION]) != NULL) { opDatReference = isSgVarRefExp ( isSgDotExp ( opArgArguments->get_expressions ()[DAT_POSITION])->get_rhs_operand ()); } else { opDatReference = isSgVarRefExp ( opArgArguments->get_expressions ()[DAT_POSITION]); } string const globalName = opDatReference->get_symbol ()->get_name ().getString (); /* * ====================================================== * Get the OP_GBL dimension: check the number of args * to the op_arg_gbl function (3 = array, 2 = scalar) * ====================================================== */ if ( opArgArguments->get_expressions ().size () == GBL_SCALAR_ARG_NUM ) { Debug::getInstance ()->debugMessage ("'" + globalName + "' is a scalar", Debug::FUNCTION_LEVEL, __FILE__, __LINE__); /* * ====================================================== * Since this is a scalar, set the dimension to 1 * ====================================================== */ parallelLoop->setOpDatDimension (OP_DAT_ArgumentGroup, 1); } else { SgIntVal * intValExp = isSgIntVal (opArgArguments->get_expressions ()[GBL_DIM_POSITION]); ROSE_ASSERT (intValExp != NULL); int globalDimension = intValExp->get_value (); parallelLoop->setOpDatDimension (OP_DAT_ArgumentGroup, globalDimension); Debug::getInstance ()->debugMessage ("'" + globalName + "' is NOT a scalar, but has dimension " + lexical_cast<string> (globalDimension), Debug::FUNCTION_LEVEL, __FILE__, __LINE__); } /* * ====================================================== * Set the other fields * ====================================================== */ parallelLoop->setOpDatType (OP_DAT_ArgumentGroup, (opArgArguments->get_expressions ()[DAT_POSITION])->get_type ()); parallelLoop->setUniqueOpDat (globalName); parallelLoop->setOpDatVariableName (OP_DAT_ArgumentGroup, globalName); parallelLoop->setDuplicateOpDat (OP_DAT_ArgumentGroup, false); parallelLoop->setOpMapValue (OP_DAT_ArgumentGroup, GLOBAL); if ( opArgArguments->get_expressions ().size () == GBL_SCALAR_ARG_NUM ) setParallelLoopAccessDescriptor (parallelLoop, opArgArguments, OP_DAT_ArgumentGroup, GBL_SCALAR_ACC_POSITION); else setParallelLoopAccessDescriptor (parallelLoop, opArgArguments, OP_DAT_ArgumentGroup, GBL_ARRAY_ACC_POSITION); } else if ( functionName == "op_arg_dat_generic" ) { Debug::getInstance ()->debugMessage ("Found generic op_dat", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); /* * ====================================================== * Obtain the op_dat reference and its name * ====================================================== */ SgVarRefExp * opDatReference = NULL; opDatReference = getOpDatReferenceFromOpArg (opArgArguments); ROSE_ASSERT (opDatReference != NULL); string const opDatName = opDatReference->get_symbol ()->get_name ().getString (); /* * ====================================================== * Obtain the map reference and name, and select access * type (direct or indirect) * ====================================================== */ SgVarRefExp * opMapReference; opMapReference = getOpMapReferenceFromOpArg (opArgArguments); ROSE_ASSERT (opMapReference != NULL); string const mappingValue = opMapReference->get_symbol ()->get_name ().getString (); if (iequals (mappingValue, OP2::OP_ID)) { /* * ====================================================== * OP_ID signals identity mapping and therefore direct * access to the data * ====================================================== */ Debug::getInstance ()->debugMessage ("...DIRECT mapping descriptor", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); parallelLoop->setOpMapValue (OP_DAT_ArgumentGroup, DIRECT); } else { Debug::getInstance ()->debugMessage ("...INDIRECT mapping descriptor", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); parallelLoop->setOpMapValue (OP_DAT_ArgumentGroup, INDIRECT); } /* * ====================================================== * In case of generic loop, I have to read also the * dimension and type to be able to set the op_dat info * in the parallel loop class * ====================================================== */ SgIntVal * opDatDimension = isSgIntVal ( opArgArguments->get_expressions ()[GENERIC_DIM_POSITION]); SgStringVal * opDataBaseTypeString = isSgStringVal ( opArgArguments->get_expressions ()[GENERIC_TYPE_POSITION]); ROSE_ASSERT (opDataBaseTypeString != NULL); SgType * opDataBaseType = getTypeFromString (opDataBaseTypeString->get_value (), opDatName); ROSE_ASSERT (opDataBaseType != NULL); setOpDatPropertiesGeneric (parallelLoop, opDatName, opDatDimension->get_value (), opDataBaseType, OP_DAT_ArgumentGroup); Debug::getInstance ()->debugMessage ("Getting access", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); setParallelLoopAccessDescriptor (parallelLoop, opArgArguments, OP_DAT_ArgumentGroup, GENERIC_ACC_POSITION); } else if ( functionName == "op_arg_mat" ) { Debug::getInstance ()->debugMessage ("Unsupported argument type", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); } else { Debug::getInstance ()->debugMessage ("Argument type not recognised", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); } /* * ====================================================== * This identifies the argument position in the data * structures, while the iteration variable 'i' identifies * the corresponding op_arg position in the op_par_loop * arguments (i == OP_DAT_ArgumentGroup + 2) * ====================================================== */ OP_DAT_ArgumentGroup++; } parallelLoop->setNumberOfOpDatArgumentGroups (numberOfOpArgs); parallelLoop->setNumberOfOpMatArgumentGroups (0); if ( parallelLoop->isDirectLoop () ) Debug::getInstance ()->debugMessage ("This is a DIRECT parallel loop", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); else Debug::getInstance ()->debugMessage ("This is an INDIRECT parallel loop", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); }
void UDrawGraph::visit (SgNode * node) { using boost::lexical_cast; using std::string; file << newVertex (counter) << beginAttributes; switch (node->variantT ()) { case V_SgInitializedName: { SgInitializedName * castedNode = isSgInitializedName (node); file << setName (castedNode->get_name ().getString ()); break; } case V_SgVarRefExp: { SgVarRefExp * castedNode = isSgVarRefExp (node); file << setName (castedNode->get_symbol ()->get_name ().getString ()); file << setColor (RED); break; } case V_SgVariableDeclaration: { file << setName (node->class_name ()); file << setShape (RHOMBUS); break; } case V_SgIntVal: { SgIntVal * castedNode = isSgIntVal (node); file << setName (lexical_cast <string> (castedNode->get_value ())); file << setColor (GREEN); break; } case V_SgFloatVal: { SgFloatVal * castedNode = isSgFloatVal (node); file << setName (lexical_cast <string> (castedNode->get_value ())); file << setColor (GREEN); break; } case V_SgAddOp: { file << setName ("+"); file << setColor (YELLOW); break; } case V_SgMinusOp: case V_SgSubtractOp: { file << setName ("-"); file << setColor (YELLOW); break; } case V_SgMultiplyOp: { file << setName ("*"); file << setColor (YELLOW); break; } case V_SgDivideOp: { file << setName ("/"); file << setColor (YELLOW); break; } case V_SgAssignOp: { file << setName ("="); file << setColor (YELLOW); break; } case V_SgLessThanOp: { file << setName ("<"); file << setColor (YELLOW); break; } case V_SgLessOrEqualOp: { file << setName ("<="); file << setColor (YELLOW); break; } case V_SgGreaterThanOp: { file << setName (">"); file << setColor (YELLOW); break; } case V_SgGreaterOrEqualOp: { file << setName (">="); file << setColor (YELLOW); break; } case V_SgAddressOfOp: { file << setName ("&"); file << setColor (YELLOW); break; } default: { file << setName (node->class_name ()); break; } } file << endAttibutes << beginAttributes; if (counter != rootID) { SgNode * parent = node->get_parent (); unsigned int const parentID = nodes[parent]; file << newEdge << beginAttributes << setDirectionalLessEdge << endAttibutes << edgeLink (parentID) << endEdge; } file << endVertex; nodes[node] = counter; counter++; }
POETCode* POETAstInterface::Ast2POET(const Ast& n) { static SgTemplateInstantiationFunctionDecl* tmp=0; SgNode* input = (SgNode*) n; if (input == 0) return EMPTY; POETCode* res = POETAstInterface::find_Ast2POET(input); if (res != 0) return res; { SgProject* sageProject=isSgProject(input); if (sageProject != 0) { int filenum = sageProject->numberOfFiles(); for (int i = 0; i < filenum; ++i) { SgSourceFile* sageFile = isSgSourceFile(sageProject->get_fileList()[i]); SgGlobal *root = sageFile->get_globalScope(); SgDeclarationStatementPtrList declList = root->get_declarations (); POETCode* curfile = ROSE_2_POET_list(declList, 0, tmp); curfile = new POETCode_ext(sageFile, curfile); POETAstInterface::set_Ast2POET(sageFile, curfile); res=LIST(curfile, res); } POETAstInterface::set_Ast2POET(sageProject,res); return res; } } { SgBasicBlock* block = isSgBasicBlock(input); if (block != 0) { res=ROSE_2_POET_list(block->get_statements(), res, tmp); POETAstInterface::set_Ast2POET(block, res); return res; } } { SgExprListExp* block = isSgExprListExp(input); if (block != 0) { res=ROSE_2_POET_list(block->get_expressions(), 0, tmp); POETAstInterface::set_Ast2POET(block, res); return res; } } { SgForStatement *f = isSgForStatement(input); if (f != 0) { POETCode* init = ROSE_2_POET_list(f->get_for_init_stmt()->get_init_stmt(),0, tmp); POETCode* ctrl = new POETCode_ext(f, TUPLE3(init,Ast2POET(f->get_test_expr()), Ast2POET(f->get_increment()))); res = CODE_ACC("Nest", PAIR(ctrl,Ast2POET(f->get_loop_body()))); POETAstInterface::set_Ast2POET(input, res); return res; } } { SgVarRefExp * v = isSgVarRefExp(input); if (v != 0) { res = STRING(v->get_symbol()->get_name().str()); POETAstInterface::set_Ast2POET(input, res); return res; } } { SgMemberFunctionRefExp * v = isSgMemberFunctionRefExp(input); if (v != 0) { res = STRING(v->get_symbol()->get_name().str()); POETAstInterface::set_Ast2POET(input, res); return res; } } { SgIntVal * v = isSgIntVal(input); if (v != 0) { res = ICONST(v->get_value()); POETAstInterface::set_Ast2POET(input, res); return res; } } { SgInitializedName* var = isSgInitializedName(input); if (var != 0) { POETCode* name = STRING(var->get_name().str()); POETCode* init = Ast2POET(var->get_initializer()); res = new POETCode_ext(var, PAIR(name,init)); POETAstInterface::set_Ast2POET(input, res); return res; } } /* { std::string fname; AstInterface::AstList params; AstNodeType returnType; AstNodePtr body; if (AstInterface :: IsFunctionDefinition( input, &fname, ¶ms, (AstInterface::AstList*)0, &body, (AstInterface::AstTypeList*)0, &returnType)) { if (body != AST_NULL) std::cerr << "body not empty:" << fname << "\n"; POETCode* c = TUPLE4(STRING(fname), ROSE_2_POET_list(0,params,0), STRING(AstInterface::GetTypeName(returnType)), Ast2POET(body.get_ptr())); res = new POETCode_ext(input, c); POETAstInterface::set_Ast2POET(input,res); return res; } } */ AstInterface::AstList c = AstInterface::GetChildrenList(input); switch (input->variantT()) { case V_SgCastExp: case V_SgAssignInitializer: res = Ast2POET(c[0]); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgDotExp: { POETCode* v1 = Ast2POET(c[1]); if (dynamic_cast<POETString*>(v1)->get_content() == "operator()") return Ast2POET(c[0]); res = CODE_ACC("Bop",TUPLE3(STRING("."), Ast2POET(c[0]), v1)); return res; } case V_SgLessThanOp: res = CODE_ACC("Bop",TUPLE3(STRING("<"),Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgSubtractOp: res = CODE_ACC("Bop",TUPLE3(STRING("-"),Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgAddOp: res = CODE_ACC("Bop",TUPLE3(STRING("+"),Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgMultiplyOp: res = CODE_ACC("Bop",TUPLE3(STRING("*"),Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgDivideOp: res = CODE_ACC("Bop",TUPLE3(STRING("/"),Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgAssignOp: res = CODE_ACC("Assign",PAIR(Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgFunctionCallExp: res = CODE_ACC("FunctionCall",PAIR(Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; } POETCode * c2 = 0; if (tmp == 0) tmp=isSgTemplateInstantiationFunctionDecl(input); switch (c.size()) { case 0: break; case 1: c2 = Ast2POET(c[0]); break; case 2: c2 = PAIR(Ast2POET(c[0]),Ast2POET(c[1])); break; case 3: c2 = TUPLE3(Ast2POET(c[0]),Ast2POET(c[1]),Ast2POET(c[2])); break; case 4: c2 = TUPLE4(Ast2POET(c[0]),Ast2POET(c[1]),Ast2POET(c[2]),Ast2POET(c[3])); break; default: //std::cerr << "too many children: " << c.size() << ":" << input->unparseToString() << "\n"; c2 = EMPTY; } if (tmp == input) tmp = 0; res = new POETCode_ext(input, c2); POETAstInterface::set_Ast2POET(input,res); return res; }
//Generates SSA form numbers for the variables contained in *ex and attaches them as AstValueAttributes to the related SgNodes //Assumption: *ex is located in in the inTrueBranch branch of the if node labeled *condLabel (These two arguments are required to generate the SSA form numbers) void SSAGenerator::processSgExpression(SgExpression* ex, Label* condLabel, bool inTrueBranch) { SgIntVal* intVal = dynamic_cast<SgIntVal*>(ex); SgMinusOp* minusOp = dynamic_cast<SgMinusOp*>(ex); SgVarRefExp* varRef = dynamic_cast<SgVarRefExp*>(ex); SgBinaryOp* binOp = dynamic_cast<SgBinaryOp*>(ex); SgFunctionCallExp* funcCall = dynamic_cast<SgFunctionCallExp*>(ex); if(intVal) //Int value { //Nothing needs to be done; Case is listed here to have a collection of all expected cases } else if(minusOp) { processSgExpression(minusOp->get_operand(), condLabel, inTrueBranch); } else if(varRef) //Reference to variable that is NOT on the left hand side of an assignment { //Assign number to variable string varName = varRef->get_symbol()->get_name().getString(); int varNumber = currentNumber(varName, condLabel, inTrueBranch); logger[Sawyer::Message::DEBUG] << "Current number for variable " << varName << ": " << varNumber << endl; AstValueAttribute<int>* varNumberAtt = new AstValueAttribute<int>(varNumber); varRef->setAttribute("SSA_NUMBER", varNumberAtt); } else if(binOp) //Binary operation { SgExpression* lhs = binOp->get_lhs_operand(); SgExpression* rhs = binOp->get_rhs_operand(); //Process right hand side first processSgExpression(rhs, condLabel, inTrueBranch); //Process left hand side second SgAssignOp* assignOp = dynamic_cast<SgAssignOp*>(binOp); if(assignOp) //Assignment to a variable { //Assign new number to that variable SgVarRefExp* lhsVarRef = dynamic_cast<SgVarRefExp*>(lhs); assert(lhsVarRef != NULL); processAssignmentTo(lhsVarRef, condLabel, inTrueBranch); } else //Arithmetic operation or boolean operation (or something unexpected) { processSgExpression(lhs, condLabel, inTrueBranch); } } else if(funcCall) //Call to a function //RERS specific; Only two function call types are supported: //(1) scanf("%d",&...); //(2) __VERIFIER_error(RERSVerifierErrorNumber); The artificial bool variable RERSErrorOccured has to be updated { string funcName = funcCall->getAssociatedFunctionSymbol()->get_name().getString(); logger[Sawyer::Message::DEBUG] << "Call to function: " << funcName << endl; if(funcName == "scanf") //(1) { SgExprListExp* funcArgs = funcCall->get_args(); SgExpressionPtrList funcArgsPtrs = funcArgs->get_expressions(); SgExpressionPtrList::iterator i = funcArgsPtrs.begin(); while(i != funcArgsPtrs.end()) { SgAddressOfOp* addrOp = dynamic_cast<SgAddressOfOp*>(*i); if(addrOp) { SgVarRefExp* varRef = dynamic_cast<SgVarRefExp*>(addrOp->get_operand()); if(varRef) { processAssignmentTo(varRef, condLabel, inTrueBranch); } else logger[Sawyer::Message::DEBUG] << "FOUND NO REFERENCE TO VARIABLE" << endl; } i++; } } else if(funcName == "__VERIFIER_error" && prepareReachabilityAnalysisZ3) { SgExprListExp* funcArgs = funcCall->get_args(); SgExpressionPtrList funcArgsPtrs = funcArgs->get_expressions(); assert(funcArgsPtrs.size() == 1); SgExpression* argument = *funcArgsPtrs.begin(); SgIntVal* intArgument = dynamic_cast<SgIntVal*>(argument); assert(intArgument != NULL); if(intArgument->get_value() == RERSVerifierErrorNumber) //(2) { int RERSErrorOccuredNumber = nextNumber("RERSErrorOccured", condLabel, inTrueBranch); logger[Sawyer::Message::DEBUG] << "Next number for variable RERSErrorOccured: " << RERSErrorOccuredNumber << endl; AstValueAttribute<int>* numberAtt = new AstValueAttribute<int>(RERSErrorOccuredNumber); funcCall->setAttribute("SSA_NUMBER", numberAtt); } } else logger[Sawyer::Message::DEBUG] << "Ignoring function call" << endl; } else //Unexpected { logger[Sawyer::Message::ERROR] << "ERROR: SgExpression could not be handled: " << ex->class_name() << endl; assert(false); } }
void DataFlow< DLX::KLT_Annotation<DLX::OpenACC::language_t>, Language::OpenCL, Runtime::OpenACC >::markSplittedData( const context_t & context ) const { std::map< ::KLT::Data<Annotation> *, std::vector<splitted_access_desc_t> > accesses_map; std::map< ::KLT::Data<Annotation> *, std::vector<splitted_access_desc_t> >::iterator it_accesses; std::map< ::KLT::LoopTrees<DLX::KLT_Annotation<DLX::OpenACC::language_t> >::node_t *, accesses_list_t>::const_iterator it; for (it = context.accesses_map.begin(); it != context.accesses_map.end(); it++) { ::KLT::LoopTrees<DLX::KLT_Annotation<DLX::OpenACC::language_t> >::node_t * node = it->first; ::KLT::LoopTrees<DLX::KLT_Annotation<DLX::OpenACC::language_t> >::node_t * parent = node->parent; ::KLT::LoopTrees<DLX::KLT_Annotation<DLX::OpenACC::language_t> >::loop_t * splitted_loop = NULL; ::DLX::Directives::clause_t< ::DLX::OpenACC::language_t, ::DLX::OpenACC::language_t::e_acc_clause_split> * split_clause = NULL; // search for a splitted loop in the parents while (parent != NULL) { ::KLT::LoopTrees<DLX::KLT_Annotation<DLX::OpenACC::language_t> >::loop_t * loop = dynamic_cast< ::KLT::LoopTrees<DLX::KLT_Annotation<DLX::OpenACC::language_t> >::loop_t *>(parent); if (loop != NULL && loop->isSplitted()) { assert(splitted_loop == NULL); // cannot have nested splitted loops splitted_loop = loop; std::vector<DLX::KLT_Annotation<DLX::OpenACC::language_t> >::const_iterator it; for (it = loop->annotations.begin(); it != loop->annotations.end(); it++) { if (it->clause->kind == DLX::OpenACC::language_t::e_acc_clause_split) { assert(split_clause == NULL); // only one split clause per loop split_clause = (::DLX::Directives::clause_t< ::DLX::OpenACC::language_t, ::DLX::OpenACC::language_t::e_acc_clause_split> *)it->clause; } } assert(split_clause != NULL); } parent = parent->parent; } assert(splitted_loop == NULL || split_clause != NULL); // (loop != NULL) => (split_clause != NULL) std::vector<data_access_t>::const_iterator it_data_access; for (it_data_access = it->second.reads.begin(); it_data_access != it->second.reads.end(); it_data_access++) { it_accesses = accesses_map.find(it_data_access->data); if (it_accesses == accesses_map.end()) it_accesses = accesses_map.insert(std::pair< ::KLT::Data<Annotation> *, std::vector<splitted_access_desc_t> >(it_data_access->data, std::vector<splitted_access_desc_t>())).first; assert(it_accesses != accesses_map.end()); it_accesses->second.push_back(splitted_access_desc_t(splitted_access_desc_t::read, splitted_loop, split_clause, &(it_data_access->subscripts))); } for (it_data_access = it->second.writes.begin(); it_data_access != it->second.writes.end(); it_data_access++) { it_accesses = accesses_map.find(it_data_access->data); if (it_accesses == accesses_map.end()) it_accesses = accesses_map.insert(std::pair< ::KLT::Data<Annotation> *, std::vector<splitted_access_desc_t> >(it_data_access->data, std::vector<splitted_access_desc_t>())).first; assert(it_accesses != accesses_map.end()); it_accesses->second.push_back(splitted_access_desc_t(splitted_access_desc_t::write, splitted_loop, split_clause, &(it_data_access->subscripts))); } } for (it_accesses = accesses_map.begin(); it_accesses != accesses_map.end(); it_accesses++) { ::KLT::Data<Annotation> * data = it_accesses->first; assert(it_accesses->second.size() > 0); if (it_accesses->second.size() > 1) { std::vector<splitted_access_desc_t>::iterator it_splitted_access = it_accesses->second.begin(); ::KLT::LoopTrees<DLX::KLT_Annotation<DLX::OpenACC::language_t> >::loop_t * splitted_loop = it_splitted_access->splitted_loop; for (; it_splitted_access != it_accesses->second.end(); it_splitted_access++) assert(splitted_loop == it_splitted_access->splitted_loop); } if (it_accesses->second[0].splitted_loop == NULL) continue; assert(it_accesses->second[0].split_clause != NULL); assert(it_accesses->second[0].subscripts != NULL); assert(it_accesses->second[0].subscripts->size() > 0); SgVarRefExp * var_ref = isSgVarRefExp(it_accesses->second[0].subscripts->at(0)); assert(var_ref != NULL); if (var_ref->get_symbol() != it_accesses->second[0].splitted_loop->iterator) { std::vector<splitted_access_desc_t>::iterator it_splitted_access; for (it_splitted_access = it_accesses->second.begin(); it_splitted_access != it_accesses->second.end(); it_splitted_access++) assert(it_splitted_access->rw == splitted_access_desc_t::read); continue; } ::KLT::Data<Annotation>::data_distribution_t * data_distribution = new ::KLT::Data<Annotation>::data_distribution_t(); data_distribution->distributed_dimension = 0; switch (it_accesses->second[0].split_clause->parameters.kind) { case ::DLX::Directives::generic_clause_t< ::DLX::OpenACC::language_t>::parameters_t< ::DLX::OpenACC::language_t::e_acc_clause_split>::e_acc_split_contiguous: { data_distribution->kind = ::KLT::Data<Annotation>::data_distribution_t::e_split_contiguous; std::vector<SgExpression *>::const_iterator it_portion; for (it_portion = it_accesses->second[0].split_clause->parameters.portions.begin(); it_portion != it_accesses->second[0].split_clause->parameters.portions.end(); it_portion++) { SgIntVal * portion = isSgIntVal(*it_portion); if (portion == NULL) { std::cerr << "(*it_portion)->class_name() = " << (*it_portion)->class_name() << std::endl; assert(false); } data_distribution->portions.push_back(portion->get_value()); } break; } case ::DLX::Directives::generic_clause_t< ::DLX::OpenACC::language_t>::parameters_t< ::DLX::OpenACC::language_t::e_acc_clause_split>::e_acc_split_chunk: { break; } default: assert(false); } data->setDistribution(data_distribution); } }
ExprSynAttr *examineExpr(SgExpression *expr, ostream &out) { stringstream ss1; stringstream ss2; stringstream ss3; SgExpression *e1; SgExpression *e2; SgBinaryOp *binop; SgUnaryOp *unaryop; SgType *type; ExprSynAttr *ret; ExprSynAttr *attr1, *attr2; string tmp_name; string tmp_type; string tmp2_name; string tmp2_type; if (expr == NULL) return NULL; ret = new ExprSynAttr(); attr1 = NULL; attr2 = NULL; switch(expr->variantT()) { /* Begin UnaryOp */ case V_SgMinusOp: out << "(-"; unaryop = isSgUnaryOp(expr); e1 = unaryop->get_operand(); attr1 = examineExpr(e1, out); out << ")"; ret->type = attr1->type; ret->sgtype = attr1->sgtype; ret->new_tmp_name(); ret->add_new_tmp_decl(ret->type, ret->result_var); ret->union_tmp_decls(attr1); ret->code << attr1->code.str(); ret->code << ret->result_var << "= -" << attr1->result_var; ret->code << ";" << endl; break; case V_SgUnaryAddOp: out << "(+"; unaryop = isSgUnaryOp(expr); e1 = unaryop->get_operand(); attr1 = examineExpr(e1, out); out << ")"; ret->type = attr1->type; ret->sgtype = attr1->sgtype; ret->new_tmp_name(); ret->add_new_tmp_decl(ret->type, ret->result_var); ret->union_tmp_decls(attr1); ret->code << attr1->code.str(); ret->code << ret->result_var << "= +" << attr1->result_var; ret->code << ";" << endl; break; case V_SgNotOp: out << "(!"; unaryop = isSgUnaryOp(expr); e1 = unaryop->get_operand(); attr1 = examineExpr(e1, out); out << ")"; ret->type = "int"; ret->sgtype = attr1->sgtype; ret->new_tmp_name(); ret->add_new_tmp_decl(ret->type, ret->result_var); ret->union_tmp_decls(attr1); ret->code << attr1->code.str(); ret->code << ret->result_var << "= (int)!" << attr1->result_var; ret->code << ";" << endl; break; case V_SgPointerDerefExp: out << "(*"; unaryop = isSgUnaryOp(expr); e1 = unaryop->get_operand(); attr1 = examineExpr(e1, out); out << ")"; ret->basetype(attr1); ret->new_tmp_name(); ret->add_new_tmp_decl(ret->type, ret->result_var); ret->union_tmp_decls(attr1); ret->code << attr1->code.str(); ret->code << ret->result_var << "= *" << attr1->result_var; ret->code << ";" << endl; break; case V_SgAddressOfOp: out << "(&"; unaryop = isSgUnaryOp(expr); e1 = unaryop->get_operand(); attr1 = examineExpr(e1, out); out << ")"; ret->type = attr1->type + "*"; /* FIXME ret->sgtype */ ret->new_tmp_name(); ret->add_new_tmp_decl(ret->type, ret->result_var); ret->union_tmp_decls(attr1); ret->code << attr1->code.str(); ret->code << ret->result_var << "= &" << attr1->result_var; ret->code << ";" << endl; break; case V_SgMinusMinusOp: unaryop = isSgUnaryOp(expr); if (unaryop->get_mode()) { out << "("; e1 = unaryop->get_operand(); attr1 = examineExpr(e1, out); out << "--)"; ret->type = attr1->type; ret->sgtype = attr1->sgtype; ret->new_tmp_name(); ret->add_new_tmp_decl(ret->type, ret->result_var); ret->union_tmp_decls(attr1); ret->code << attr1->code.str(); ret->code << ret->result_var << "=" << attr1->result_var << ";" << endl; ret->code << attr1->result_var << "=" << attr1->result_var << "-1;" << endl; } else { out << "(--"; e1 = unaryop->get_operand(); attr1 = examineExpr(e1, out); out << ")"; ret->type = attr1->type; ret->sgtype = attr1->sgtype; ret->result_var = attr1->result_var; ret->union_tmp_decls(attr1); ret->code << attr1->code.str(); ret->code << ret->result_var << "=" << attr1->result_var << "-1;" << endl; } break; case V_SgPlusPlusOp: unaryop = isSgUnaryOp(expr); if (unaryop->get_mode()) { out << "("; e1 = unaryop->get_operand(); attr1 = examineExpr(e1, out); out << "++)"; ret->type = attr1->type; ret->sgtype = attr1->sgtype; ret->new_tmp_name(); ret->add_new_tmp_decl(ret->type, ret->result_var); ret->union_tmp_decls(attr1); ret->code << attr1->code.str(); ret->code << ret->result_var << "=" << attr1->result_var << ";" << endl; ret->code << attr1->result_var << "=" << attr1->result_var << "+1;" << endl; } else { out << "(++"; e1 = unaryop->get_operand(); attr1 = examineExpr(e1, out); out << ")"; ret->type = attr1->type; ret->sgtype = attr1->sgtype; ret->result_var = attr1->result_var; ret->union_tmp_decls(attr1); ret->code << attr1->code.str(); ret->code << ret->result_var << "=" << attr1->result_var << "+1;" << endl; } break; case V_SgBitComplementOp: out << "(~"; unaryop = isSgUnaryOp(expr); e1 = unaryop->get_operand(); attr1 = examineExpr(e1, out); out << ")"; ret->type = attr1->type; ret->sgtype = attr1->sgtype; ret->new_tmp_name(); ret->add_new_tmp_decl(ret->type, ret->result_var); ret->union_tmp_decls(attr1); ret->code << attr1->code.str(); ret->code << ret->result_var << "= ~" << attr1->result_var; ret->code << ";" << endl; break; case V_SgCastExp: { out << "("; SgCastExp *castexp = isSgCastExp(expr); e1 = castexp->get_operand(); type = castexp->get_type(); examineType(type, out); out << ")"; attr1 = examineExpr(e1, out); stringstream casts; examineType(type, casts); ret->type = casts.str(); ret->sgtype = type; ret->new_tmp_name(tmp_name); ret->union_tmp_decls(attr1, NULL); ret->add_new_tmp_decl(ret->type, tmp_name); ret->result_var = tmp_name; ret->code << attr1->code.str() << tmp_name; ret->code << "=(" << ret->type << ")" << attr1->result_var; ret->code << ";" << endl; break; } /* End UnaryOp */ /* Begin BinaryOp */ case V_SgEqualityOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << "=="; attr2 = examineExpr(e2, out); out << ")"; ret->type = "int"; ret->sgtype = attr1->sgtype; binop_noassign(ret, attr1, attr2, "=="); break; case V_SgLessThanOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << "<"; attr2 = examineExpr(e2, out); out << ")"; ret->type = "int"; ret->sgtype = attr1->sgtype; binop_noassign(ret, attr1, attr2, "<"); break; case V_SgGreaterThanOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << ">"; attr2 = examineExpr(e2, out); out << ")"; ret->type = "int"; ret->sgtype = attr1->sgtype; binop_noassign(ret, attr1, attr2, ">"); break; case V_SgNotEqualOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << "!="; attr2 = examineExpr(e2, out); out << ")"; ret->type = "int"; ret->sgtype = attr1->sgtype; binop_noassign(ret, attr1, attr2, "!="); break; case V_SgLessOrEqualOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << "<="; attr2 = examineExpr(e2, out); out << ")"; ret->type = "int"; ret->sgtype = attr1->sgtype; binop_noassign(ret, attr1, attr2, "<="); break; case V_SgGreaterOrEqualOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << ">="; attr2 = examineExpr(e2, out); out << ")"; ret->type = "int"; ret->sgtype = attr1->sgtype; binop_noassign(ret, attr1, attr2, ">="); break; case V_SgAddOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << "+"; attr2 = examineExpr(e2, out); out << ")"; ret->cast_type(attr1, attr2); binop_noassign(ret, attr1, attr2, "+"); break; case V_SgSubtractOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << "-"; attr2 = examineExpr(e2, out); out << ")"; ret->cast_type(attr1, attr2); binop_noassign(ret, attr1, attr2, "-"); break; case V_SgMultiplyOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << "*"; attr2 = examineExpr(e2, out); out << ")"; ret->cast_type(attr1, attr2); binop_noassign(ret, attr1, attr2, "*"); break; case V_SgDivideOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << "/"; attr2 = examineExpr(e2, out); out << ")"; ret->cast_type(attr1, attr2); binop_noassign(ret, attr1, attr2, "/"); break; case V_SgIntegerDivideOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << "/"; attr2 = examineExpr(e2, out); out << ")"; ret->cast_type(attr1, attr2); binop_noassign(ret, attr1, attr2, "/"); break; case V_SgModOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << "%"; attr2 = examineExpr(e2, out); out << ")"; ret->cast_type(attr1, attr2); binop_noassign(ret, attr1, attr2, "%"); break; case V_SgAndOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << "&&"; attr2 = examineExpr(e2, out); out << ")"; ret->cast_type(attr1, attr2); ret->type = "int"; binop_noassign(ret, attr1, attr2, "&&"); break; case V_SgOrOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << "||"; attr2 = examineExpr(e2, out); out << ")"; ret->cast_type(attr1, attr2); ret->type = "int"; binop_noassign(ret, attr1, attr2, "||"); break; case V_SgBitXorOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << "^"; attr2 = examineExpr(e2, out); out << ")"; ret->cast_type(attr1, attr2); binop_noassign(ret, attr1, attr2, "^"); break; case V_SgBitAndOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << "&"; attr2 = examineExpr(e2, out); out << ")"; ret->cast_type(attr1, attr2); binop_noassign(ret, attr1, attr2, "&"); break; case V_SgBitOrOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << "|"; attr2 = examineExpr(e2, out); out << ")"; ret->cast_type(attr1, attr2); binop_noassign(ret, attr1, attr2, "|"); break; case V_SgCommaOpExp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << ","; attr2 = examineExpr(e2, out); out << ")"; ret->cast_type(attr1, attr2); binop_noassign(ret, attr1, attr2, ","); break; case V_SgLshiftOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << "<<"; attr2 = examineExpr(e2, out); out << ")"; ret->cast_type(attr1, attr2); binop_noassign(ret, attr1, attr2, "<<"); break; case V_SgRshiftOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << ">>"; attr2 = examineExpr(e2, out); out << ")"; ret->cast_type(attr1, attr2); binop_noassign(ret, attr1, attr2, ">>"); break; case V_SgAssignOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); attr1 = examineExpr(e1, out); out << "="; attr2 = examineExpr(e2, out); ret->cast_type(attr1, attr2); ret->union_tmp_decls(attr1, attr2); ret->result_var = attr1->result_var; ret->code << attr2->code.str() << attr1->code.str() << ret->result_var; ret->code << "=" << attr2->result_var; ret->code << ";" << endl; break; case V_SgPlusAssignOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); attr1 = examineExpr(e1, out); out << "+="; attr2 = examineExpr(e2, out); ret->cast_type(attr1, attr2); ret = binop_assign(ret, attr1, attr2, "+"); break; case V_SgMinusAssignOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); attr1 = examineExpr(e1, out); out << "-="; attr2 = examineExpr(e2, out); ret->cast_type(attr1, attr2); ret = binop_assign(ret, attr1, attr2, "-"); break; case V_SgAndAssignOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); attr1 = examineExpr(e1, out); out << "&="; attr2 = examineExpr(e2, out); ret->cast_type(attr1, attr2); ret = binop_assign(ret, attr1, attr2, "&"); break; case V_SgIorAssignOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); attr1 = examineExpr(e1, out); out << "|="; attr2 = examineExpr(e2, out); ret->cast_type(attr1, attr2); ret = binop_assign(ret, attr1, attr2, "|"); break; case V_SgMultAssignOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); attr1 = examineExpr(e1, out); out << "*="; attr2 = examineExpr(e2, out); ret->cast_type(attr1, attr2); ret = binop_assign(ret, attr1, attr2, "*"); break; case V_SgDivAssignOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); attr1 = examineExpr(e1, out); out << "/="; attr2 = examineExpr(e2, out); ret->cast_type(attr1, attr2); ret = binop_assign(ret, attr1, attr2, "/"); break; case V_SgModAssignOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); attr1 = examineExpr(e1, out); out << "%="; attr2 = examineExpr(e2, out); ret->cast_type(attr1, attr2); ret = binop_assign(ret, attr1, attr2, "%"); break; case V_SgXorAssignOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); attr1 = examineExpr(e1, out); out << "^="; attr2 = examineExpr(e2, out); ret->cast_type(attr1, attr2); ret = binop_assign(ret, attr1, attr2, "^"); break; case V_SgLshiftAssignOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); attr1 = examineExpr(e1, out); out << "<<="; attr2 = examineExpr(e2, out); ret->cast_type(attr1, attr2); ret = binop_assign(ret, attr1, attr2, "<<"); break; case V_SgRshiftAssignOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); attr1 = examineExpr(e1, out); out << ">>="; attr2 = examineExpr(e2, out); ret->cast_type(attr1, attr2); ret = binop_assign(ret, attr1, attr2, ">>"); break; case V_SgExponentiationOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << "ExpUnknown"; attr2 = examineExpr(e2, out); out << ")"; break; case V_SgConcatenationOp: binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); out << "("; attr1 = examineExpr(e1, out); out << "CatUnknown"; attr2 = examineExpr(e2, out); out << ")"; break; case V_SgPntrArrRefExp: { binop = isSgBinaryOp(expr); e1 = binop->get_lhs_operand(); e2 = binop->get_rhs_operand(); attr1 = examineExpr(e1, out); out << "["; attr2 = examineExpr(e2, out); out << "]"; ret->basetype(attr1); ret->union_tmp_decls(attr1, attr2); ret->result_var = attr1->result_var + "[" + attr2->result_var + "]"; ret->code << attr1->code.str() << attr2->code.str(); break; } /* End BinaryOp */ /* Begin variables */ case V_SgVarRefExp: { stringstream casts; SgVarRefExp *varref = isSgVarRefExp(expr); if (NULL == varref) return NULL; SgVariableSymbol *svsym = varref->get_symbol(); if (NULL == svsym) return NULL; out << svsym->get_name().getString(); ret->result_var = svsym->get_name().getString(); examineType(svsym->get_type(), casts); ret->type = casts.str(); ret->sgtype = svsym->get_type(); /* ret->new_tmp_name(); examineType(svsym->get_type(), casts); ret->type = casts.str(); ret->sgtype = svsym->get_type(); ret->add_new_tmp_decl(ret->type, ret->result_var); ret->code << ret->result_var << " = " << svsym->get_name().getString(); ret->code << ";" << endl; */ break; } case V_SgLabelRefExp: SgLabelRefExp *labref = isSgLabelRefExp(expr); out << labref->get_name().getString(); break; /* Begin Constants */ case V_SgIntVal: { stringstream casts; SgIntVal *intval = isSgIntVal(expr); out << intval->get_value(); casts << intval->get_value(); ret->result_var = casts.str(); ret->type = "int"; ret->sgtype = intval->get_type(); break; } case V_SgLongIntVal: { stringstream casts; SgLongIntVal *longval = isSgLongIntVal(expr); out << longval->get_value() << "L"; casts << longval->get_value() << "L"; ret->result_var = casts.str(); ret->type = "long"; ret->sgtype = longval->get_type(); break; } case V_SgUnsignedIntVal: { stringstream casts; SgUnsignedIntVal *uintval = isSgUnsignedIntVal(expr); out << uintval->get_value() << "U"; casts << uintval->get_value() << "U"; ret->result_var = casts.str(); ret->type = "unsigned"; ret->sgtype = uintval->get_type(); break; } case V_SgUnsignedLongVal: { stringstream casts; SgUnsignedLongVal *ulongval = isSgUnsignedLongVal(expr); out << ulongval->get_value() << "UL"; casts << ulongval->get_value() << "UL"; ret->result_var = casts.str(); ret->type = "unsigned long"; ret->sgtype = ulongval->get_type(); break; } case V_SgDoubleVal: { stringstream casts; SgDoubleVal *doubleval = isSgDoubleVal(expr); out << doubleval->get_value(); casts << doubleval->get_value(); ret->result_var = casts.str(); ret->type = "double"; ret->sgtype = doubleval->get_type(); break; } case V_SgFloatVal: { stringstream casts; SgFloatVal *floatval = isSgFloatVal(expr); out << floatval->get_value(); casts << floatval->get_value(); ret->result_var = casts.str(); ret->type = "float"; ret->sgtype = floatval->get_type(); break; } default: out << "/* UNKNOWN EXPR[" << expr->class_name() << "](" << expr->variantT() << ") " << expr->unparseToString() << " */" << endl; cerr << "UNKNOWN EXPR[" << expr->class_name() << "] " << expr->unparseToString() << endl; break; } if (NULL != attr1) delete attr1; if (NULL != attr2) delete attr2; return ret; }
bool StencilAnalysis::isShareableReference(const std::vector<SgExpression*> subscripts, const bool corner_yz //=FALSE ) { //March 2 2011, made changes in the function, we have more robust sharing conditions //checks if an array reference can be replaced with shared memory reference //by looking at the index expressions //assumes the variable is already checked for candidacy //check if subsrcipts are _gidx, _gidy or _gidz std::vector<SgExpression*>::const_iterator it; size_t count = 0; int indexNo = 0; for(it= subscripts.begin(); it != subscripts.end(); it++) { indexNo++; SgExpression* index = isSgExpression(*it); Rose_STL_Container<SgNode*> varList = NodeQuery::querySubTree(index, V_SgVarRefExp); if(varList.size() != 1) //there should be only 1 variable and that should be gidx,y,z return false; //check if that varRef is x, y, z SgVarRefExp* varExp = isSgVarRefExp(*(varList.begin())); ROSE_ASSERT(varExp); string index_str = varExp->unparseToString(); if(indexNo == 1 && index_str != GIDX ) return false; if(indexNo == 2 && index_str != GIDY ) return false; if(indexNo == 3 && index_str != GIDZ ) return false; Rose_STL_Container<SgNode*> constList = NodeQuery::querySubTree(index, V_SgIntVal); if(constList.size() > 1 ) return false; if(constList.size() == 1) { SgIntVal* constVal = isSgIntVal(*(constList.begin())); ROSE_ASSERT(constVal); if(constVal->get_value() > MAX_ORDER) return false; //we keep maximum 3 planes in shared memory if(constVal->get_value() > 1 && indexNo == 3) return false; Rose_STL_Container<SgNode*> binOpList = NodeQuery::querySubTree(index, V_SgBinaryOp); if(binOpList.size() != 1) return false; SgBinaryOp* binOp = isSgBinaryOp(*(binOpList.begin())); //we want either one add or subtract operation in the index expression //no complex indexing is supported for now. //A[i+2][i-4] is valid but A[i*2] is not valid if( !isSgAddOp(binOp) && !isSgSubtractOp(binOp)) return false; if(indexNo == 3 && !corner_yz) { //corner of yz is only shareable when corner_yz is true return false; } } count++; } return (count == subscripts.size()) ? true : false ; }
int StencilAnalysis::getSharingCategory(const std::vector<SgExpression*> subscripts) { //return 2 if it is up or down //return 1 if it is off-center //return 0 if it is center //return -1 if it is neither //check if subsrcipts are _gidx, _gidy or _gidz std::vector<SgExpression*>::const_iterator it; size_t count = 0; int indexNo = 0; size_t category = 0; for(it= subscripts.begin(); it != subscripts.end(); it++) { indexNo++; SgExpression* index = isSgExpression(*it); Rose_STL_Container<SgNode*> varList = NodeQuery::querySubTree(index, V_SgVarRefExp); if(varList.size() != 1) //there should be only 1 variable and that should be gidx,y,z return -1; //check if that varRef is x, y, z SgVarRefExp* varExp = isSgVarRefExp(*(varList.begin())); ROSE_ASSERT(varExp); string index_str = varExp->unparseToString(); if(indexNo == 1 && index_str != GIDX ) return -1; else if(indexNo == 2 && index_str != GIDY ) return -1; else if(indexNo == 3 && index_str != GIDZ ) return -1; Rose_STL_Container<SgNode*> constList = NodeQuery::querySubTree(index, V_SgIntVal); if(constList.size() > 1 ) return -1; if(constList.size() == 1) { category = 1; SgIntVal* constVal = isSgIntVal(*(constList.begin())); ROSE_ASSERT(constVal); if(constVal->get_value() > MAX_ORDER) return -1; //we keep maximum 3 planes in shared memory if(constVal->get_value() > 1 && indexNo == 3) return -1; Rose_STL_Container<SgNode*> binOpList = NodeQuery::querySubTree(index, V_SgBinaryOp); if(binOpList.size() != 1) return -1; SgBinaryOp* binOp = isSgBinaryOp(*(binOpList.begin())); //we want either one add or subtract operation in the index expression //no complex indexing is supported for now. //A[i+2][i-4] is valid but A[i*2] is not valid if( !isSgAddOp(binOp) && !isSgSubtractOp(binOp)) return -1; if(indexNo == 3) { category = 2; } } count++; } return (count == subscripts.size()) ? category : -1 ; }