2023-09-14 19:43:13 +03:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <set>
|
|
|
|
|
|
|
|
|
|
#include "../Utils/AstWrapper.h"
|
|
|
|
|
#include "../Utils/utils.h"
|
|
|
|
|
#include "../DirectiveProcessing/shadow.h"
|
|
|
|
|
#include "../GraphLoop/graph_loops.h"
|
|
|
|
|
|
|
|
|
|
static const char* paramNames[] =
|
|
|
|
|
{ "NONE_T", "ARRAY_T", "STRING_ARRAY_T", "STRING_T", "SCALAR_CHAR_T", "SCALAR_BOOL_T", "SCALAR_SHORT_T", "SCALAR_INT_T", "SCALAR_LONG_INT_T",
|
|
|
|
|
"SCALAR_FLOAT_T", "SCALAR_DOUBLE_T",
|
|
|
|
|
"SCALAR_CMPLX_FLOAT_T", "SCALAR_CMPLX_DOUBLE_T", "EXTERNAL_T", "UNKNOWN_T" };
|
|
|
|
|
|
|
|
|
|
typedef enum parF { NONE_T, ARRAY_T, STRING_ARRAY_T, STRING_T, SCALAR_CHAR_T, SCALAR_BOOL_T, SCALAR_SHORT_T, SCALAR_INT_T, SCALAR_LONG_INT_T,
|
|
|
|
|
SCALAR_FLOAT_T, SCALAR_DOUBLE_T,
|
|
|
|
|
SCALAR_CMPLX_FLOAT_T, SCALAR_CMPLX_DOUBLE_T, EXTERNAL_T, UNKNOWN_T} paramType;
|
|
|
|
|
|
|
|
|
|
#ifndef IN_BIT
|
|
|
|
|
#define IN_BIT 16
|
|
|
|
|
#endif
|
|
|
|
|
#ifndef OUT_BIT
|
|
|
|
|
#define OUT_BIT 256
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
struct FuncParam
|
|
|
|
|
{
|
|
|
|
|
FuncParam() { countOfPars = 0; }
|
|
|
|
|
|
|
|
|
|
void init(const int numPar)
|
|
|
|
|
{
|
|
|
|
|
countOfPars = numPar;
|
|
|
|
|
if (numPar)
|
|
|
|
|
{
|
|
|
|
|
parameters.resize(numPar);
|
|
|
|
|
parametersT.resize(numPar);
|
|
|
|
|
inout_types.resize(numPar);
|
|
|
|
|
std::fill(parametersT.begin(), parametersT.end(), NONE_T);
|
2024-05-11 16:45:15 +03:00
|
|
|
std::fill(inout_types.begin(), inout_types.end(), 0);
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-11 16:45:15 +03:00
|
|
|
void completeParams()
|
|
|
|
|
{
|
|
|
|
|
for (int z = 0; z < countOfPars; ++z)
|
|
|
|
|
if (inout_types[z] == 0)
|
|
|
|
|
inout_types[z] = IN_BIT;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-14 19:43:13 +03:00
|
|
|
bool isArgIn(const int num) const
|
|
|
|
|
{
|
|
|
|
|
if (num >= countOfPars)
|
|
|
|
|
return false;
|
|
|
|
|
else
|
|
|
|
|
return (inout_types[num] & IN_BIT) != 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isArgOut(const int num) const
|
|
|
|
|
{
|
|
|
|
|
if (num >= countOfPars)
|
|
|
|
|
return false;
|
|
|
|
|
else
|
|
|
|
|
return (inout_types[num] & OUT_BIT) != 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isArgInOut(const int num) const
|
|
|
|
|
{
|
|
|
|
|
if (num >= countOfPars)
|
|
|
|
|
return false;
|
|
|
|
|
else
|
|
|
|
|
return isArgIn(num) && isArgOut(num);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool isArgIn(int64_t type) { return (type & IN_BIT) != 0; }
|
|
|
|
|
static bool isArgOut(int64_t type) { return (type & OUT_BIT) != 0; }
|
|
|
|
|
static bool isArgInOut(int64_t type) { return isArgIn(type) && isArgOut(type); }
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> identificators;
|
|
|
|
|
std::vector<void*> parameters;
|
|
|
|
|
std::vector<paramType> parametersT;
|
|
|
|
|
std::vector<int> inout_types;
|
|
|
|
|
int countOfPars;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#ifndef IN_BIT
|
|
|
|
|
#undef IN_BIT
|
|
|
|
|
#endif
|
|
|
|
|
#ifndef OUT_BIT
|
|
|
|
|
#undef OUT_BIT
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
struct NestedFuncCall
|
|
|
|
|
{
|
|
|
|
|
std::string CalledFuncName;
|
|
|
|
|
std::vector<std::vector<int>> NoOfParamUsedForCall;
|
|
|
|
|
|
|
|
|
|
NestedFuncCall(std::string funcName) : CalledFuncName(funcName) { }
|
|
|
|
|
|
|
|
|
|
NestedFuncCall(std::string funcName, int ParsNum) :
|
|
|
|
|
CalledFuncName(funcName),
|
|
|
|
|
NoOfParamUsedForCall(std::vector<std::vector<int>>(ParsNum))
|
|
|
|
|
{ }
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-05 13:08:57 +03:00
|
|
|
struct FuncInfoCallFrom {
|
|
|
|
|
// <name, line>
|
|
|
|
|
std::pair<std::string, int> detailCallsFrom;
|
|
|
|
|
// <pointer, SG_VAR> SgStatement for PROC_STAT, SgExpression for FUNC_CALL, VAR_REF for external calls
|
|
|
|
|
std::pair<void*, int> pointerDetailCallsFrom;
|
|
|
|
|
// parent SgStatement* of FUNC_CALL
|
|
|
|
|
void* parentForPointer;
|
|
|
|
|
FuncParam actualParams;
|
|
|
|
|
};
|
|
|
|
|
|
2023-09-14 19:43:13 +03:00
|
|
|
struct FuncInfo
|
|
|
|
|
{
|
|
|
|
|
std::string funcName;
|
|
|
|
|
std::pair<int, int> linesNum;
|
|
|
|
|
std::string fileName;
|
|
|
|
|
Statement *funcPointer;
|
|
|
|
|
bool isMain;
|
|
|
|
|
bool isInterface;
|
|
|
|
|
|
|
|
|
|
std::set<std::string> callsFrom; //calls from this function
|
|
|
|
|
std::set<FuncInfo*> callsFromV;
|
2023-11-05 13:08:57 +03:00
|
|
|
std::vector<FuncInfoCallFrom> callsFromDetailed;
|
2023-09-14 19:43:13 +03:00
|
|
|
|
|
|
|
|
std::map<std::string, std::set<std::string>> commonBlocks;
|
|
|
|
|
|
|
|
|
|
std::vector<FuncInfo*> callsTo; //calls of this function
|
|
|
|
|
FuncParam funcParams;
|
|
|
|
|
std::vector<bool> isParamUsedAsIndex;
|
|
|
|
|
std::vector<NestedFuncCall> funcsCalledFromThis; // size = amount of calls in this func;
|
|
|
|
|
// if (FuncsCalledFromThis[func_call_idx].
|
|
|
|
|
// NoOfParamUsedForCall.size() == 0) - no params of cur func used
|
|
|
|
|
|
|
|
|
|
ShadowNode* shadowTreeStart;
|
|
|
|
|
ShadowNode* shadowTreeEnd;
|
|
|
|
|
std::map<void*, ShadowNode*> allShadowNodes;
|
|
|
|
|
std::set<DIST::Array*> allUsedArrays; // real array refs
|
|
|
|
|
std::set<DIST::Array*> usedArraysWrite; // real array refs
|
|
|
|
|
|
|
|
|
|
std::vector<LoopGraph*> loopsInFunc;
|
|
|
|
|
|
|
|
|
|
std::set<int> linesOfIO;
|
|
|
|
|
std::set<int> linesOfStop;
|
|
|
|
|
|
|
|
|
|
std::map<std::string, FuncInfo*> interfaceBlocks;
|
|
|
|
|
std::map<std::string, FuncInfo*> interfaceSynonims;
|
|
|
|
|
|
2024-05-12 13:37:42 +03:00
|
|
|
std::vector<FuncInfo*> entry; // all entry points
|
|
|
|
|
|
2023-09-14 19:43:13 +03:00
|
|
|
std::set<std::string> externalCalls;
|
|
|
|
|
|
|
|
|
|
bool isPure; // does this func or funcs called from this have common block[s] and have no side effects
|
|
|
|
|
bool doNotInline;
|
|
|
|
|
bool doNotAnalyze;
|
|
|
|
|
bool needToInline;
|
|
|
|
|
bool deadFunction;
|
|
|
|
|
|
|
|
|
|
// for RESOLVE_PAR_REGIONS
|
|
|
|
|
int inRegion; // 0 - none, 1 - explicit, 2 - implicit, 3 - indirect
|
|
|
|
|
std::set<uint64_t> callRegions; // 0 - default; forall i > 0, i - user region
|
|
|
|
|
bool isInRegion() { return inRegion == 1 || inRegion == 2; }
|
|
|
|
|
bool isIndirect() { return inRegion == 3; }
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
std::vector<FuncInfo*> fullCopiesOfThisFunction;
|
|
|
|
|
|
|
|
|
|
FuncInfo() :
|
|
|
|
|
doNotInline(false), funcPointer(NULL), doNotAnalyze(false), needToInline(false),
|
|
|
|
|
deadFunction(false), inRegion(0), isPure(false), isMain(false), shadowTreeStart(NULL), shadowTreeEnd(NULL),
|
|
|
|
|
isInterface(false) { }
|
|
|
|
|
|
|
|
|
|
FuncInfo(const std::string &funcName, const std::pair<int, int> &lineNum) :
|
|
|
|
|
funcName(funcName), linesNum(lineNum), doNotInline(false), funcPointer(NULL),
|
|
|
|
|
doNotAnalyze(false), needToInline(false), deadFunction(false), inRegion(0), isMain(false),
|
|
|
|
|
isPure(false), shadowTreeStart(NULL), shadowTreeEnd(NULL), isInterface(false) { }
|
|
|
|
|
|
|
|
|
|
#if !__SPC
|
|
|
|
|
FuncInfo(const std::string &funcName, const std::pair<int, int> &lineNum, Statement *pointer) :
|
|
|
|
|
funcName(funcName), linesNum(lineNum), doNotInline(false), funcPointer(pointer),
|
|
|
|
|
doNotAnalyze(false), needToInline(false), deadFunction(false), inRegion(0), isMain(false),
|
|
|
|
|
isPure(false), shadowTreeStart(NULL), shadowTreeEnd(NULL), isInterface(false) { fileName = pointer->fileName(); }
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
std::vector<std::pair<void*, int>> GetDetailedCallInfo(const std::string &funcName)
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::pair<void*, int>> result;
|
2023-11-05 13:08:57 +03:00
|
|
|
for (int i = 0; i < callsFromDetailed.size(); ++i)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-11-05 13:08:57 +03:00
|
|
|
if (callsFromDetailed[i].detailCallsFrom.first == funcName)
|
|
|
|
|
result.push_back(callsFromDetailed[i].pointerDetailCallsFrom);
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string getFuncNameWithContainsByRegion(const uint64_t regionId)
|
|
|
|
|
{
|
|
|
|
|
if (regionId && callRegions.size() > 1 && callRegions.find(regionId) != callRegions.end())
|
|
|
|
|
return funcName + "_r" + std::to_string(regionId);
|
|
|
|
|
return funcName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string getFuncNameByRegion(const std::string &shortName, const uint64_t regionId)
|
|
|
|
|
{
|
|
|
|
|
if (regionId && callRegions.size() > 1 && callRegions.find(regionId) != callRegions.end())
|
|
|
|
|
return shortName + "_r" + std::to_string(regionId);
|
|
|
|
|
return shortName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void removeNonDistrArrays()
|
|
|
|
|
{
|
|
|
|
|
std::set<DIST::Array*> newUsedArrays;
|
|
|
|
|
for (auto &elem : allUsedArrays)
|
|
|
|
|
if (elem->GetDistributeFlagVal() == DIST::DISTR)
|
|
|
|
|
newUsedArrays.insert(elem);
|
|
|
|
|
allUsedArrays = newUsedArrays;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool usesIO() const { return (linesOfIO.size() != 0 || linesOfStop.size() != 0); }
|
2023-11-22 20:21:18 +03:00
|
|
|
|
|
|
|
|
std::string getCallName(const std::pair<void*, int>& call_info, const std::string& name, int line)
|
|
|
|
|
{
|
2024-02-25 11:16:56 +03:00
|
|
|
if (line <= 0)
|
|
|
|
|
return name;
|
|
|
|
|
|
2023-11-22 20:21:18 +03:00
|
|
|
std::set<std::string> names;
|
|
|
|
|
|
|
|
|
|
for (auto& call : callsFromDetailed)
|
|
|
|
|
{
|
|
|
|
|
if (call.pointerDetailCallsFrom == call_info && call.detailCallsFrom.second == line)
|
|
|
|
|
return call.detailCallsFrom.first;
|
|
|
|
|
|
|
|
|
|
if (call.detailCallsFrom.second == line)
|
|
|
|
|
if (call.detailCallsFrom.first.find(name) != std::string::npos)
|
|
|
|
|
names.insert(call.detailCallsFrom.first);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//TODO: detect func call better
|
|
|
|
|
if (names.size() == 1)
|
|
|
|
|
return *names.begin();
|
|
|
|
|
|
2024-09-30 20:24:34 +03:00
|
|
|
//try to find in next lvl calls
|
|
|
|
|
for (auto& call : callsFromDetailed)
|
|
|
|
|
{
|
|
|
|
|
if (call.detailCallsFrom.second == line)
|
|
|
|
|
{
|
|
|
|
|
std::string name_next = call.detailCallsFrom.first;
|
|
|
|
|
std::set<FuncInfo*> next, done;
|
|
|
|
|
|
|
|
|
|
for (auto& callFrom : callsFromV)
|
|
|
|
|
if (callFrom->funcName == name_next)
|
|
|
|
|
next.insert(callFrom);
|
|
|
|
|
|
|
|
|
|
done = next;
|
|
|
|
|
while (next.size())
|
|
|
|
|
{
|
|
|
|
|
auto curr = next;
|
|
|
|
|
next.clear();
|
|
|
|
|
|
|
|
|
|
for (auto& callFrom : curr)
|
|
|
|
|
{
|
|
|
|
|
for (auto& call : callFrom->callsFromDetailed)
|
|
|
|
|
{
|
|
|
|
|
if (call.detailCallsFrom.first == name)
|
|
|
|
|
return call.detailCallsFrom.first;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto& callFromNext : callFrom->callsFromV)
|
|
|
|
|
{
|
|
|
|
|
if (done.find(callFromNext) == done.end())
|
|
|
|
|
{
|
|
|
|
|
next.insert(callFromNext);
|
|
|
|
|
done.insert(callFromNext);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-11-22 20:21:18 +03:00
|
|
|
return "";
|
|
|
|
|
}
|
2023-09-14 19:43:13 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct CallV
|
|
|
|
|
{
|
|
|
|
|
std::string fName;
|
|
|
|
|
std::string fileName;
|
|
|
|
|
bool isMain;
|
|
|
|
|
int inRegion;
|
|
|
|
|
|
|
|
|
|
CallV() : inRegion(0), isMain(false) { }
|
|
|
|
|
|
|
|
|
|
CallV(const std::string &fName) :
|
|
|
|
|
fName(fName), fileName(""), isMain(false), inRegion(0)
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
CallV(const std::string &fName, const std::string &fileName, bool isMain) :
|
|
|
|
|
fName(fName), fileName(fileName), isMain(isMain), inRegion(0)
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
std::string to_string()
|
|
|
|
|
{
|
|
|
|
|
return fName + "@" + fileName + "@" + (isMain ? "1" : "0") + "@" + std::to_string(inRegion);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void propagateArrayFlags(const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls, const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays, std::map<std::string, std::vector<Messages>> &SPF_messages);
|
|
|
|
|
void removeDistrStateFromDeadFunctions(const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo, const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>>& declaredArrays);
|
|
|
|
|
bool detectMpiCalls(const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo, std::map<std::string, std::vector<Messages>>& SPF_messages);
|
|
|
|
|
int getLvlCall(FuncInfo* currF, int lvl, const std::string& func, const std::string& file, int line);
|
|
|
|
|
void compliteArrayUsage(DIST::Arrays<int>& allArraysForRegion, std::map<std::tuple<int, std::string, std::string>, DIST::Array*>& createdArrays, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls, const std::map<DIST::Array*, std::tuple<int, std::string, std::string>>& tableOfUniqNamesByArray);
|
|
|
|
|
void remoteNotUsedArrays(std::map<std::tuple<int, std::string, std::string>, DIST::Array*>& createdArrays, const std::set<DIST::Array*>& usedArraysAcrossRegions, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
|