int main(int argc, char * argv[]) { SgProject *project = frontend (argc, argv); SgFunctionDeclaration* func_decl = SageInterface::findDeclarationStatement<SgFunctionDeclaration> (project, "foo", NULL, true); Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(func_decl->get_definition(), V_SgVarRefExp); for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++) { SgVarRefExp *vRef = isSgVarRefExp((*i)); cout<<"varRefExp: "<< vRef->unparseToString()<<endl; } // We expect two references // from input_ompVariableCollecting.C if (nodeList.size() !=2) { cerr<<"Error. We should find exactly two variable references."<<endl; } ROSE_ASSERT (nodeList.size() ==2); return backend(project); }
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
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 ; }