#include "loops_splitter.h" #include #include #include "../LoopAnalyzer/loop_analyzer.h" #include "../ExpressionTransform/expr_transform.h" #include "../Utils/errors.h" #include "../CFGraph/CFGraph.h" #include "../SageAnalysisTool/OmegaForSage/include/lang-interf.h" #include "../DirectiveProcessing/directive_parser.h" #include "../DirectiveProcessing/directive_omp_parser.h" using std::string; using std::vector; using std::map; using std::set; using std::pair; using std::make_pair; using std::wstring; using std::stack; #define PRINT_SPLITTED_FRAGMENTS 0 static map> currIR; static inline bool lineInsideBorder(int lineNumber, const pair& border) { return lineNumber >= border.first->lineNumber() && lineNumber < border.second->lineNumber(); } static vector filterByBlock(SgStatement* block) { int blockStart = block->lineNumber(); int blockEnd = block->lastNodeOfStmt()->lineNumber(); if (blockEnd < blockStart) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (blockEnd <= 0 || blockStart <= 0) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); SgStatement* funcStat = getFuncStat(block); int lineStart = funcStat->lineNumber(); vector currBlocks; for (auto& func : currIR) { if (func.first->linesNum.first == lineStart) { currBlocks = func.second; break; } } if (currBlocks.size() == 0) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); vector filtered; for (auto& block : currBlocks) { bool needToAdd = false; for (auto& ir : block->getInstructions()) { int line = ir->getInstruction()->getOperator()->lineNumber(); if (blockStart <= line && blockEnd >= line) needToAdd = true; } if (needToAdd) filtered.push_back(block); } return filtered; } static int getIntervalIdx (const vector>& intervals, int line) { int id = -1; for (int z = 0; z < intervals.size(); ++z) { if (intervals[z].first <= line && line <= intervals[z].second) { id = z; break; } } return id; } /** * Построить map с зависимостями: * <Оператор Х : пара<сет зависящих от Х операторов : сет используюемых в Х операторов>> * с since включительно, по till не включительно */ static map, set>>> cacheDeps; //TODO: added lines for function calls static map, set>> buildReachMapForLoop(const LoopGraph* parentGraphUpest, const LoopGraph* parentGraph, SgStatement* since, SgStatement* till, const set& privates, const vector& depGraphs) { if (cacheDeps.count(parentGraph)) return cacheDeps.at(parentGraph); const int sinceLine = since->lineNumber(); const int tillLine = till->lineNumber(); map, set>> result; set privArrays; for (auto& elem : parentGraph->usedArraysAll) if (privates.find(elem->GetShortName()) != privates.end()) privArrays.insert(elem->GetShortName()); map> defInBlocks; map> useInBlocks; vector blocks; for (SgStatement* cur = since; cur != till; cur = cur->lexNext()) { blocks.push_back(cur); cur = cur->lastNodeOfStmt(); } //TODO: необходимо реализовать нормальный алгоритм определения зависимостей по приватному массиву. if (privArrays.size() != 0) { for (auto& block : blocks) { auto filtered = filterByBlock(block); int blockStart = block->lineNumber(); int blockEnd = block->lastNodeOfStmt()->lineNumber(); for (auto& blockIR : filtered) { for (auto& ir : blockIR->getInstructions()) { auto inst = ir->getInstruction(); int inLine = inst->getOperator()->lineNumber(); if (inLine < blockStart || inLine > blockEnd) continue; if (inst->getOperation() == SAPFOR::CFG_OP::LOAD || inst->getOperation() == SAPFOR::CFG_OP::STORE) { auto name = getNameByArg(inst->getArg1()); if (privArrays.find(name) != privArrays.end()) { if (inst->getOperation() == SAPFOR::CFG_OP::LOAD) useInBlocks[name].insert(block); else defInBlocks[name].insert(block); } } } } } // сделать очередность блоков по IR, сейчас предполагается линейная очередность блоков, что не вседа верно, // но возможно другого варианта не может быть, кроме случаев с goto. for (int z = 0; z < blocks.size(); ++z) { for (auto& data : useInBlocks) { const string array = data.first; if (data.second.find(blocks[z]) != data.second.end()) { if (defInBlocks.find(array) != defInBlocks.end()) { bool defFound = false; for (int t = z - 1; t >= 0; --t) { if (defInBlocks[array].find(blocks[t]) != defInBlocks[array].end()) { result[blocks[z]].first.insert(blocks[t]); result[blocks[t]].second.insert(blocks[z]); defFound = true; } if (defFound && useInBlocks[array].find(blocks[t]) != useInBlocks[array].end()) break; } } } } } } vector, vector>>> data; const LoopGraph* lp = parentGraphUpest; while (lp) { auto attrsTr = getAttributes(lp->loop->GetOriginal(), set{ SPF_PARALLEL_DIR }); for (auto attr : attrsTr) fillShadowAcrossFromComment(ACROSS_OP, new Statement(attr), data); if (lp == parentGraph) break; lp = lp->children[0]; } set arraysWithAcross; for (auto& elem : data) arraysWithAcross.insert(elem.first.first); for (depGraph* dependencyGraph : depGraphs) { if (dependencyGraph == NULL) continue; for (depNode* node : dependencyGraph->getNodes()) { if (node->typedep == PRIVATEDEP) continue; if (node->typedep == REDUCTIONDEP) continue; if (node->varin != node->varout) { bool isPrivateArray = false; if (node->typedep == ARRAYDEP) if (privates.find(node->varin->symbol()->identifier()) != privates.end() || privates.find(node->varout->symbol()->identifier()) != privates.end()) isPrivateArray = true; if (isPrivateArray) continue; SgStatement* statIn = node->stmtin; SgStatement* statOut = node->stmtout; checkNull(statIn, convertFileName(__FILE__).c_str(), __LINE__); checkNull(statOut, convertFileName(__FILE__).c_str(), __LINE__); if (statOut != statIn) { int inLine = node->stmtin->lineNumber(); int outLine = node->stmtout->lineNumber(); if (inLine == outLine) continue; const string nameIn = node->varin->symbol()->identifier(); const string nameOut = node->varout->symbol()->identifier(); bool isAcross = arraysWithAcross.count(nameIn) || arraysWithAcross.count(nameOut); bool hasDependency = false; for (int i = 1; i < node->knowndist.size(); ++i) { //ANTI and REDUCE hasDependency |= (node->knowndist[i] == 0) || ((node->knowndist[i] == 1) && (node->distance[i] != 0 || (isAcross && (node->kinddep == ddanti)))); } if (hasDependency) { bool inIncluded = false, outIncluded = false; if (lineInsideBorder(inLine, make_pair(since, till))) inIncluded = true; if (lineInsideBorder(outLine, make_pair(since, till))) outIncluded = true; if (!inIncluded && !outIncluded) continue; if (inIncluded && outIncluded) { result[node->stmtin].first.insert(node->stmtout); result[node->stmtout].second.insert(node->stmtin); } } } } } } // added scalar dependencies vector bblocks; vector> startEndBlock; for (auto& block : blocks) { auto filtered = filterByBlock(block); bblocks.insert(bblocks.end(), filtered.begin(), filtered.end()); int blockStart = block->lineNumber(); int blockEnd = block->lastNodeOfStmt()->lineNumber(); startEndBlock.push_back(make_pair(blockStart, blockEnd)); } map> callDeps; map funcByName; map>> outForFunc; // create gen kill for blocks map>> gen, kill; map>> genForIR, killForIR; map> notInitedGlobals; for (auto& byFunc : currIR) { callDeps[byFunc.first].insert(byFunc.first->callsFromV.begin(), byFunc.first->callsFromV.end()); funcByName[byFunc.first->funcName] = byFunc.first; } vector> ssc; vector> callLvls = groupByCallDependencies(callDeps, ssc); //TODO: take into account ssc structure for (auto& byLvl : callLvls) { for (auto& byFunc : byLvl) { auto itCFG = currIR.find(byFunc); if (itCFG == currIR.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); map> outForCurr; buildGenKillForCFG(itCFG->second, funcByName, outForFunc, gen, kill, &genForIR, &killForIR, notInitedGlobals, SAPFOR::CFG_Settings(0)); if (outForFunc.count(byFunc)) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); outForFunc[byFunc] = outForCurr; } } for (auto& bblock : bblocks) { auto rd_in = bblock->getRD_In(); for (auto& ir : bblock->getInstructions()) { auto istr = ir->getInstruction(); int line = istr->getOperator()->lineNumber(); if (line <= 0) continue; if (line < sinceLine || line >= tillLine) continue; int idOperator = getIntervalIdx(startEndBlock, line); if (idOperator == -1) continue; set use; if (istr->getArg1() && istr->getArg1()->getType() == SAPFOR::CFG_ARG_TYPE::VAR) use.insert(istr->getArg1()); if (istr->getArg2() && istr->getArg2()->getType() == SAPFOR::CFG_ARG_TYPE::VAR) use.insert(istr->getArg2()); for (auto& varUse : use) { auto it = rd_in.find(varUse); if (it != rd_in.end()) { for (auto& num : it->second) { if (num == SAPFOR::UNINIT) continue; auto whereByNum = getInstructionAndBlockByNumber(currIR, num); if (whereByNum.first == NULL) continue; int line = whereByNum.first->getOperator()->lineNumber(); if (idOperator != getIntervalIdx(startEndBlock, line)) { if (line >= sinceLine && line < tillLine) { result[istr->getOperator()].first.insert(whereByNum.first->getOperator()); result[whereByNum.first->getOperator()].second.insert(istr->getOperator()); } } } } //else err? } auto itGen = genForIR.find(istr); if (itGen != genForIR.end()) for (auto& elem : itGen->second) if (elem.first->getType() == SAPFOR::CFG_ARG_TYPE::VAR) rd_in[elem.first] = elem.second; } } if (0) // deb print { for (auto& array : defInBlocks) { printf("%s defs in:\n", array.first.c_str()); for (auto& place : array.second) printf(" -- %d\n", place->lineNumber()); printf("\n"); } for (auto& array : useInBlocks) { printf("%s uses in:\n", array.first.c_str()); for (auto& place : array.second) printf(" -- %d\n", place->lineNumber()); printf("\n"); } for (auto& it : result) { printf("st: %d:\n", it.first->lineNumber()); printf("Depends on:\n"); for (auto& itt : it.second.first) printf("%d ", itt->lineNumber()); printf("\n"); printf("Used in:\n"); for (auto& itt : it.second.second) printf("%d ", itt->lineNumber()); printf("\n"); printf("\n"); } } cacheDeps[parentGraph] = result; return result; } static SgForStmt* createNewLoop(const LoopGraph *globalLoop) { SgStatement *insertBeforeThis = globalLoop->loop->GetOriginal(); SgStatement *newLoop = NULL; const LoopGraph *curLoopGraph = globalLoop; vector graphs(globalLoop->perfectLoop); for (int i = 0; i < globalLoop->perfectLoop; ++i) { graphs[i] = curLoopGraph; if (curLoopGraph->children.size()) curLoopGraph = curLoopGraph->children[0]; } for (int i = graphs.size() - 1; i > 0; --i) { SgForStmt* curForStmt = (SgForStmt*)graphs[i]->loop->GetOriginal(); newLoop = new SgForStmt(curForStmt->doName(), curForStmt->start(), curForStmt->end(), curForStmt->step(), newLoop); } SgForStmt *curForStmt = (SgForStmt*)graphs[0]->loop->GetOriginal(); SgForStmt *newGlobalLoop = new SgForStmt(curForStmt->doName(), curForStmt->start(), curForStmt->end(), curForStmt->step(), newLoop); insertBeforeThis->insertStmtBefore(*newGlobalLoop, *insertBeforeThis->controlParent()); for (int z = 0; z < insertBeforeThis->numberOfAttributes(); ++z) newGlobalLoop->addAttribute(new SgAttribute(*insertBeforeThis->getAttribute(z))); SgStatement *lowestInsertedFor = insertBeforeThis; for (int i = 0; i < globalLoop->perfectLoop; ++i) //пройти по всем enddo lowestInsertedFor = lowestInsertedFor->lexPrev(); return (SgForStmt*)lowestInsertedFor->lexPrev(); //самый внутренний цикл } static void setupOpenDependencies(set& openDependencies, const vector>& borders, const set& loopsPrivates, const vector& depGraphs) { for (depGraph* dependencyGraph : depGraphs) { if (dependencyGraph == NULL) continue; for (depNode* node : dependencyGraph->getNodes()) { if (node->typedep == PRIVATEDEP) continue; if (node->typedep == REDUCTIONDEP) continue; if (node->varin != node->varout) { bool isPrivateArray = false; if (node->typedep == ARRAYDEP) if (loopsPrivates.find(node->varin->symbol()->identifier()) != loopsPrivates.end() || loopsPrivates.find(node->varout->symbol()->identifier()) != loopsPrivates.end()) isPrivateArray = true; if (isPrivateArray) continue; SgStatement* statIn = node->stmtin; SgStatement* statOut = node->stmtout; checkNull(statIn, convertFileName(__FILE__).c_str(), __LINE__); checkNull(statOut, convertFileName(__FILE__).c_str(), __LINE__); SgStatement* sInFor = statIn; while (sInFor && sInFor->variant() != FOR_NODE) sInFor = sInFor->controlParent(); SgStatement* sOutFor = statOut; while (sOutFor && sOutFor->variant() != FOR_NODE) sOutFor = sOutFor->controlParent(); if (statOut != statIn) { bool hasDependency = false; for (int i = 1; i < node->knowndist.size(); ++i) { //ANTI and REDUCE hasDependency |= (node->knowndist[i] == 0) || ((node->knowndist[i] == 1) && (node->distance[i] != 0)); } if (hasDependency) { int inLine = node->stmtin->lineNumber(); int outLine = node->stmtout->lineNumber(); bool inIncluded = false, outIncluded = false; for (const auto& border : borders) { if (lineInsideBorder(inLine, border)) inIncluded = true; if (lineInsideBorder(outLine, border)) outIncluded = true; } if (!inIncluded && !outIncluded) continue; if (!inIncluded && openDependencies.find(inLine) == openDependencies.end()) openDependencies.insert(inLine); if (!outIncluded && openDependencies.find(outLine) == openDependencies.end()) openDependencies.insert(outLine); } } } } } } static void addReachingDefinitionsDependencies(set& openDependencies, const vector>& borders, const map, set>>& requireReachMap) { for (const auto& border : borders) { for (SgStatement* current = border.first; current != border.second; current = current->lexNext()) { auto found = requireReachMap.find(current); if (found != requireReachMap.end()) { for (auto it = found->second.first.begin(); it != found->second.first.end(); ++it) { int lineNumber = (*it)->lineNumber(); bool included = false; for (const auto& b : borders) { if (lineInsideBorder(lineNumber, b)) { included = true; break; } } if (!included && openDependencies.find(lineNumber) == openDependencies.end()) openDependencies.insert(lineNumber); } for (auto it = found->second.second.begin(); it != found->second.second.end(); ++it) { int lineNumber = (*it)->lineNumber(); bool included = false; for (const auto& b : borders) { if (lineInsideBorder(lineNumber, b)) { included = true; break; } } if (!included && openDependencies.find(lineNumber) == openDependencies.end()) openDependencies.insert(lineNumber); } } } } } static bool dependencyAlreadyEnclosed(int lineNum, const vector>& borders) { for (const auto& border : borders) if (lineInsideBorder(lineNum, border)) return true; return false; } // добавить зависимости из openDependencies в borders static void expandCopyBorders(SgStatement *globalSince, SgStatement *globalTill, vector> &borders, const set& openDependencies) { for (int lineNumOfDependency : openDependencies) { if (dependencyAlreadyEnclosed(lineNumOfDependency, borders)) continue; SgStatement *since = NULL, *till = NULL; since = globalSince; for (since = globalSince; since != globalTill; since = since->lastNodeOfStmt()->lexNext()) { if (since->lineNumber() <= lineNumOfDependency && since->lastNodeOfStmt()->lineNumber() >= lineNumOfDependency) { till = since->lastNodeOfStmt()->lexNext(); break; } } if (since == globalTill) //зависимости вне основного цикла? ну уж нет. printInternalError(convertFileName(__FILE__).c_str(), __LINE__); borders.push_back(make_pair(since, till)); } } // склеить соседние границы в borders static void glueBorders(vector> &borders) { if (borders.size() <= 1) return; map, pair> bordersMap; for (int z = 0; z < borders.size(); ++z) bordersMap[make_pair(borders[z].first->lineNumber(), borders[z].second->lineNumber())] = borders[z]; borders.clear(); for (auto &elem : bordersMap) borders.push_back(elem.second); bool needToUpdate = true; while (needToUpdate) { needToUpdate = false; vector> newBorders; newBorders.push_back(borders[0]); int lastIdx = 0; for (int z = 1; z < borders.size(); ++z) { if (newBorders[lastIdx].second == borders[z].first) newBorders[lastIdx].second = borders[z].second; else { newBorders.push_back(borders[z]); lastIdx++; } } if (newBorders.size() != borders.size()) { borders = newBorders; needToUpdate = (borders.size() > 1); } } } static vector getLoopsFrom(const vector>& borders, LoopGraph *parentGraph, LoopGraph* parentGraphUpest) { vector result; while (parentGraphUpest != parentGraph) { result.push_back(parentGraphUpest); if (parentGraphUpest->children.size() == 0 || parentGraphUpest->children.size() > 1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); parentGraphUpest = parentGraphUpest->children[0]; } result.push_back(parentGraph); for (LoopGraph *loop : parentGraph->children) for (const auto& frag : borders) if (loop->lineNum >= frag.first->lineNumber() && loop->lineNumAfterLoop <= frag.second->lineNumber()) result.push_back(loop); return result; } static vector getDepGraphsFor(const vector &loops, LoopGraph *parentGraph, const map& depInfoForLoopGraph) { vector result; for (auto& loop : loops) { if (depInfoForLoopGraph.count(loop)) result.push_back(depInfoForLoopGraph.at(loop)); else result.push_back(NULL); } return result; } static bool continueSplitting(SgStatement* globalSince, SgStatement* globalTill, const vector>& borders) { //Если вырежем опять, исходный цикл останется пустым return !(borders.size() == 1 && borders[0].first == globalSince && borders[0].second == globalTill); } // построить borders - множество операторов, которые будут вынесены в отдельный цикл static bool setupSplitBorders(LoopGraph* parentGraphUpest, LoopGraph* parentGraph, SgStatement* globalSince, SgStatement* globalTill, vector>& borders, const set& privates, const map& depInfoForLoopGraph) { //Каким-то образом, мы вырезали всё из цикла и хотим продолжать. if (globalSince == globalTill) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); borders.clear(); SgStatement *since, *till; since = globalSince; till = since->lastNodeOfStmt()->lexNext(); // инициализация borders - первый оператор тела цикла borders.push_back(make_pair(since, till)); vector loops = getLoopsFrom(borders, parentGraph, parentGraphUpest); vector depGraphs = getDepGraphsFor(loops, parentGraph, depInfoForLoopGraph); __spf_print(PRINT_SPLITTED_FRAGMENTS, "Initial fragment: %d - %d\n", since->lineNumber(), till->lineNumber()); const auto requireReachMap = buildReachMapForLoop(parentGraphUpest, parentGraph, globalSince, globalTill, privates, depGraphs); // множество номеров строк операторов, с которыми есть зависимость и которые не включены в borders set openDependencies; setupOpenDependencies(openDependencies, borders, privates, depGraphs); addReachingDefinitionsDependencies(openDependencies, borders, requireReachMap); while (openDependencies.size() > 0) { #if PRINT_SPLITTED_FRAGMENTS == 1 __spf_print(PRINT_SPLITTED_FRAGMENTS, "Line dependencies:\n", globalSince->lineNumber(), globalTill->lineNumber()); for (auto& it : openDependencies) __spf_print(PRINT_SPLITTED_FRAGMENTS, " %d,", it); __spf_print(PRINT_SPLITTED_FRAGMENTS, "\n"); #endif expandCopyBorders(globalSince, globalTill, borders, openDependencies); openDependencies.clear(); loops = getLoopsFrom(borders, parentGraph, parentGraphUpest); depGraphs = getDepGraphsFor(loops, parentGraph, depInfoForLoopGraph); setupOpenDependencies(openDependencies, borders, privates, depGraphs); addReachingDefinitionsDependencies(openDependencies, borders, requireReachMap); } #if PRINT_SPLITTED_FRAGMENTS == 1 for (auto &fragment : borders) __spf_print(PRINT_SPLITTED_FRAGMENTS, "fragment %d - %d\n", fragment.first->lineNumber(), fragment.second->lineNumber()); #endif glueBorders(borders); return continueSplitting(globalSince, globalTill, borders); } static void filterSpfAttributes(SgStatement* stat) { int count = stat->numberOfAttributes(); if (count) { SgStatement* lastNode = stat->lastNodeOfStmt(); //TODO: added filter for private, reduction and ... for (int z = 0; z < count; ++z) { SgAttribute* attr = stat->getAttribute(z); if (attr->getAttributeType() == SPF_ANALYSIS_DIR) { SgStatement* data = (SgStatement*)attr->getAttributeData(); if (data->localLineNumber() != SPF_USER_DIR) continue; //__spf_print(1, "%s", data->unparse()); set privates; fillPrivatesFromComment(new Statement(data), privates); if (privates.size()) { set assignTo; for (SgStatement* st = stat; st != lastNode; st = st->lexNext()) { if (st->variant() == ASSIGN_STAT) { auto ex = st->expr(0)->symbol(); if (ex) assignTo.insert(ex->identifier()); } } set actualPrivate; for (auto& elem : privates) if (assignTo.find(elem) != assignTo.end()) actualPrivate.insert(elem); if (actualPrivate.size() != privates.size()) { __spf_print(1, "actual private size %d, in dir %d\n", actualPrivate.size(), privates.size()); SgExpression* exprList = data->expr(0); vector newData; while (exprList) { if (exprList->lhs()->variant() == ACC_PRIVATE_OP) { if (actualPrivate.size()) { SgExpression* list = exprList->lhs()->lhs(); vector newList; while (list) { if (actualPrivate.find(list->lhs()->symbol()->identifier()) != actualPrivate.end()) newList.push_back(list->lhs()); list = list->rhs(); } if (newList.size()) { exprList->lhs()->setLhs(makeExprList(newList)); newData.push_back(exprList->lhs()); } } } else newData.push_back(exprList->lhs()); exprList = exprList->rhs(); } if (newData.size() == 0) { __spf_print(1, "remove attribute on line %d\n", stat->lineNumber()); stat->deleteAttribute(z); count--; } else { __spf_print(1, "set new data size %d\n", newData.size()); data->setExpression(0, makeExprList(newData)); } } } } } } } static void moveStatements(SgForStmt *newLoop, const vector> &fragments, int deep) { //newLoop is lowest SgStatement* lastInserted = newLoop->lastNodeOfStmt(); SgStatement* cp = lastInserted->controlParent(); for (const auto& fragment : fragments) { SgStatement *toMoveStmt = fragment.first; while (toMoveStmt != fragment.second) { SgStatement *st = toMoveStmt; toMoveStmt = toMoveStmt->lastNodeOfStmt()->lexNext(); lastInserted->insertStmtBefore(*st->extractStmt(), *cp); } } for (int z = 0; z < deep - 1; ++z) { newLoop = isSgForStmt(newLoop->controlParent()); checkNull(newLoop, convertFileName(__FILE__).c_str(), __LINE__); } filterSpfAttributes(newLoop); } static bool hasIndirectChildLoops(const LoopGraph* parentGraph, vector &messages) { SgStatement* st = parentGraph->loop->GetOriginal()->lexNext(); int directLoops = 0; while (st->variant() != CONTROL_END) { if (st->variant() == FOR_NODE) directLoops++; st = st->lastNodeOfStmt()->lexNext(); } if (directLoops != parentGraph->children.size()) { messages.push_back(Messages(ERROR, parentGraph->loop->GetOriginal()->lineNumber(), R105, L"This loop has indirect child loops and can not be splitted", 2010)); __spf_print(1, "This loop has indirect child loops and can not be splitted on line %d\n", parentGraph->lineNum); return true; } else return false; } static bool hasUnexpectedDependencies(const LoopGraph* parentGraph, const depGraph* parentDepGraph, const set& privateVars, vector& messages) { bool has = false; int countOfMessages = 10; int idxOfMessages = 0; if (parentDepGraph == NULL) return false; for (depNode* node : parentDepGraph->getNodes()) { if (node->typedep != ARRAYDEP) { bool privateInChild = false; for (LoopGraph* childGraph : parentGraph->children) { SgStatement *childLoop = childGraph->loop->GetOriginal(); if (lineInsideBorder(node->stmtin->lineNumber(), make_pair(childLoop, childLoop->lastNodeOfStmt()->lexNext()))) privateInChild = (node->typedep == PRIVATEDEP); } // is it private for this loop if (!privateInChild) if (node->varin->symbol() && privateVars.find(node->varin->symbol()->identifier()) != privateVars.end()) privateInChild = true; has |= !privateInChild; if (!privateInChild) { if (idxOfMessages < countOfMessages) { idxOfMessages++; string str; __spf_printToBuf(str, "Can not split this loop because of dependency: %s", node->displayDepToStr().c_str()); __spf_print(1, "%s on line %d\n", str.c_str(), parentGraph->lineNum); wstring strR, strE; __spf_printToLongBuf(strE, L"Can not split this loop because of dependency: %s", to_wstring(node->displayDepToStr()).c_str()); __spf_printToLongBuf(strR, R104, to_wstring(node->displayDepToStr()).c_str()); messages.push_back(Messages(WARR, parentGraph->lineNum, strR, strE, 2009)); } } } } return has; } static int splitLoop(LoopGraph *loopGraph, vector &messages, int deep, const map& depInfoForLoopGraph) { LoopGraph *lowestParentGraph = loopGraph; for (int i = 0; i < std::min(loopGraph->perfectLoop, deep) - 1; ++i) { if (lowestParentGraph->children.size() == 1) lowestParentGraph = lowestParentGraph->children[0]; else printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } if (hasIndirectChildLoops(lowestParentGraph, messages)) return -1; if (lowestParentGraph->hasLimitsToSplit()) { messages.push_back(Messages(ERROR, loopGraph->lineNum, R106 + std::to_wstring(lowestParentGraph->lineNum), L"This loop has limits (goto, print, stops or not DO-ENDDO) for splitting (reason: loop on line " + std::to_wstring(lowestParentGraph->lineNum) + L")", 2010)); __spf_print(1, "%d loop has limits (goto, print, stops or not DO-ENDDO) for splitting (reason: loop on line %d)\n", loopGraph->lineNum, lowestParentGraph->lineNum); return -1; } set privates; tryToFindPrivateInAttributes(loopGraph->loop, privates); const set privVars; const depGraph* lowestParentDepGraph = NULL; if (depInfoForLoopGraph.count(lowestParentGraph)) lowestParentDepGraph = depInfoForLoopGraph.at(lowestParentGraph); if (hasUnexpectedDependencies(lowestParentGraph, lowestParentDepGraph, privates, messages)) { messages.push_back(Messages(ERROR, loopGraph->lineNum, R107 + std::to_wstring(lowestParentGraph->lineNum), L"This loop has unexpected dependencies and can not be splitted (reason: loop on line " + std::to_wstring(lowestParentGraph->lineNum) + L")", 2010)); __spf_print(1, "%d loop has unexpected dependencies and can not be splitted (reason: loop on line %d)\n", loopGraph->lineNum, lowestParentGraph->lineNum); return -1; } SgStatement *globalSince, *globalTill; globalSince = lowestParentGraph->loop->GetOriginal()->lexNext(); globalTill = lowestParentGraph->loop->GetOriginal()->lastNodeOfStmt(); vector> borders; bool setup = setupSplitBorders(loopGraph, lowestParentGraph, globalSince, globalTill, borders, privates, depInfoForLoopGraph); SgStatement* prev = loopGraph->loop->lexPrev(); bool hasSplited = false; while (setup && borders.size() > 0) // пока цикл можно делить { hasSplited = true; #if PRINT_SPLITTED_FRAGMENTS == 1 __spf_print(PRINT_SPLITTED_FRAGMENTS, "global since %d, global till %d\n", globalSince->lineNumber(), globalTill->lineNumber()); __spf_print(PRINT_SPLITTED_FRAGMENTS, "result fragment: "); for (auto& it : borders) __spf_print(PRINT_SPLITTED_FRAGMENTS, "%d - %d, ", it.first->lineNumber(), it.second->lineNumber()); __spf_print(PRINT_SPLITTED_FRAGMENTS, "\n"); #endif moveStatements(createNewLoop(loopGraph), borders, deep); globalSince = lowestParentGraph->loop->GetOriginal()->lexNext(); setup = setupSplitBorders(loopGraph, lowestParentGraph, globalSince, globalTill, borders, privates, depInfoForLoopGraph); } //move comment to uppest loop if (hasSplited) { if (loopGraph->loop->comments()) { prev->lexNext()->addComment(loopGraph->loop->comments()); loopGraph->loop->delComments(); } } return hasSplited ? 0 : 1; } int splitLoops(SgFile *file, vector &loopGraphs, vector &messages, const map& depInfoForLoopGraph, const map& commonBlocks, const map>& allFuncInfo, int &countOfTransform) { cacheDeps.clear(); map mapLoopGraph; createMapLoopGraph(loopGraphs, mapLoopGraph); int totalErr = 0; for (auto &loopPair : mapLoopGraph) { if (!loopPair.second->isFor) continue; LoopGraph *loop = loopPair.second; auto attrsTr = getAttributes(loop->loop->GetOriginal(), set{ SPF_TRANSFORM_DIR }); for (auto attr : attrsTr) { SgExpression *list = attr->expr(0); if (list->lhs()->variant() == SPF_FISSION_OP) { checkNull(list->lhs()->lhs(), convertFileName(__FILE__).c_str(), __LINE__); SgExprListExp *listExp = isSgExprListExp(list->lhs()->lhs()); checkNull(listExp, convertFileName(__FILE__).c_str(), __LINE__); int deep = listExp->length(); currIR = buildCFGforCurrentFunc(loop->loop, SAPFOR::CFG_Settings(true, true), commonBlocks, allFuncInfo); totalErr = splitLoop(loop, messages, deep, depInfoForLoopGraph); if (totalErr > 0) { messages.push_back(Messages(ERROR, loop->lineNum, R196, L"The loop transformation cannot be performed due to dependencies between operators", 2022)); __spf_print(1, "%d The loop transformation cannot be performed due to dependencies between operators\n", loop->lineNum); } else if (totalErr == 0) { filterSpfAttributes(loop->loop->GetOriginal()); countOfTransform++; } deleteCFG(currIR); } } } cacheDeps.clear(); return totalErr; }