Files
SAPFOR/Sapfor/_src/GraphCall/graph_calls_base.cpp

982 lines
35 KiB
C++
Raw Normal View History

2023-09-14 19:43:13 +03:00
#include "../Utils/leak_detector.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include <map>
#include <vector>
#include <set>
#include <string>
#include "../Utils/errors.h"
#include "graph_calls.h"
#include "../Distribution/Distribution.h"
#include "../Utils/utils.h"
#include "../ParallelizationRegions/ParRegions.h"
using std::vector;
using std::map;
using std::string;
using std::wstring;
using std::set;
using std::to_string;
using std::tuple;
using std::pair;
#define DEB 0
void createMapOfFunc(const vector<FuncInfo*> &allFuncInfo, map<pair<string, int>, FuncInfo*> &mapFuncInfo)
{
for (auto &func : allFuncInfo)
mapFuncInfo[make_pair(func->fileName, func->linesNum.first)] = func;
}
void createMapOfFunc(const vector<FuncInfo*> &allFuncInfo, map<string, FuncInfo*> &mapFuncInfo)
{
for (auto &func : allFuncInfo)
mapFuncInfo[func->funcName] = func;
}
void createMapOfFunc(const map<string, vector<FuncInfo*>> &allFuncInfo, map<string, FuncInfo*> &mapFuncInfo)
{
for (auto it = allFuncInfo.begin(); it != allFuncInfo.end(); ++it)
for (int k = 0; k < it->second.size(); ++k)
mapFuncInfo[it->second[k]->funcName] = it->second[k];
}
FuncInfo* getFuncInfo(const map<string, FuncInfo*> &funcMap, const string &funcName)
{
auto it = funcMap.find(funcName);
if (it == funcMap.end())
return NULL;
return it->second;
}
string removeString(const string &toRemove, const string &inStr)
{
string outStr(inStr);
const size_t found = outStr.find(toRemove);
if (found != string::npos)
outStr.erase(found, toRemove.length());
return outStr;
}
void updateFuncInfo(const map<string, vector<FuncInfo*>> &allFuncInfo) // const here
{
bool changesDone = false;
map<string, FuncInfo*> mapFuncInfo;
createMapOfFunc(allFuncInfo, mapFuncInfo);
do
{
changesDone = false;
for (auto &it : mapFuncInfo)
{
FuncInfo *currInfo = it.second;
for(auto &funcCall : currInfo->funcsCalledFromThis)
{
// Find pointer to info of called function
auto itCalledFunc = mapFuncInfo.find(funcCall.CalledFuncName);
if (itCalledFunc != mapFuncInfo.end() && !itCalledFunc->second->isInterface)
{
FuncInfo *calledFunc = itCalledFunc->second;
// check for pureness
if (!calledFunc->isPure && currInfo->isPure)
{
currInfo->isPure = false;
changesDone = true;
}
// check for using parameter as index
// Iterate through all pars of the call
2025-02-10 12:16:52 +03:00
for (int parNo = 0; parNo < funcCall.NoOfParamUsedForCall.size(); ++parNo)
2023-09-14 19:43:13 +03:00
{
2025-02-10 12:16:52 +03:00
auto& parOfCalled = funcCall.NoOfParamUsedForCall[parNo];
2023-09-14 19:43:13 +03:00
// If this par of called func is used as index change
if (calledFunc->isParamUsedAsIndex[parNo])
{
// Then pars of calling func which are used in this par of called
// are also used as index
for (auto &parOfCalling : parOfCalled)
{
if (!currInfo->isParamUsedAsIndex[parOfCalling])
{
changesDone = true;
currInfo->isParamUsedAsIndex[parOfCalling] = true;
}
}
}
}
// propagate inout types
2025-02-10 12:16:52 +03:00
for (int parNo = 0; parNo < funcCall.NoOfParamUsedForCall.size(); ++parNo)
2023-09-14 19:43:13 +03:00
{
2025-02-10 12:16:52 +03:00
auto& parOfCalled = funcCall.NoOfParamUsedForCall[parNo];
if (parOfCalled.size() == 0)
continue;
if (calledFunc->funcParams.isArgOut(parNo))
2023-09-14 19:43:13 +03:00
{
2025-02-10 12:16:52 +03:00
for (auto& num : parOfCalled)
{
if (!currInfo->funcParams.isArgOut(num))
2023-09-14 19:43:13 +03:00
{
2025-02-10 12:16:52 +03:00
currInfo->funcParams.inout_types[num] |= OUT_BIT;
changesDone = true;
2023-09-14 19:43:13 +03:00
}
2025-02-10 12:16:52 +03:00
}
}
2023-09-14 19:43:13 +03:00
2025-02-10 12:16:52 +03:00
if (calledFunc->funcParams.isArgIn(parNo))
{
for (auto& num : parOfCalled)
{
if (!currInfo->funcParams.isArgIn(num))
2023-09-14 19:43:13 +03:00
{
2025-02-10 12:16:52 +03:00
currInfo->funcParams.inout_types[num] |= IN_BIT;
changesDone = true;
2023-09-14 19:43:13 +03:00
}
2025-02-10 12:16:52 +03:00
}
2023-09-14 19:43:13 +03:00
}
}
}
}
}
} while (changesDone);
// check for io usage
do
{
changesDone = false;
for (auto &it : mapFuncInfo)
{
FuncInfo *currInfo = it.second;
for (auto &callInfo : currInfo->callsFromDetailed)
2023-09-14 19:43:13 +03:00
{
auto& funcCall = callInfo.detailCallsFrom;
2023-09-14 19:43:13 +03:00
auto itCalledFunc = mapFuncInfo.find(funcCall.first);
if (itCalledFunc != mapFuncInfo.end())
{
FuncInfo *calledFunc = itCalledFunc->second;
if (calledFunc->linesOfIO.size())
{
const int lineOfCall = funcCall.second;
auto it = currInfo->linesOfIO.find(lineOfCall);
if (it == currInfo->linesOfIO.end())
{
currInfo->linesOfIO.insert(lineOfCall);
changesDone = true;
2025-02-10 12:16:52 +03:00
}
2023-09-14 19:43:13 +03:00
}
}
}
}
} while (changesDone);
2025-02-10 12:16:52 +03:00
//fill all pars IN, if they have NONE status
for (auto& it : mapFuncInfo)
{
FuncInfo* currInfo = it.second;
currInfo->funcParams.completeParams();
}
2023-09-14 19:43:13 +03:00
}
int CreateCallGraphViz(const char *fileName, const map<string, vector<FuncInfo*>> &funcByFile, map<string, CallV> &V, vector<string> &E)
{
map<string, FuncInfo*> allFuncs;
createMapOfFunc(funcByFile, allFuncs);
string graph = "";
graph += "digraph G{\n";
auto it = funcByFile.begin();
int fileNum = 0;
set<string> inCluster;
set<string> unknownCluster;
char buf[1024];
while (it != funcByFile.end())
{
sprintf(buf, "subgraph cluster%d {\n", fileNum);
graph += buf;
const int dimSize = (int)it->second.size();
set<string> uniqNames;
for (int k = 0; k < dimSize; ++k)
{
const string currfunc = it->second[k]->funcName;
auto it = uniqNames.find(currfunc);
if (it == uniqNames.end())
{
uniqNames.insert(it, currfunc);
inCluster.insert(currfunc);
sprintf(buf, "\"%s\"\n", currfunc.c_str());
graph += buf;
}
}
sprintf(buf, "label = \"file <%s>\"\n", removeString(".\\", it->first).c_str());
graph += buf;
graph += "}\n";
fileNum++;
it++;
}
it = funcByFile.begin();
while (it != funcByFile.end())
{
const char *formatString = "\"%s\" -> \"%s\" [minlen=2.0];\n";
const int dimSize = (int)it->second.size();
for (int k = 0; k < dimSize; ++k)
{
const string &callFrom = it->second[k]->funcName;
const FuncInfo *callFromP = it->second[k];
for (auto &callItem : it->second[k]->callsFrom)
{
sprintf(buf, formatString, callFrom.c_str(), callItem.c_str());
graph += buf;
if (inCluster.find(callFrom) == inCluster.end())
unknownCluster.insert(callFrom);
if (inCluster.find(callItem) == inCluster.end())
unknownCluster.insert(callItem);
if (V.find(callFrom) == V.end())
{
V[callFrom] = CallV(callFromP->funcName, callFromP->fileName, callFromP->isMain);
V[callFrom].inRegion = callFromP->inRegion;
}
if (V.find(callItem) == V.end())
{
auto it = allFuncs.find(callItem);
if (it == allFuncs.end())
V[callItem] = CallV(callItem);
else
{
auto currF = it->second;
V[callItem] = CallV(callItem, currF->fileName, currF->isMain);
V[callItem].inRegion = currF->inRegion;
}
}
E.push_back(callFrom);
E.push_back(callItem);
}
}
it++;
}
if (unknownCluster.size() > 0)
{
sprintf(buf, "subgraph cluster%d {\n", fileNum);
graph += buf;
for (auto &func : unknownCluster)
{
sprintf(buf, "\"%s\"\n", func.c_str());
graph += buf;
}
sprintf(buf, "label = \"file <UNKNOWN>\"\n");
graph += buf;
graph += "}\n";
}
graph += "overlap=false\n";
graph += "}\n";
if (fileName)
{
FILE *out = fopen(fileName, "w");
if (out == NULL)
{
__spf_print(1, "can not open file %s\n", fileName);
return -1;
}
fprintf(out, graph.c_str());
fclose(out);
}
return 0;
}
int CreateFuncInfo(const char *fileName, const map<string, vector<FuncInfo*>> &funcByFile)
{
string funcOut = "";
for (auto &byFile : funcByFile)
{
funcOut += "FILE " + byFile.first + ":\n";
for (auto &func : byFile.second)
{
funcOut += (func->isInterface ? ("INTERFACE OF ") : "") + string(" FUNCTION '") +
func->funcName + "' " + (func->isPure ? " is PURE" : "is IMPURE") + "\n";
char buf[256];
sprintf(buf, " LINES [%d, %d] \n", func->linesNum.first, func->linesNum.second);
funcOut += buf;
sprintf(buf, " PARAMETERS %d:\n", func->funcParams.countOfPars);
funcOut += buf;
for (int z = 0; z < func->funcParams.countOfPars; ++z)
{
bool in = func->funcParams.isArgIn(z);
bool out = func->funcParams.isArgOut(z);
const char *inout = "";
if (in && out)
inout = "IN/OUT";
else if (in)
inout = "IN";
else if (out)
inout = "OUT";
sprintf(buf, " %s: type '%s', %s\n", func->funcParams.identificators[z].c_str(),
paramNames[func->funcParams.parametersT[z]],
inout);
funcOut += buf;
}
}
}
if (fileName)
{
FILE *out = fopen(fileName, "w");
if (out == NULL)
{
__spf_print(1, "can not open file %s\n", fileName);
return -1;
}
fprintf(out, funcOut.c_str());
fclose(out);
}
return 0;
}
extern map<string, vector<FuncInfo*>> allFuncInfo; // file -> Info
FuncInfo* isUserFunctionInProject(const string &func)
{
FuncInfo *ret = NULL;
for (auto &it : allFuncInfo)
{
for (auto &currF : it.second)
{
if (currF->funcName == func)
{
ret = currF;
break;
}
}
if (ret)
break;
}
return ret;
}
string convertToString(const FuncInfo *currFunc)
{
string result = "";
if (currFunc)
{
result += "|" + currFunc->funcName + "|" + to_string(currFunc->linesNum.first) +
"#" + to_string(currFunc->linesNum.second) +
"#" + to_string(currFunc->callsFromDetailed.size()) +
2023-09-14 19:43:13 +03:00
"#" + to_string(currFunc->needToInline) + "#" + to_string(currFunc->doNotInline) +
"#" + to_string(currFunc->doNotAnalyze) + "#" + to_string((int)currFunc->isMain);
result += "#" + to_string(currFunc->funcParams.countOfPars);
if (currFunc->funcParams.countOfPars)
{
for (int z = 0; z < currFunc->funcParams.countOfPars; ++z)
{
result += "#" + currFunc->funcParams.identificators[z] + "#" + to_string(currFunc->funcParams.inout_types[z]);
result += "#" + string(paramNames[currFunc->funcParams.parametersT[z]]);
}
}
for (int i = 0; i < currFunc->callsFromDetailed.size(); ++i)
result += "|" + currFunc->callsFromDetailed[i].detailCallsFrom.first + "|" + to_string(currFunc->callsFromDetailed[i].detailCallsFrom.second);
2023-09-14 19:43:13 +03:00
}
return result;
}
// Find dead functions and fill callTo / callFrom information
void findDeadFunctionsAndFillCalls(map<string, vector<FuncInfo*>> &allFuncInfo, map<string, vector<Messages>> &allMessages, bool noPrint)
{
map<string, FuncInfo*> mapFuncInfo;
createMapOfFunc(allFuncInfo, mapFuncInfo);
set<string> allExternalCalls;
set<string> allChildCalls;
2025-02-09 20:48:06 +03:00
2023-09-14 19:43:13 +03:00
for (auto &it : mapFuncInfo)
{
FuncInfo *currInfo = it.second;
allChildCalls.insert(currInfo->callsFrom.begin(), currInfo->callsFrom.end());
allExternalCalls.insert(currInfo->externalCalls.begin(), currInfo->externalCalls.end());
}
for (auto &it : mapFuncInfo)
{
FuncInfo *currInfo = it.second;
if (allChildCalls.find(it.first) == allChildCalls.end())
if (!currInfo->isMain && allExternalCalls.find(currInfo->funcName) == allExternalCalls.end())
currInfo->deadFunction = currInfo->doNotAnalyze = true;
}
if (!noPrint)
{
for (auto &it : allFuncInfo)
{
const string &currF = it.first;
auto itM = allMessages.find(currF);
if (itM == allMessages.end())
itM = allMessages.insert(itM, make_pair(currF, vector<Messages>()));
for (auto& func : it.second)
if (func->deadFunction)
itM->second.push_back(Messages(WARR, func->linesNum.first, R47, L"This function is not called in current project", 1015));
}
}
for (auto &it : mapFuncInfo)
{
FuncInfo *currInfo = it.second;
for (auto &k : currInfo->callsFrom)
{
auto itFound = mapFuncInfo.find(k);
if (itFound != mapFuncInfo.end())
{
FuncInfo *callFrom = itFound->second;
callFrom->callsTo.push_back(currInfo);
currInfo->callsFromV.insert(callFrom);
}
}
}
2025-02-09 20:48:06 +03:00
FuncInfo* main = NULL;
for (auto& it : mapFuncInfo)
if (it.second->isMain)
main = it.second;
2023-09-14 19:43:13 +03:00
2025-02-09 20:48:06 +03:00
checkNull(main, convertFileName(__FILE__).c_str(), __LINE__);
set<FuncInfo*> liveFunctions;
liveFunctions.insert(main);
for (auto& callFrom : main->callsFromV)
liveFunctions.insert(callFrom);
//find live functions
2023-09-14 19:43:13 +03:00
bool changes = true;
while (changes)
2025-02-09 20:48:06 +03:00
{
changes = false;
for (auto& currInfo : liveFunctions)
{
for (auto& callFrom : currInfo->callsFromV) {
if (liveFunctions.find(callFrom) == liveFunctions.end()) {
changes = true;
liveFunctions.insert(callFrom);
}
}
}
}
// propagate 'deadFunction' status for all 'CallsFrom' from dead functions
changes = true;
while (changes)
2023-09-14 19:43:13 +03:00
{
changes = false;
for (auto& it : mapFuncInfo)
{
FuncInfo* currInfo = it.second;
if (currInfo->deadFunction == false)
continue;
for (auto& callFrom : currInfo->callsFrom)
{
auto itFrom = mapFuncInfo.find(callFrom);
if (itFrom != mapFuncInfo.end())
{
2025-02-09 20:48:06 +03:00
auto func = itFrom->second;
if (!func->deadFunction && liveFunctions.find(func) == liveFunctions.end())
2023-09-14 19:43:13 +03:00
{
changes = true;
2025-02-09 20:48:06 +03:00
func->deadFunction = func->doNotAnalyze = true;
2023-09-14 19:43:13 +03:00
}
}
}
}
}
}
static inline void addLinks(const FuncParam &actual, const FuncParam &formal, map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls)
{
if (actual.parameters.size() != formal.parameters.size())
return;
else
{
for (int i = 0; i < actual.parameters.size(); ++i)
if (actual.parametersT[i] == formal.parametersT[i] && formal.parametersT[i] == ARRAY_T)
{
//printf("add lhs %s -> rhs %s\n", ((DIST::Array*)formal.parameters[i])->GetName().c_str(), ((DIST::Array*)actual.parameters[i])->GetName().c_str());
if (((DIST::Array*)formal.parameters[i]) == ((DIST::Array*)actual.parameters[i]))
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
arrayLinksByFuncCalls[(DIST::Array*)formal.parameters[i]].insert((DIST::Array*)actual.parameters[i]);
}
}
}
static bool propagateUp(DIST::Array *from, set<DIST::Array*> to, DIST::distFlag flag, bool &change, map<string, vector<Messages>> &SPF_messages)
{
bool globalChange = false;
if (from->GetDistributeFlagVal() == flag)
{
for (auto &realRef : to)
{
auto val = realRef->GetDistributeFlagVal();
if (val != flag)
{
//exclude this case
if (flag == DIST::IO_PRIV && val == DIST::SPF_PRIV ||
flag == DIST::NO_DISTR && val == DIST::SPF_PRIV ||
flag == DIST::NO_DISTR && val == DIST::IO_PRIV)
;
else
{
realRef->SetDistributeFlag(flag);
if (flag == DIST::IO_PRIV)
{
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Array '%s' can not be distributed because of DVM's I/O constraints", to_wstring(realRef->GetShortName()).c_str());
__spf_printToLongBuf(messageR, R68, to_wstring(realRef->GetShortName()).c_str());
auto places = realRef->GetDeclInfo();
for (auto& place : places)
getObjectForFileFromMap(place.first.c_str(), SPF_messages).push_back(Messages(WARR, place.second, messageR, messageE, 1037));
}
#if DEB
printf("up: set %d %s\n", flag, realRef->GetName().c_str());
#endif
change = true;
globalChange = true;
}
}
}
}
return globalChange;
}
static bool propagateFlag(bool isDown, const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls,
const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
map<string, vector<Messages>> &SPF_messages)
{
bool globalChange = false;
bool change = true;
while (change)
{
change = false;
for (auto &array : declaredArrays)
{
set<DIST::Array*> realArrayRefs;
getRealArrayRefs(array.second.first, array.second.first, realArrayRefs, arrayLinksByFuncCalls);
bool allNonDistr = true;
bool allDistr = true;
bool nonDistrSpfPriv = false;
bool nonDistrIOPriv = false;
bool init = false;
// propagate SPF to down calls
for (auto &realRef : realArrayRefs)
{
if (realRef != array.second.first)
{
bool nonDistr = realRef->IsNotDistribute();
if (realRef->GetDistributeFlagVal() == DIST::SPF_PRIV)
nonDistrSpfPriv = true;
else if (realRef->GetDistributeFlagVal() == DIST::IO_PRIV)
nonDistrIOPriv = true;
allNonDistr = allNonDistr && nonDistr;
allDistr = allDistr && !nonDistr;
init = true;
}
}
if (init)
{
if (allNonDistr && array.second.first->IsNotDistribute() == false)
{
if (isDown)
{
if (nonDistrSpfPriv)
{
array.second.first->SetDistributeFlag(DIST::SPF_PRIV);
if (DEB)
printf("down: set %d %s\n", DIST::SPF_PRIV, array.second.first->GetName().c_str());
}
else if (nonDistrIOPriv)
{
array.second.first->SetDistributeFlag(DIST::IO_PRIV);
if (DEB)
printf("down: set %d %s\n", DIST::IO_PRIV, array.second.first->GetName().c_str());
}
else
{
array.second.first->SetDistributeFlag(DIST::NO_DISTR);
if (DEB)
printf("down: set %d %s\n", DIST::NO_DISTR, array.second.first->GetName().c_str());
}
change = true;
globalChange = true;
}
}
else
{
if (!isDown)
{
bool ret = propagateUp(array.second.first, realArrayRefs, DIST::SPF_PRIV, change, SPF_messages);
globalChange = globalChange || ret;
ret = propagateUp(array.second.first, realArrayRefs, DIST::IO_PRIV, change, SPF_messages);
globalChange = globalChange || ret;
ret = propagateUp(array.second.first, realArrayRefs, DIST::NO_DISTR, change, SPF_messages);
globalChange = globalChange || ret;
}
}
}
}
}
return globalChange;
}
void propagateArrayFlags(const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls,
const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
map<string, vector<Messages>> &SPF_messages)
{
bool change = true;
while (change)
{
bool changeD = propagateFlag(true, arrayLinksByFuncCalls, declaredArrays, SPF_messages);
bool changeU = propagateFlag(false, arrayLinksByFuncCalls, declaredArrays, SPF_messages);
change = changeD || changeU;
}
}
static void aggregateUsedArrays(map<string, FuncInfo*> &funcByName, const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls)
{
//change to real refs
for (auto &func : funcByName)
{
{
set<DIST::Array*> curr = func.second->allUsedArrays;
set<DIST::Array*> newRefs;
for (auto &array : curr)
getRealArrayRefs(array, array, newRefs, arrayLinksByFuncCalls);
func.second->allUsedArrays.clear();
for (auto &newArray : newRefs)
if (newArray->IsNotDistribute() == false)
func.second->allUsedArrays.insert(newArray);
}
{
set<DIST::Array*> curr = func.second->usedArraysWrite;
set<DIST::Array*> newRefs;
for (auto &array : curr)
getRealArrayRefs(array, array, newRefs, arrayLinksByFuncCalls);
func.second->usedArraysWrite.clear();
for (auto &newArray : newRefs)
if (newArray->IsNotDistribute() == false)
func.second->usedArraysWrite.insert(newArray);
}
}
bool changed = true;
while (changed)
{
changed = false;
for (auto &func : funcByName)
{
for (auto &callsFrom : func.second->callsFrom)
{
auto itF = funcByName.find(callsFrom);
if (itF != funcByName.end())
{
for (auto &usedArray : itF->second->allUsedArrays)
{
auto itA = func.second->allUsedArrays.find(usedArray);
if (itA == func.second->allUsedArrays.end())
{
changed = true;
func.second->allUsedArrays.insert(usedArray);
}
}
}
}
}
}
changed = true;
while (changed)
{
changed = false;
for (auto &func : funcByName)
{
for (auto &callsFrom : func.second->callsFrom)
{
auto itF = funcByName.find(callsFrom);
if (itF != funcByName.end())
{
for (auto &usedArray : itF->second->usedArraysWrite)
{
auto itA = func.second->usedArraysWrite.find(usedArray);
if (itA == func.second->usedArraysWrite.end())
{
changed = true;
func.second->usedArraysWrite.insert(usedArray);
}
}
}
}
}
}
}
void createLinksBetweenFormalAndActualParams(map<string, vector<FuncInfo*>> &allFuncInfo, map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls,
const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
map<string, vector<Messages>> &SPF_messages, bool keepFiles)
{
for (auto &funcsOnFile : allFuncInfo)
{
for (auto &func : funcsOnFile.second)
{
//printf("func %s :\n", func->funcName.c_str());
const string &name = func->funcName;
for (auto &caller : func->callsTo)
for (int i = 0; i < caller->callsFromDetailed.size(); ++i)
if (caller->callsFromDetailed[i].detailCallsFrom.first == name)
addLinks(caller->callsFromDetailed[i].actualParams, func->funcParams, arrayLinksByFuncCalls);
2023-09-14 19:43:13 +03:00
}
}
#if DEB
printf("BEFORE\n");
//debug dump
for (auto& elem : declaredArrays)
{
auto array = elem.second.first;
auto flag = array->GetDistributeFlagVal();
// int { DISTR = 0, NO_DISTR, SPF_PRIV, IO_PRIV } distFlagType;
string flagS = "";
if (flag == DIST::DISTR)
flagS = "DISTR";
else if (flag == DIST::NO_DISTR)
flagS = "NO_DISTR";
else if (flag == DIST::SPF_PRIV)
flagS = "SPF_PRIV";
else if (flag == DIST::IO_PRIV)
flagS = "IO_PRIV";
printf("%s %s flag %s\n", array->GetShortName(), array->GetName(), flagS.c_str());
}
#endif
if (keepFiles)
{
FILE *file = fopen("_arrayLinksByCalls.txt", "w");
for (auto &elem : arrayLinksByFuncCalls)
{
fprintf(file, "%s -> ", elem.first->GetName().c_str());
for (auto &rhs : elem.second)
fprintf(file, " %s ", rhs->GetName().c_str());
fprintf(file, "\n");
}
fclose(file);
}
propagateArrayFlags(arrayLinksByFuncCalls, declaredArrays, SPF_messages);
//propagate distr state
bool change = true;
while (change)
{
change = false;
for (auto &array : declaredArrays)
{
set<DIST::Array*> realArrayRefs;
getRealArrayRefs(array.second.first, array.second.first, realArrayRefs, arrayLinksByFuncCalls);
if (realArrayRefs.size() && (*realArrayRefs.begin()) != array.second.first &&
!(*realArrayRefs.begin())->IsNotDistribute() && array.second.first->IsNotDistribute())
{
array.second.first->SetDistributeFlag(DIST::DISTR);
change = true;
}
}
}
map<string, FuncInfo*> funcByName;
createMapOfFunc(allFuncInfo, funcByName);
aggregateUsedArrays(funcByName, arrayLinksByFuncCalls);
#if DEB
printf("AFTER\n");
//debug dump
for (auto &elem : declaredArrays)
{
auto array = elem.second.first;
auto flag = array->GetDistributeFlagVal();
// int { DISTR = 0, NO_DISTR, SPF_PRIV, IO_PRIV } distFlagType;
string flagS = "";
if (flag == DIST::DISTR)
flagS = "DISTR";
else if (flag == DIST::NO_DISTR)
flagS = "NO_DISTR";
else if (flag == DIST::SPF_PRIV)
flagS = "SPF_PRIV";
else if (flag == DIST::IO_PRIV)
flagS = "IO_PRIV";
printf("%s %s flag %s\n", array->GetShortName(), array->GetName(), flagS.c_str());
}
printf("");
#endif
}
bool detectMpiCalls(const map<string, vector<FuncInfo*>>& allFuncInfo, map<string, vector<Messages>>& SPF_messages)
{
bool retVal = false;
map<string, FuncInfo*> funcByName;
createMapOfFunc(allFuncInfo, funcByName);
for (auto& byFile : allFuncInfo)
{
for (auto& func : byFile.second)
{
for (auto& callInfo: func->callsFromDetailed)
2023-09-14 19:43:13 +03:00
{
auto& callsFromThis = callInfo.detailCallsFrom;
2023-09-14 19:43:13 +03:00
if (isMpiFunction(callsFromThis.first) && funcByName.find(callsFromThis.first) == funcByName.end())
{
retVal = true;
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Detected mpi call, turn on special regime of paralyzing");
__spf_printToLongBuf(messageR, R148);
SPF_messages[byFile.first].push_back(Messages(NOTE, callsFromThis.second, messageR, messageE, 1051));
}
}
}
}
return retVal;
}
void excludeArraysFromDistribution(const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls,
const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> declaredArrays,
map<string, vector<LoopGraph*>>& loopGraph,
vector<ParallelRegion*> parallelRegions,
map<string, vector<Messages>>& SPF_messages,
map<tuple<int, string, string>, DIST::Array*>& createdArrays,
int sharedMemoryParallelization)
2023-09-14 19:43:13 +03:00
{
checkArraysMapping(loopGraph, SPF_messages, arrayLinksByFuncCalls);
propagateArrayFlags(arrayLinksByFuncCalls, declaredArrays, SPF_messages);
if (sharedMemoryParallelization == 0)
2023-09-14 19:43:13 +03:00
{
for (int z = 0; z < parallelRegions.size(); ++z)
filterArrayInCSRGraph(loopGraph, allFuncInfo, parallelRegions[z], arrayLinksByFuncCalls, SPF_messages);
propagateArrayFlags(arrayLinksByFuncCalls, declaredArrays, SPF_messages);
}
for (auto& loopByFile : loopGraph)
{
for (auto& loop : loopByFile.second)
{
loop->removeNonDistrArrays();
loop->removeGraphData();
}
}
for (auto& funcByFile : allFuncInfo)
for (auto& func : funcByFile.second)
func->removeNonDistrArrays();
//restore
for (int z = 0; z < parallelRegions.size(); ++z)
{
parallelRegions[z]->GetAllArraysToModify().cleanData();
parallelRegions[z]->GetGraphToModify().ClearGraphCSR();
parallelRegions[z]->GetReducedGraphToModify().ClearGraphCSR();
}
createdArrays.clear();
}
void compliteArrayUsage(DIST::Arrays<int>& allArraysForRegion,
map<tuple<int, string, string>, DIST::Array*>& createdArrays,
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls,
const map<DIST::Array*, tuple<int, string, string>>& tableOfUniqNamesByArray)
{
set<DIST::Array*> usedArraysLocal;
usedArraysLocal.insert(allArraysForRegion.GetArrays().begin(), allArraysForRegion.GetArrays().end());
//add array that linked with used
for (auto& used : usedArraysLocal)
{
set<DIST::Array*> allArrayRefs;
getAllArrayRefs(used, used, allArrayRefs, arrayLinksByFuncCalls);
for (auto& array : allArrayRefs)
{
if (usedArraysLocal.find(array) == usedArraysLocal.end())
{
auto key = tableOfUniqNamesByArray.find(array);
if (key != tableOfUniqNamesByArray.end())
{
createdArrays.insert(make_pair(key->second, key->first));
allArraysForRegion.AddArrayToGraph(array);
}
}
}
}
}
void remoteNotUsedArrays(map<tuple<int, string, string>, DIST::Array*>& createdArrays,
const set<DIST::Array*>& usedArraysAcrossRegions,
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls)
{
//remove arrays that is not used
map<tuple<int, string, string>, DIST::Array*> createdArraysNew;
for (auto it = createdArrays.begin(); it != createdArrays.end(); ++it)
{
if (usedArraysAcrossRegions.find(it->second) != usedArraysAcrossRegions.end())
createdArraysNew.insert(*it);
else
{
set<DIST::Array*> realArrayRefs;
getRealArrayRefs(it->second, it->second, realArrayRefs, arrayLinksByFuncCalls);
for (auto& array : realArrayRefs)
{
if (array == it->second)
continue;
if (usedArraysAcrossRegions.find(array) != usedArraysAcrossRegions.end())
createdArraysNew.insert(*it);
}
}
}
createdArrays = createdArraysNew;
}