#include #include #include #include #include #include #include #include #include #include #include #include #include #include "loop_analyzer.h" #include #include #include "../Utils/leak_detector.h" #if _WIN32 && NDEBUG && __BOOST #include #endif extern int passDone; #include "../Distribution/Distribution.h" #include "../Distribution/GraphCSR.h" #include "../Distribution/Arrays.h" #include "../ParallelizationRegions/ParRegions.h" #include "../Utils/errors.h" #include "../DirectiveProcessing/directive_parser.h" #include "../DirectiveProcessing/directive_creator.h" #include "../Utils/SgUtils.h" #include "../Utils/AstWrapper.h" #include "../GraphCall/graph_calls_func.h" #include "../GraphLoop/graph_loops_func.h" #include "../ParallelizationRegions/ParRegions_func.h" #include "../DynamicAnalysis/gCov_parser_func.h" #include "../ExpressionTransform/expr_transform.h" #include "../SageAnalysisTool/depInterfaceExt.h" #include "../VisualizerCalls/get_information.h" #include "../VisualizerCalls/SendMessage.h" #include "../Transformations/enddo_loop_converter.h" #include "../DirectiveProcessing/remote_access.h" #include "../DirectiveProcessing/directive_omp_parser.h" #define PRINT_ARRAY_ARCS 0 #define PRINT_LOOP_STRUCT 0 #define PRINT_PROF_INFO 0 #define DEB 0 extern REGIME currRegime; extern std::vector* currMessages; extern int sharedMemoryParallelization; extern int parallizeFreeLoops; using std::vector; using std::pair; using std::tuple; using std::map; using std::set; using std::make_pair; using std::make_tuple; using std::get; using std::string; using std::wstring; using std::stack; REGIME currRegime = UNDEF; std::vector* currMessages; static bool hasArrayAccessInSubscr(SgExpression *exp) { bool retVal = false; if (exp->variant() == ARRAY_REF) return true; if (exp->lhs()) retVal |= hasArrayAccessInSubscr(exp->lhs()); if (exp->rhs()) retVal |= hasArrayAccessInSubscr(exp->rhs()); return retVal; } bool checkExistence(SgExpression *exp, const string& doName) { bool retVal = false; if (exp->variant() == VAR_REF) if (exp->symbol()->identifier() == doName) retVal = true; if (exp->lhs()) retVal |= checkExistence(exp->lhs(), doName); if (exp->rhs()) retVal |= checkExistence(exp->rhs(), doName); return retVal; } static pair constructArrayRefForPrint(SgArrayRefExp *arrayRef, const int dimNum, SgExpression *subscr) { bool needToPrint = true; const int num = arrayRef->numberOfSubscripts(); string ref(arrayRef->symbol()->identifier()); ref += "("; for (int i = 0; i < num; ++i) { if (i == dimNum) { char *copySub = copyOfUnparse(subscr->unparse()); ref += copySub; if (subscr->variant() == INT_VAL) needToPrint = false; removeFromCollection(copySub); delete []copySub; } else ref += "*"; if (i != num - 1) ref += ","; else ref += ")"; } std::transform(ref.begin(), ref.end(), ref.begin(), ::toupper); return make_pair(needToPrint, ref); } static void addInfoToMap(map> &loopInfo, SgForStmt *position, SgSymbol *symb, SgArrayRefExp *arrayRefIn, const int dimNum, const REMOTE_TYPE &value, const int currLine, const int maxDimSize) { ArrayRefExp *arrayRef = new ArrayRefExp(arrayRefIn); auto it = loopInfo.find(position); if (loopInfo.end() == it) it = loopInfo.insert(it, make_pair(position, map())); auto it1 = it->second.find(symb); if (it1 == it->second.end()) it1 = it->second.insert(it1, make_pair(symb, ArrayInfo())); auto it2 = it1->second.arrayAccessUnrec.find(arrayRef); if (it2 == it1->second.arrayAccessUnrec.end()) { it2 = it1->second.arrayAccessUnrec.insert(it2, make_pair(arrayRef, make_pair(currLine, vector()))); it2->second.second.resize(maxDimSize); std::fill(it2->second.second.begin(), it2->second.second.end(), REMOTE_NONE); } if (dimNum == -1) { for (int z = 0; z < it2->second.second.size(); ++z) it2->second.second[z] |= value; } else it2->second.second[dimNum] |= value; if (value == REMOTE_TRUE) __spf_print(DEB, "RemoteAccess[%d]: true for dim %d and array %s, loop line %d\n", __LINE__, dimNum, symb->identifier(), position->lineNumber()); } enum { READ_OP, WRITE_OP, UNREC_OP }; static void addInfoToVectors(map> &loopInfo, SgForStmt *position, SgSymbol *symb, const int dimNum, const pair newCoef, int type, const int maxDimSize, const double currentW) { auto itLoop = loopInfo.find(position); if (itLoop == loopInfo.end()) itLoop = loopInfo.insert(itLoop, make_pair(position, map())); auto itSymb = itLoop->second.find(symb); if (itSymb == itLoop->second.end()) itSymb = itLoop->second.insert(itSymb, make_pair(symb, ArrayInfo())); itSymb->second.setDimSize(maxDimSize); if (type == READ_OP) { auto itAdd = itSymb->second.readOps[dimNum].coefficients.find(newCoef); //add only uniq if (itAdd == itSymb->second.readOps[dimNum].coefficients.end()) itAdd = itSymb->second.readOps[dimNum].coefficients.insert(itAdd, make_pair(newCoef, currentW)); } else if (type == WRITE_OP) { auto itAdd = itSymb->second.writeOps[dimNum].coefficients.find(newCoef); if (itAdd == itSymb->second.writeOps[dimNum].coefficients.end()) itAdd = itSymb->second.writeOps[dimNum].coefficients.insert(itAdd, make_pair(newCoef, currentW)); } else if (type == UNREC_OP) itSymb->second.unrecReadOps[dimNum] = true; else printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } static vector matchSubscriptToLoopSymbols(const vector &parentLoops, SgExpression *subscr, SgArrayRefExp *arrayRefIn, const int side, const int dimNum, map> &loopInfo, const int currLine, const int numOfSubscriptions, const double currentW) { SgExpression *origSubscr = subscr; ArrayRefExp *arrayRef = new ArrayRefExp(arrayRefIn); // REVERT_SUBS has been done before REMOTE_ACC PASS if (currRegime == REMOTE_ACC) { auto data = getAttributes(arrayRefIn, set{ ARRAY_REF }); if (data.size() == 1) { SgExpression *dataS = data[0]->lhs(); for (int z = 0; z < dimNum; ++z) dataS = dataS->rhs(); subscr = dataS->lhs(); } } int countOfSymbols = 0; int position = -1; vector allPositions; bool hasArrayAcc = hasArrayAccessInSubscr(subscr); SgSymbol *currOrigArrayS = OriginalSymbol(arrayRef->symbol()); if (!hasArrayAcc) { for (int i = 0; i < (int)parentLoops.size(); ++i) { if (checkExistence(subscr, parentLoops[i]->doName()->identifier())) { countOfSymbols++; position = i; allPositions.push_back(i); } } } pair coefs = pair(0, 0); // more than one loop symbol in subscription if (countOfSymbols > 1) { __spf_print(PRINT_ARRAY_ARCS, " <%d|%d> ", 0, 0); if (currRegime == DATA_DISTR || currRegime == SHARED_MEMORY_PAR) { const pair &arrayRefString = constructArrayRefForPrint(arrayRef, dimNum, origSubscr); __spf_print(1, "WARN: array ref '%s' at line %d has more than one loop's variables\n", arrayRefString.second.c_str(), currLine); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"array ref '%s' has more than one loop's variables", to_wstring(arrayRefString.second).c_str()); __spf_printToLongBuf(messageR, R54, to_wstring(arrayRefString.second).c_str()); if (currLine > 0) currMessages->push_back(Messages(WARR, currLine, messageR, messageE, 1021)); } for (int i = 0; i < allPositions.size(); ++i) { if (currRegime == REMOTE_ACC) { if (side == RIGHT) addInfoToMap(loopInfo, parentLoops[allPositions[i]], currOrigArrayS, arrayRef, dimNum, REMOTE_TRUE, currLine, numOfSubscriptions); } else addInfoToVectors(loopInfo, parentLoops[allPositions[i]], currOrigArrayS, dimNum, make_pair(0, 0), UNREC_OP, numOfSubscriptions, currentW); } } // no loop symbol in subscription else if (countOfSymbols == 0) { __spf_print(PRINT_ARRAY_ARCS, " <%d|%d> ", 0, 0); if (currRegime == REMOTE_ACC) { if (side == RIGHT) for (int i = 0; i < (int)parentLoops.size(); ++i) addInfoToMap(loopInfo, parentLoops[i], currOrigArrayS, arrayRef, dimNum, REMOTE_TRUE, currLine, numOfSubscriptions); } else if (currRegime == DATA_DISTR || currRegime == SHARED_MEMORY_PAR) { const pair &arrayRefString = constructArrayRefForPrint(arrayRef, dimNum, origSubscr); if (!hasArrayAcc) { if (parentLoops.size() != 0 && (arrayRefString.first || side == LEFT)) { __spf_print(1, "WARN: array ref '%s' in %d dimension at line %d does not have loop variables\n", arrayRefString.second.c_str(), dimNum + 1, currLine); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"array ref '%s' in %d dimension does not have loop variables", to_wstring(arrayRefString.second).c_str(), dimNum + 1); __spf_printToLongBuf(messageR, R55, to_wstring(arrayRefString.second).c_str(), dimNum + 1); if (currLine > 0) currMessages->push_back(Messages(WARR, currLine, messageR, messageE, 1021)); } } else { __spf_print(1, "WARN: array ref '%s' at line %d has indirect access\n", arrayRefString.second.c_str(), currLine); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"array ref '%s' has indirect access", to_wstring(arrayRefString.second).c_str()); __spf_printToLongBuf(messageR, R56, to_wstring(arrayRefString.second).c_str()); if (currLine > 0) currMessages->push_back(Messages(WARR, currLine, messageR, messageE, 1022)); } } } else { bool needToCacl = true; if (subscr->variant() == VAR_REF) { if (subscr->symbol()->id() == (parentLoops[position]->doName())->id()) { coefs.first = 1; needToCacl = false; } } if (needToCacl) getCoefsOfSubscript(coefs, subscr, parentLoops[position]->doName()); __spf_print(PRINT_ARRAY_ARCS, " <%d %d> ", coefs.first, coefs.second); if (coefs.first == 0) // && coefs.second == 0) { if (currRegime == REMOTE_ACC) { if (side == RIGHT) addInfoToMap(loopInfo, parentLoops[position], currOrigArrayS, arrayRef, dimNum, REMOTE_TRUE, currLine, numOfSubscriptions); } else if (currRegime == DATA_DISTR || currRegime == SHARED_MEMORY_PAR) { const pair &arrayRefString = constructArrayRefForPrint(arrayRef, dimNum, origSubscr); __spf_print(1, "WARN: can not calculate index expression for array ref '%s' at line %d\n", arrayRefString.second.c_str(), currLine); addInfoToVectors(loopInfo, parentLoops[position], currOrigArrayS, dimNum, coefs, UNREC_OP, numOfSubscriptions, currentW); if (side == LEFT) allPositions.clear(); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"can not calculate index expression for array ref '%s'", to_wstring(arrayRefString.second).c_str()); __spf_printToLongBuf(messageR, R57, to_wstring(arrayRefString.second).c_str()); if (currLine > 0) currMessages->push_back(Messages(WARR, currLine, messageR, messageE, 1023)); } } else { if (currRegime == REMOTE_ACC) { if (side == RIGHT) { vector& currOp = loopInfo[parentLoops[position]][currOrigArrayS].arrayAccess[arrayRef].second; if (currOp.size() < numOfSubscriptions) currOp.resize(numOfSubscriptions); //add only uniq auto itAdd = currOp[dimNum].coefficients.find(coefs); if (itAdd == currOp[dimNum].coefficients.end()) itAdd = currOp[dimNum].coefficients.insert(itAdd, make_pair(coefs, currentW)); } if (coefs.first < 0) addInfoToMap(loopInfo, parentLoops[position], currOrigArrayS, arrayRef, dimNum, REMOTE_TRUE, currLine, numOfSubscriptions); else //if we found regular access to array - set it false addInfoToMap(loopInfo, parentLoops[position], currOrigArrayS, arrayRef, dimNum, REMOTE_FALSE, currLine, numOfSubscriptions); } if (coefs.first < 0 && sharedMemoryParallelization == 0) { if (currRegime == DATA_DISTR) { const pair &arrayRefString = constructArrayRefForPrint(arrayRef, dimNum, origSubscr); const int line = (currLine < 0) ? parentLoops[position]->localLineNumber() : currLine; __spf_print(1, "WARN: coefficient A in A*x+B is not positive for array ref '%s' at line %d, inverse distribution in not supported yet\n", arrayRefString.second.c_str(), line); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"coefficient A in A*x+B is not positive for array ref '%s', inverse distribution in not supported yet", to_wstring(arrayRefString.second).c_str()); __spf_printToLongBuf(messageR, R58, to_wstring(arrayRefString.second).c_str()); if (line > 0) currMessages->push_back(Messages(WARR, line, messageR, messageE, 1024)); if (side == LEFT) allPositions.clear(); else addInfoToVectors(loopInfo, parentLoops[position], currOrigArrayS, dimNum, coefs, UNREC_OP, numOfSubscriptions, currentW); } } else { if (side == LEFT) addInfoToVectors(loopInfo, parentLoops[position], currOrigArrayS, dimNum, coefs, WRITE_OP, numOfSubscriptions, currentW); else addInfoToVectors(loopInfo, parentLoops[position], currOrigArrayS, dimNum, coefs, READ_OP, numOfSubscriptions, currentW); } } } if (currRegime == ARRAY_ACC_CORNER) { int *valueSubs = new int[2]; valueSubs[0] = coefs.first; valueSubs[1] = coefs.second; #ifdef __SPF addToCollection(__LINE__, __FILE__, valueSubs, 2); #endif const vector &coefs = getAttributes(subscr, set{ INT_VAL }); if (coefs.size() == 0) { subscr->addAttribute(INT_VAL, valueSubs, sizeof(int*)); if (position != -1 && allPositions.size() == 1 && position < parentLoops.size()) subscr->addAttribute(FOR_NODE, parentLoops[position], sizeof(SgStatement)); } } return allPositions; } static vector matchArrayToLoopSymbols(const vector &parentLoops, vector>& privatesVarsForLoop, SgExpression *currExp, const int side, map> &loopInfo, const int currLine, map &sortedLoopGraph, const ParallelRegion *reg, const double currentW, const map> &arrayLinksByFuncCalls) { SgArrayRefExp *arrayRef = (SgArrayRefExp*)currExp; int numOfSubs = arrayRef->numberOfSubscripts(); currExp = currExp->lhs(); vector wasFoundForLoop(parentLoops.size()); vector matched(numOfSubs); vector matchedToDim(parentLoops.size()); std::fill(wasFoundForLoop.begin(), wasFoundForLoop.end(), 0); std::fill(matched.begin(), matched.end(), -1); std::fill(matchedToDim.begin(), matchedToDim.end(), -1); int maxMatched = 0; int sumMatched = 0; for (int i = 0; i < numOfSubs; ++i) { vector matchToLoops = matchSubscriptToLoopSymbols(parentLoops, currExp->lhs(), arrayRef, side, i, loopInfo, currLine, numOfSubs, currentW); for (int k = 0; k < matchToLoops.size(); ++k) { wasFoundForLoop[matchToLoops[k]]++; matchedToDim[matchToLoops[k]] = i; } matched[i] = matchToLoops.size(); sumMatched += matchToLoops.size(); maxMatched = std::max(maxMatched, (int)matchToLoops.size()); currExp = currExp->rhs(); } //full array is used, add unknown operations to all loops if (numOfSubs == 0) { SgSymbol *currOrigArrayS = OriginalSymbol(arrayRef->symbol()); auto arrType = isSgArrayType(currOrigArrayS->type()); if (arrType != NULL) { for (int d = 0; d < arrType->dimension(); ++d) for (int i = 0; i < parentLoops.size(); ++i) addInfoToVectors(loopInfo, parentLoops[i], currOrigArrayS, d, make_pair(0, 0), UNREC_OP, arrType->dimension(), currentW); } } if (currRegime == ARRAY_ACC_CORNER) return wasFoundForLoop; bool ifUnknownArrayAssignFound = false; vector canNotMapToLoop; for (int i = 0; i < wasFoundForLoop.size(); ++i) { if (wasFoundForLoop[i] != 1 && // always true for distributed data case privatesVarsForLoop[i].find(string(arrayRef->symbol()->identifier())) == privatesVarsForLoop[i].end()) { auto itLoop = sortedLoopGraph.find(parentLoops[i]->lineNumber()); if (itLoop == sortedLoopGraph.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); ifUnknownArrayAssignFound = true; if (side == LEFT && (currRegime == DATA_DISTR || currRegime == COMP_DISTR || currRegime == SHARED_MEMORY_PAR)) itLoop->second->hasUnknownArrayAssigns = true; itLoop->second->hasUnknownDistributedMap = true; canNotMapToLoop.push_back(parentLoops[i]->lineNumber()); } } if (side == LEFT) { if (ifUnknownArrayAssignFound && (currRegime == DATA_DISTR || currRegime == SHARED_MEMORY_PAR)) { const string arrayRefS = arrayRef->unparse(); for (auto &line : canNotMapToLoop) { __spf_print(1, "WARN: can not map write to array '%s' to loop on line %d\n", arrayRefS.c_str(), line); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"can not map write to array '%s' to this loop", to_wstring(arrayRefS).c_str()); __spf_printToLongBuf(messageR, R59, to_wstring(arrayRefS).c_str()); if (line > 0) currMessages->push_back(Messages(WARR, line, messageR, messageE, 1025)); } } } else if (side == RIGHT) { SgSymbol* currOrigArrayS = OriginalSymbol(arrayRef->symbol()); if (currRegime == REMOTE_ACC) { DIST::Array* currArray = getArrayFromDeclarated(declaratedInStmt(currOrigArrayS), currOrigArrayS->identifier()); if (!currArray && currOrigArrayS->type()->variant() == T_ARRAY) checkNull(currArray, convertFileName(__FILE__).c_str(), __LINE__); if (currArray) { // for integration with SAPFOR-C map> tmpInfo; vector parentGraphLoops; auto tmpRef = new ArrayRefExp(arrayRef); for (auto& loop : parentLoops) { auto it = sortedLoopGraph.find(loop->lineNumber()); if (it == sortedLoopGraph.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); parentGraphLoops.push_back(it->second); } auto requests = checkArrayRefInLoopForRemoteStatus(ifUnknownArrayAssignFound, sumMatched, numOfSubs, maxMatched, currLine, currArray, wasFoundForLoop, tmpRef, tmpInfo, matchedToDim, sortedLoopGraph, arrayLinksByFuncCalls, reg, parentGraphLoops); //clean memory for (auto& loop : tmpInfo) for (auto& array : loop.second) delete array.second; for (auto& req : requests) addInfoToMap(loopInfo, (SgForStmt*)req.position->loop->GetOriginal(), currOrigArrayS, arrayRef, req.dimNum, req.value, req.currLine, req.maxDimSize); } } } return wasFoundForLoop; } static void mapArrayRef(SgStatement* currentSt, SgExpression* currExp, const vector& parentLoops, vector>& privatesVarsForLoop, const int side, const int lineNum, map>& loopInfo, map &sortedLoopGraph, map>& notMappedDistributedArrays, set& mappedDistrbutedArrays, const ParallelRegion* reg, const double currentW, const map>& arrayLinksByFuncCalls) { const char* printSide = NULL; if (PRINT_ARRAY_ARCS) printBlanks(2, (int)parentLoops.size()); if (side == LEFT) printSide = "W_OP"; else printSide = "R_OP"; __spf_print(PRINT_ARRAY_ARCS, "%s to array <%s> on line %d: ", printSide, OriginalSymbol(currExp->symbol())->identifier(), lineNum); bool wasMapped = false; vector matched = matchArrayToLoopSymbols(parentLoops, privatesVarsForLoop, currExp, side, loopInfo, lineNum, sortedLoopGraph, reg, currentW, arrayLinksByFuncCalls); for (int z = 0; z < matched.size(); ++z) wasMapped |= (matched[z] != 0); if (parentLoops.size() == 0) { SgSymbol* symb = currExp->symbol(); if (symb->type()->variant() == T_ARRAY) notMappedDistributedArrays[symb->identifier()] = make_pair(symb, currentSt); } else { if (wasMapped) mappedDistrbutedArrays.insert(currExp->symbol()->identifier()); else { SgSymbol* symb = currExp->symbol(); if (symb->type()->variant() == T_ARRAY) notMappedDistributedArrays[symb->identifier()] = make_pair(symb, currentSt); } } __spf_print(PRINT_ARRAY_ARCS, "\n"); } static void findArrayRef(const vector &parentLoops, SgExpression *currExp, const int lineNum, const int side, map> &loopInfo, const set &privatesVars, vector>& privatesVarsForLoop, map &sortedLoopGraph, const map> &commonBlocks, const map, pair> &declaredArrays, bool wasDistributedArrayRef, map> ¬MappedDistributedArrays, set &mappedDistrbutedArrays, SgStatement *currentSt, const ParallelRegion *reg, const double currentW, const map> &arrayLinksByFuncCalls) { int nextSide = side; if (isArrayRef(currExp)) { //... and current array is not in private list if (sharedMemoryParallelization || privatesVars.find(string(OriginalSymbol(currExp->symbol())->identifier())) == privatesVars.end()) { if (wasDistributedArrayRef) { int depth = 1; for (int i = parentLoops.size() - 1; i >= 0; --i, ++depth) { auto itLoop = sortedLoopGraph.find(parentLoops[i]->lineNumber()); if (itLoop == sortedLoopGraph.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (itLoop->second->perfectLoop != depth) break; if (!(sharedMemoryParallelization && side == RIGHT)) itLoop->second->hasIndirectAccess = true; } mapArrayRef(currentSt, currExp, parentLoops, privatesVarsForLoop, side, lineNum, loopInfo, sortedLoopGraph, notMappedDistributedArrays, mappedDistrbutedArrays, reg, currentW, arrayLinksByFuncCalls); } else { wasDistributedArrayRef = true; mapArrayRef(currentSt, currExp, parentLoops, privatesVarsForLoop, side, lineNum, loopInfo, sortedLoopGraph, notMappedDistributedArrays, mappedDistrbutedArrays, reg, currentW, arrayLinksByFuncCalls); } } else if (currRegime == DATA_DISTR && side == LEFT) { auto symb = OriginalSymbol(currExp->symbol()); SgStatement *decl = declaratedInStmt(symb); auto uniqKey = getUniqName(commonBlocks, decl, symb); auto itFound = declaredArrays.find(uniqKey); if (itFound == declaredArrays.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); //TODO: array access to non distributed arrays, add CONSISTENT if (itFound->second.first->GetDistributeFlagVal() != DIST::DISTR) { set loopsPrivates; set loopsPrivatesS; set loopsRedUnited; map> loopsReductions; map>> loopsReductionsLoc; for (int z = 0; z < parentLoops.size(); ++z) { auto& loop = parentLoops[z]; for (auto &data : getAttributes(loop, set{ SPF_ANALYSIS_DIR })) { fillPrivatesFromComment(new Statement(data), loopsPrivatesS); for (auto& elem : loopsPrivatesS) loopsPrivates.insert(elem->GetOriginal()->identifier()); fillReductionsFromComment(new Statement(data), loopsReductions); fillReductionsFromComment(new Statement(data), loopsReductionsLoc); } } for (auto &elem : loopsReductions) { for (auto &setElem : elem.second) { loopsPrivates.insert(setElem->GetOriginal()->identifier()); loopsRedUnited.insert(setElem->GetOriginal()->identifier()); } } for (auto &elem : loopsReductionsLoc) { for (auto &setElem : elem.second) { loopsPrivates.insert(get<0>(setElem)->GetOriginal()->identifier()); loopsPrivates.insert(get<1>(setElem)->GetOriginal()->identifier()); loopsRedUnited.insert(get<0>(setElem)->GetOriginal()->identifier()); loopsRedUnited.insert(get<1>(setElem)->GetOriginal()->identifier()); } } const string key = string(OriginalSymbol(currExp->symbol())->identifier()); if (loopsPrivates.find(key) == loopsPrivates.end()) { for (auto& loop : parentLoops) { __spf_print(1, "WARN: write to non distributed array '%s' in loop on line %d\n", symb->identifier(), loop->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"write to non distributed array '%s' in this loop", to_wstring(symb->identifier()).c_str()); __spf_printToLongBuf(messageR, R61, to_wstring(symb->identifier()).c_str()); if (loop->lineNumber() > 0) currMessages->push_back(Messages(WARR, loop->lineNumber(), messageR, messageE, 1026)); sortedLoopGraph[loop->lineNumber()]->hasWritesToNonDistribute = true; } } if (loopsPrivates.find(key) != loopsPrivates.end() || loopsRedUnited.find(key) != loopsRedUnited.end()) { auto currOrigArrayS = OriginalSymbol(currExp->symbol()); if (currOrigArrayS->type()->variant() == T_ARRAY) { DIST::Array* currArray = getArrayFromDeclarated(declaratedInStmt(currOrigArrayS), currOrigArrayS->identifier()); checkNull(currArray, convertFileName(__FILE__).c_str(), __LINE__); { set realArrayRefs; getRealArrayRefs(currArray, currArray, realArrayRefs, arrayLinksByFuncCalls); for (auto& array : realArrayRefs) array->SetPrivateInLoopStatus(true); } } } } } nextSide = (side == LEFT) ? RIGHT : side; } bool needToContinue = true; if (currExp->variant() == FUNC_CALL) { SgFunctionCallExp *funcExp = (SgFunctionCallExp*)currExp; auto currFunc = isUserFunctionInProject(funcExp->funName()->identifier()); if (currFunc) { for (int z = 0; z < funcExp->numberOfArgs(); ++z) { if ((currFunc->funcParams.inout_types[z] & OUT_BIT) != 0) nextSide = LEFT; else nextSide = RIGHT; findArrayRef(parentLoops, funcExp->arg(z), lineNum, nextSide, loopInfo, privatesVars, privatesVarsForLoop, sortedLoopGraph, commonBlocks, declaredArrays, wasDistributedArrayRef, notMappedDistributedArrays, mappedDistrbutedArrays, currentSt, reg, currentW, arrayLinksByFuncCalls); } needToContinue = false; } } if (needToContinue) { if (currExp->lhs()) findArrayRef(parentLoops, currExp->lhs(), lineNum, nextSide, loopInfo, privatesVars, privatesVarsForLoop, sortedLoopGraph, commonBlocks, declaredArrays, wasDistributedArrayRef, notMappedDistributedArrays, mappedDistrbutedArrays, currentSt, reg, currentW, arrayLinksByFuncCalls); if (currExp->rhs()) findArrayRef(parentLoops, currExp->rhs(), lineNum, nextSide, loopInfo, privatesVars, privatesVarsForLoop, sortedLoopGraph, commonBlocks, declaredArrays, wasDistributedArrayRef, notMappedDistributedArrays, mappedDistrbutedArrays, currentSt, reg, currentW, arrayLinksByFuncCalls); } } #define FIRST(x) get<0>(x) #define SECOND(x) get<1>(x) #define THIRD(x) get<2>(x) map shortFileNames; static int uniqfileNames = 0; string getShortName(const tuple &uniqKey) { const char *declFileName = SECOND(uniqKey).c_str(); const char *varName = THIRD(uniqKey).c_str(); const int position = FIRST(uniqKey); map::iterator it; it = shortFileNames.find(string(declFileName)); string retVal = ""; if (it == shortFileNames.end()) { retVal = string("f") + std::to_string(uniqfileNames) + string("_"); shortFileNames[string(declFileName)] = retVal; uniqfileNames++; } else retVal = it->second; return retVal + std::to_string(position) + string("_") + string(varName); } static int fillSizes(SgExpression *res, int &left, int &right) { int err = 0; if (res->lhs()->variant() == INT_VAL) left = res->lhs()->valueInteger(); else if (res->lhs()->variant() == MINUS_OP) left = -1 * res->lhs()->lhs()->valueInteger(); else err = -1; if (res->rhs()->variant() == INT_VAL) right = res->rhs()->valueInteger(); else if (res->rhs()->variant() == MINUS_OP) right = -1 * res->rhs()->lhs()->valueInteger(); else err = -1; return err; } static pair getElem(SgExpression *exp) { if (exp->lhs() && exp->rhs()) return make_pair(new Expression(exp->lhs()), new Expression(exp->rhs())); else if (exp->lhs()) return make_pair(new Expression(exp->lhs()), (Expression*)NULL); else if (exp->rhs()) return make_pair((Expression*)NULL, new Expression(exp->rhs())); else return make_pair((Expression*)NULL, (Expression*)NULL); } static void fillIdsFromEx(SgExpression* ex, set& ids) { if (ex) { if (ex->variant() == VAR_REF) ids.insert(ex->symbol()->identifier()); fillIdsFromEx(ex->lhs(), ids); fillIdsFromEx(ex->rhs(), ids); } } static void doReplacement(SgExpression *ex, const map &idsToIdx, const map> &values) { if (ex) { if (ex->lhs() && ex->lhs()->variant() == VAR_REF) { string key = ex->lhs()->symbol()->identifier(); auto it = idsToIdx.find(key); if (it != idsToIdx.end()) { if (values.find(it->second) != values.end()) { const int value = *values.find(it->second)->second.begin(); ex->setLhs(*new SgValueExp(value)); } } } if (ex->rhs() && ex->rhs()->variant() == VAR_REF) { string key = ex->rhs()->symbol()->identifier(); auto it = idsToIdx.find(key); if (it != idsToIdx.end()) { const int value = *values.find(it->second)->second.begin(); ex->setRhs(*new SgValueExp(value)); } } doReplacement(ex->lhs(), idsToIdx, values); doReplacement(ex->rhs(), idsToIdx, values); } } static SgExpression* replaceConstatantProcedurePars(SgExpression *dimList, SgStatement *proc, const map>& allFuncInfo) { if (proc == NULL) return dimList; if (allFuncInfo.size() == 0) return dimList; const string procN = proc->symbol()->identifier(); map mapFunc; createMapOfFunc(allFuncInfo, mapFunc); auto it = mapFunc.find(procN); if (it == mapFunc.end()) return dimList; FuncInfo* currF = it->second; if (currF->funcParams.countOfPars == 0) return dimList; set ids; fillIdsFromEx(dimList, ids); if (ids.size() == 0) return dimList; set idxFound; map idsToIdx; for (int z = 0; z < currF->funcParams.countOfPars; ++z) { if (ids.find(currF->funcParams.identificators[z]) != ids.end()) { idxFound.insert(z); idsToIdx[currF->funcParams.identificators[z]] = z; } } if (idxFound.size() == 0 || currF->callsTo.size() == 0) return dimList; map> values; //TODO: many call levels of functions for (int z = 0; z < currF->callsTo.size(); ++z) { FuncInfo* callOfThis = currF->callsTo[z]; for (int p = 0; p < callOfThis->callsFromDetailed.size(); ++p) { if (callOfThis->callsFromDetailed[p].detailCallsFrom.first == procN) { for (auto& par : idxFound) { auto parType = callOfThis->callsFromDetailed[p].actualParams.parametersT[par]; if (parType != SCALAR_INT_T) return dimList; else { if (callOfThis->callsFromDetailed[p].actualParams.parameters[par] == NULL) return dimList; values[par].insert(((int*)(callOfThis->callsFromDetailed[p].actualParams.parameters[par]))[0]); } } } } } for (auto& elem : values) if (elem.second.size() != 1) return dimList; doReplacement(dimList, idsToIdx, values); return dimList; } vector> getArraySizes(vector> &sizes, SgSymbol *symb, SgStatement *decl, const map> &arrayLinksByFuncCalls, const map> &allFuncInfo) { SgArrayType *type = isSgArrayType(symb->type()); vector> retVal; if (type != NULL) { SgExpression *dimList = type->getDimList()->copyPtr(); int consistInAllocates = 0; set allocValues; SgExpression *alloc = NULL; dimList = replaceConstatantProcedurePars(dimList, getFuncStat(decl, { MODULE_STMT, BLOCK_DATA }), allFuncInfo); while (dimList) { SgExpression *res = ReplaceArrayBoundSizes(dimList->lhs()->copyPtr()); if (res && res->variant() == INT_VAL) { sizes.push_back(make_pair(1, res->valueInteger())); retVal.push_back(make_pair((Expression*)NULL, new Expression(dimList->lhs()))); } else if (res && res->variant() == DDOT) { int err, tmpRes; if (res->lhs()) { err = CalculateInteger(res->lhs(), tmpRes); if (err != -1) res->setLhs(new SgValueExp(tmpRes)); } if (res->rhs()) { err = CalculateInteger(res->rhs(), tmpRes); if (err != -1) res->setRhs(new SgValueExp(tmpRes)); } int left, right; bool ok = res->lhs() && res->rhs(); if (ok) { int err = fillSizes(res, left, right); ok = (err == 0); } if (ok) { sizes.push_back(make_pair(left, right)); retVal.push_back(getElem(dimList->lhs())); } else { if (alloc == NULL) { for (auto &data : getAttributes(decl, set{ ALLOCATE_STMT })) { if (data->variant() != ALLOCATE_STMT) continue; //TODO: if (string(data->fileName()) != current_file->filename()) continue; SgExpression *list = data->expr(0); while (list) { SgArrayRefExp *arrayRef = isSgArrayRefExp(list->lhs()); if (arrayRef != NULL) { SgSymbol *origS = OriginalSymbol(arrayRef->symbol()); DIST::Array *currArray = getArrayFromDeclarated(declaratedInStmt(origS), origS->identifier()); string toCmp = string(origS->identifier()); //TODO: extend if (currArray && currArray->GetLocation().first == DIST::l_PARAMETER) { auto it = arrayLinksByFuncCalls.find(currArray); if (it != arrayLinksByFuncCalls.end()) { bool found = false; for (auto &elem : it->second) { if (elem->GetLocation().first != DIST::l_PARAMETER) { if (elem->GetShortName() == string(symb->identifier())) { consistInAllocates++; alloc = list->lhs()->lhs(); allocValues.insert(alloc->unparse()); found = true; break; } } } if (found) break; } } else { if (toCmp == string(symb->identifier())) { consistInAllocates++; alloc = list->lhs()->lhs(); allocValues.insert(alloc->unparse()); break; } } } list = list->rhs(); } } } else // set next in list alloc = alloc->rhs(); //TODO: dont check string representations of alloc expression!! check integer result, if all strings are equal if (consistInAllocates != 1 && allocValues.size() != 1) { sizes.push_back(make_pair(-1, -1)); retVal.push_back(make_pair((Expression*)NULL, (Expression*)NULL)); } else { SgExpression *result = ReplaceArrayBoundSizes(alloc->lhs()->copyPtr()); if (result->lhs()) { err = CalculateInteger(result->lhs(), tmpRes); if (err != -1) result->setLhs(new SgValueExp(tmpRes)); } if (result->rhs()) { err = CalculateInteger(result->rhs(), tmpRes); if (err != -1) result->setRhs(new SgValueExp(tmpRes)); } if (result->variant() == INT_VAL) { sizes.push_back(make_pair(1, result->valueInteger())); retVal.push_back(make_pair((Expression*)NULL, new Expression(alloc->lhs()))); } else if (result->variant() == DDOT) { retVal.push_back(getElem(alloc->lhs())); int left = 0, right = 0; bool ok = result->lhs() && result->rhs(); if (ok) { int err = fillSizes(result, left, right); ok = (err == 0); } if (ok) sizes.push_back(make_pair(left, right)); else sizes.push_back(make_pair(-1, -1)); } else { sizes.push_back(make_pair(-1, -1)); retVal.push_back(make_pair((Expression*)NULL, (Expression*)NULL)); } } } } else { sizes.push_back(make_pair(-1, -1)); retVal.push_back(make_pair((Expression*)NULL, (Expression*)NULL)); } dimList = dimList->rhs(); } } return retVal; } void recalculateArraySizes(set &arraysDone, const set &allArrays, const map> &arrayLinksByFuncCalls, const map> &allFuncInfo) { for (auto& array : allArrays) { auto itF = arraysDone.find(array); if (itF != arraysDone.end()) continue; itF = arraysDone.insert(itF, array); if (array->IsTemplate()) continue; SgSymbol* symb = array->GetDeclSymbol()->GetOriginal(); if (!symb) continue; auto& sizeInfo = array->GetSizes(); bool needToUpdate = false; for (auto& elem : sizeInfo) { if (elem.first == elem.second) { needToUpdate = true; break; } } if (!needToUpdate) continue; auto& declInfo = array->GetDeclInfo(); bool wasSelect = false; vector files; pair mainDecl; for (auto& elem : declInfo) { int fileId = SgFile::switchToFile(elem.first); if (fileId != -1) { files.push_back(fileId); mainDecl = elem; SgFile* tmpfile = &(CurrentProject->file(fileId)); wasSelect = true; break; } } if (!wasSelect) { //try to find in includes for (int i = CurrentProject->numberOfFiles() - 1; i >= 0; --i) { SgFile* file = &(CurrentProject->file(i)); for (SgStatement* st = file->firstStatement(); st; st = st->lexNext()) { for (auto& elem : declInfo) { if (make_pair(string(st->fileName()), st->lineNumber()) == elem) { wasSelect = true; break; } } if (wasSelect) { //wasSelect = false; SgStatement* decl = declaratedInStmt(symb); vector> sizes; auto sizesEx = getArraySizes(sizes, symb, decl, arrayLinksByFuncCalls, allFuncInfo); array->SetSizes(sizes); array->SetSizesExpr(sizesEx); } } if (wasSelect) break; } if (!wasSelect) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } else { if (wasSelect) { if (array->GetLocation().first == DIST::l_MODULE) { files.clear(); for (int i = CurrentProject->numberOfFiles() - 1; i >= 0; --i) files.push_back(i); } for (auto& file : files) { CurrentProject->file(file); SgStatement* decl = NULL; string currF = current_file->filename(); if (array->GetLocation().first == DIST::l_MODULE) { SgStatement* st = current_file->firstStatement(); while (st) { if (st->lineNumber() == mainDecl.second && st->fileName() == mainDecl.first) { decl = st; symb = NULL; SgExpression* ex = decl->expr(0); while (ex) { if (ex->lhs() && isArrayRef(ex->lhs())) { auto s = ex->lhs()->symbol(); if (s && s->identifier() == array->GetShortName()) { symb = s; break; } } ex = ex->rhs(); } break; } st = st->lexNext(); } } else { if (symb->getFileId() != current_file_id) { SgStatement* st = current_file->firstStatement(); int lastLine = 1; while (st) { if (st->lineNumber() > lastLine) lastLine = st->lineNumber(); st = st->lexNext(); } symb = array->GetDeclSymbol(currF, make_pair(1, lastLine), getAllFilesInProject())->GetOriginal(); } decl = declaratedInStmt(symb, NULL, false); } if (decl == NULL) continue; if (symb == NULL) { decl->unparsestdout(); printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } vector> sizes; auto sizesEx = getArraySizes(sizes, symb, decl, arrayLinksByFuncCalls, allFuncInfo); if (array->GetDimSize() != sizes.size()) { sizes.clear(); auto sizesEx = getArraySizes(sizes, symb, decl, arrayLinksByFuncCalls, allFuncInfo); printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } array->SetSizes(sizes); array->SetSizesExpr(sizesEx); bool needToContinue = false; for (auto& elem : sizes) { if (elem.first == elem.second) { needToContinue = true; break; } } if (!needToContinue) break; } } else printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } } } bool isIntrinsic(const char *funName) { if (intrinsicF.find(funName) == intrinsicF.end()) return false; else return true; } static set getPrivatesFromModule(SgStatement *mod, const map, pair> &declaredArrays, const map>> &declaratedArraysSt, const map &modulesByName) { set privates; SgStatement *end = mod->lastNodeOfStmt(); while (mod != end && mod->lineNumber() > 0) { if (mod->variant() == CONTAINS_STMT) break; if (mod->variant() == USE_STMT) { auto itF = modulesByName.find(mod->symbol()->identifier()); if (itF == modulesByName.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); const set recPrivates = getPrivatesFromModule(itF->second, declaredArrays, declaratedArraysSt, modulesByName); for (auto it = recPrivates.begin(); it != recPrivates.end(); ++it) privates.insert(*it); } else { tryToFindPrivateInAttributes(mod, privates); fillNonDistrArraysAsPrivate(mod, declaredArrays, declaratedArraysSt, privates); } mod = mod->lexNext(); } return privates; } extern map> tableOfUniqNamesByArray; static void convertOneLoop(LoopGraph *currLoop, map> &outInfo, const map &toConvert, const set &privateArrays, const map> &commonBlocks, const map, pair> &declaredArrays, const map> &arrayLinksByFuncCalls, map, DIST::Array*> &createdArrays, bool freeArrays = false) { map toAdd; for (auto& conv : toConvert) { SgSymbol *currentArray = OriginalSymbol(conv.first); ArrayInfo *currentInfo = (ArrayInfo*)(&conv.second); DIST::Array *arrayToAdd; SgStatement *decl = declaratedInStmt(currentArray); const char *symbIdent = currentArray->identifier(); if (privateArrays.find(symbIdent) == privateArrays.end() || sharedMemoryParallelization) { const tuple uniqKey = getUniqName(commonBlocks, decl, currentArray); auto itFound = createdArrays.find(uniqKey); if (itFound == createdArrays.end()) { auto itArray = declaredArrays.find(uniqKey); if (itArray == declaredArrays.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); arrayToAdd = itArray->second.first; itFound = createdArrays.insert(itFound, make_pair(uniqKey, arrayToAdd)); } else arrayToAdd = itFound->second; if (!sharedMemoryParallelization && arrayToAdd->IsNotDistribute() == true) continue; set links; getRealArrayRefs(arrayToAdd, arrayToAdd, links, arrayLinksByFuncCalls); int countOflinks = 0; for (auto &linkedArray : links) { if (arrayToAdd == linkedArray) continue; ++countOflinks; auto key = tableOfUniqNamesByArray[linkedArray]; auto value = declaredArrays.find(key)->second; if (value.second == 0 && createdArrays.find(key) == createdArrays.end()) createdArrays.insert(make_pair(key, linkedArray)); } if (freeArrays) if (countOflinks == 0) continue; toAdd[arrayToAdd] = currentInfo; for (int z = 0; z < currentInfo->getDimSize(); ++z) { if (currentInfo->readOps[z].coefficients.size() || currentInfo->writeOps[z].coefficients.size()) { arrayToAdd->SetMappedDim(z); for (auto &realRef : links) realRef->SetMappedDim(z); } } } } outInfo[currLoop] = toAdd; } static map> convertLoopInfo(const map> &loopInfo, const map &sortedLoopGraph, const set &privateArrays, const map> &commonBlocks, const map, pair> &declaredArrays, const map> &arrayLinksByFuncCalls, map, DIST::Array*> &createdArrays) { map> outInfo; for (auto it = loopInfo.begin(); it != loopInfo.end(); ++it) { auto itGraph = sortedLoopGraph.find(it->first->lineNumber()); if (itGraph == sortedLoopGraph.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); convertOneLoop(itGraph->second, outInfo, it->second, privateArrays, commonBlocks, declaredArrays, arrayLinksByFuncCalls, createdArrays); } return outInfo; } inline static void fillPrivatesFromDecl(SgExpression *ex, set &delcsSymbViewed, set &delcsStatViewed, const map, pair> &declaredArrays, const map>> &declaratedArraysSt, set &privatesVars) { if (!ex) return; if (isArrayRef(ex)) { SgSymbol *symb = ex->symbol(); if (symb->type()) { if (symb->type()->variant() == T_ARRAY) { SgSymbol *s = ex->symbol(); auto it = delcsSymbViewed.find(s); if (it == delcsSymbViewed.end()) { delcsSymbViewed.insert(it, s); SgStatement *decl = declaratedInStmt(s); auto itD = delcsStatViewed.find(decl); if (itD == delcsStatViewed.end()) { delcsStatViewed.insert(itD, decl); tryToFindPrivateInAttributes(decl, privatesVars); fillNonDistrArraysAsPrivate(decl, declaredArrays, declaratedArraysSt, privatesVars); } } } } } fillPrivatesFromDecl(ex->rhs(), delcsSymbViewed, delcsStatViewed, declaredArrays, declaratedArraysSt, privatesVars); fillPrivatesFromDecl(ex->lhs(), delcsSymbViewed, delcsStatViewed, declaredArrays, declaratedArraysSt, privatesVars); } static void changeLoopWeight(double ¤tWeight, const map &sortedLoopGraph, const int line, bool increase = true) { auto loopIt = sortedLoopGraph.find(line); if (loopIt == sortedLoopGraph.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (increase) currentWeight *= loopIt->second->countOfIters; else currentWeight /= loopIt->second->countOfIters; } static bool hasNonPureFunctions(SgExpression *ex, LoopGraph *loopRef, vector &messagesForFile, const int line, const map &funcByName) { bool retVal = false; if (ex == NULL) return retVal; if (ex->variant() == FUNC_CALL) { if (isIntrinsicFunctionName(ex->symbol()->identifier()) == 0) { auto itF = funcByName.find(ex->symbol()->identifier()); bool isPure = false; if (itF != funcByName.end()) isPure = itF->second->isPure; if (!isPure) { retVal = true; loopRef->hasNonPureProcedures = true; messagesForFile.push_back(Messages(WARR, line, R79, L"Only pure procedures were supported", 1044)); } } } bool retL = false, retR = false; if (ex->lhs()) retL = hasNonPureFunctions(ex->lhs(), loopRef, messagesForFile, line, funcByName); if (ex->rhs()) retR = hasNonPureFunctions(ex->rhs(), loopRef, messagesForFile, line, funcByName); return retVal || retL || retR; } void fillFromModule(SgSymbol* s, const map>& privatesByModule, set& privates) { if (s) { auto it = privatesByModule.find(s->identifier()); if (it != privatesByModule.end()) privates.insert(it->second.begin(), it->second.end()); } } static SgStatement* takeOutConditions(stack& conditions, stack& ifBlocks, SgStatement* st) { auto res = createIfConditions(conditions, ifBlocks, st); auto before = st->lexPrev(); for (auto& elem : res) if (elem) st->insertStmtBefore(*elem, *st->controlParent()); SgLabel* lab = st->label(); if (lab) // move lab to first condition { st->deleteLabel(true); if (res.size() == 0) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); res[0]->setLabel(*lab); } return before; } extern void createMapLoopGraph(map &sortedLoopGraph, const vector *loopGraph); void loopAnalyzer(SgFile *file, vector ®ions, map, DIST::Array*> &createdArrays, vector &messagesForFile, REGIME regime, const map> &AllfuncInfo, const map, pair> &declaredArrays, const map>> &declaratedArraysSt, const map> &arrayLinksByFuncCalls, const map> &defUseByPlace, bool skipDeps, vector *loopGraph) { currMessages = &messagesForFile; currRegime = regime; map> commonBlocks; map sortedLoopGraph; map, set>>> allLoops; createMapLoopGraph(sortedLoopGraph, loopGraph); int funcNum = file->numberOfFunctions(); __spf_print(PRINT_PROF_INFO,"functions num in file = %d\n", funcNum); vector modules; findModulesInFile(file, modules); map modulesByName; for (int i = 0; i < modules.size(); ++i) modulesByName[modules[i]->symbol()->identifier()] = modules[i]; map> privatesByModule; if(!sharedMemoryParallelization) for (int i = 0; i < modules.size(); ++i) privatesByModule[modules[i]->symbol()->identifier()] = getPrivatesFromModule(modules[i], declaredArrays, declaratedArraysSt, modulesByName); map funcByName; createMapOfFunc(AllfuncInfo, funcByName); const vector &funcInfo = AllfuncInfo.find(file->filename())->second; for (int i = 0; i < funcNum; ++i) { createNeededException(); string fName = file->functions(i)->symbol()->identifier(); #if _WIN32 if (file->functions(i)->variant() != MODULE_STMT) sendMessage_2lvl(wstring(L"обработка функции '") + wstring(fName.begin(), fName.end()) + L"'"); else sendMessage_2lvl(wstring(L"обработка модуля '") + wstring(fName.begin(), fName.end()) + L"'"); #else if (file->functions(i)->variant() != MODULE_STMT) sendMessage_2lvl(wstring(L"processing function '") + wstring(fName.begin(), fName.end()) + L"'"); else sendMessage_2lvl(wstring(L"processing module '") + wstring(fName.begin(), fName.end()) + L"'"); #endif set delcsSymbViewed; set delcsStatViewed; if (funcInfo[i]->doNotAnalyze) continue; map> loopInfo; set loopWithOutArrays; set privatesVars; SgStatement *st = file->functions(i); string funcName = ""; if (st->variant() == PROG_HEDR) { SgProgHedrStmt *progH = (SgProgHedrStmt*)st; __spf_print(PRINT_PROF_INFO, "*** Program <%s> started at line %d / %s\n", progH->symbol()->identifier(), st->lineNumber(), st->fileName()); funcName = progH->symbol()->identifier(); } else if (st->variant() == PROC_HEDR) { SgProcHedrStmt *procH = (SgProcHedrStmt*)st; __spf_print(PRINT_PROF_INFO, "*** Function <%s> started at line %d / %s\n", procH->symbol()->identifier(), st->lineNumber(), st->fileName()); funcName = procH->symbol()->identifier(); } else if (st->variant() == FUNC_HEDR) { SgFuncHedrStmt *funcH = (SgFuncHedrStmt*)st; __spf_print(PRINT_PROF_INFO, "*** Function <%s> started at line %d / %s\n", funcH->symbol()->identifier(), st->lineNumber(), st->fileName()); funcName = funcH->symbol()->identifier(); } vector loopsForFunction; for (auto& loop : *loopGraph) { auto fStat = getFuncStat(loop->loop->GetOriginal()); if (fStat->symbol()->identifier() == funcName) loopsForFunction.push_back(loop); } if(!sharedMemoryParallelization) { SgStatement* tmpModFind = st; while (tmpModFind->variant() != GLOBAL) { tmpModFind = tmpModFind->controlParent(); if (tmpModFind->variant() == MODULE_STMT) fillFromModule(tmpModFind->symbol(), privatesByModule, privatesVars); } } commonBlocks.clear(); getCommonBlocksRef(commonBlocks, st, st->lastNodeOfStmt()); __spf_print(PRINT_PROF_INFO, " number of common blocks %d\n", (int)commonBlocks.size()); SgStatement *lastNode = st->lastNodeOfStmt(); vector parentLoops; vector> privatesVarsForLoop; //For remote access pair *under_dvm_dir = NULL; map> notMappedDistributedArrays; set mappedDistrbutedArrays; double currentWeight = 1.0; while (st != lastNode) { createNeededException(); if (st == NULL) { currMessages->push_back(Messages(ERROR, 1, R128, L"internal error in analysis, parallel directives will not be generated for this file!", 3008)); __spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n"); break; } if (st->variant() == CONTAINS_STMT) break; if (!__gcov_doesThisLineExecuted(st->fileName(), st->lineNumber())) { st = st->lexNext(); continue; } const int currentLine = st->lineNumber() < -1 ? st->localLineNumber() : st->lineNumber(); ParallelRegion *currReg = getRegionByLine(regions, st->fileName(), currentLine); if (currReg == NULL) { st = st->lexNext(); continue; } if (isSgExecutableStatement(st) == NULL) delcsStatViewed.insert(st); else if (!sharedMemoryParallelization && !isDVM_stat(st) && !isSPF_stat(st)) for (int i = 0; i < 3; ++i) fillPrivatesFromDecl(st->expr(i), delcsSymbViewed, delcsStatViewed, declaredArrays, declaratedArraysSt, privatesVars); //printf("new st with var = %d, on line %d\n", st->variant(), st->lineNumber()); const int currV = st->variant(); if (currV == FOR_NODE) { if(!sharedMemoryParallelization) { tryToFindPrivateInAttributes(st, privatesVars); fillNonDistrArraysAsPrivate(st, declaredArrays, declaratedArraysSt, privatesVars); } set toAdd; tryToFindPrivateInAttributes(st, toAdd); if (PRINT_LOOP_STRUCT) printBlanks(2, (int)parentLoops.size()); __spf_print(PRINT_LOOP_STRUCT, "FOR NODE on line %d\n", st->lineNumber()); parentLoops.push_back((SgForStmt*)st); changeLoopWeight(currentWeight, sortedLoopGraph, st->lineNumber()); privatesVarsForLoop.push_back(toAdd); if (regime == REMOTE_ACC) { SgStatement *prev = st->lexPrev(); if (prev) { if (prev->variant() == DVM_PARALLEL_ON_DIR) { auto it = sortedLoopGraph.find(st->lineNumber()); if (it == sortedLoopGraph.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); under_dvm_dir = new pair((SgForStmt*)st, it->second); } } } } else if (currV == CONTROL_END) { SgStatement *contrlParent = st->controlParent(); if (contrlParent) { if (contrlParent->variant() == FOR_NODE) { changeLoopWeight(currentWeight, sortedLoopGraph, contrlParent->lineNumber(), false); if (loopInfo.find((SgForStmt*)contrlParent) == loopInfo.end() && !sortedLoopGraph[contrlParent->lineNumber()]->hasUnknownDistributedMap) loopWithOutArrays.insert(contrlParent->lineNumber()); set unitedPrivates; for (int p = 0; p < parentLoops.size(); ++p) for (auto &privVar : privatesVarsForLoop[p]) unitedPrivates.insert(privVar); set setDiff; if(!sharedMemoryParallelization) for (auto &privVars : privatesVars) if (unitedPrivates.find(privVars) == unitedPrivates.end()) setDiff.insert(privVars); allLoops[contrlParent->lineNumber()] = make_pair((SgForStmt*)contrlParent, make_pair(unitedPrivates, setDiff)); parentLoops.pop_back(); privatesVarsForLoop.pop_back(); if (regime == REMOTE_ACC) { if (under_dvm_dir) { if (contrlParent == under_dvm_dir->first && under_dvm_dir->second->userDvmDirective == NULL) { ParallelRegion *currReg = getRegionByLine(regions, under_dvm_dir->first->fileName(), under_dvm_dir->first->lineNumber()); if (currReg) { const DIST::Arrays &allArrays = currReg->GetAllArrays(); DIST::GraphCSR &reducedG = currReg->GetReducedGraphToModify(); const DataDirective &data = currReg->GetDataDir(); const vector &currVar = currReg->GetCurrentVariant(); const pair currDir = make_pair(under_dvm_dir->second, under_dvm_dir->second->directive); auto convertedLoopInfo = convertLoopInfo(loopInfo, sortedLoopGraph, privatesVars, commonBlocks, declaredArrays, arrayLinksByFuncCalls, createdArrays); auto uniqRemotes = createRemoteInParallel(currDir, allArrays, convertedLoopInfo, reducedG, data, currVar, messagesForFile, currReg->GetId(), arrayLinksByFuncCalls, funcByName); addRemotesToDir(under_dvm_dir, uniqRemotes); } delete under_dvm_dir; under_dvm_dir = NULL; } } } } } else printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } else if (currV == ASSIGN_STAT) { if (st->expr(0)) findArrayRef(parentLoops, st->expr(0), st->lineNumber(), LEFT, loopInfo, privatesVars, privatesVarsForLoop, sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays, mappedDistrbutedArrays, st, currReg, currentWeight, arrayLinksByFuncCalls); if (st->expr(1)) findArrayRef(parentLoops, st->expr(1), st->lineNumber(), RIGHT, loopInfo, privatesVars, privatesVarsForLoop, sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays, mappedDistrbutedArrays, st, currReg, currentWeight, arrayLinksByFuncCalls); if (regime == REMOTE_ACC) { if (st->expr(1)) { bool cond = true; if (st->expr(1)->variant() == FUNC_CALL) { string fName = ((SgFunctionCallExp*)st->expr(1))->funName()->identifier(); cond = (fName != "allocated"); } // detect copy operator: A(:, :, :) = B(:, :, :) if (st->expr(1)->variant() == ARRAY_REF && st->expr(0)->variant() == ARRAY_REF) { set ddots; vector dummy; fillVars(st->expr(0), { DDOT }, ddots, dummy); fillVars(st->expr(1), { DDOT }, ddots, dummy); if (ddots.size() != 0) cond = false; } // detect copy operator: A = B if (st->expr(1)->variant() == ARRAY_REF && st->expr(0)->variant() == ARRAY_REF) { SgExpression *left = st->expr(0); SgExpression *right = st->expr(1); if (left->lhs() == NULL && left->rhs() == NULL && right->lhs() == NULL && right->rhs() == NULL) cond = false; } // detect operator: A[(:,:,:)] = F(X[(:,:,:)], Y[(:,:,:)], Z[(:,:,:)], ...) //TODO: check right part if (st->expr(0)->variant() == ARRAY_REF) { SgExpression *left = st->expr(0); set ddots; vector dummy; fillVars(st->expr(0), { DDOT }, ddots, dummy); if ((left->lhs() == NULL && left->rhs() == NULL ) || ddots.size() != 0) cond = false; } if (cond) { const DIST::Arrays &allArrays = currReg->GetAllArrays(); if (under_dvm_dir == NULL) createRemoteDir<1>(st, funcByName, sortedLoopGraph, allArrays, currReg->GetDataDir(), currReg->GetCurrentVariant(), currReg->GetId(), *currMessages, arrayLinksByFuncCalls); } } if (st->expr(0)) { const DIST::Arrays& allArrays = currReg->GetAllArrays(); if (under_dvm_dir == NULL) createRemoteDir<0>(st, funcByName, sortedLoopGraph, allArrays, currReg->GetDataDir(), currReg->GetCurrentVariant(), currReg->GetId(), *currMessages, arrayLinksByFuncCalls); } } } else if (currV == IF_NODE || currV == ELSEIF_NODE || currV == LOGIF_NODE || currV == SWITCH_NODE) { SgStatement* before = NULL; // convert IF conditions if access to dist array appears if (regime == REMOTE_ACC && under_dvm_dir == NULL) { stack conditions; stack ifBlocks; bool needToConv = false; bool prevWithSameLine = (st->lexPrev()->lineNumber() == st->lineNumber()); if (currV == IF_NODE) { needToConv = isNeedToConvertIfCondition(st->expr(0)); conditions.push(st->expr(0)); ifBlocks.push(st); SgIfStmt* ifS = (SgIfStmt*)st; auto body = ifS->falseBody(); while (body) { if (body->variant() == ELSEIF_NODE) { needToConv = needToConv || isNeedToConvertIfCondition(body->expr(0)->copyPtr()); conditions.push(body->expr(0)); ifBlocks.push(body); } else break; body = body->lastNodeOfStmt(); } needToConv = needToConv && !prevWithSameLine; } else if (currV == LOGIF_NODE) { needToConv = isNeedToConvertIfCondition(st->expr(0)) && !prevWithSameLine; conditions.push(st->expr(0)); ifBlocks.push(st); } else if (currV == SWITCH_NODE) { needToConv = isNeedToConvertIfCondition(st->expr(0)) && !prevWithSameLine; conditions.push(st->expr(0)); ifBlocks.push(st); } if (needToConv && !conditions.empty()) st = before = takeOutConditions(conditions, ifBlocks, st); } if (st->expr(0)) { findArrayRef(parentLoops, st->expr(0), st->lineNumber(), RIGHT, loopInfo, privatesVars, privatesVarsForLoop, sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays, mappedDistrbutedArrays, st, currReg, currentWeight, arrayLinksByFuncCalls); if (regime == REMOTE_ACC) if (under_dvm_dir == NULL) createRemoteDir<0>(st, funcByName, sortedLoopGraph, currReg->GetAllArrays(), currReg->GetDataDir(), currReg->GetCurrentVariant(), currReg->GetId(), *currMessages, arrayLinksByFuncCalls); } if (regime == REMOTE_ACC && before) st = before; } else if (currV == PROC_STAT) { auto func = isUserFunctionInProject(st->symbol()->identifier()); if (func != NULL) { SgExpression *parList = st->expr(0); set toRedistr; if (parList) { SgExprListExp *list = isSgExprListExp(parList); for (int z = 0; z < list->length(); ++z) { SgExpression *par = list->elem(z); if ((func->funcParams.inout_types[z] & OUT_BIT) != 0) findArrayRef(parentLoops, par, st->lineNumber(), LEFT, loopInfo, privatesVars, privatesVarsForLoop, sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays, mappedDistrbutedArrays, st, currReg, currentWeight, arrayLinksByFuncCalls); else findArrayRef(parentLoops, par, st->lineNumber(), RIGHT, loopInfo, privatesVars, privatesVarsForLoop, sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays, mappedDistrbutedArrays, st, currReg, currentWeight, arrayLinksByFuncCalls); if (regime == REMOTE_ACC) { if (isArrayRef(par) && isPassFullArray(par)) { SgSymbol *s = OriginalSymbol(par->symbol()); DIST::Array *inPar = getArrayFromDeclarated(declaratedInStmt(s), s->identifier()); if (inPar && !inPar->IsNotDistribute()) { if (func->funcParams.parametersT[z] != ARRAY_T) toRedistr.insert(inPar->GetTemplateArray(currReg->GetId())); else { if (inPar->GetDimSize() != ((DIST::Array*)func->funcParams.parameters[z])->GetDimSize()) toRedistr.insert(inPar->GetTemplateArray(currReg->GetId())); } } } } } if (regime == REMOTE_ACC && list->length()) if (under_dvm_dir == NULL) createRemoteDir<0>(st, funcByName, sortedLoopGraph, currReg->GetAllArrays(), currReg->GetDataDir(), currReg->GetCurrentVariant(), currReg->GetId(), *currMessages, arrayLinksByFuncCalls); } if (regime == REMOTE_ACC) { const DataDirective &dataDirectives = currReg->GetDataDir(); const vector ¤tVariant = currReg->GetCurrentVariant(); auto &tmp = dataDirectives.distrRules; std::vector> currentVar; for (int z1 = 0; z1 < currentVariant.size(); ++z1) currentVar.push_back(make_pair(tmp[z1].first, &tmp[z1].second[currentVariant[z1]])); for (auto &toRed : toRedistr) { auto cp = st->controlParent(); auto redist = new SgStatement(DVM_REDISTRIBUTE_DIR); auto newRule = new SgExprListExp(); newRule->setLhs(*new SgExpression(KEYWORD_VAL, "*")); for (int z = 1; z < toRed->GetDimSize(); ++z) newRule->append(*new SgExpression(KEYWORD_VAL, "*")); auto templS = new SgSymbol(VARIABLE_NAME, toRed->GetShortName().c_str()); redist->setExpression(0, *new SgVarRefExp(*templS)); redist->setExpression(1, *newRule); st->insertStmtBefore(*redist, *cp); redist = new SgStatement(DVM_REDISTRIBUTE_DIR); newRule = new SgExprListExp(); const DistrVariant *varD = NULL; for (auto &elem : currentVar) { if (elem.first == toRed) { varD = elem.second; break; } } if (!varD) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (int z = 0; z < toRed->GetDimSize(); ++z) { char *type = "*"; if (varD->distRule[z] == distType::BLOCK) type = "BLOCK"; if (z == 0) newRule->setLhs(*new SgExpression(KEYWORD_VAL, type)); else newRule->append(*new SgExpression(KEYWORD_VAL, type)); } redist->setExpression(0, *new SgVarRefExp(*templS)); redist->setExpression(1, *newRule); st->insertStmtAfter(*redist, *cp); } } } } else if (currV == USE_STMT) { if (st->lineNumber() > 0 && !sharedMemoryParallelization) { auto itF = privatesByModule.find(st->symbol()->identifier()); if (itF == privatesByModule.end()) { wstring messageE, messageR; __spf_printToLongBuf(messageE, L"Module with name '%s' must be placed in current file", to_wstring(st->symbol()->identifier()).c_str()); __spf_printToLongBuf(messageR, R62, to_wstring(st->symbol()->identifier()).c_str()); currMessages->push_back(Messages(ERROR, st->lineNumber(), messageR, messageE, 1028)); __spf_print(1, "Module at line %d with name '%s' must be placed in current file\n", st->lineNumber(), st->symbol()->identifier()); printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } for (auto it = itF->second.begin(); it != itF->second.end(); ++it) privatesVars.insert(*it); } } else { if(!sharedMemoryParallelization) { tryToFindPrivateInAttributes(st, privatesVars); fillNonDistrArraysAsPrivate(st, declaredArrays, declaratedArraysSt, privatesVars); } if (isDVM_stat(st) == false && isSgExecutableStatement(st)) { if (regime == REMOTE_ACC) { if (st->expr(0) && (currV == SWITCH_NODE || currV == FORALL_STAT || currV == WHILE_NODE || currV == WHERE_NODE || currV == ALLDO_NODE || currV == ARITHIF_NODE || currV == ASSGOTO_NODE || currV == COMGOTO_NODE)) { const DIST::Arrays &allArrays = currReg->GetAllArrays(); if (under_dvm_dir == NULL) createRemoteDir<0>(st, funcByName, sortedLoopGraph, allArrays, currReg->GetDataDir(), currReg->GetCurrentVariant(), currReg->GetId(), *currMessages, arrayLinksByFuncCalls); } } else { int const var = st->variant(); int side = (var == READ_STAT || var == WRITE_STAT || var == PRINT_STAT) ? LEFT : RIGHT; for (int z = 0; z < 3; ++z) if (st->expr(z)) findArrayRef(parentLoops, st->expr(z), st->lineNumber(), side, loopInfo, privatesVars, privatesVarsForLoop, sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays, mappedDistrbutedArrays, st, currReg, currentWeight, arrayLinksByFuncCalls); } } } st = st->lexNext(); } auto convertedLoopInfo = convertLoopInfo(loopInfo, sortedLoopGraph, privatesVars, commonBlocks, declaredArrays, arrayLinksByFuncCalls, createdArrays); if (regime == DATA_DISTR || regime == SHARED_MEMORY_PAR) { processLoopInformationForFunction(convertedLoopInfo); //find dependencies for loops in function initAnnotationsSysExt(0); set funcWasInit; map collection; int idx = 0; for (auto &loop : convertedLoopInfo) { ++idx; createNeededException(); if (!skipDeps) { string fName = file->functions(i)->symbol()->identifier(); #ifdef _WIN32 sendMessage_2lvl(wstring(L"обработка цикла ") + std::to_wstring(idx) + L"/" + std::to_wstring(convertedLoopInfo.size())); #else sendMessage_2lvl(wstring(L"processing loop ") + std::to_wstring(idx) + L"/" + std::to_wstring(convertedLoopInfo.size())); #endif tryToFindDependencies(loop.first, allLoops, funcWasInit, file, regions, currMessages, collection, funcByName, defUseByPlace); } } vector tmpLoops; map tmpToConvert; if (file->functions(i)->variant() != PROG_HEDR) { for (auto ¬Mapped : notMappedDistributedArrays) { if (mappedDistrbutedArrays.find(notMapped.first) == mappedDistrbutedArrays.end()) { auto reg = getRegionByLine(regions, notMapped.second.second->fileName(), notMapped.second.second->lineNumber()); if (reg) { LoopGraph *tmpLoop = new LoopGraph(); tmpLoop->region = reg; tmpLoop->isFor = true; tmpLoops.push_back(tmpLoop); ArrayInfo toAdd; SgSymbol *arrayS = notMapped.second.first; toAdd.setDimSize(((SgArrayType*)arrayS->type())->dimension()); for (int z = 0; z < toAdd.getDimSize(); ++z) toAdd.readOps[z] = ArrayOp(make_pair(make_pair(1, 0), 1.0)); tmpToConvert[arrayS] = toAdd; convertOneLoop(tmpLoop, convertedLoopInfo, tmpToConvert, privatesVars, commonBlocks, declaredArrays, arrayLinksByFuncCalls, createdArrays, true); } } } } if(!sharedMemoryParallelization) addToDistributionGraph(convertedLoopInfo, arrayLinksByFuncCalls); for (auto &toDel : tmpLoops) { convertedLoopInfo.erase(toDel); delete toDel; } tmpToConvert.clear(); if (!skipDeps) { for (auto &loopLine : loopWithOutArrays) { if (loopLine > 0) { tryToFindDependencies(sortedLoopGraph[loopLine], allLoops, funcWasInit, file, regions, currMessages, collection, funcByName, defUseByPlace); sortedLoopGraph[loopLine]->withoutDistributedArrays = true; } } // TODO: add messages! for (auto &loopLine : loopWithOutArrays) { if (sortedLoopGraph[loopLine]->withoutDistributedArrays && loopLine > 0) { //TODO: enable linear writes to non distr arrays for CONSISTENT bool hasWritesToArray = false; //TODO: add IPA for non pure bool hasNonPureProcedures = false; auto loopRef = sortedLoopGraph[loopLine]; SgStatement *loopSt = loopRef->loop; map> reductions; map>> reductionsLoc; set privatesS; for (auto &data : getAttributes(loopSt, set{ SPF_ANALYSIS_DIR, SPF_PARALLEL_DIR })) { Statement *dataSt = new Statement(data); fillReductionsFromComment(dataSt, reductions); fillReductionsFromComment(dataSt, reductionsLoc); fillPrivatesFromComment(dataSt, privatesS); } for (auto &red : reductions) privatesS.insert(red.second.begin(), red.second.end()); for (auto &red : reductionsLoc) { for (auto &elem : red.second) { privatesS.insert(get<0>(elem)); privatesS.insert(get<1>(elem)); } } set privates; for (auto& elem : privatesS) privates.insert(elem->GetOriginal()->identifier()); for (SgStatement *start = loopSt->lexNext(); start != loopSt->lastNodeOfStmt(); start = start->lexNext()) { //TODO: detect write in proc calls if (start->variant() == ASSIGN_STAT) { if (start->expr(0)->variant() == ARRAY_REF || start->expr(0)->variant() == ARRAY_OP) { SgSymbol* s = NULL; if (start->expr(0)->variant() == ARRAY_REF) s = start->expr(0)->symbol(); else if (start->expr(0)->variant() == ARRAY_OP) s = start->expr(0)->lhs()->symbol(); if (s && privates.find(s->identifier()) == privates.end()) if (sharedMemoryParallelization == 0) hasWritesToArray = true; } } if (start->variant() == PROC_STAT && isIntrinsicFunctionName(start->symbol()->identifier()) == 0) { checkNull(isSgCallStmt(start), convertFileName(__FILE__).c_str(), __LINE__); auto itF = funcByName.find(isSgCallStmt(start)->name()->identifier()); bool isPure = false; if (itF != funcByName.end()) isPure = itF->second->isPure; if (!isPure) { hasNonPureProcedures = true; loopRef->hasNonPureProcedures = true; messagesForFile.push_back(Messages(WARR, start->lineNumber(), R80, L"Only pure procedures were supported", 1044)); } } for (int z = 1; z < 3; ++z) if (hasNonPureFunctions(start->expr(z), loopRef, messagesForFile, start->lineNumber(), funcByName)) hasNonPureProcedures = true; } if (hasWritesToArray || hasNonPureProcedures) loopRef->withoutDistributedArrays = false; } } if (parallizeFreeLoops) selectFreeLoopsForParallelization(loopsForFunction, funcName, (regime == DATA_DISTR), regions, messagesForFile); } sendMessage_2lvl(L""); } else if (regime == COMP_DISTR) { createParallelDirectives(convertedLoopInfo, regions, arrayLinksByFuncCalls, messagesForFile); if (parallizeFreeLoops) selectFreeLoopsForParallelization(loopsForFunction, funcName, (regime == DATA_DISTR), regions, messagesForFile); } if(regime == SHARED_MEMORY_PAR) createParallelDirectives(convertedLoopInfo, regions, arrayLinksByFuncCalls, messagesForFile); __spf_print(PRINT_PROF_INFO, "Function ended\n"); } } void arrayAccessAnalyzer(SgFile *file, vector &messagesForFile, const map, pair> &declaredArrays, REGIME regime) { currMessages = &messagesForFile; currRegime = regime; map> commonBlocks; map sortedLoopGraph; map, set>>> allLoops; map> notMappedDistributedArrays; set mappedDistrbutedArrays; int funcNum = file->numberOfFunctions(); __spf_print(PRINT_PROF_INFO, "functions num in file = %d\n", funcNum); const map> arrayLinksByFuncCalls; for (int i = 0; i < funcNum; ++i) { map> loopInfo; set privatesVars; vector> privatesVarsForLoop; SgStatement *st = file->functions(i); string funcName = ""; if (st->variant() == PROG_HEDR) { SgProgHedrStmt *progH = (SgProgHedrStmt*)st; __spf_print(PRINT_PROF_INFO, "*** Program <%s> started at line %d / %s\n", progH->symbol()->identifier(), st->lineNumber(), st->fileName()); funcName = progH->symbol()->identifier(); } else if (st->variant() == PROC_HEDR) { SgProcHedrStmt *procH = (SgProcHedrStmt*)st; __spf_print(PRINT_PROF_INFO, "*** Function <%s> started at line %d / %s\n", procH->symbol()->identifier(), st->lineNumber(), st->fileName()); funcName = procH->symbol()->identifier(); } else if (st->variant() == FUNC_HEDR) { SgFuncHedrStmt *funcH = (SgFuncHedrStmt*)st; __spf_print(PRINT_PROF_INFO, "*** Function <%s> started at line %d / %s\n", funcH->symbol()->identifier(), st->lineNumber(), st->fileName()); funcName = funcH->symbol()->identifier(); } commonBlocks.clear(); getCommonBlocksRef(commonBlocks, st, st->lastNodeOfStmt()); __spf_print(PRINT_PROF_INFO, " number of common blocks %d\n", (int)commonBlocks.size()); SgStatement *lastNode = st->lastNodeOfStmt(); vector parentLoops; double currentWeight = 1.0; while (st != lastNode) { createNeededException(); if (st == NULL) { currMessages->push_back(Messages(ERROR, 1, R128, L"internal error in analysis, parallel directives will not be generated for this file!", 3008)); __spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n"); break; } if (st->variant() == CONTAINS_STMT) break; const int currV = st->variant(); if (currV == FOR_NODE) { if (PRINT_LOOP_STRUCT) printBlanks(2, (int)parentLoops.size()); __spf_print(PRINT_LOOP_STRUCT, "FOR NODE on line %d\n", st->lineNumber()); parentLoops.push_back((SgForStmt*)st); sortedLoopGraph[st->lineNumber()] = new LoopGraph(); privatesVarsForLoop.push_back(set()); } else if (currV == CONTROL_END) { SgStatement *contrlParent = st->controlParent(); if (contrlParent) { if (contrlParent->variant() == FOR_NODE) { parentLoops.pop_back(); delete sortedLoopGraph[contrlParent->lineNumber()]; sortedLoopGraph.erase(contrlParent->lineNumber()); privatesVarsForLoop.pop_back(); } } else printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } else if (currV == ASSIGN_STAT) { if (st->expr(0)) findArrayRef(parentLoops, st->expr(0), st->lineNumber(), LEFT, loopInfo, privatesVars, privatesVarsForLoop, sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays, mappedDistrbutedArrays, st, NULL, currentWeight, arrayLinksByFuncCalls); if (st->expr(1)) findArrayRef(parentLoops, st->expr(1), st->lineNumber(), RIGHT, loopInfo, privatesVars, privatesVarsForLoop, sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays, mappedDistrbutedArrays, st, NULL, currentWeight, arrayLinksByFuncCalls); } else if (currV == IF_NODE || currV == ELSEIF_NODE || currV == LOGIF_NODE || currV == SWITCH_NODE) { if (st->expr(0)) findArrayRef(parentLoops, st->expr(0), st->lineNumber(), RIGHT, loopInfo, privatesVars, privatesVarsForLoop, sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays, mappedDistrbutedArrays, st, NULL, currentWeight, arrayLinksByFuncCalls); } else if (currV == PROC_STAT) { if (st->expr(0)) { if (isIntrinsicFunctionName(st->symbol()->identifier())) findArrayRef(parentLoops, st->expr(0), st->lineNumber(), RIGHT, loopInfo, privatesVars, privatesVarsForLoop, sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays, mappedDistrbutedArrays, st, NULL, currentWeight, arrayLinksByFuncCalls); else { SgExpression *listEx = st->expr(0); while (listEx) { findArrayRef(parentLoops, listEx->lhs(), st->lineNumber(), LEFT, loopInfo, privatesVars, privatesVarsForLoop, sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays, mappedDistrbutedArrays, st, NULL, currentWeight, arrayLinksByFuncCalls); listEx = listEx->rhs(); } } } } st = st->lexNext(); } __spf_print(PRINT_PROF_INFO, "Function ended\n"); } } //TODO: copy all functions from FDVM and fix them static inline int getStructureSize(SgSymbol *s) { return 0; //printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } static inline int getNumericTypeLength(SgType *t) { SgExpression *le; SgValueExp *ve; if (t->variant() == T_STRING) return (0); if (TYPE_RANGES(t->thetype)) { le = t->length(); if (ve = isSgValueExp(le)) return ve->intValue(); else return 0; } if (TYPE_KIND_LEN(t->thetype)) { le = t->selector()->lhs(); if (ve = isSgValueExp(le)) if (t->variant() == T_COMPLEX || t->variant() == T_DCOMPLEX) return 2 * ve->intValue(); else return ve->intValue(); else return 0; } return 0; } static inline int getIntrinsicTypeSize(SgType *t) { const int default_real_size = 4; const int default_integer_size = 4; switch (t->variant()) { case T_INT: case T_BOOL: return default_integer_size; case T_FLOAT: return default_real_size; case T_COMPLEX: return 2 * default_real_size; case T_DOUBLE: return 2 * default_real_size; case T_DCOMPLEX: return 4 * default_real_size; case T_STRING: case T_CHAR: return 1; default: return 0; } } static SgExpression* getLengthOfKindExpr(SgType *t, SgExpression *se, SgExpression *le) { switch (t->variant()) { case T_INT: case T_FLOAT: case T_BOOL: case T_DOUBLE: return se->lhs(); case T_COMPLEX: case T_DCOMPLEX: return &(*new SgValueExp(2) * (*(se->lhs()))); case T_CHAR: case T_STRING: { SgExpression *length, *kind; if (se->rhs() && se->rhs()->variant() == LENGTH_OP) { length = se->rhs()->lhs(); kind = se->lhs()->lhs(); } else if (se->rhs() && se->rhs()->variant() != LENGTH_OP) { length = se->lhs()->lhs(); kind = se->rhs()->lhs(); } else { length = se->lhs(); kind = NULL; } length = le ? le : length; if (kind) return &(*length * (*kind)); else return length; } default: return(NULL); } } SgExpression* getTypeLengthExpr(SgType *t) { SgExpression *len; SgExpression *selector; if (t->variant() == T_DERIVED_TYPE) return new SgValueExp(getStructureSize(t->symbol())); len = TYPE_RANGES(t->thetype) ? t->length() : NULL; selector = TYPE_KIND_LEN(t->thetype) ? t->selector() : NULL; if (!len && !selector) //the number of bytes is not specified in type declaration statement return (new SgValueExp(getIntrinsicTypeSize(t))); else if (len && !selector) //INTEGER*2,REAL*8,CHARACTER*(N+1) return CalculateInteger(len->copyPtr()); else return CalculateInteger(getLengthOfKindExpr(t, selector, len)->copyPtr()); //specified kind or/and len } int getSizeOfType(SgType *t) { int len = -1; if (IS_INTRINSIC_TYPE(t)) return getIntrinsicTypeSize(t); if (t->variant() == T_DERIVED_TYPE) return getStructureSize(t->symbol()); if (len = getNumericTypeLength(t)) return len; SgExpression *le = getTypeLengthExpr(t); if (le->isInteger()) { len = le->valueInteger(); len = len < 0 ? 0 : len; //according to standard F90 } else len = -1; //may be error situation return len; } void insertSpfAnalysisBeforeParalleLoops(const vector &loops) { for (auto &loop : loops) { SgStatement *spfStat = new SgStatement(SPF_ANALYSIS_DIR); spfStat->setlineNumber(loop->lineNum); spfStat->setLocalLineNumber(0); spfStat->setFileName((char*)current_file->filename()); if (!loop->hasLimitsToParallel()) { loop->loop->addAttribute(SPF_ANALYSIS_DIR, spfStat, sizeof(SgStatement)); //uncomment it to debug private analysis //loop->loop->insertStmtBefore(*spfStat, *loop->loop->controlParent()); } insertSpfAnalysisBeforeParalleLoops(loop->children); } } #undef PRINT_ARRAY_ARCS #undef PRINT_LOOP_STRUCT #undef PRINT_PROF_INFO #undef FIRST #undef SECOND #undef THIRD