Files
SAPFOR/src/Transformations/LoopSplitting/loops_splitter.cpp

1076 lines
42 KiB
C++
Raw Normal View History

2023-09-14 19:43:13 +03:00
#include "loops_splitter.h"
#include <string>
#include <vector>
#include "../LoopAnalyzer/loop_analyzer.h"
#include "expr_transform.h"
2025-06-04 13:08:38 +03:00
#include "errors.h"
2023-09-14 19:43:13 +03:00
#include "../CFGraph/CFGraph.h"
#include "../SageAnalysisTool/OmegaForSage/include/lang-interf.h"
#include "../DirectiveProcessing/directive_parser.h"
2024-04-12 16:36:37 +03:00
#include "../DirectiveProcessing/directive_omp_parser.h"
2023-09-14 19:43:13 +03:00
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<FuncInfo*, vector<SAPFOR::BasicBlock*>> currIR;
static inline bool lineInsideBorder(int lineNumber, const pair<SgStatement*, SgStatement*>& border)
{
return lineNumber >= border.first->lineNumber() && lineNumber < border.second->lineNumber();
}
static vector<SAPFOR::BasicBlock*> 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<SAPFOR::BasicBlock*> 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<SAPFOR::BasicBlock*> 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<pair<int, int>>& 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;
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> map <EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
* <<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD> : <EFBFBD><EFBFBD><EFBFBD><EFBFBD><<EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD> <EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> : <EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>>>
* <EFBFBD> since <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD> till <EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static map<const LoopGraph*, map<SgStatement*, pair<set<SgStatement*>, set<SgStatement*>>>> cacheDeps;
//TODO: added lines for function calls
static map<SgStatement*, pair<set<SgStatement*>, set<SgStatement*>>>
buildReachMapForLoop(const LoopGraph* parentGraphUpest, const LoopGraph* parentGraph, SgStatement* since, SgStatement* till,
const set<string>& privates, const vector<depGraph*>& depGraphs)
{
if (cacheDeps.count(parentGraph))
return cacheDeps.at(parentGraph);
const int sinceLine = since->lineNumber();
const int tillLine = till->lineNumber();
map<SgStatement*, pair<set<SgStatement*>, set<SgStatement*>>> result;
set<string> privArrays;
for (auto& elem : parentGraph->usedArraysAll)
if (privates.find(elem->GetShortName()) != privates.end())
privArrays.insert(elem->GetShortName());
map<string, set<SgStatement*>> defInBlocks;
map<string, set<SgStatement*>> useInBlocks;
vector<SgStatement*> blocks;
for (SgStatement* cur = since; cur != till; cur = cur->lexNext())
{
blocks.push_back(cur);
cur = cur->lastNodeOfStmt();
}
//TODO: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
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);
}
}
}
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> IR, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>,
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> 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<pair<pair<string, string>, vector<pair<int, int>>>> data;
const LoopGraph* lp = parentGraphUpest;
while (lp)
{
auto attrsTr = getAttributes<SgStatement*, SgStatement*>(lp->loop->GetOriginal(), set<int>{ SPF_PARALLEL_DIR });
for (auto attr : attrsTr)
fillShadowAcrossFromComment(ACROSS_OP, new Statement(attr), data);
if (lp == parentGraph)
break;
lp = lp->children[0];
}
set<string> 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<SAPFOR::BasicBlock*> bblocks;
vector<pair<int, int>> 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<FuncInfo*, set<FuncInfo*>> callDeps;
map<string, FuncInfo*> funcByName;
map<FuncInfo*, map<SAPFOR::Argument*, set<int>>> outForFunc;
// create gen kill for blocks
map<SAPFOR::BasicBlock*, map<SAPFOR::Argument*, set<int>>> gen, kill;
map<SAPFOR::Instruction*, map<SAPFOR::Argument*, set<int>>> genForIR, killForIR;
map<SAPFOR::BasicBlock*, set<SAPFOR::Argument*>> notInitedGlobals;
for (auto& byFunc : currIR)
{
callDeps[byFunc.first].insert(byFunc.first->callsFromV.begin(), byFunc.first->callsFromV.end());
funcByName[byFunc.first->funcName] = byFunc.first;
}
vector<set<FuncInfo*>> ssc;
vector<set<FuncInfo*>> 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<SAPFOR::Argument*, set<int>> 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<SAPFOR::Argument*> 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<const LoopGraph*> 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) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> enddo
lowestInsertedFor = lowestInsertedFor->lexPrev();
return (SgForStmt*)lowestInsertedFor->lexPrev(); //<2F><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
}
static void setupOpenDependencies(set<int>& openDependencies, const vector<pair<SgStatement*, SgStatement*>>& borders,
const set<string>& loopsPrivates, const vector<depGraph*>& 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<int>& openDependencies, const vector<pair<SgStatement*, SgStatement*>>& borders,
const map<SgStatement*, pair<set<SgStatement*>, set<SgStatement*>>>& 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<pair<SgStatement*, SgStatement*>>& borders)
{
for (const auto& border : borders)
if (lineInsideBorder(lineNum, border))
return true;
return false;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> openDependencies <20> borders
static void expandCopyBorders(SgStatement *globalSince, SgStatement *globalTill, vector<pair<SgStatement*, SgStatement*>> &borders,
const set<int>& 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) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>? <20><> <20><> <20><><EFBFBD>.
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
borders.push_back(make_pair(since, till));
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> borders
static void glueBorders(vector<pair<SgStatement*, SgStatement*>> &borders)
{
if (borders.size() <= 1)
return;
map<pair<int, int>, pair<SgStatement*, SgStatement*>> 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<pair<SgStatement*, SgStatement*>> 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<LoopGraph*> getLoopsFrom(const vector<pair<SgStatement*, SgStatement*>>& borders, LoopGraph *parentGraph, LoopGraph* parentGraphUpest)
{
vector<LoopGraph*> 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<depGraph*> getDepGraphsFor(const vector<LoopGraph*> &loops, LoopGraph *parentGraph, const map<LoopGraph*, depGraph*>& depInfoForLoopGraph)
{
vector<depGraph*> 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<pair<SgStatement*, SgStatement*>>& borders)
{
//<2F><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return !(borders.size() == 1 && borders[0].first == globalSince && borders[0].second == globalTill);
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> borders - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
static bool setupSplitBorders(LoopGraph* parentGraphUpest, LoopGraph* parentGraph, SgStatement* globalSince, SgStatement* globalTill,
vector<pair<SgStatement*, SgStatement*>>& borders,
const set<string>& privates,
const map<LoopGraph*, depGraph*>& depInfoForLoopGraph)
{
//<2F><><EFBFBD><EFBFBD><EFBFBD>-<2D><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
if (globalSince == globalTill)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
borders.clear();
SgStatement *since, *till;
since = globalSince;
till = since->lastNodeOfStmt()->lexNext();
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> borders - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
borders.push_back(make_pair(since, till));
vector<LoopGraph*> loops = getLoopsFrom(borders, parentGraph, parentGraphUpest);
vector<depGraph*> 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);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> borders
set<int> 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();
2024-04-12 16:36:37 +03:00
if (data->localLineNumber() != SPF_USER_DIR)
2023-09-14 19:43:13 +03:00
continue;
//__spf_print(1, "%s", data->unparse());
set<string> privates;
fillPrivatesFromComment(new Statement(data), privates);
if (privates.size())
{
set<string> 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<string> 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<SgExpression*> newData;
while (exprList)
{
if (exprList->lhs()->variant() == ACC_PRIVATE_OP)
{
if (actualPrivate.size())
{
SgExpression* list = exprList->lhs()->lhs();
vector<SgExpression*> 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<pair<SgStatement*, SgStatement*>> &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> &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<string>& privateVars, vector<Messages>& 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> &messages, int deep, const map<LoopGraph*, depGraph*>& 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<string> privates;
tryToFindPrivateInAttributes(loopGraph->loop, privates);
const set<string> 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<pair<SgStatement*, SgStatement*>> borders;
bool setup = setupSplitBorders(loopGraph, lowestParentGraph, globalSince, globalTill, borders, privates, depInfoForLoopGraph);
SgStatement* prev = loopGraph->loop->lexPrev();
bool hasSplited = false;
while (setup && borders.size() > 0) // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
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<LoopGraph*> &loopGraphs, vector<Messages> &messages,
const map<LoopGraph*, depGraph*>& depInfoForLoopGraph,
const map<string, CommonBlock*>& commonBlocks,
const map<string, vector<FuncInfo*>>& allFuncInfo, int &countOfTransform)
{
cacheDeps.clear();
map<int, LoopGraph*> mapLoopGraph;
createMapLoopGraph(loopGraphs, mapLoopGraph);
int totalErr = 0;
for (auto &loopPair : mapLoopGraph)
{
if (!loopPair.second->isFor())
2023-09-14 19:43:13 +03:00
continue;
LoopGraph *loop = loopPair.second;
auto attrsTr = getAttributes<SgStatement*, SgStatement*>(loop->loop->GetOriginal(), set<int>{ 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;
}