#include "../Utils/leak_detector.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dvm.h" #include "loop_analyzer.h" #include "../Utils/utils.h" #include "../Utils/SgUtils.h" #include "../ParallelizationRegions/ParRegions_func.h" #include "../SageAnalysisTool/depGraph.h" #include "../SageAnalysisTool/OmegaForSage/include/lang-interf.h" 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::chrono::high_resolution_clock; using std::chrono::duration_cast; using std::chrono::milliseconds; extern map depInfoForLoopGraph; extern void initializeDepAnalysisForFunction(SgFile *file, SgStatement *func, const map &allFuncs, vector &messagesForFile); extern int staticPrivateAnalysis; extern bool fullDepGraph; static const set *currentNonDistrArrays = NULL; static map varInOut; static map *currentCollection = NULL; bool isRemovableDependence(const depNode *currNode, const set &privVars) { bool result = true; bool varIn = false, varOut = false; switch (currNode->typedep) { case WRONGDEP: result = false; break; case ARRAYDEP: if (currentNonDistrArrays && currentNonDistrArrays->size() > 0) { SgSymbol *vIn = OriginalSymbol(currNode->varin->symbol()); SgSymbol *vOut = OriginalSymbol(currNode->varout->symbol()); auto found = varInOut.find(vIn); if (found == varInOut.end()) found = varInOut.insert(found, make_pair(vIn, vIn->identifier())); varIn = currentNonDistrArrays->find(found->second) != currentNonDistrArrays->end(); found = varInOut.find(vOut); if (found == varInOut.end()) found = varInOut.insert(found, make_pair(vOut, vOut->identifier())); varOut = currentNonDistrArrays->find(found->second) != currentNonDistrArrays->end(); } //dont check if textual identically if ((!isEqExpressions(currNode->varin, currNode->varout, *currentCollection) || varIn || varOut) && (currNode->varin != currNode->varout)) { // TODO: process all loop, not only top loop if (currNode->knowndist[1] == 0 || currNode->distance[1] != 0) { if (currNode->knowndist[1] == 0) result = false; } else if (varIn || varOut) // found dependencies between non ditributed arrays { result = false; } } break; case PRIVATEDEP: case REDUCTIONDEP: break; case SCALARDEP: if (privVars.find(currNode->varin->symbol()->identifier()) == privVars.end()) result = false; break; default: result = false; break; } return result; } static SgStatement* getCurrentFunc(SgStatement *st) { while (st && st->variant() != PROG_HEDR && st->variant() != PROC_HEDR && st->variant() != FUNC_HEDR) st = st->controlParent(); checkNull(st, convertFileName(__FILE__).c_str(), __LINE__); return st; } depGraph *getDependenciesGraph(const LoopGraph *currLoop, SgFile *file, const set *privVars) { SgForStmt *currLoopRef = (SgForStmt*)currLoop->loop->GetOriginal(); auto t = high_resolution_clock::now(); map tmpCollection; currentCollection = &tmpCollection; set tmpPriv; depGraph *depg = new depGraph(file, getCurrentFunc(currLoopRef), currLoopRef, privVars ? *privVars : tmpPriv); float elapsed = duration_cast(high_resolution_clock::now() - t).count() / 1000.; if (elapsed > 1.0f) printf("SAPFOR: time of graph bulding for loop %d = %f sec\n", currLoop->lineNum, elapsed); currentCollection = NULL; return depg; } //TODO: remove? static int isOnlyDef(SgStatement *loopSt, const map> &defUseByPlace, const string &symb) { SgStatement *last = loopSt->lastNodeOfStmt(); bool wasFoundSome = false; int count = 0; for (auto st = loopSt; st != last; st = st->lexNext()) { auto it = defUseByPlace.find(st); if (it != defUseByPlace.end()) { for (auto &elem : it->second) { if (elem.getVar() == symb) { wasFoundSome = true; if (elem.isUse()) return -1; if (elem.isDef()) count++; } } } } if (!wasFoundSome) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return count; } static set fillNestedReduction(LoopGraph* currLoop) { set redVars; tryToFindPrivateInAttributes(currLoop->loop, redVars, true, true); int lastPerfect = currLoop->perfectLoop; currLoop = currLoop->parent; while (currLoop && currLoop->perfectLoop == lastPerfect + 1) { tryToFindPrivateInAttributes(currLoop->loop, redVars, true, true); lastPerfect = currLoop->perfectLoop; currLoop = currLoop->parent; } return redVars; } static SgExpression *startS = NULL, *endS = NULL; static SgExpression *startS_save = NULL, *endS_save = NULL; // try to find dependencies: reductions and privates for scalar // and regular and other for arrrays //TODO: add optimization - dont call omega test for arrays many times void tryToFindDependencies(LoopGraph *currLoop, const map, set>>> &allLoops, set &funcWasInit, SgFile *file, vector regions, vector *currMessages, map &collection, const map &allFuncs, const map> &defUseByPlace) { auto it = allLoops.find(currLoop->lineNum); if (it == allLoops.end()) return; map localAllLoopMap; for (auto &elem : allLoops) localAllLoopMap.insert(make_pair(elem.first, elem.second.first)); ParallelRegion *currReg = getRegionByLine(regions, it->second.first->fileName(), currLoop->lineNum); if (currReg && currLoop->hasLimitsToParallel() == false || fullDepGraph) { SgForStmt *currLoopRef = it->second.first; set redVars = fillNestedReduction(currLoop); bool onlyOneStep = false; // if identical /*string startL = string(currLoopRef->start()->unparse()); string endL = string(currLoopRef->end()->unparse()); if (startL == endL) onlyOneStep = true;*/ // XXX: turn off this "optimization" //make unknown iters count for better analysis bool interChanged = false; if (currLoop->countOfIters == 1) { interChanged = true; if (!startS) startS = new SgExpression(VAR_REF, new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "_tmp1_"))); if (!endS) endS = new SgExpression(VAR_REF, new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "_tmp2_"))); startS_save = currLoopRef->start(); endS_save = currLoopRef->end(); currLoopRef->setStart(*startS); currLoopRef->setEnd(*endS); } const set &privVars = it->second.second.first; const set &nonDistrArrays = it->second.second.second; SgStatement *func = getFuncStat(currLoopRef); if (funcWasInit.find(func) == funcWasInit.end()) { funcWasInit.insert(func); initializeDepAnalysisForFunction(file, func, allFuncs, *currMessages); } currentNonDistrArrays = &nonDistrArrays; currentCollection = &collection; depGraph *depg = getDependenciesGraph(currLoop, file, &privVars); if (interChanged) { currLoopRef->setStart(*startS_save); currLoopRef->setEnd(*endS_save); } currentNonDistrArrays = NULL; currentCollection = NULL; /*auto t = high_resolution_clock::now(); depGraph *depg = new depGraph(file, getCurrentFunc(currLoopRef), currLoopRef, privVars); float elapsed = duration_cast(high_resolution_clock::now() - t).count() / 1000.; if (elapsed > 1.0f) printf("SAPFOR: time of graph bulding for loop %d = %f sec\n", currLoop->lineNum, elapsed);*/ if (depg) { const std::vector &nodes = depg->getNodes(); //vector privatesToAdd; vector reductionsToAdd; vector unknownScalarDep; bool findUnknownDepLen = false; map> acrossToAdd; bool varIn = false, varOut = false; bool isEqual = false; for (int k = 0; k < nodes.size(); ++k) { const depNode *currNode = nodes[k]; switch (currNode->typedep) { case WRONGDEP: break; case ARRAYDEP: if (nonDistrArrays.size() > 0) { SgSymbol *vIn = OriginalSymbol(currNode->varin->symbol()); SgSymbol *vOut = OriginalSymbol(currNode->varout->symbol()); auto found = varInOut.find(vIn); if (found == varInOut.end()) found = varInOut.insert(found, make_pair(vIn, vIn->identifier())); varIn = nonDistrArrays.find(found->second) != nonDistrArrays.end(); found = varInOut.find(vOut); if (found == varInOut.end()) found = varInOut.insert(found, make_pair(vOut, vOut->identifier())); varOut = nonDistrArrays.find(found->second) != nonDistrArrays.end(); } isEqual = isEqExpressions(currNode->varin, currNode->varout, collection); //dont check if textual identically if ((!isEqual || varIn || varOut) && (currNode->varin != currNode->varout)) { // TODO: process all loop, not only top loop if (currNode->knowndist[1] == 0 || currNode->distance[1] != 0) { if (currNode->knowndist[1] == 0) { if (!findUnknownDepLen) { auto message = currNode->createDepMessagebetweenArrays(); wstring depMessageEng = to_wstring(message.first), depMessageRus = to_wstring(message.second); depMessageEng += L" with unknown distance in loop on line " + std::to_wstring(currLoopRef->lineNumber()) + L" prevents parallelization"; depMessageRus += L"#" + std::to_wstring(currLoopRef->lineNumber()); currMessages->push_back(Messages(NOTE, currNode->stmtin->lineNumber(), L"R124:" + depMessageRus, depMessageEng, 3006)); // __spf_print only first unknown dep length findUnknownDepLen = true; if (!onlyOneStep) currLoop->hasUnknownArrayDep = true; } } else if (!findUnknownDepLen) //currNode->distance[1] != 0 { const ddnature nature = (ddnature)currNode->kinddep; int position = -1; if (nature == ddflow) position = 0; else if (nature == ddanti) position = 1; if (position != -1) { SgSymbol *arrayS = OriginalSymbol(currNode->varin->symbol()); SgArrayRefExp *arrayRef = (SgArrayRefExp*)(currNode->varin); bool existSubs = false; auto it = acrossToAdd.find(arrayS); if (it == acrossToAdd.end()) { int subsPos = -1; SgSymbol *doName = currLoopRef->symbol(); for (int z = 0; z < arrayRef->numberOfSubscripts() && !existSubs; ++z) { existSubs = checkExistence(arrayRef->subscript(z), doName->identifier()); if (existSubs) subsPos = z; } if (existSubs) it = acrossToAdd.insert(it, make_pair(arrayS, make_tuple(0, 0, subsPos))); } else existSubs = true; if (existSubs) { if (position == 0) get<0>(it->second) = std::max(get<0>(it->second), abs((int)currNode->distance[1])); else get<1>(it->second) = std::max(get<1>(it->second), abs((int)currNode->distance[1])); } } } } else if (!isEqual && (varIn || varOut)) // found dependencies between non ditributed arrays { if (currNode->knowndist[1] == 0 || currNode->distance[1] != 0) { if (!findUnknownDepLen) { auto message = currNode->createDepMessagebetweenArrays(); wstring depMessageEng = to_wstring(message.first), depMessageRus = to_wstring(message.second); depMessageEng += L" prevents parallelization"; currMessages->push_back(Messages(NOTE, currNode->stmtin->lineNumber(), L"R124:" + depMessageRus, depMessageEng, 3006)); // __spf_print only first unknown dep length findUnknownDepLen = true; if (!onlyOneStep) currLoop->hasUnknownArrayDep = true; } } } } //currNode->displayDep(); break; case PRIVATEDEP: //privates detected by PRIVATE_ANALYSIS_IR /*if (privVars.find(currNode->varin->symbol()->identifier()) == privVars.end()) privatesToAdd.push_back(currNode); //unknownScalarDep.push_back(currNode); */ break; case REDUCTIONDEP: if (currLoop->privateScalars.find(currNode->varin->symbol()->identifier()) == currLoop->privateScalars.end() && redVars.find(currNode->varin->symbol()->identifier()) == redVars.end()) reductionsToAdd.push_back(currNode); break; case SCALARDEP: if (currLoop->privateScalars.find(currNode->varin->symbol()->identifier()) == currLoop->privateScalars.end() && redVars.find(currNode->varin->symbol()->identifier()) == redVars.end()) unknownScalarDep.push_back(currNode); break; default: break; } } if (!onlyOneStep) { //NOTE: do it via PRIVATE_ANALYSIS_IR //addPrivatesToLoops(currLoop, privatesToAdd, localAllLoopMap, *currMessages); addReductionsToLoops(currLoop, reductionsToAdd, localAllLoopMap, *currMessages); if (!findUnknownDepLen && !currLoop->hasLimitsToParallel()) addAcrossToLoops(currLoop, acrossToAdd, localAllLoopMap, *currMessages); currLoop->hasUnknownScalarDep = (unknownScalarDep.size() != 0); for (int k = 0; k < unknownScalarDep.size(); ++k) { __spf_print(1, " unknown scalar dependencies by '%s' on line %d (try to specify its type)\n", unknownScalarDep[k]->varin->symbol()->identifier(), unknownScalarDep[k]->stmtin->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"unknown scalar dependencies by '%s' (try to specify its type)", to_wstring(unknownScalarDep[k]->varin->symbol()->identifier()).c_str()); __spf_printToLongBuf(messageR, R112, to_wstring(unknownScalarDep[k]->varin->symbol()->identifier()).c_str()); currMessages->push_back(Messages(WARR, unknownScalarDep[k]->stmtin->lineNumber(), messageR, messageE, 3005)); currLoop->linesOfScalarDep.push_back(unknownScalarDep[k]->stmtin->lineNumber()); } } depInfoForLoopGraph[currLoop] = depg; if (currLoop->hasLimitsToParallel()) currLoop->addConflictMessages(currMessages); } } else if (currReg && currLoop->hasLimitsToParallel()) { // loop has limits currLoop->addConflictMessages(currMessages); } for (int k = 0; k < currLoop->children.size(); ++k) tryToFindDependencies(currLoop->children[k], allLoops, funcWasInit, file, regions, currMessages, collection, allFuncs, defUseByPlace); }