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;
|
2023-11-05 13:08:57 +03:00
|
|
|
for (auto &callInfo : currInfo->callsFromDetailed)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-11-05 13:08:57 +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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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)
|
2023-11-05 13:08:57 +03:00
|
|
|
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)
|
|
|
|
|
{
|
2023-11-05 13:08:57 +03:00
|
|
|
for (auto& callInfo: func->callsFromDetailed)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-11-05 13:08:57 +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,
|
2024-06-19 18:08:27 +03:00
|
|
|
int sharedMemoryParallelization)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
|
|
|
|
checkArraysMapping(loopGraph, SPF_messages, arrayLinksByFuncCalls);
|
|
|
|
|
propagateArrayFlags(arrayLinksByFuncCalls, declaredArrays, SPF_messages);
|
|
|
|
|
|
2024-06-19 18:08:27 +03:00
|
|
|
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;
|
|
|
|
|
}
|