33 Commits

Author SHA1 Message Date
Egor Mayorov
18b2666c0e swap operators in AST 2025-06-02 08:28:49 +03:00
Egor Mayorov
edc19e4e9b Use more complex algorythm for building new order of statements 2025-06-02 08:28:49 +03:00
Egor Mayorov
6a50d83b33 update in new order 2025-06-02 08:28:49 +03:00
Egor Mayorov
caf4d8da0d biulding new order 2025-06-02 08:28:49 +03:00
Egor Mayorov
adbd9c64e8 some loop analysis done 2025-06-02 08:28:49 +03:00
Egor Mayorov
703f21405d Add _bin to gitignore 2025-06-02 08:28:49 +03:00
Egor Mayorov
9fe2f0fe25 Some actions simplify analyzing IR 2025-06-02 08:28:49 +03:00
Egor Mayorov
2edc10f7dc Pass with output file added 2025-06-02 08:28:48 +03:00
Egor Mayorov
7f131d577e change pass deps 2025-06-02 08:28:48 +03:00
Egor Mayorov
3ab6eb50f5 New pass 2025-06-02 08:28:48 +03:00
8161609173 Merge pull request 'fix range stuctures' (#60) from private_arrays_fix into master 2025-06-02 05:26:21 +00:00
a2e6269508 fix range stuctures 2025-06-02 08:23:40 +03:00
ALEXks
72a1c1d853 fixed merge 2025-05-30 13:00:40 +03:00
5c89299ad5 Merge pull request 'o.nikitin_private_arrays' (#58) from o.nikitin_private_arrays into master
Reviewed-on: #58
2025-05-30 09:45:49 +00:00
ALEXks
26e36bed46 fixed code style 2025-05-30 12:45:05 +03:00
ALEXks
8dcbd587ec fixed submodule 2025-05-30 12:31:19 +03:00
ALEXks
f7a78f9626 restored messages 2025-05-30 12:29:35 +03:00
fbe22fca43 Merge branch 'master' into o.nikitin_private_arrays 2025-05-30 12:21:13 +03:00
bbb9823f1d updated submodule 2025-05-30 12:20:08 +03:00
402ae91c33 Merge pull request 'weighted_par_regions' (#57) from weighted_par_regions into master
added weighted parallel regions (by Mikhail K)
2025-05-29 06:08:47 +00:00
ba632b29ce cleanup and replaced parseFortranDouble to strtod 2025-05-29 09:07:20 +03:00
18edf55d15 merged mastser 2025-05-28 16:31:27 +03:00
c347f56e47 Merge branch 'master' into o.nikitin_private_arrays 2025-05-28 16:24:17 +03:00
11e9fab482 change file structure 2025-05-27 02:25:39 +03:00
73d0b201f2 change passes 2025-05-19 20:59:59 +03:00
1973d095f5 made functions static 2025-05-19 20:59:59 +03:00
O. Nikitin
f679666d01 fix operator!= 2025-05-19 20:52:06 +03:00
0df1d3d5fe add dataflow solvation 2025-05-19 20:52:06 +03:00
54eb1ecc95 add Region constructor and SolveDataflow function 2025-05-19 20:52:06 +03:00
b7ebccf045 add Collapse 2025-05-19 20:52:06 +03:00
738f2c5d12 Support APPLY_FRAGMENT(WEIGHT(double)) clause: add weights to fragments of parallel regions (and use it in at loopAnalyzer) 2025-05-10 15:27:03 +03:00
ALEXks
29a8c30370 fixed Array::toJson 2025-05-07 20:16:43 +03:00
ALEXks
99f5febd58 added json for SPF_GetAllDeclaratedArrays pass 2025-05-07 19:59:54 +03:00
19 changed files with 1372 additions and 54 deletions

2
.gitignore vendored
View File

@@ -74,6 +74,8 @@ Sapfor/Sapc++/Sapc++/x64/
Sapfor/Sapc++/x64/
/build
/cmake-build-debug
Sapfor/out/
Sapfor/_bin/*
_bin/*

View File

@@ -113,7 +113,13 @@ set(OMEGA src/SageAnalysisTool/OmegaForSage/add-assert.cpp
src/SageAnalysisTool/set.cpp)
set(PRIV src/PrivateAnalyzer/private_analyzer.cpp
src/PrivateAnalyzer/private_analyzer.h)
src/PrivateAnalyzer/private_analyzer.h
src/PrivateAnalyzer/private_arrays_search.cpp
src/PrivateAnalyzer/private_arrays_search.h
src/PrivateAnalyzer/range_structures.cpp
src/PrivateAnalyzer/range_structures.h
src/PrivateAnalyzer/region.cpp
src/PrivateAnalyzer/region.h)
set(FDVM ${fdvm_sources}/acc.cpp
${fdvm_sources}/acc_across.cpp
@@ -182,6 +188,8 @@ set(TR_IMPLICIT_NONE src/Transformations/set_implicit_none.cpp
src/Transformations/set_implicit_none.h)
set(TR_REPLACE_ARRAYS_IN_IO src/Transformations/replace_dist_arrays_in_io.cpp
src/Transformations/replace_dist_arrays_in_io.h)
SET(SWAP_OPERATORS src/SwapOperators/swapOperators.cpp
src/SwapOperators/swapOperators.h)
set(TRANSFORMS
${TR_DEAD_CODE}
@@ -420,7 +428,8 @@ set(SOURCE_EXE
${ZLIB}
${GR_LAYOUT}
${PR_PARAM}
${PROJ_MAN})
${PROJ_MAN}
${SWAP_OPERATORS})
add_executable(Sapfor_F ${SOURCE_EXE})
source_group (CFGraph FILES ${CFG})
@@ -464,6 +473,7 @@ source_group (Utils FILES ${UTILS})
source_group (VerificationCode FILES ${VERIF})
source_group (ProjectParameters FILES ${PR_PARAM})
source_group (ProjectManipulation FILES ${PROJ_MAN})
source_group (SwapOperators FILES ${SWAP_OPERATORS})
source_group (VisualizerCalls FILES ${VS_CALLS})
source_group (VisualizerCalls\\GraphLayout FILES ${GR_LAYOUT})

View File

@@ -395,7 +395,7 @@ static SAPFOR::Argument* processExpression(SgExpression* ex, vector<IR_Block*>&
if (ex)
{
const int var = ex->variant();
if ((var == VAR_REF || var == CONST_REF || var == LABEL_REF) && !ex->lhs() && !ex->rhs()) // <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if ((var == VAR_REF || var == CONST_REF || var == LABEL_REF) && !ex->lhs() && !ex->rhs()) // variable reference
{
if (var == CONST_REF)
{
@@ -450,7 +450,7 @@ static SAPFOR::Argument* processExpression(SgExpression* ex, vector<IR_Block*>&
return arg1;
auto reg = isLeft ? NULL : createRegister();
Instruction* instr = new Instruction(isLeft ? CFG_OP::STORE : CFG_OP::LOAD, arg1, createConstArg(numArgs), isLeft ? isLeft : reg);
Instruction* instr = new Instruction(isLeft ? CFG_OP::STORE : CFG_OP::LOAD, arg1, createConstArg(numArgs), isLeft ? isLeft : reg, NULL, ex);
blocks.push_back(new IR_Block(instr));
return reg;
}
@@ -485,7 +485,7 @@ static SAPFOR::Argument* processExpression(SgExpression* ex, vector<IR_Block*>&
auto arg1 = arrayRef ? arrayRef : createArrayArg(ref, blocks, func, numArgs, commonVars);
auto reg = isLeft ? NULL : createRegister();
instr = new Instruction(isLeft ? CFG_OP::STORE : CFG_OP::LOAD, arg1, createConstArg(1), isLeft ? isLeft : reg);
instr = new Instruction(isLeft ? CFG_OP::STORE : CFG_OP::LOAD, arg1, createConstArg(1), isLeft ? isLeft : reg, NULL, ex);
blocks.push_back(new IR_Block(instr));
return reg;
}
@@ -602,7 +602,7 @@ static SAPFOR::Argument* processExpression(SgExpression* ex, vector<IR_Block*>&
{
if (returnReg == NULL)
{
Instruction* instr = new Instruction(CFG_OP::LOAD, arg, NULL, reg);
Instruction* instr = new Instruction(CFG_OP::LOAD, arg, NULL, reg, NULL, ex);
blocks.push_back(new IR_Block(instr));
}
else
@@ -1572,7 +1572,7 @@ vector<IR_Block*> buildIR(SgStatement* function, const FuncInfo* func, const vec
else
findReturn(0, blocks.size(), blocks, blocks.back()->getNumber());
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> GOTO <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// adding links by GOTO and jumps
for (int z = 0; z < blocks.size(); ++z)
{
auto op = blocks[z]->getInstruction()->getOperation();
@@ -1592,7 +1592,7 @@ vector<IR_Block*> buildIR(SgStatement* function, const FuncInfo* func, const vec
blocks[z]->setJump(it->second);
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// replacing the label with the instruction number
arg->setValue(to_string(it->second->getNumber()));
arg->setType(CFG_ARG_TYPE::INSTR);
}

View File

@@ -827,4 +827,4 @@ namespace Distribution
#undef PAIR
#undef MAP
#undef SET
#undef TO_STR
#undef TO_STR

View File

@@ -1635,9 +1635,9 @@ void loopAnalyzer(SgFile *file, vector<ParallelRegion*> &regions, map<tuple<int,
string fName = file->functions(i)->symbol()->identifier();
#if _WIN32
if (file->functions(i)->variant() != MODULE_STMT)
sendMessage_2lvl(wstring(L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '") + wstring(fName.begin(), fName.end()) + L"'");
sendMessage_2lvl(wstring(L"обработка функции '") + wstring(fName.begin(), fName.end()) + L"'");
else
sendMessage_2lvl(wstring(L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '") + wstring(fName.begin(), fName.end()) + L"'");
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"'");
@@ -1710,7 +1710,10 @@ void loopAnalyzer(SgFile *file, vector<ParallelRegion*> &regions, map<tuple<int,
map<string, pair<SgSymbol*, SgStatement*>> notMappedDistributedArrays;
set<string> mappedDistrbutedArrays;
const ParallelRegionLines* prevParLines = NULL;
double prevLinesWeight = 1.0;
double currentWeight = 1.0;
while (st != lastNode)
{
createNeededException();
@@ -1733,13 +1736,31 @@ void loopAnalyzer(SgFile *file, vector<ParallelRegion*> &regions, map<tuple<int,
}
const int currentLine = st->lineNumber() < -1 ? st->localLineNumber() : st->lineNumber();
ParallelRegion *currReg = getRegionByLine(regions, st->fileName(), currentLine);
auto regAndLines = getRegionAndLinesByLine(regions, st->fileName(), currentLine);
auto *currReg = regAndLines.first;
auto *parLines = regAndLines.second;
if (currReg == NULL)
{
st = st->lexNext();
continue;
}
if (parLines != prevParLines)
{
prevParLines = parLines;
auto newParLinesWeight = parLines ? parLines->weight : 1.0;
if (prevParLines)
currentWeight /= prevLinesWeight;
if (parLines)
currentWeight *= newParLinesWeight;
prevLinesWeight = newParLinesWeight;
prevParLines = parLines;
}
if (isSgExecutableStatement(st) == NULL)
delcsStatViewed.insert(st);
else if (!sharedMemoryParallelization &&
@@ -2168,7 +2189,7 @@ void loopAnalyzer(SgFile *file, vector<ParallelRegion*> &regions, map<tuple<int,
{
string fName = file->functions(i)->symbol()->identifier();
#ifdef _WIN32
sendMessage_2lvl(wstring(L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> ") + std::to_wstring(idx) + L"/" + std::to_wstring(convertedLoopInfo.size()));
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

View File

@@ -93,8 +93,10 @@ static inline SgStatement* getParentStat(SgStatement *st)
return iterator;
}
static void updateRegionInfo(SgStatement *st, map<string, pair<Statement*, Statement*>> &startEnd, map<string, pair<int, int>> &lines_,
set<string> &funcCallFromReg, const map<string, FuncInfo*> &mapFuncs)
static void updateRegionInfo(SgStatement *st, map<string, pair<Statement*, Statement*>> &startEnd,
map<string, pair<int, int>> &lines_,
map<string, map<string, set<int>>> &funcCallFromReg,
const map<string, FuncInfo*> &mapFuncs)
{
string containsPrefix = "";
SgStatement *st_ps = getParentStat(st);
@@ -103,17 +105,26 @@ static void updateRegionInfo(SgStatement *st, map<string, pair<Statement*, State
containsPrefix = st_ps->symbol()->identifier() + string(".");
extendRegionInfo(st, startEnd, lines_);
set<string> callsFromStatement;
if (st->variant() == PROC_STAT)
{
string fullName = st->symbol()->identifier();
//check contains
if (mapFuncs.find(containsPrefix + fullName) != mapFuncs.end())
fullName = containsPrefix + fullName;
funcCallFromReg.insert(fullName);
callsFromStatement.insert(fullName);
}
for (int z = 0; z < 3; ++z)
findFuncCalls(st->expr(z), funcCallFromReg, containsPrefix, mapFuncs);
findFuncCalls(st->expr(z), callsFromStatement, containsPrefix, mapFuncs);
string filename = st->fileName();
int line = st->lineNumber();
for (const auto &func_name : callsFromStatement)
funcCallFromReg[func_name][filename].insert(line);
}
static void fillArrayNamesInReg(set<string> &usedArrayInRegion, SgExpression *exp)
@@ -318,8 +329,9 @@ void fillRegionLines(SgFile *file, vector<ParallelRegion*> &regions, vector<Mess
string regionName = "";
map<string, pair<Statement*, Statement*>> startEnd;
map<string, pair<int, int>> lines_;
set<string> funcCallFromReg;
map<string, map<string, set<int>>> funcCallFromReg;
bool regionStarted = false;
double fragmentWeight = 1.0;
vector<SgStatement*> toDel;
for (int i = 0; i < funcNum; ++i)
@@ -368,6 +380,33 @@ void fillRegionLines(SgFile *file, vector<ParallelRegion*> &regions, vector<Mess
itFunc->second->callRegions.insert(0);
}
}
// parse SPF_APPLY_FRAGMENT clause
auto *apply_fragment = data->expr(1);
fragmentWeight = 1.0;
while (apply_fragment)
{
auto *curr = apply_fragment->lhs();
if (curr)
{
__spf_print(1, "%s %d\n", curr->unparse(), curr->variant());
if (curr->variant() == SPF_WEIGHT_OP)
{
if (curr->lhs() &&
isSgValueExp(curr->lhs()) &&
isSgValueExp(curr->lhs())->doubleValue())
{
fragmentWeight = strtod(isSgValueExp(curr->lhs())->doubleValue(), NULL);
__spf_print(1, "->> %lf\n", fragmentWeight);
}
else
__spf_print(1, "WEIGHT clause without double argument\n");
}
}
apply_fragment = apply_fragment->rhs();
}
}
if (next && next->variant() == SPF_END_PARALLEL_REG_DIR)
@@ -400,10 +439,12 @@ void fillRegionLines(SgFile *file, vector<ParallelRegion*> &regions, vector<Mess
extendRegionInfo(st, startEnd, lines_, true);
for (auto itRegInfo = startEnd.begin(); itRegInfo != startEnd.end(); ++itRegInfo)
currReg->AddLines(lines_[itRegInfo->first], itRegInfo->first, &itRegInfo->second);
currReg->AddLines(lines_[itRegInfo->first], itRegInfo->first, &itRegInfo->second, fragmentWeight);
for (auto &func : funcCallFromReg)
currReg->AddFuncCalls(func);
for (auto &by_func : funcCallFromReg)
for (auto &by_file : by_func.second)
for(auto &by_line : by_file.second)
currReg->AddFuncCalls(by_func.first, by_file.first, by_line);
filterUserDirectives(currReg, usedArrayInRegion, userDvmRedistrDirs, userDvmRealignDirs, userDvmShadowDirs);
currReg->AddUserDirectives(userDvmRealignDirs, DVM_REALIGN_DIR);
@@ -496,34 +537,48 @@ void fillRegionLinesStep2(vector<ParallelRegion*> &regions, const map<string, ve
{
if (regions[i]->GetName() != "DEFAULT")
for (auto &func : regions[i]->GetFuncCalls())
setExplicitFlag(func, funcMap);
setExplicitFlag(func.first, funcMap);
}
for (int i = 0; i < regions.size(); ++i)
{
if (regions[i]->GetName() != "DEFAULT")
{
set<string> uniqFuncCalls;
for (auto &elem : regions[i]->GetFuncCalls())
uniqFuncCalls.insert(elem);
map<string, double> uniqFuncCalls;
map<string, map<string, set<int>>> callPlaces;
for (auto &elem : regions[i]->GetFuncCalls())
{
double max_weight = 0;
for (auto* fragment : elem.second)
if (fragment->weight > max_weight)
max_weight = fragment->weight;
uniqFuncCalls[elem.first] = max_weight;
}
bool wasChanged = true;
auto funcsBefore = uniqFuncCalls;
bool wasChanged = 1;
while (wasChanged)
{
wasChanged = 0;
wasChanged = false;
auto updated = uniqFuncCalls;
for (auto &uniqF : uniqFuncCalls)
{
auto func = funcMap.find(uniqF);
auto func = funcMap.find(uniqF.first);
if (func != funcMap.end())
{
for (auto &calls : func->second->callsFrom)
for (auto &call : func->second->callsFromDetailed)
{
auto it = uniqFuncCalls.find(calls);
if (it == uniqFuncCalls.end())
{
uniqFuncCalls.insert(it, calls);
wasChanged = 1;
}
auto it = updated.find(call.detailCallsFrom.first);
if (it == updated.end())
updated.insert({call.detailCallsFrom.first, uniqF.second});
else
it->second = std::max(it->second, uniqF.second);
callPlaces[call.detailCallsFrom.first][func->second->fileName].insert(call.detailCallsFrom.second);
}
}
}
@@ -532,21 +587,27 @@ void fillRegionLinesStep2(vector<ParallelRegion*> &regions, const map<string, ve
string toPrint = "";
for (auto &elem : uniqFuncCalls)
{
auto it = funcMap.find(elem);
auto it = funcMap.find(elem.first);
if (it != funcMap.end())
{
regions[i]->AddLines(it->second->linesNum, it->second->fileName);
regions[i]->AddFuncCallsToAllCalls(it->second);
regions[i]->AddLines(it->second->linesNum, it->second->fileName, NULL, elem.second);
if (it->second->inRegion == 0)
it->second->inRegion = 2;
it->second->callRegions.insert(i);
toPrint += elem + " ";
toPrint += elem.first + " ";
}
}
for (auto &elem : callPlaces)
{
for (const auto &byFile : elem.second)
for (auto byLine : byFile.second)
regions[i]->AddFuncCalls(elem.first, byFile.first, byLine);
}
if (toPrint != "")
__spf_print(1, "[%s]: funcs: %s\n", regions[i]->GetName().c_str(), toPrint.c_str());
}

View File

@@ -19,7 +19,7 @@
struct ParallelRegionLines
{
ParallelRegionLines()
ParallelRegionLines(double weight = 1.0) : weight(weight)
{
lines = std::make_pair(-1, -1);
stats = std::make_pair<Statement*, Statement*>(NULL, NULL);
@@ -27,14 +27,15 @@ struct ParallelRegionLines
intervalAfter = std::make_pair<Statement*, Statement*>(NULL, NULL);
}
ParallelRegionLines(const std::pair<int, int> &lines) : lines(lines)
ParallelRegionLines(const std::pair<int, int> &lines, double weight = 1.0) : lines(lines), weight(weight)
{
stats = std::make_pair<Statement*, Statement*>(NULL, NULL);
intervalBefore = std::make_pair<Statement*, Statement*>(NULL, NULL);
intervalAfter = std::make_pair<Statement*, Statement*>(NULL, NULL);
}
ParallelRegionLines(const std::pair<int, int> &lines, const std::pair<Statement*, Statement*> stats) : lines(lines), stats(stats)
ParallelRegionLines(const std::pair<int, int> &lines, const std::pair<Statement*, Statement*> stats, double weight = 1.0)
: lines(lines), stats(stats), weight(weight)
{
intervalBefore = std::make_pair<Statement*, Statement*>(NULL, NULL);
intervalAfter = std::make_pair<Statement*, Statement*>(NULL, NULL);
@@ -62,6 +63,8 @@ struct ParallelRegionLines
// <start, end> interval
std::pair<Statement*, Statement*> intervalBefore;
std::pair<Statement*, Statement*> intervalAfter;
double weight; // weight of the fragment among all fragments of this region
};
#if __SPF
@@ -116,7 +119,7 @@ public:
currentVariant = copy.currentVariant;
}
int AddLines(const std::pair<int, int> &linesToAdd, const std::string &file, const std::pair<Statement*, Statement*> *startEnd = NULL)
int AddLines(const std::pair<int, int> &linesToAdd, const std::string &file, const std::pair<Statement*, Statement*> *startEnd = NULL, double weight = 1.0)
{
if (linesToAdd.first > linesToAdd.second)
return -1;
@@ -126,17 +129,29 @@ public:
it = lines.insert(it, make_pair(file, std::vector<ParallelRegionLines>()));
if (startEnd)
it->second.push_back(ParallelRegionLines(linesToAdd, *startEnd));
it->second.push_back(ParallelRegionLines(linesToAdd, *startEnd, weight));
else
it->second.push_back(ParallelRegionLines(linesToAdd));
it->second.push_back(ParallelRegionLines(linesToAdd, weight));
return 0;
}
void AddFuncCalls(const std::string &func) { functionsCall.insert(func); }
void AddFuncCalls(const std::string &func, const std::string &file, const int line)
{
auto *found_lines = GetLinesByLine(file, line);
if (found_lines)
functionsCall[func].insert(found_lines);
}
#if __SPF
void AddFuncCallsToAllCalls(FuncInfo *func) { allFunctionsCall.insert(func); }
void AddFuncCallsToAllCalls(FuncInfo *func, const std::string &file, const int line)
{
auto *found_lines = GetLinesByLine(file, line);
if (found_lines)
allFunctionsCall[func].insert(found_lines);
}
#endif
uint64_t GetId() const { return regionId; }
@@ -176,10 +191,10 @@ public:
const DataDirective& GetDataDir() const { return dataDirectives; }
DataDirective& GetDataDirToModify() { return dataDirectives; }
const std::set<std::string>& GetFuncCalls() const { return functionsCall; }
const std::map<std::string, std::set<const ParallelRegionLines*>>& GetFuncCalls() const { return functionsCall; }
#if __SPF
const std::set<FuncInfo*>& GetAllFuncCalls() const { return allFunctionsCall; }
const std::map<FuncInfo*, std::set<const ParallelRegionLines*>>& GetAllFuncCalls() const { return allFunctionsCall; }
const std::map<FuncInfo*, std::map<DIST::Array*, std::vector<ParallelRegionLines>>>& GetUsedLocalArrays() const { return usedLocalArrays; }
const std::map<FuncInfo*, std::map<DIST::Array*, std::vector<ParallelRegionLines>>>& GetUsedCommonArrays() const { return usedCommonArrays; }
@@ -218,7 +233,7 @@ public:
}
#endif
bool HasThisLine(const int line, const std::string &file) const
bool HasThisLine(const int line, const std::string &file, const ParallelRegionLines** found = nullptr) const
{
bool retVal = false;
auto it = lines.find(file);
@@ -229,6 +244,9 @@ public:
if (it->second[i].lines.first <= line && it->second[i].lines.second >= line)
{
retVal = true;
if (found)
*found = &(it->second[i]);
break;
}
}
@@ -292,7 +310,7 @@ public:
fprintf(fileOut, " originalName '%s'\n", originalName.c_str());
fprintf(fileOut, " functions call from %d:\n", (int)functionsCall.size());
for (auto &func : functionsCall)
fprintf(fileOut, " '%s'\n", func.c_str());
fprintf(fileOut, " '%s'\n", func.first.c_str());
fprintf(fileOut, " total lines %d:\n", (int)lines.size());
for (auto &line : lines)
{
@@ -362,11 +380,11 @@ private:
std::string originalName;
// file -> lines info
std::map<std::string, std::vector<ParallelRegionLines>> lines;
std::set<std::string> functionsCall;
std::map<std::string, std::set<const ParallelRegionLines*>> functionsCall; // func name -> fragments with calls
#if __SPF
// for RESOLVE_PAR_REGIONS
std::set<FuncInfo*> allFunctionsCall;
std::map<FuncInfo*, std::set<const ParallelRegionLines*>> allFunctionsCall; // function -> fragments with calls
std::map<FuncInfo*, std::map<DIST::Array*, std::vector<ParallelRegionLines>>> usedLocalArrays; // func -> array -> lines
std::map<FuncInfo*, std::map<DIST::Array*, std::vector<ParallelRegionLines>>> usedCommonArrays; // func -> array -> lines
//
@@ -408,4 +426,5 @@ private:
ParallelRegion* getRegionById(const std::vector<ParallelRegion*>& regions, const uint64_t regionId);
ParallelRegion* getRegionByName(const std::vector<ParallelRegion*>& regions, const std::string& regionName);
ParallelRegion* getRegionByLine(const std::vector<ParallelRegion*>& regions, const std::string& file, const int line);
std::pair<ParallelRegion*, const ParallelRegionLines*> getRegionAndLinesByLine(const std::vector<ParallelRegion*>& regions, const std::string& file, const int line);
std::set<ParallelRegion*> getAllRegionsByLine(const std::vector<ParallelRegion*>& regions, const std::string& file, const int line);

View File

@@ -0,0 +1,141 @@
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <vector>
#include <queue>
#include <numeric>
#include <iostream>
#include "private_arrays_search.h"
#include "range_structures.h"
#include "region.h"
#include "../Utils/SgUtils.h"
#include "../GraphLoop/graph_loops.h"
#include "../CFGraph/CFGraph.h"
using namespace std;
void Collapse(Region* region)
{
if (region->getBasickBlocks().empty())
return;
for (auto& [arrayName, arrayRanges] : region->getHeader()->array_out)
{
for (Region* byBlock : region->getBasickBlocks())
{
AccessingSet intersection = byBlock->array_def[arrayName].Intersect(arrayRanges);
region->array_def[arrayName] = region->array_def[arrayName].Union(intersection);
}
}
for (auto& byBlock : region->getBasickBlocks())
{
for (auto& [arrayName, arrayRanges] : byBlock->array_use)
{
AccessingSet diff = byBlock->array_use[arrayName].Diff(byBlock->array_in[arrayName]);
region->array_use[arrayName] = region->array_use[arrayName].Union(diff);
}
}
ArrayAccessingIndexes useUnion;
for (auto& byBlock : region->getBasickBlocks())
for (auto& [arrayName, arrayRanges] : byBlock->array_use)
useUnion[arrayName] = useUnion[arrayName].Union(byBlock->array_use[arrayName]);
for (auto& [arrayName, arrayRanges] : useUnion)
region->array_priv[arrayName] = useUnion[arrayName].Diff(region->array_use[arrayName]);
for (Region* prevBlock : region->getHeader()->getPrevRegions())
prevBlock->replaceInNextRegions(region, region->getHeader());
for (Region* nextBlock : region->getHeader()->getNextRegions())
nextBlock->replaceInPrevRegions(region, region->getHeader());
}
static void SolveDataFlowIteratively(Region* DFG)
{
unordered_set<Region*> worklist(DFG->getBasickBlocks());
do
{
Region* b = *worklist.begin();
ArrayAccessingIndexes newIn;
bool flagFirst = true;
for (Region* prevBlock : b->getPrevRegions())
{
if (flagFirst)
{
newIn = prevBlock->array_out;
flagFirst = false;
}
else
{
if (prevBlock->array_out.empty())
{
newIn.clear();
continue;
}
for (const auto& [arrayName, accessSet] : prevBlock->array_out)
{
if (newIn.find(arrayName) != newIn.end())
newIn[arrayName] = newIn[arrayName].Intersect(accessSet);
else
newIn[arrayName] = AccessingSet();
}
}
}
b->array_in = move(newIn);
ArrayAccessingIndexes newOut;
if (b->array_def.empty())
newOut = b->array_in;
else if (b->array_in.empty())
newOut = b->array_def;
else
{
for (auto& [arrayName, accessSet] : b->array_def)
{
if (newOut.find(arrayName) != newOut.end())
newOut[arrayName] = b->array_def[arrayName].Union(b->array_in[arrayName]);
else
newOut[arrayName] = accessSet;
}
}
/* can not differ */
if (newOut != b->array_out)
b->array_out = newOut;
else
worklist.erase(b);
}
while (!worklist.empty());
}
static void SolveDataFlow(Region* DFG)
{
if (!DFG)
return;
SolveDataFlowIteratively(DFG);
for (Region* subRegion : DFG->getSubRegions())
SolveDataFlow(subRegion);
Collapse(DFG);
}
map<LoopGraph*, ArrayAccessingIndexes> FindPrivateArrays(map<string, vector<LoopGraph*>> &loopGraph, map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& FullIR)
{
map<LoopGraph*, ArrayAccessingIndexes> result;
for (const auto& [loopName, loops] : loopGraph)
{
for (const auto& loop : loops)
{
for (const auto& [funcInfo, blocks]: FullIR)
{
Region* loopRegion = new Region(loop, blocks);
SolveDataFlow(loopRegion);
result[loop] = loopRegion->array_priv;
delete(loopRegion);
}
}
}
return result;
}

View File

@@ -0,0 +1,14 @@
#pragma once
#include <vector>
#include <map>
#include <unordered_set>
#include "range_structures.h"
#include "region.h"
#include "../GraphLoop/graph_loops.h"
#include "../CFGraph/CFGraph.h"
void Collapse(Region* region);
std::map<LoopGraph*, ArrayAccessingIndexes> FindPrivateArrays(std::map<std::string, std::vector<LoopGraph*>>& loopGraph, std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& FullIR);
std::pair<SAPFOR::BasicBlock*, std::unordered_set<SAPFOR::BasicBlock*>> GetBasicBlocksForLoop(const LoopGraph* loop, const std::vector<SAPFOR::BasicBlock*> blocks);

View File

@@ -0,0 +1,293 @@
#include <vector>
#include <map>
#include <unordered_set>
#include <string>
#include <numeric>
#include "range_structures.h"
using namespace std;
static vector<uint64_t> FindParticularSolution(const ArrayDimension& dim1, const ArrayDimension& dim2)
{
for (uint64_t i = 0; i < dim1.tripCount; i++)
{
uint64_t leftPart = dim1.start + i * dim1.step;
for (uint64_t j = 0; j < dim2.tripCount; j++)
{
uint64_t rightPart = dim2.start + j * dim2.step;
if (leftPart == rightPart)
return { i, j };
}
}
return {};
}
/* dim1 /\ dim2 */
static ArrayDimension* DimensionIntersection(const ArrayDimension& dim1, const ArrayDimension& dim2)
{
vector<uint64_t> partSolution = FindParticularSolution(dim1, dim2);
if (partSolution.empty())
return NULL;
int64_t x0 = partSolution[0], y0 = partSolution[1];
/* x = x_0 + c * t */
/* y = y_0 + d * t */
int64_t c = dim2.step / gcd(dim1.step, dim2.step);
int64_t d = dim1.step / gcd(dim1.step, dim2.step);
int64_t tXMin, tXMax, tYMin, tYMax;
tXMin = -x0 / c;
tXMax = (dim1.tripCount - 1 - x0) / c;
tYMin = -y0 / d;
tYMax = (dim2.tripCount - 1 - y0) / d;
int64_t tMin = max(tXMin, tYMin);
uint64_t tMax = min(tXMax, tYMax);
if (tMin > tMax)
return NULL;
uint64_t start3 = dim1.start + x0 * dim1.step;
uint64_t step3 = c * dim1.step;
ArrayDimension* result = new(ArrayDimension){ start3, step3, tMax + 1 };
return result;
}
/* dim1 / dim2 */
static vector<ArrayDimension> DimensionDifference(const ArrayDimension& dim1, const ArrayDimension& dim2)
{
ArrayDimension* intersection = DimensionIntersection(dim1, dim2);
if (!intersection)
return { dim1 };
vector<ArrayDimension> result;
/* add the part before intersection */
if (dim1.start < intersection->start)
result.push_back({ dim1.start, dim1.step, (intersection->start - dim1.start) / dim1.step });
/* add the parts between intersection steps */
uint64_t start = (intersection->start - dim1.start) / dim1.step;
uint64_t interValue = intersection->start;
for (int64_t i = start; dim1.start + i * dim1.step <= intersection->start + intersection->step * (intersection->tripCount - 1); i++)
{
uint64_t centerValue = dim1.start + i * dim1.step;
if (centerValue == interValue)
{
if (i - start > 1)
{
result.push_back({ dim1.start + (start + 1) * dim1.step, dim1.step, i - start - 1 });
start = i;
}
interValue += intersection->step;
}
}
/* add the part after intersection */
if (intersection->start + intersection->step * (intersection->tripCount - 1) < dim1.start + dim1.step * (dim1.tripCount - 1))
{
/* first value after intersection */
uint64_t right_start = intersection->start + intersection->step * (intersection->tripCount - 1) + dim1.step;
uint64_t tripCount = (dim1.start + dim1.step * dim1.tripCount - right_start) / dim1.step;
result.push_back({ right_start, dim1.step, tripCount });
}
delete(intersection);
return result;
}
static vector<ArrayDimension> DimensionUnion(const ArrayDimension& dim1, const ArrayDimension& dim2)
{
vector<ArrayDimension> res;
ArrayDimension* inter = DimensionIntersection(dim1, dim2);
if (!inter)
return { dim1, dim2 };
res.push_back(*inter);
delete(inter);
vector<ArrayDimension> diff1, diff2;
diff1 = DimensionDifference(dim1, dim2);
diff2 = DimensionDifference(dim2, dim1);
res.insert(res.end(), diff1.begin(), diff1.end());
res.insert(res.end(), diff2.begin(), diff2.end());
return res;
}
static vector<ArrayDimension> ElementsIntersection(const vector<ArrayDimension>& firstElement, const vector<ArrayDimension>& secondElement)
{
if (firstElement.empty() || secondElement.empty())
return {};
size_t dimAmount = firstElement.size();
/* check if there is no intersecction */
for (size_t i = 0; i < dimAmount; i++)
if (FindParticularSolution(firstElement[i], secondElement[i]).empty())
return {};
vector<ArrayDimension> result(dimAmount);
for (size_t i = 0; i < dimAmount; i++)
{
ArrayDimension* resPtr = DimensionIntersection(firstElement[i], secondElement[i]);
if (resPtr)
result[i] = *resPtr;
else
return {};
}
return result;
}
static vector<vector<ArrayDimension>> ElementsDifference(const vector<ArrayDimension>& firstElement,
const vector<ArrayDimension>& secondElement)
{
if (firstElement.empty() || secondElement.empty())
return {};
vector<ArrayDimension> intersection = ElementsIntersection(firstElement, secondElement);
vector<vector<ArrayDimension>> result;
if (intersection.empty())
return { firstElement };
for (int i = 0; i < firstElement.size(); i++)
{
auto dimDiff = DimensionDifference(firstElement[i], secondElement[i]);
if (!dimDiff.empty())
{
vector<ArrayDimension> firstCopy = firstElement;
for (const auto& range : dimDiff)
{
firstCopy[i] = range;
result.push_back(firstCopy);
}
}
}
return result;
}
static void ElementsUnion(const vector<ArrayDimension>& firstElement, const vector<ArrayDimension>& secondElement,
vector<vector<ArrayDimension>>& lc, vector<vector<ArrayDimension>>& rc,
vector<ArrayDimension>& intersection)
{
/* lc(rc) is a set of ranges, which only exist in first(second) element*/
intersection = ElementsIntersection(firstElement, secondElement);
lc = ElementsDifference(firstElement, intersection);
rc = ElementsDifference(secondElement, intersection);
}
void AccessingSet::FindUncovered(const vector<ArrayDimension>& element, vector<vector<ArrayDimension>>& result) const {
vector<vector<ArrayDimension>> newTails;
result.push_back(element);
for (const auto& currentElement : allElements)
{
for (const auto& tailLoc : result)
{
auto intersection = ElementsIntersection(tailLoc, currentElement);
auto diff = ElementsDifference(tailLoc, intersection);
if (!diff.empty()) {
newTails.insert(newTails.end(), diff.begin(), diff.end());
}
}
result = newTails;
newTails.clear();
}
}
bool AccessingSet::ContainsElement(const vector<ArrayDimension>& element) const
{
vector<vector<ArrayDimension>> tails;
FindUncovered(element, tails);
return !tails.empty();
}
void AccessingSet::FindCoveredBy(const vector<ArrayDimension>& element, vector<vector<ArrayDimension>>& result) const
{
for (const auto& currentElement : allElements)
{
auto intersection = ElementsIntersection(element, currentElement);
if (!intersection.empty())
result.push_back(intersection);
}
}
vector<vector<ArrayDimension>> AccessingSet::GetElements() const { return allElements; }
void AccessingSet::Insert(const vector<ArrayDimension>& element)
{
vector<vector<ArrayDimension>> tails;
FindUncovered(element, tails);
allElements.insert(allElements.end(), tails.begin(), tails.end());
}
AccessingSet AccessingSet::Union(const AccessingSet& source) {
AccessingSet result;
for (auto& element : source.GetElements())
result.Insert(element);
for (auto& element : allElements)
result.Insert(element);
return result;
}
AccessingSet AccessingSet::Intersect(const AccessingSet& secondSet) const
{
vector<vector<ArrayDimension>> result;
if (secondSet.GetElements().empty() || this->allElements.empty())
return AccessingSet(result);
for (const auto& element : allElements)
{
if (secondSet.ContainsElement(element))
result.push_back(element);
else
{
vector<vector<ArrayDimension>> coveredBy;
secondSet.FindCoveredBy(element, coveredBy);
if (!coveredBy.empty())
result.insert(result.end(), coveredBy.begin(), coveredBy.end());
}
}
return AccessingSet(result);
}
AccessingSet AccessingSet::Diff(const AccessingSet& secondSet) const
{
if (secondSet.GetElements().empty() || allElements.empty())
return *this;
AccessingSet intersection = this->Intersect(secondSet);
AccessingSet uncovered = *this;
vector<vector<ArrayDimension>> result;
for (const auto& element : intersection.GetElements())
{
vector<vector<ArrayDimension>> current_uncovered;
uncovered.FindUncovered(element, current_uncovered);
uncovered = AccessingSet(current_uncovered);
}
return uncovered;
}
bool operator!=(const ArrayDimension& lhs, const ArrayDimension& rhs)
{
return !(lhs.start == rhs.start && lhs.step == rhs.step && lhs.tripCount == rhs.tripCount);
}
bool operator!=(const AccessingSet& lhs, const AccessingSet& rhs)
{
for (size_t i = 0; i < lhs.allElements.size(); i++)
for (size_t j = 0; j < lhs.allElements[i].size(); j++)
if (lhs.allElements[i][j] != rhs.allElements[i][j])
return true;
return false;
}
bool operator!=(const ArrayAccessingIndexes& lhs, const ArrayAccessingIndexes& rhs)
{
if (lhs.size() != rhs.size())
return true;
for (auto& [key, value] : lhs)
if (rhs.find(key) == rhs.end())
return true;
return false;
}

View File

@@ -0,0 +1,37 @@
#pragma once
#include <vector>
#include <map>
#include <unordered_set>
#include <string>
#include <cstdint>
struct ArrayDimension
{
uint64_t start, step, tripCount;
};
class AccessingSet {
private:
std::vector<std::vector<ArrayDimension>> allElements;
public:
AccessingSet(std::vector<std::vector<ArrayDimension>> input) : allElements(input) {};
AccessingSet() {};
AccessingSet(const AccessingSet& a) { allElements = a.GetElements(); };
std::vector<std::vector<ArrayDimension>> GetElements() const;
void Insert(const std::vector<ArrayDimension>& element);
AccessingSet Union(const AccessingSet& source);
AccessingSet Intersect(const AccessingSet& secondSet) const;
AccessingSet Diff(const AccessingSet& secondSet) const;
bool ContainsElement(const std::vector<ArrayDimension>& element) const;
void FindCoveredBy(const std::vector<ArrayDimension>& element, std::vector<std::vector<ArrayDimension>>& result) const;
void FindUncovered(const std::vector<ArrayDimension>& element, std::vector<std::vector<ArrayDimension>>& result) const;
friend bool operator!=(const AccessingSet& lhs, const AccessingSet& rhs);
};
using ArrayAccessingIndexes = std::map<std::string, AccessingSet>;
bool operator!=(const ArrayDimension& lhs, const ArrayDimension& rhs);
bool operator!=(const AccessingSet& lhs, const AccessingSet& rhs);
bool operator!=(const ArrayAccessingIndexes& lhs, const ArrayAccessingIndexes& rhs);

View File

@@ -0,0 +1,251 @@
#include<vector>
#include<map>
#include<unordered_set>
#include<unordered_map>
#include<string>
#include <numeric>
#include "range_structures.h"
#include "region.h"
#include "../Utils/SgUtils.h"
using namespace std;
static bool isParentStmt(SgStatement* stmt, SgStatement* parent)
{
for (; stmt; stmt = stmt->controlParent())
if (stmt == parent)
return true;
return false;
}
/*returns head block and loop*/
pair<SAPFOR::BasicBlock*, unordered_set<SAPFOR::BasicBlock*>> GetBasicBlocksForLoop(const LoopGraph* loop, const vector<SAPFOR::BasicBlock*> blocks)
{
unordered_set<SAPFOR::BasicBlock*> block_loop;
SAPFOR::BasicBlock* head_block = nullptr;
auto loop_operator = loop->loop->GetOriginal();
for (const auto& block : blocks)
{
if (!block || (block->getInstructions().size() == 0))
continue;
SgStatement* first = block->getInstructions().front()->getInstruction()->getOperator();
SgStatement* last = block->getInstructions().back()->getInstruction()->getOperator();
if (isParentStmt(first, loop_operator) && isParentStmt(last, loop_operator))
{
block_loop.insert(block);
if ((!head_block) && (first == loop_operator) && (last == loop_operator) &&
(block->getInstructions().size() == 2) &&
(block->getInstructions().back()->getInstruction()->getOperation() == SAPFOR::CFG_OP::JUMP_IF))
{
head_block = block;
}
}
}
return { head_block, block_loop };
}
static void BuildLoopIndex(map<string, LoopGraph*>& loopForIndex, LoopGraph* loop) {
string index = loop->loopSymbol;
loopForIndex[index] = loop;
for (const auto& childLoop : loop->children)
BuildLoopIndex(loopForIndex, childLoop);
}
static string FindIndexName(int pos, SAPFOR::BasicBlock* block, map<string, LoopGraph*>& loopForIndex) {
unordered_set<SAPFOR::Argument*> args = { block->getInstructions()[pos]->getInstruction()->getArg1() };
for (int i = pos - 1; i >= 0; i--)
{
SAPFOR::Argument* res = block->getInstructions()[i]->getInstruction()->getResult();
if (res && args.find(res) != args.end())
{
SAPFOR::Argument* arg1 = block->getInstructions()[i]->getInstruction()->getArg1();
SAPFOR::Argument* arg2 = block->getInstructions()[i]->getInstruction()->getArg2();
if (arg1)
{
string name = arg1->getValue();
int idx = name.find('%');
if (idx != -1 && loopForIndex.find(name.substr(idx + 1)) != loopForIndex.end())
return name.substr(idx + 1);
else
args.insert(arg1);
}
if (arg2)
{
string name = arg2->getValue();
int idx = name.find('%');
if (idx != -1 && loopForIndex.find(name.substr(idx + 1)) != loopForIndex.end())
return name.substr(idx + 1);
else
args.insert(arg2);
}
}
}
return "";
}
static int GetDefUseArray(SAPFOR::BasicBlock* block, LoopGraph* loop, ArrayAccessingIndexes& def, ArrayAccessingIndexes& use) {
auto instructions = block->getInstructions();
map<string, LoopGraph*> loopForIndex;
BuildLoopIndex(loopForIndex, loop);
for (int i = 0; i < instructions.size(); i++)
{
auto instruction = instructions[i];
if (!instruction->getInstruction()->getArg1())
continue;
auto operation = instruction->getInstruction()->getOperation();
auto type = instruction->getInstruction()->getArg1()->getType();
if ((operation == SAPFOR::CFG_OP::STORE || operation == SAPFOR::CFG_OP::LOAD) && type == SAPFOR::CFG_ARG_TYPE::ARRAY)
{
vector<SAPFOR::Argument*> index_vars;
vector<int> refPos;
string array_name;
if (operation == SAPFOR::CFG_OP::STORE)
array_name = instruction->getInstruction()->getArg1()->getValue();
else
array_name = instruction->getInstruction()->getArg2()->getValue();
int j = i - 1;
while (j >= 0 && instructions[j]->getInstruction()->getOperation() == SAPFOR::CFG_OP::REF)
{
index_vars.push_back(instructions[j]->getInstruction()->getArg1());
refPos.push_back(j);
j--;
}
/*to choose correct dimension*/
int n = index_vars.size();
vector<ArrayDimension> accessPoint(n);
auto* ref = isSgArrayRefExp(instruction->getInstruction()->getExpression());
vector<pair<int, int>> coefsForDims;
for (int i = 0; ref && i < ref->numberOfSubscripts(); ++i)
{
const vector<int*>& coefs = getAttributes<SgExpression*, int*>(ref->subscript(i), set<int>{ INT_VAL });
if (coefs.size() == 1)
{
const pair<int, int> coef(coefs[0][0], coefs[0][1]);
coefsForDims.push_back(coef);
}
}
if(coefsForDims.empty())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
while (!index_vars.empty())
{
auto var = index_vars.back();
int currentVarPos = refPos.back();
pair currentCoefs = coefsForDims.back();
ArrayDimension current_dim;
if (var->getType() == SAPFOR::CFG_ARG_TYPE::CONST)
current_dim = { stoul(var->getValue()), 1, 1 };
else
{
string name, full_name = var->getValue();
int pos = full_name.find('%');
LoopGraph* currentLoop;
if (pos != -1)
{
name = full_name.substr(pos + 1);
if (loopForIndex.find(name) != loopForIndex.end())
currentLoop = loopForIndex[name];
else
return -1;
}
else
{
name = FindIndexName(currentVarPos, block, loopForIndex);
if (name == "")
return -1;
if (loopForIndex.find(name) != loopForIndex.end())
currentLoop = loopForIndex[name];
else
return -1;
}
uint64_t start = currentLoop->startVal * currentCoefs.first + currentCoefs.second;
uint64_t step = currentCoefs.first;
current_dim = { start, step, (uint64_t)currentLoop->calculatedCountOfIters };
}
accessPoint[n - index_vars.size()] = current_dim;
index_vars.pop_back();
refPos.pop_back();
coefsForDims.pop_back();
}
if (operation == SAPFOR::CFG_OP::STORE)
def[array_name].Insert(accessPoint);
else
use[array_name].Insert(accessPoint);
}
}
return 0;
}
static void SetConnections(unordered_map<SAPFOR::BasicBlock*, Region*>& bbToRegion, const unordered_set<SAPFOR::BasicBlock*>& blockSet)
{
for (SAPFOR::BasicBlock* block : blockSet)
{
for (SAPFOR::BasicBlock* nextBlock : block->getNext())
if (bbToRegion.find(nextBlock) != bbToRegion.end())
bbToRegion[block]->addNextRegion(bbToRegion[nextBlock]);
for (SAPFOR::BasicBlock* prevBlock : block->getPrev())
if (bbToRegion.find(prevBlock) != bbToRegion.end())
bbToRegion[block]->addPrevRegion(bbToRegion[prevBlock]);
}
}
static Region* CreateSubRegion(LoopGraph* loop, const vector<SAPFOR::BasicBlock*>& Blocks, const unordered_map<SAPFOR::BasicBlock*, Region*>& bbToRegion)
{
Region* region = new Region;
auto [header, blockSet] = GetBasicBlocksForLoop(loop, Blocks);
if (bbToRegion.find(header) != bbToRegion.end())
region->setHeader(bbToRegion.at(header));
else
{
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
return NULL;
}
for (SAPFOR::BasicBlock* block : blockSet)
if (bbToRegion.find(block) != bbToRegion.end())
region->addBasickBlocks(bbToRegion.at(block));
for (LoopGraph* childLoop : loop->children)
region->addSubRegions(CreateSubRegion(childLoop, Blocks, bbToRegion));
return region;
}
Region::Region(LoopGraph* loop, const vector<SAPFOR::BasicBlock*>& Blocks)
{
auto [header, blockSet] = GetBasicBlocksForLoop(loop, Blocks);
unordered_map<SAPFOR::BasicBlock*, Region*> bbToRegion;
for (auto poiner : blockSet)
{
bbToRegion[poiner] = new Region(*poiner);
this->basickBlocks.insert(bbToRegion[poiner]);
GetDefUseArray(poiner, loop, bbToRegion[poiner]->array_def, bbToRegion[poiner]->array_use);
}
this->header = bbToRegion[header];
SetConnections(bbToRegion, blockSet);
//create subRegions
for (LoopGraph* childLoop : loop->children)
subRegions.insert(CreateSubRegion(childLoop, Blocks, bbToRegion));
}

View File

@@ -0,0 +1,60 @@
#pragma once
#include <vector>
#include <map>
#include <unordered_set>
#include <string>
#include "../GraphLoop/graph_loops.h"
#include "../CFGraph/CFGraph.h"
class Region : public SAPFOR::BasicBlock {
public:
Region() { header = nullptr; }
Region(SAPFOR::BasicBlock block) : SAPFOR::BasicBlock::BasicBlock(block) { header = nullptr; }
Region(LoopGraph* loop, const std::vector<SAPFOR::BasicBlock*>& Blocks);
Region* getHeader() { return header; }
void setHeader(Region* region) { header = region; }
std::unordered_set<Region*>& getBasickBlocks() { return basickBlocks; }
void addBasickBlocks(Region* region) { basickBlocks.insert(region); }
const std::unordered_set<Region*>& getPrevRegions() { return prevRegions; }
std::unordered_set<Region*> getNextRegions() { return nextRegions; }
void addPrevRegion(Region* region) { prevRegions.insert(region); }
void addNextRegion(Region* region) { nextRegions.insert(region); }
void replaceInPrevRegions(Region* source, Region* destination)
{
prevRegions.erase(destination);
prevRegions.insert(source);
}
void replaceInNextRegions(Region* source, Region* destination)
{
nextRegions.erase(destination);
nextRegions.insert(source);
}
std::unordered_set<Region*> getSubRegions() { return subRegions; }
void addSubRegions(Region* region) { subRegions.insert(region); }
ArrayAccessingIndexes array_def, array_use, array_out, array_in, array_priv;
private:
std::unordered_set<Region*> subRegions, basickBlocks;
/*next Region which is BB for current BB Region*/
std::unordered_set<Region*> nextRegions;
/*prev Regions which is BBs for current BB Region*/
std::unordered_set<Region*> prevRegions;
Region* header;
};

View File

@@ -55,6 +55,7 @@
#include "VerificationCode/verifications.h"
#include "Distribution/CreateDistributionDirs.h"
#include "PrivateAnalyzer/private_analyzer.h"
#include "PrivateAnalyzer/private_arrays_search.h"
#include "ExpressionTransform/expr_transform.h"
#include "Predictor/PredictScheme.h"
@@ -71,6 +72,8 @@
#include "VisualizerCalls/SendMessage.h"
#include "VisualizerCalls/BuildGraph.h"
#include "SwapOperators/swapOperators.h"
#include "Transformations/enddo_loop_converter.h"
#include "Transformations/loop_transform.h"
#include "Transformations/array_assign_to_loop.h"
@@ -948,6 +951,10 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne
internalExit = err;
}
}
else if (curr_regime == SWAP_OPERATORS)
{
runSwapOperators(file, loopGraph, fullIR, countOfTransform);
}
else if (curr_regime == PRIVATE_REMOVING_ANALYSIS)
{
auto itFound = loopGraph.find(file->filename());
@@ -1028,6 +1035,8 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne
if(func->funcPointer->variant() != ENTRY_STAT)
countOfTransform += removeDeadCode(func->funcPointer, allFuncInfo, commonBlocks);
}
else if (curr_regime == FIND_PRIVATE_ARRAYS)
FindPrivateArrays(loopGraph, fullIR);
else if (curr_regime == TEST_PASS)
{
//test pass
@@ -1044,7 +1053,8 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne
PRIVATE_REMOVING,
PRIVATE_ARRAYS_EXPANSION,
PRIVATE_ARRAYS_SHRINKING,
REMOVE_DEAD_CODE };
REMOVE_DEAD_CODE,
SWAP_OPERATORS };
if ((countOfTransform == 0 || internalExit > 0) && applyFor.find(curr_regime) != applyFor.end())
{
@@ -2338,6 +2348,7 @@ void runPass(const int curr_regime, const char *proj_name, const char *folderNam
case INSERT_NO_DISTR_FLAGS_FROM_GUI:
case PRIVATE_REMOVING:
case RENAME_INLCUDES:
case SWAP_OPERATORS:
runAnalysis(*project, curr_regime, true, "", folderName);
break;
case INLINE_PROCEDURES:

View File

@@ -122,6 +122,8 @@ enum passes {
CREATE_INTER_TREE,
INSERT_INTER_TREE,
SWAP_OPERATORS,
SHADOW_GROUPING,
INLINE_PROCEDURES,
FILL_PARALLEL_REG_IR,
@@ -183,6 +185,8 @@ enum passes {
SET_IMPLICIT_NONE,
RENAME_INLCUDES,
FIND_PRIVATE_ARRAYS,
TEST_PASS,
EMPTY_PASS
};
@@ -315,6 +319,7 @@ static void setPassValues()
passNames[CHECK_PAR_REG_DIR] = "CHECK_PAR_REG_DIR";
passNames[CREATE_INTER_TREE] = "CREATE_INTER_TREE";
passNames[INSERT_INTER_TREE] = "INSERT_INTER_TREE";
passNames[SWAP_OPERATORS] = "SWAP_OPERATORS";
passNames[CREATE_PARALLEL_REGIONS] = "CREATE_PARALLEL_REGIONS";
passNames[PRIVATE_REMOVING_ANALYSIS] = "PRIVATE_REMOVING_ANALYSIS";
passNames[PRIVATE_REMOVING] = "PRIVATE_REMOVING";
@@ -367,6 +372,7 @@ static void setPassValues()
passNames[SET_IMPLICIT_NONE] = "SET_IMPLICIT_NONE";
passNames[RENAME_INLCUDES] = "RENAME_INLCUDES";
passNames[INSERT_NO_DISTR_FLAGS_FROM_GUI] = "INSERT_NO_DISTR_FLAGS_FROM_GUI";
passNames[FIND_PRIVATE_ARRAYS] = "FIND_PRIVATE_ARRAYS";
passNames[TEST_PASS] = "TEST_PASS";
}

View File

@@ -0,0 +1,353 @@
#include <map>
#include <unordered_set>
#include <vector>
#include <queue>
#include <iostream>
#include "../Utils/errors.h"
#include "../Utils/SgUtils.h"
#include "../GraphCall/graph_calls.h"
#include "../GraphCall/graph_calls_func.h"
#include "../CFGraph/CFGraph.h"
#include "../CFGraph/IR.h"
#include "../GraphLoop/graph_loops.h"
#include "swapOperators.h"
using namespace std;
unordered_set<int> loop_tags = {FOR_NODE/*, FORALL_NODE, WHILE_NODE, DO_WHILE_NODE*/};
unordered_set<int> importantDepsTags = {FOR_NODE, IF_NODE};
unordered_set<int> importantUpdDepsTags = {ELSEIF_NODE};
unordered_set<int> importantEndTags = {CONTROL_END};
vector<SAPFOR::IR_Block*> findInstructionsFromOperator(SgStatement* st, vector<SAPFOR::BasicBlock*> Blocks)
{
vector<SAPFOR::IR_Block*> result;
string filename = st -> fileName();
for (auto& block: Blocks)
{
vector<SAPFOR::IR_Block*> instructionsInBlock = block -> getInstructions();
for (auto& instruction: instructionsInBlock)
{
SgStatement* curOperator = instruction -> getInstruction() -> getOperator();
if (curOperator -> lineNumber() == st -> lineNumber())
result.push_back(instruction);
}
}
return result;
}
vector<SAPFOR::BasicBlock*> findFuncBlocksByFuncStatement(SgStatement *st, map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& FullIR)
{
vector<SAPFOR::BasicBlock*> result;
Statement* forSt = (Statement*)st;
for (auto& func: FullIR)
{
if (func.first -> funcPointer -> getCurrProcessFile() == forSt -> getCurrProcessFile()
&& func.first -> funcPointer -> lineNumber() == forSt -> lineNumber())
result = func.second;
}
return result;
}
map<SgForStmt*, vector<SAPFOR::BasicBlock*>> findAndAnalyzeLoops(SgStatement *st, vector<SAPFOR::BasicBlock*> blocks)
{
map<SgForStmt*, vector<SAPFOR::BasicBlock*>> result;
SgStatement *lastNode = st->lastNodeOfStmt();
while (st && st != lastNode)
{
if (loop_tags.find(st -> variant()) != loop_tags.end())
{
// part with find statements of loop
SgForStmt *forSt = (SgForStmt*)st;
SgStatement *loopBody = forSt -> body();
SgStatement *lastLoopNode = st->lastNodeOfStmt();
// part with find blocks and instructions of loops
unordered_set<int> blocks_nums;
while (loopBody && loopBody != lastLoopNode)
{
SAPFOR::IR_Block* IR = findInstructionsFromOperator(loopBody, blocks).front();
if (blocks_nums.find(IR -> getBasicBlock() -> getNumber()) == blocks_nums.end())
{
result[forSt].push_back(IR -> getBasicBlock());
blocks_nums.insert(IR -> getBasicBlock() -> getNumber());
}
loopBody = loopBody -> lexNext();
}
std::sort(result[forSt].begin(), result[forSt].end());
}
st = st -> lexNext();
}
return result;
}
map<SgStatement*, set<SgStatement*>> AnalyzeLoopAndFindDeps(SgForStmt* forStatement, vector<SAPFOR::BasicBlock*> loopBlocks, map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& FullIR)
{
map<SgStatement*, set<SgStatement*>> result;
for (SAPFOR::BasicBlock* bb: loopBlocks)
{
map<SAPFOR::Argument*, set<int>> blockReachingDefinitions = bb -> getRD_In();
vector<SAPFOR::IR_Block*> instructions = bb -> getInstructions();
for (SAPFOR::IR_Block* irBlock: instructions)
{
// TODO: Think about what to do with function calls and array references. Because there are also dependencies there that are not reflected in RD, but they must be taken into account
SAPFOR::Instruction* instr = irBlock -> getInstruction();
result[instr -> getOperator()];
// take Argument 1 and it's RD and push operators to final set
if (instr -> getArg1() != NULL)
{
SAPFOR::Argument* arg = instr -> getArg1();
set<int> prevInstructionsNumbers = blockReachingDefinitions[arg];
for (int i: prevInstructionsNumbers)
{
SAPFOR::Instruction* foundInstruction = getInstructionAndBlockByNumber(FullIR, i).first;
if (foundInstruction != NULL)
{
SgStatement* prevOp = foundInstruction -> getOperator();
if (prevOp != forStatement && instr -> getOperator() != forStatement && instr -> getOperator() -> lineNumber() > prevOp -> lineNumber()
&& prevOp -> lineNumber() > forStatement -> lineNumber())
result[instr -> getOperator()].insert(prevOp);
}
}
}
// take Argument 2 (if exists) and it's RD and push operators to final set
if (instr -> getArg2() != NULL)
{
SAPFOR::Argument* arg = instr -> getArg2();
set<int> prevInstructionsNumbers = blockReachingDefinitions[arg];
for (int i: prevInstructionsNumbers)
{
SAPFOR::Instruction* foundInstruction = getInstructionAndBlockByNumber(FullIR, i).first;
if (foundInstruction != NULL)
{
SgStatement* prevOp = foundInstruction -> getOperator();
if (prevOp != forStatement && instr -> getOperator() != forStatement&& instr -> getOperator() -> lineNumber() > prevOp -> lineNumber()
&& prevOp -> lineNumber() > forStatement -> lineNumber())
result[instr -> getOperator()].insert(prevOp);
}
}
}
// update RD
if (instr -> getResult() != NULL)
blockReachingDefinitions[instr -> getResult()] = {instr -> getNumber()};
}
}
return result;
}
void buildAdditionalDeps(SgForStmt* forStatement, map<SgStatement*, set<SgStatement*>>& dependencies)
{
SgStatement* lastNode = forStatement->lastNodeOfStmt();
vector<SgStatement*> importantDeps;
SgStatement* st = (SgStatement*) forStatement;
st = st -> lexNext();
SgStatement* logIfOp = NULL;
while (st && st != lastNode)
{
if(importantDeps.size() != 0)
{
if (st != importantDeps.back())
{
dependencies[st].insert(importantDeps.back());
}
}
if (logIfOp != NULL)
{
dependencies[st].insert(logIfOp);
logIfOp = NULL;
}
if (st -> variant() == LOGIF_NODE)
{
logIfOp = st;
}
if (importantDepsTags.find(st -> variant()) != importantDepsTags.end())
{
importantDeps.push_back(st);
}
if (importantUpdDepsTags.find(st -> variant()) != importantUpdDepsTags.end())
{
importantDeps.pop_back();
importantDeps.push_back(st);
}
if (importantEndTags.find(st -> variant()) != importantEndTags.end())
{
if(importantDeps.size() != 0)
{
importantDeps.pop_back();
}
}
st = st -> lexNext();
}
}
struct ReadyOp {
SgStatement* stmt;
int degree;
size_t arrival;
ReadyOp(SgStatement* s, int d, size_t a): stmt(s), degree(d), arrival(a) {}
};
struct ReadyOpCompare {
bool operator()(const ReadyOp& a, const ReadyOp& b) const {
if (a.degree != b.degree)
return a.degree > b.degree;
else
return a.arrival > b.arrival;
}
};
vector<SgStatement*> scheduleOperations(const map<SgStatement*, set<SgStatement*>>& dependencies)
{
// get all statements
unordered_set<SgStatement*> allStmtsSet;
for (const auto& pair : dependencies)
{
allStmtsSet.insert(pair.first);
for (SgStatement* dep : pair.second)
{
allStmtsSet.insert(dep);
}
}
vector<SgStatement*> allStmts(allStmtsSet.begin(), allStmtsSet.end());
// count deps and build reversed graph
unordered_map<SgStatement*, vector<SgStatement*>> graph;
unordered_map<SgStatement*, int> inDegree;
unordered_map<SgStatement*, int> degree;
for (auto op : allStmts)
inDegree[op] = 0;
// find and remember initial dependencies
unordered_set<SgStatement*> dependentStmts;
for (const auto& pair : dependencies)
{
SgStatement* op = pair.first;
const auto& deps = pair.second;
degree[op] = deps.size();
inDegree[op] = deps.size();
if (!deps.empty())
dependentStmts.insert(op);
for (auto dep : deps)
graph[dep].push_back(op);
}
for (SgStatement* op : allStmts)
{
if (!degree.count(op))
{
degree[op] = 0;
}
}
// build queues
using PQ = priority_queue<ReadyOp, vector<ReadyOp>, ReadyOpCompare>;
PQ readyDependent;
queue<SgStatement*> readyIndependent;
size_t arrivalCounter = 0;
for (auto op : allStmts)
{
if (inDegree[op] == 0)
{
if (dependentStmts.count(op))
{
readyDependent.emplace(op, degree[op], arrivalCounter++);
}
else
{
readyIndependent.push(op);
}
}
}
// main sort algorythm
vector<SgStatement*> executionOrder;
while (!readyDependent.empty() || !readyIndependent.empty())
{
SgStatement* current = nullptr;
if (!readyDependent.empty())
{
current = readyDependent.top().stmt;
readyDependent.pop();
}
else
{
current = readyIndependent.front();
readyIndependent.pop();
}
executionOrder.push_back(current);
for (SgStatement* neighbor : graph[current])
{
inDegree[neighbor]--;
if (inDegree[neighbor] == 0) {
if (dependentStmts.count(neighbor))
{
readyDependent.emplace(neighbor, degree[neighbor], arrivalCounter++);
}
else
{
readyIndependent.push(neighbor);
}
}
}
}
return executionOrder;
}
void buildNewAST(SgStatement* loop, vector<SgStatement*>& newBody)
{
SgStatement* endDo = loop->lastNodeOfStmt();
SgStatement* st = loop;
int lineNum = loop -> lineNumber() + 1;
for (int i = 0; i < newBody.size(); i++)
{
st -> setLexNext(*newBody[i]);
st = st -> lexNext();
st -> setlineNumber(lineNum);
lineNum++;
}
st -> setLexNext(*endDo);
}
void runSwapOperators(SgFile *file, std::map<std::string, std::vector<LoopGraph*>>& loopGraph, std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& FullIR, int& countOfTransform)
{
std::cout << "SWAP_OPERATORS Pass" << std::endl; // to remove
countOfTransform += 1; // to remove
const int funcNum = file -> numberOfFunctions();
for (int i = 0; i < funcNum; ++i)
{
SgStatement *st = file -> functions(i);
vector<SAPFOR::BasicBlock*> blocks = findFuncBlocksByFuncStatement(st, FullIR);
map<SgForStmt*, vector<SAPFOR::BasicBlock*>> loopsMapping = findAndAnalyzeLoops(st, blocks);
for (pair<SgForStmt*, vector<SAPFOR::BasicBlock*>> loopForAnalyze: loopsMapping)
{
map<SgStatement*, set<SgStatement*>> dependencyGraph = AnalyzeLoopAndFindDeps(loopForAnalyze.first, loopForAnalyze.second, FullIR);
// TODO: Write a function that will go through the operators and update all dependencies so that there are no mix-ups and splits inside the semantic blocks (for if, do and may be some other cases)
buildAdditionalDeps(loopForAnalyze.first, dependencyGraph);
cout << endl;
int firstLine = loopForAnalyze.first -> lineNumber();
int lastLine = loopForAnalyze.first -> lastNodeOfStmt() -> lineNumber();
cout << "LOOP ANALYZE FROM " << firstLine << " TO " << lastLine << " RES" << endl;
// for (auto &v: dependencyGraph) {
// cout << "OPERATOR: " << v.first -> lineNumber() << " " << v.first -> variant() << "\nDEPENDS ON:" << endl;
// if (v.second.size() != 0)
// for (auto vv: v.second)
// cout << vv -> lineNumber() << " ";
// cout << endl;
// }
vector<SgStatement*> new_order = scheduleOperations(dependencyGraph);
cout << "RESULT ORDER:" << endl;
for (auto v: new_order)
if (v -> lineNumber() > firstLine)
cout << v -> lineNumber() << endl;
buildNewAST(loopForAnalyze.first, new_order);
st = loopForAnalyze.first -> lexNext();
while (st != loopForAnalyze.first -> lastNodeOfStmt())
{
cout << st -> lineNumber() << " " << st -> sunparse() << endl;
st = st -> lexNext();
}
}
}
return;
};

View File

@@ -0,0 +1,6 @@
#pragma once
#include "../GraphLoop/graph_loops.h"
#include "../CFGraph/CFGraph.h"
void runSwapOperators(SgFile *file, std::map<std::string, std::vector<LoopGraph*>>& loopGraph, std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& FullIR, int& countOfTransform);

View File

@@ -212,6 +212,8 @@ void InitPassesDependencies(map<passes, vector<passes>> &passDepsIn, set<passes>
Pass(BUILD_IR) <= Pass(SUBST_EXPR_RD) <= Pass(SUBST_EXPR_RD_AND_UNPARSE);
list({BUILD_IR, CALL_GRAPH2}) <= Pass(SWAP_OPERATORS);
list({ LOOP_ANALYZER_DATA_DIST_S1, SUBST_EXPR_RD } ) <= Pass(PRIVATE_REMOVING_ANALYSIS);
list({ PRIVATE_REMOVING_ANALYSIS, REVERT_SUBST_EXPR_RD }) <= Pass(PRIVATE_REMOVING);
@@ -316,6 +318,8 @@ void InitPassesDependencies(map<passes, vector<passes>> &passDepsIn, set<passes>
list({ VERIFY_INCLUDES, CORRECT_VAR_DECL }) <= Pass(SET_IMPLICIT_NONE);
list({ CALL_GRAPH2, CALL_GRAPH, BUILD_IR, LOOP_GRAPH, LOOP_ANALYZER_DATA_DIST_S2 }) <= Pass(FIND_PRIVATE_ARRAYS);
passesIgnoreStateDone.insert({ CREATE_PARALLEL_DIRS, INSERT_PARALLEL_DIRS, INSERT_SHADOW_DIRS, EXTRACT_PARALLEL_DIRS,
EXTRACT_SHADOW_DIRS, CREATE_REMOTES, UNPARSE_FILE, REMOVE_AND_CALC_SHADOW,
REVERSE_CREATED_NESTED_LOOPS, PREDICT_SCHEME, CALCULATE_STATS_SCHEME, REVERT_SPF_DIRS, CLEAR_SPF_DIRS, TRANSFORM_SHADOW_IF_FULL,

View File

@@ -1415,6 +1415,35 @@ ParallelRegion* getRegionByLine(const vector<ParallelRegion*>& regions, const st
return NULL;
}
std::pair<ParallelRegion*, const ParallelRegionLines*> getRegionAndLinesByLine(const vector<ParallelRegion*>& regions, const string& file, const int line)
{
if (regions.size() == 1 && regions[0]->GetName() == "DEFAULT") // only default
return { regions[0], NULL };
else if (regions.size() > 0)
{
map<ParallelRegion*, const ParallelRegionLines*> regFound;
const ParallelRegionLines* foundLines = NULL;
for (int i = 0; i < regions.size(); ++i)
if (regions[i]->HasThisLine(line, file, &foundLines))
regFound[regions[i]] = foundLines;
if (regFound.size() == 0)
return { NULL, NULL };
else if (regFound.size() == 1)
return *regFound.begin();
else
{
__spf_print(1, "WARN: this lines included in more than one region!!\n");
return { NULL, NULL };
}
}
else
return { NULL, NULL };
return { NULL, NULL };
}
set<ParallelRegion*> getAllRegionsByLine(const vector<ParallelRegion*>& regions, const string& file, const int line)
{
set<ParallelRegion*> regFound;