Files
SAPFOR/Sapfor/_src/LoopAnalyzer/loop_analyzer.cpp

2642 lines
112 KiB
C++
Raw Normal View History

2023-09-14 19:43:13 +03:00
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include <string>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <utility>
#include <assert.h>
#include "loop_analyzer.h"
#include <tuple>
#include <stack>
#include "../Utils/leak_detector.h"
#if _WIN32 && NDEBUG && __BOOST
#include <boost/thread.hpp>
#endif
extern int passDone;
#include "../Distribution/Distribution.h"
#include "../Distribution/GraphCSR.h"
#include "../Distribution/Arrays.h"
#include "../ParallelizationRegions/ParRegions.h"
#include "../Utils/errors.h"
#include "../DirectiveProcessing/directive_parser.h"
#include "../DirectiveProcessing/directive_creator.h"
#include "../Utils/SgUtils.h"
#include "../Utils/AstWrapper.h"
#include "../GraphCall/graph_calls_func.h"
#include "../GraphLoop/graph_loops_func.h"
#include "../ParallelizationRegions/ParRegions_func.h"
#include "../DynamicAnalysis/gCov_parser_func.h"
#include "../ExpressionTransform/expr_transform.h"
#include "../SageAnalysisTool/depInterfaceExt.h"
#include "../VisualizerCalls/get_information.h"
#include "../VisualizerCalls/SendMessage.h"
#include "../Transformations/enddo_loop_converter.h"
#include "../DirectiveProcessing/remote_access.h"
2024-04-02 17:48:48 +03:00
#include "../DirectiveProcessing/directive_omp_parser.h"
2023-09-14 19:43:13 +03:00
#define PRINT_ARRAY_ARCS 0
#define PRINT_LOOP_STRUCT 0
#define PRINT_PROF_INFO 0
#define DEB 0
extern REGIME currRegime;
extern std::vector<Messages>* currMessages;
extern int sharedMemoryParallelization;
extern int parallizeFreeLoops;
2023-09-14 19:43:13 +03:00
using std::vector;
using std::pair;
using std::tuple;
using std::map;
using std::set;
using std::make_pair;
using std::make_tuple;
using std::get;
using std::string;
using std::wstring;
using std::stack;
REGIME currRegime = UNDEF;
std::vector<Messages>* currMessages;
static bool hasArrayAccessInSubscr(SgExpression *exp)
{
bool retVal = false;
if (exp->variant() == ARRAY_REF)
return true;
if (exp->lhs())
retVal |= hasArrayAccessInSubscr(exp->lhs());
if (exp->rhs())
retVal |= hasArrayAccessInSubscr(exp->rhs());
return retVal;
}
bool checkExistence(SgExpression *exp, const string& doName)
{
bool retVal = false;
if (exp->variant() == VAR_REF)
if (exp->symbol()->identifier() == doName)
retVal = true;
if (exp->lhs())
retVal |= checkExistence(exp->lhs(), doName);
if (exp->rhs())
retVal |= checkExistence(exp->rhs(), doName);
return retVal;
}
static pair<bool, string> constructArrayRefForPrint(SgArrayRefExp *arrayRef, const int dimNum, SgExpression *subscr)
{
bool needToPrint = true;
const int num = arrayRef->numberOfSubscripts();
string ref(arrayRef->symbol()->identifier());
ref += "(";
for (int i = 0; i < num; ++i)
{
if (i == dimNum)
{
char *copySub = copyOfUnparse(subscr->unparse());
ref += copySub;
if (subscr->variant() == INT_VAL)
needToPrint = false;
removeFromCollection(copySub);
delete []copySub;
}
else
ref += "*";
if (i != num - 1)
ref += ",";
else
ref += ")";
}
std::transform(ref.begin(), ref.end(), ref.begin(), ::toupper);
return make_pair(needToPrint, ref);
}
static void addInfoToMap(map<SgForStmt*, map<SgSymbol*, ArrayInfo>> &loopInfo, SgForStmt *position, SgSymbol *symb,
SgArrayRefExp *arrayRefIn, const int dimNum, const REMOTE_TYPE &value, const int currLine,
const int maxDimSize)
{
ArrayRefExp *arrayRef = new ArrayRefExp(arrayRefIn);
auto it = loopInfo.find(position);
if (loopInfo.end() == it)
it = loopInfo.insert(it, make_pair(position, map<SgSymbol*, ArrayInfo>()));
auto it1 = it->second.find(symb);
if (it1 == it->second.end())
it1 = it->second.insert(it1, make_pair(symb, ArrayInfo()));
auto it2 = it1->second.arrayAccessUnrec.find(arrayRef);
if (it2 == it1->second.arrayAccessUnrec.end())
{
it2 = it1->second.arrayAccessUnrec.insert(it2, make_pair(arrayRef, make_pair(currLine, vector<REMOTE_TYPE>())));
it2->second.second.resize(maxDimSize);
std::fill(it2->second.second.begin(), it2->second.second.end(), REMOTE_NONE);
}
if (dimNum == -1)
{
for (int z = 0; z < it2->second.second.size(); ++z)
it2->second.second[z] |= value;
}
else
it2->second.second[dimNum] |= value;
if (value == REMOTE_TRUE)
__spf_print(DEB, "RemoteAccess[%d]: true for dim %d and array %s, loop line %d\n", __LINE__, dimNum, symb->identifier(), position->lineNumber());
}
enum { READ_OP, WRITE_OP, UNREC_OP };
static void addInfoToVectors(map<SgForStmt*, map<SgSymbol*, ArrayInfo>> &loopInfo, SgForStmt *position, SgSymbol *symb,
const int dimNum, const pair<int, int> newCoef, int type, const int maxDimSize, const double currentW)
2023-09-14 19:43:13 +03:00
{
auto itLoop = loopInfo.find(position);
if (itLoop == loopInfo.end())
itLoop = loopInfo.insert(itLoop, make_pair(position, map<SgSymbol*, ArrayInfo>()));
auto itSymb = itLoop->second.find(symb);
if (itSymb == itLoop->second.end())
itSymb = itLoop->second.insert(itSymb, make_pair(symb, ArrayInfo()));
itSymb->second.setDimSize(maxDimSize);
if (type == READ_OP)
{
auto itAdd = itSymb->second.readOps[dimNum].coefficients.find(newCoef);
//add only uniq
if (itAdd == itSymb->second.readOps[dimNum].coefficients.end())
itAdd = itSymb->second.readOps[dimNum].coefficients.insert(itAdd, make_pair(newCoef, currentW));
}
else if (type == WRITE_OP)
{
auto itAdd = itSymb->second.writeOps[dimNum].coefficients.find(newCoef);
if (itAdd == itSymb->second.writeOps[dimNum].coefficients.end())
itAdd = itSymb->second.writeOps[dimNum].coefficients.insert(itAdd, make_pair(newCoef, currentW));
}
else if (type == UNREC_OP)
itSymb->second.unrecReadOps[dimNum] = true;
else
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
static vector<int> matchSubscriptToLoopSymbols(const vector<SgForStmt*> &parentLoops, SgExpression *subscr,
SgArrayRefExp *arrayRefIn, const int side, const int dimNum,
map<SgForStmt*, map<SgSymbol*, ArrayInfo>> &loopInfo,
const int currLine, const int numOfSubscriptions, const double currentW)
2023-09-14 19:43:13 +03:00
{
SgExpression *origSubscr = subscr;
ArrayRefExp *arrayRef = new ArrayRefExp(arrayRefIn);
// REVERT_SUBS has been done before REMOTE_ACC PASS
if (currRegime == REMOTE_ACC)
{
auto data = getAttributes<SgExpression*, SgExpression*>(arrayRefIn, set<int>{ ARRAY_REF });
if (data.size() == 1)
{
SgExpression *dataS = data[0]->lhs();
for (int z = 0; z < dimNum; ++z)
dataS = dataS->rhs();
subscr = dataS->lhs();
}
}
int countOfSymbols = 0;
int position = -1;
vector<int> allPositions;
bool hasArrayAcc = hasArrayAccessInSubscr(subscr);
SgSymbol *currOrigArrayS = OriginalSymbol(arrayRef->symbol());
if (!hasArrayAcc)
{
for (int i = 0; i < (int)parentLoops.size(); ++i)
{
if (checkExistence(subscr, parentLoops[i]->doName()->identifier()))
{
countOfSymbols++;
position = i;
allPositions.push_back(i);
}
}
}
pair<int, int> coefs = pair<int, int>(0, 0);
// more than one loop symbol in subscription
if (countOfSymbols > 1)
{
__spf_print(PRINT_ARRAY_ARCS, " <%d|%d> ", 0, 0);
if (currRegime == DATA_DISTR || currRegime == SHARED_MEMORY_PAR)
2023-09-14 19:43:13 +03:00
{
const pair<bool, string> &arrayRefString = constructArrayRefForPrint(arrayRef, dimNum, origSubscr);
__spf_print(1, "WARN: array ref '%s' at line %d has more than one loop's variables\n", arrayRefString.second.c_str(), currLine);
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"array ref '%s' has more than one loop's variables", to_wstring(arrayRefString.second).c_str());
__spf_printToLongBuf(messageR, R54, to_wstring(arrayRefString.second).c_str());
if (currLine > 0)
currMessages->push_back(Messages(WARR, currLine, messageR, messageE, 1021));
}
for (int i = 0; i < allPositions.size(); ++i)
{
if (currRegime == REMOTE_ACC)
{
if (side == RIGHT)
addInfoToMap(loopInfo, parentLoops[allPositions[i]], currOrigArrayS, arrayRef, dimNum, REMOTE_TRUE, currLine, numOfSubscriptions);
}
else
addInfoToVectors(loopInfo, parentLoops[allPositions[i]], currOrigArrayS, dimNum, make_pair(0, 0), UNREC_OP, numOfSubscriptions, currentW);
}
}
// no loop symbol in subscription
else if (countOfSymbols == 0)
{
__spf_print(PRINT_ARRAY_ARCS, " <%d|%d> ", 0, 0);
if (currRegime == REMOTE_ACC)
{
if (side == RIGHT)
for (int i = 0; i < (int)parentLoops.size(); ++i)
addInfoToMap(loopInfo, parentLoops[i], currOrigArrayS, arrayRef, dimNum, REMOTE_TRUE, currLine, numOfSubscriptions);
}
else if (currRegime == DATA_DISTR || currRegime == SHARED_MEMORY_PAR)
2023-09-14 19:43:13 +03:00
{
const pair<bool, string> &arrayRefString = constructArrayRefForPrint(arrayRef, dimNum, origSubscr);
if (!hasArrayAcc)
{
if (parentLoops.size() != 0 && (arrayRefString.first || side == LEFT))
{
__spf_print(1, "WARN: array ref '%s' in %d dimension at line %d does not have loop variables\n", arrayRefString.second.c_str(), dimNum + 1, currLine);
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"array ref '%s' in %d dimension does not have loop variables", to_wstring(arrayRefString.second).c_str(), dimNum + 1);
__spf_printToLongBuf(messageR, R55, to_wstring(arrayRefString.second).c_str(), dimNum + 1);
if (currLine > 0)
currMessages->push_back(Messages(WARR, currLine, messageR, messageE, 1021));
}
}
else
{
__spf_print(1, "WARN: array ref '%s' at line %d has indirect access\n", arrayRefString.second.c_str(), currLine);
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"array ref '%s' has indirect access", to_wstring(arrayRefString.second).c_str());
__spf_printToLongBuf(messageR, R56, to_wstring(arrayRefString.second).c_str());
if (currLine > 0)
currMessages->push_back(Messages(WARR, currLine, messageR, messageE, 1022));
}
}
}
else
{
bool needToCacl = true;
if (subscr->variant() == VAR_REF)
{
if (subscr->symbol()->id() == (parentLoops[position]->doName())->id())
{
coefs.first = 1;
needToCacl = false;
}
}
if (needToCacl)
getCoefsOfSubscript(coefs, subscr, parentLoops[position]->doName());
__spf_print(PRINT_ARRAY_ARCS, " <%d %d> ", coefs.first, coefs.second);
if (coefs.first == 0) // && coefs.second == 0)
{
if (currRegime == REMOTE_ACC)
{
if (side == RIGHT)
addInfoToMap(loopInfo, parentLoops[position], currOrigArrayS, arrayRef, dimNum, REMOTE_TRUE, currLine, numOfSubscriptions);
}
else if (currRegime == DATA_DISTR || currRegime == SHARED_MEMORY_PAR)
2023-09-14 19:43:13 +03:00
{
const pair<bool, string> &arrayRefString = constructArrayRefForPrint(arrayRef, dimNum, origSubscr);
__spf_print(1, "WARN: can not calculate index expression for array ref '%s' at line %d\n", arrayRefString.second.c_str(), currLine);
addInfoToVectors(loopInfo, parentLoops[position], currOrigArrayS, dimNum, coefs, UNREC_OP, numOfSubscriptions, currentW);
if (side == LEFT)
allPositions.clear();
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"can not calculate index expression for array ref '%s'", to_wstring(arrayRefString.second).c_str());
__spf_printToLongBuf(messageR, R57, to_wstring(arrayRefString.second).c_str());
if (currLine > 0)
currMessages->push_back(Messages(WARR, currLine, messageR, messageE, 1023));
}
}
else
{
if (currRegime == REMOTE_ACC)
{
if (side == RIGHT)
{
vector<ArrayOp>& currOp = loopInfo[parentLoops[position]][currOrigArrayS].arrayAccess[arrayRef].second;
if (currOp.size() < numOfSubscriptions)
currOp.resize(numOfSubscriptions);
//add only uniq
auto itAdd = currOp[dimNum].coefficients.find(coefs);
if (itAdd == currOp[dimNum].coefficients.end())
itAdd = currOp[dimNum].coefficients.insert(itAdd, make_pair(coefs, currentW));
}
if (coefs.first < 0)
addInfoToMap(loopInfo, parentLoops[position], currOrigArrayS, arrayRef, dimNum, REMOTE_TRUE, currLine, numOfSubscriptions);
else
//if we found regular access to array - set it false
addInfoToMap(loopInfo, parentLoops[position], currOrigArrayS, arrayRef, dimNum, REMOTE_FALSE, currLine, numOfSubscriptions);
}
if (coefs.first < 0 && sharedMemoryParallelization == 0)
2023-09-14 19:43:13 +03:00
{
if (currRegime == DATA_DISTR)
{
const pair<bool, string> &arrayRefString = constructArrayRefForPrint(arrayRef, dimNum, origSubscr);
const int line = (currLine < 0) ? parentLoops[position]->localLineNumber() : currLine;
__spf_print(1, "WARN: coefficient A in A*x+B is not positive for array ref '%s' at line %d, inverse distribution in not supported yet\n", arrayRefString.second.c_str(), line);
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"coefficient A in A*x+B is not positive for array ref '%s', inverse distribution in not supported yet", to_wstring(arrayRefString.second).c_str());
__spf_printToLongBuf(messageR, R58, to_wstring(arrayRefString.second).c_str());
if (line > 0)
currMessages->push_back(Messages(WARR, line, messageR, messageE, 1024));
if (side == LEFT)
allPositions.clear();
else
addInfoToVectors(loopInfo, parentLoops[position], currOrigArrayS, dimNum, coefs, UNREC_OP, numOfSubscriptions, currentW);
}
}
else
{
if (side == LEFT)
addInfoToVectors(loopInfo, parentLoops[position], currOrigArrayS, dimNum, coefs, WRITE_OP, numOfSubscriptions, currentW);
else
addInfoToVectors(loopInfo, parentLoops[position], currOrigArrayS, dimNum, coefs, READ_OP, numOfSubscriptions, currentW);
}
}
}
if (currRegime == ARRAY_ACC_CORNER)
{
int *valueSubs = new int[2];
valueSubs[0] = coefs.first;
valueSubs[1] = coefs.second;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, valueSubs, 2);
#endif
const vector<int*> &coefs = getAttributes<SgExpression*, int*>(subscr, set<int>{ INT_VAL });
if (coefs.size() == 0)
{
subscr->addAttribute(INT_VAL, valueSubs, sizeof(int*));
if (position != -1 && allPositions.size() == 1 && position < parentLoops.size())
subscr->addAttribute(FOR_NODE, parentLoops[position], sizeof(SgStatement));
}
}
return allPositions;
}
static vector<int> matchArrayToLoopSymbols(const vector<SgForStmt*> &parentLoops, vector<set<string>>& privatesVarsForLoop,
SgExpression *currExp, const int side,
2023-09-14 19:43:13 +03:00
map<SgForStmt*, map<SgSymbol*, ArrayInfo>> &loopInfo, const int currLine,
map<int, LoopGraph*> &sortedLoopGraph, const ParallelRegion *reg, const double currentW,
const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls)
{
SgArrayRefExp *arrayRef = (SgArrayRefExp*)currExp;
int numOfSubs = arrayRef->numberOfSubscripts();
currExp = currExp->lhs();
vector<int> wasFoundForLoop(parentLoops.size());
vector<int> matched(numOfSubs);
vector<int> matchedToDim(parentLoops.size());
std::fill(wasFoundForLoop.begin(), wasFoundForLoop.end(), 0);
std::fill(matched.begin(), matched.end(), -1);
std::fill(matchedToDim.begin(), matchedToDim.end(), -1);
int maxMatched = 0;
int sumMatched = 0;
for (int i = 0; i < numOfSubs; ++i)
{
vector<int> matchToLoops = matchSubscriptToLoopSymbols(parentLoops, currExp->lhs(), arrayRef, side, i, loopInfo, currLine, numOfSubs, currentW);
for (int k = 0; k < matchToLoops.size(); ++k)
{
wasFoundForLoop[matchToLoops[k]]++;
matchedToDim[matchToLoops[k]] = i;
}
matched[i] = matchToLoops.size();
sumMatched += matchToLoops.size();
maxMatched = std::max(maxMatched, (int)matchToLoops.size());
currExp = currExp->rhs();
}
//full array is used, add unknown operations to all loops
if (numOfSubs == 0)
{
SgSymbol *currOrigArrayS = OriginalSymbol(arrayRef->symbol());
auto arrType = isSgArrayType(currOrigArrayS->type());
if (arrType != NULL)
{
for (int d = 0; d < arrType->dimension(); ++d)
for (int i = 0; i < parentLoops.size(); ++i)
addInfoToVectors(loopInfo, parentLoops[i], currOrigArrayS, d, make_pair(0, 0), UNREC_OP, arrType->dimension(), currentW);
}
}
if (currRegime == ARRAY_ACC_CORNER)
return wasFoundForLoop;
bool ifUnknownArrayAssignFound = false;
vector<int> canNotMapToLoop;
for (int i = 0; i < wasFoundForLoop.size(); ++i)
{
if (wasFoundForLoop[i] != 1 &&
// always true for distributed data case
privatesVarsForLoop[i].find(string(arrayRef->symbol()->identifier())) == privatesVarsForLoop[i].end())
2023-09-14 19:43:13 +03:00
{
auto itLoop = sortedLoopGraph.find(parentLoops[i]->lineNumber());
if (itLoop == sortedLoopGraph.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
ifUnknownArrayAssignFound = true;
if (side == LEFT && (currRegime == DATA_DISTR || currRegime == COMP_DISTR || currRegime == SHARED_MEMORY_PAR))
2023-09-14 19:43:13 +03:00
itLoop->second->hasUnknownArrayAssigns = true;
itLoop->second->hasUnknownDistributedMap = true;
canNotMapToLoop.push_back(parentLoops[i]->lineNumber());
}
}
if (side == LEFT)
{
if (ifUnknownArrayAssignFound && (currRegime == DATA_DISTR || currRegime == SHARED_MEMORY_PAR))
2023-09-14 19:43:13 +03:00
{
const string arrayRefS = arrayRef->unparse();
for (auto &line : canNotMapToLoop)
{
__spf_print(1, "WARN: can not map write to array '%s' to loop on line %d\n", arrayRefS.c_str(), line);
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"can not map write to array '%s' to this loop", to_wstring(arrayRefS).c_str());
__spf_printToLongBuf(messageR, R59, to_wstring(arrayRefS).c_str());
if (line > 0)
currMessages->push_back(Messages(WARR, line, messageR, messageE, 1025));
}
}
}
else if (side == RIGHT)
{
SgSymbol* currOrigArrayS = OriginalSymbol(arrayRef->symbol());
if (currRegime == REMOTE_ACC)
{
DIST::Array* currArray = getArrayFromDeclarated(declaratedInStmt(currOrigArrayS), currOrigArrayS->identifier());
if (!currArray && currOrigArrayS->type()->variant() == T_ARRAY)
checkNull(currArray, convertFileName(__FILE__).c_str(), __LINE__);
if (currArray)
{
// for integration with SAPFOR-C
map<LoopGraph*, map<DIST::Array*, ArrayInfo*>> tmpInfo;
vector<LoopGraph*> parentGraphLoops;
auto tmpRef = new ArrayRefExp(arrayRef);
for (auto& loop : parentLoops)
{
auto it = sortedLoopGraph.find(loop->lineNumber());
if (it == sortedLoopGraph.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
parentGraphLoops.push_back(it->second);
}
auto requests = checkArrayRefInLoopForRemoteStatus(ifUnknownArrayAssignFound, sumMatched, numOfSubs, maxMatched,
currLine, currArray, wasFoundForLoop, tmpRef,
tmpInfo, matchedToDim, sortedLoopGraph, arrayLinksByFuncCalls,
reg, parentGraphLoops);
//clean memory
for (auto& loop : tmpInfo)
for (auto& array : loop.second)
delete array.second;
for (auto& req : requests)
addInfoToMap(loopInfo, (SgForStmt*)req.position->loop->GetOriginal(), currOrigArrayS, arrayRef, req.dimNum, req.value, req.currLine, req.maxDimSize);
}
}
}
return wasFoundForLoop;
}
static void mapArrayRef(SgStatement* currentSt, SgExpression* currExp,
const vector<SgForStmt*>& parentLoops, vector<set<string>>& privatesVarsForLoop,
const int side, const int lineNum,
2023-09-14 19:43:13 +03:00
map<SgForStmt*, map<SgSymbol*, ArrayInfo>>& loopInfo,
map<int, LoopGraph*> &sortedLoopGraph, map<string, pair<SgSymbol*, SgStatement*>>& notMappedDistributedArrays,
set<string>& mappedDistrbutedArrays,
const ParallelRegion* reg, const double currentW, const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls)
{
const char* printSide = NULL;
if (PRINT_ARRAY_ARCS)
printBlanks(2, (int)parentLoops.size());
if (side == LEFT)
printSide = "W_OP";
else
printSide = "R_OP";
__spf_print(PRINT_ARRAY_ARCS, "%s to array <%s> on line %d: ", printSide, OriginalSymbol(currExp->symbol())->identifier(), lineNum);
bool wasMapped = false;
vector<int> matched = matchArrayToLoopSymbols(parentLoops, privatesVarsForLoop, currExp, side, loopInfo, lineNum, sortedLoopGraph, reg, currentW, arrayLinksByFuncCalls);
2023-09-14 19:43:13 +03:00
for (int z = 0; z < matched.size(); ++z)
wasMapped |= (matched[z] != 0);
if (parentLoops.size() == 0)
{
SgSymbol* symb = currExp->symbol();
if (symb->type()->variant() == T_ARRAY)
notMappedDistributedArrays[symb->identifier()] = make_pair(symb, currentSt);
}
else
{
if (wasMapped)
mappedDistrbutedArrays.insert(currExp->symbol()->identifier());
else
{
SgSymbol* symb = currExp->symbol();
if (symb->type()->variant() == T_ARRAY)
notMappedDistributedArrays[symb->identifier()] = make_pair(symb, currentSt);
}
}
__spf_print(PRINT_ARRAY_ARCS, "\n");
}
static void findArrayRef(const vector<SgForStmt*> &parentLoops, SgExpression *currExp, const int lineNum, const int side,
2023-09-14 19:43:13 +03:00
map<SgForStmt*, map<SgSymbol*, ArrayInfo>> &loopInfo, const set<string> &privatesVars,
vector<set<string>>& privatesVarsForLoop, map<int, LoopGraph*> &sortedLoopGraph,
const map<string, vector<SgExpression*>> &commonBlocks,
const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
bool wasDistributedArrayRef, map<string, pair<SgSymbol*, SgStatement*>> &notMappedDistributedArrays,
set<string> &mappedDistrbutedArrays, SgStatement *currentSt, const ParallelRegion *reg, const double currentW,
const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls)
{
int nextSide = side;
if (isArrayRef(currExp))
{
//... and current array is not in private list
if (sharedMemoryParallelization ||
privatesVars.find(string(OriginalSymbol(currExp->symbol())->identifier())) == privatesVars.end())
2023-09-14 19:43:13 +03:00
{
if (wasDistributedArrayRef)
{
int depth = 1;
for (int i = parentLoops.size() - 1; i >= 0; --i, ++depth)
{
auto itLoop = sortedLoopGraph.find(parentLoops[i]->lineNumber());
if (itLoop == sortedLoopGraph.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (itLoop->second->perfectLoop != depth)
break;
if (!(sharedMemoryParallelization && side == RIGHT))
itLoop->second->hasIndirectAccess = true;
2023-09-14 19:43:13 +03:00
}
mapArrayRef(currentSt, currExp, parentLoops, privatesVarsForLoop, side, lineNum, loopInfo, sortedLoopGraph,
2023-09-14 19:43:13 +03:00
notMappedDistributedArrays, mappedDistrbutedArrays, reg, currentW, arrayLinksByFuncCalls);
}
else
{
wasDistributedArrayRef = true;
mapArrayRef(currentSt, currExp, parentLoops, privatesVarsForLoop, side, lineNum, loopInfo, sortedLoopGraph,
2023-09-14 19:43:13 +03:00
notMappedDistributedArrays, mappedDistrbutedArrays, reg, currentW, arrayLinksByFuncCalls);
}
}
else if (currRegime == DATA_DISTR && side == LEFT)
2023-09-14 19:43:13 +03:00
{
auto symb = OriginalSymbol(currExp->symbol());
SgStatement *decl = declaratedInStmt(symb);
auto uniqKey = getUniqName(commonBlocks, decl, symb);
2023-09-14 19:43:13 +03:00
auto itFound = declaredArrays.find(uniqKey);
if (itFound == declaredArrays.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
2023-09-14 19:43:13 +03:00
//TODO: array access to non distributed arrays, add CONSISTENT
if (itFound->second.first->GetDistributeFlagVal() != DIST::DISTR)
{
set<string> loopsPrivates;
set<Symbol*> loopsPrivatesS;
set<string> loopsRedUnited;
map<string, set<Symbol*>> loopsReductions;
map<string, set<tuple<Symbol*, Symbol*, int>>> loopsReductionsLoc;
2023-09-14 19:43:13 +03:00
for (int z = 0; z < parentLoops.size(); ++z)
2023-09-14 19:43:13 +03:00
{
auto& loop = parentLoops[z];
for (auto &data : getAttributes<SgStatement*, SgStatement*>(loop, set<int>{ SPF_ANALYSIS_DIR }))
2023-09-14 19:43:13 +03:00
{
fillPrivatesFromComment(new Statement(data), loopsPrivatesS);
for (auto& elem : loopsPrivatesS)
loopsPrivates.insert(elem->GetOriginal()->identifier());
fillReductionsFromComment(new Statement(data), loopsReductions);
fillReductionsFromComment(new Statement(data), loopsReductionsLoc);
2023-09-14 19:43:13 +03:00
}
}
2023-09-14 19:43:13 +03:00
for (auto &elem : loopsReductions)
{
for (auto &setElem : elem.second)
2023-09-14 19:43:13 +03:00
{
loopsPrivates.insert(setElem->GetOriginal()->identifier());
loopsRedUnited.insert(setElem->GetOriginal()->identifier());
2023-09-14 19:43:13 +03:00
}
}
2023-09-14 19:43:13 +03:00
for (auto &elem : loopsReductionsLoc)
{
for (auto &setElem : elem.second)
2023-09-14 19:43:13 +03:00
{
loopsPrivates.insert(get<0>(setElem)->GetOriginal()->identifier());
loopsPrivates.insert(get<1>(setElem)->GetOriginal()->identifier());
loopsRedUnited.insert(get<0>(setElem)->GetOriginal()->identifier());
loopsRedUnited.insert(get<1>(setElem)->GetOriginal()->identifier());
2023-09-14 19:43:13 +03:00
}
}
2023-09-14 19:43:13 +03:00
const string key = string(OriginalSymbol(currExp->symbol())->identifier());
if (loopsPrivates.find(key) == loopsPrivates.end())
{
for (auto& loop : parentLoops)
2023-09-14 19:43:13 +03:00
{
__spf_print(1, "WARN: write to non distributed array '%s' in loop on line %d\n", symb->identifier(), loop->lineNumber());
2023-09-14 19:43:13 +03:00
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"write to non distributed array '%s' in this loop", to_wstring(symb->identifier()).c_str());
2023-09-14 19:43:13 +03:00
__spf_printToLongBuf(messageR, R61, to_wstring(symb->identifier()).c_str());
2023-09-14 19:43:13 +03:00
if (loop->lineNumber() > 0)
currMessages->push_back(Messages(WARR, loop->lineNumber(), messageR, messageE, 1026));
sortedLoopGraph[loop->lineNumber()]->hasWritesToNonDistribute = true;
2023-09-14 19:43:13 +03:00
}
}
2023-09-14 19:43:13 +03:00
if (loopsPrivates.find(key) != loopsPrivates.end() || loopsRedUnited.find(key) != loopsRedUnited.end())
{
auto currOrigArrayS = OriginalSymbol(currExp->symbol());
if (currOrigArrayS->type()->variant() == T_ARRAY)
2023-09-14 19:43:13 +03:00
{
DIST::Array* currArray = getArrayFromDeclarated(declaratedInStmt(currOrigArrayS), currOrigArrayS->identifier());
checkNull(currArray, convertFileName(__FILE__).c_str(), __LINE__);
2023-09-14 19:43:13 +03:00
{
set<DIST::Array*> realArrayRefs;
getRealArrayRefs(currArray, currArray, realArrayRefs, arrayLinksByFuncCalls);
2023-09-14 19:43:13 +03:00
for (auto& array : realArrayRefs)
array->SetPrivateInLoopStatus(true);
2023-09-14 19:43:13 +03:00
}
}
}
}
}
nextSide = (side == LEFT) ? RIGHT : side;
}
bool needToContinue = true;
if (currExp->variant() == FUNC_CALL)
{
SgFunctionCallExp *funcExp = (SgFunctionCallExp*)currExp;
auto currFunc = isUserFunctionInProject(funcExp->funName()->identifier());
if (currFunc)
{
for (int z = 0; z < funcExp->numberOfArgs(); ++z)
{
if ((currFunc->funcParams.inout_types[z] & OUT_BIT) != 0)
nextSide = LEFT;
else
nextSide = RIGHT;
findArrayRef(parentLoops, funcExp->arg(z), lineNum, nextSide, loopInfo, privatesVars, privatesVarsForLoop, sortedLoopGraph,
commonBlocks, declaredArrays, wasDistributedArrayRef, notMappedDistributedArrays,
mappedDistrbutedArrays, currentSt, reg, currentW, arrayLinksByFuncCalls);
}
needToContinue = false;
}
}
if (needToContinue)
{
if (currExp->lhs())
findArrayRef(parentLoops, currExp->lhs(), lineNum, nextSide, loopInfo, privatesVars, privatesVarsForLoop, sortedLoopGraph,
commonBlocks, declaredArrays, wasDistributedArrayRef, notMappedDistributedArrays,
mappedDistrbutedArrays, currentSt, reg, currentW, arrayLinksByFuncCalls);
if (currExp->rhs())
findArrayRef(parentLoops, currExp->rhs(), lineNum, nextSide, loopInfo, privatesVars, privatesVarsForLoop, sortedLoopGraph,
commonBlocks, declaredArrays, wasDistributedArrayRef, notMappedDistributedArrays,
mappedDistrbutedArrays, currentSt, reg, currentW, arrayLinksByFuncCalls);
}
}
#define FIRST(x) get<0>(x)
#define SECOND(x) get<1>(x)
#define THIRD(x) get<2>(x)
map<string, string> shortFileNames;
static int uniqfileNames = 0;
string getShortName(const tuple<int, string, string> &uniqKey)
{
const char *declFileName = SECOND(uniqKey).c_str();
const char *varName = THIRD(uniqKey).c_str();
const int position = FIRST(uniqKey);
map<string, string>::iterator it;
it = shortFileNames.find(string(declFileName));
string retVal = "";
if (it == shortFileNames.end())
{
retVal = string("f") + std::to_string(uniqfileNames) + string("_");
shortFileNames[string(declFileName)] = retVal;
uniqfileNames++;
}
else
retVal = it->second;
return retVal + std::to_string(position) + string("_") + string(varName);
}
static int fillSizes(SgExpression *res, int &left, int &right)
{
int err = 0;
if (res->lhs()->variant() == INT_VAL)
left = res->lhs()->valueInteger();
else if (res->lhs()->variant() == MINUS_OP)
left = -1 * res->lhs()->lhs()->valueInteger();
else
err = -1;
if (res->rhs()->variant() == INT_VAL)
right = res->rhs()->valueInteger();
else if (res->rhs()->variant() == MINUS_OP)
right = -1 * res->rhs()->lhs()->valueInteger();
else
err = -1;
return err;
}
static pair<Expression*, Expression*> getElem(SgExpression *exp)
{
if (exp->lhs() && exp->rhs())
return make_pair(new Expression(exp->lhs()), new Expression(exp->rhs()));
else if (exp->lhs())
return make_pair(new Expression(exp->lhs()), (Expression*)NULL);
else if (exp->rhs())
return make_pair((Expression*)NULL, new Expression(exp->rhs()));
else
return make_pair((Expression*)NULL, (Expression*)NULL);
}
static void fillIdsFromEx(SgExpression* ex, set<string>& ids)
{
if (ex)
{
if (ex->variant() == VAR_REF)
ids.insert(ex->symbol()->identifier());
fillIdsFromEx(ex->lhs(), ids);
fillIdsFromEx(ex->rhs(), ids);
}
}
static void doReplacement(SgExpression *ex, const map<string, int> &idsToIdx, const map<int, set<int>> &values)
{
if (ex)
{
if (ex->lhs() && ex->lhs()->variant() == VAR_REF)
{
string key = ex->lhs()->symbol()->identifier();
auto it = idsToIdx.find(key);
if (it != idsToIdx.end())
{
if (values.find(it->second) != values.end())
{
const int value = *values.find(it->second)->second.begin();
ex->setLhs(*new SgValueExp(value));
}
}
}
if (ex->rhs() && ex->rhs()->variant() == VAR_REF)
{
string key = ex->rhs()->symbol()->identifier();
auto it = idsToIdx.find(key);
if (it != idsToIdx.end())
{
const int value = *values.find(it->second)->second.begin();
ex->setRhs(*new SgValueExp(value));
}
}
doReplacement(ex->lhs(), idsToIdx, values);
doReplacement(ex->rhs(), idsToIdx, values);
}
}
static SgExpression* replaceConstatantProcedurePars(SgExpression *dimList, SgStatement *proc, const map<string, vector<FuncInfo*>>& allFuncInfo)
{
if (proc == NULL)
return dimList;
if (allFuncInfo.size() == 0)
return dimList;
const string procN = proc->symbol()->identifier();
map<string, FuncInfo*> mapFunc;
createMapOfFunc(allFuncInfo, mapFunc);
auto it = mapFunc.find(procN);
if (it == mapFunc.end())
return dimList;
FuncInfo* currF = it->second;
if (currF->funcParams.countOfPars == 0)
return dimList;
set<string> ids;
fillIdsFromEx(dimList, ids);
if (ids.size() == 0)
return dimList;
set<int> idxFound;
map<string, int> idsToIdx;
for (int z = 0; z < currF->funcParams.countOfPars; ++z)
{
if (ids.find(currF->funcParams.identificators[z]) != ids.end())
{
idxFound.insert(z);
idsToIdx[currF->funcParams.identificators[z]] = z;
}
}
if (idxFound.size() == 0 || currF->callsTo.size() == 0)
return dimList;
map<int, set<int>> values;
//TODO: many call levels of functions
for (int z = 0; z < currF->callsTo.size(); ++z)
{
FuncInfo* callOfThis = currF->callsTo[z];
for (int p = 0; p < callOfThis->callsFromDetailed.size(); ++p)
2023-09-14 19:43:13 +03:00
{
if (callOfThis->callsFromDetailed[p].detailCallsFrom.first == procN)
2023-09-14 19:43:13 +03:00
{
for (auto& par : idxFound)
{
auto parType = callOfThis->callsFromDetailed[p].actualParams.parametersT[par];
2023-09-14 19:43:13 +03:00
if (parType != SCALAR_INT_T)
return dimList;
else
{
if (callOfThis->callsFromDetailed[p].actualParams.parameters[par] == NULL)
2023-09-14 19:43:13 +03:00
return dimList;
values[par].insert(((int*)(callOfThis->callsFromDetailed[p].actualParams.parameters[par]))[0]);
2023-09-14 19:43:13 +03:00
}
}
}
}
}
for (auto& elem : values)
if (elem.second.size() != 1)
return dimList;
doReplacement(dimList, idsToIdx, values);
return dimList;
}
2024-11-21 15:07:16 +03:00
vector<pair<Expression*, Expression*>> getArraySizes(vector<pair<int, int>> &sizes, SgSymbol *symb, SgStatement *decl,
const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls,
const map<string, vector<FuncInfo*>> &allFuncInfo)
2023-09-14 19:43:13 +03:00
{
SgArrayType *type = isSgArrayType(symb->type());
vector<pair<Expression*, Expression*>> retVal;
if (type != NULL)
{
SgExpression *dimList = type->getDimList()->copyPtr();
int consistInAllocates = 0;
set<string> allocValues;
SgExpression *alloc = NULL;
dimList = replaceConstatantProcedurePars(dimList, getFuncStat(decl, { MODULE_STMT, BLOCK_DATA }), allFuncInfo);
while (dimList)
{
SgExpression *res = ReplaceArrayBoundSizes(dimList->lhs()->copyPtr());
if (res && res->variant() == INT_VAL)
{
sizes.push_back(make_pair(1, res->valueInteger()));
retVal.push_back(make_pair((Expression*)NULL, new Expression(dimList->lhs())));
}
else if (res && res->variant() == DDOT)
{
int err, tmpRes;
if (res->lhs())
{
err = CalculateInteger(res->lhs(), tmpRes);
if (err != -1)
res->setLhs(new SgValueExp(tmpRes));
}
if (res->rhs())
{
err = CalculateInteger(res->rhs(), tmpRes);
if (err != -1)
res->setRhs(new SgValueExp(tmpRes));
}
int left, right;
bool ok = res->lhs() && res->rhs();
if (ok)
{
int err = fillSizes(res, left, right);
ok = (err == 0);
}
if (ok)
{
sizes.push_back(make_pair(left, right));
retVal.push_back(getElem(dimList->lhs()));
}
else
{
if (alloc == NULL)
{
for (auto &data : getAttributes<SgStatement*, SgStatement*>(decl, set<int>{ ALLOCATE_STMT }))
{
if (data->variant() != ALLOCATE_STMT)
continue;
//TODO:
if (string(data->fileName()) != current_file->filename())
continue;
SgExpression *list = data->expr(0);
while (list)
{
SgArrayRefExp *arrayRef = isSgArrayRefExp(list->lhs());
if (arrayRef != NULL)
{
SgSymbol *origS = OriginalSymbol(arrayRef->symbol());
DIST::Array *currArray = getArrayFromDeclarated(declaratedInStmt(origS), origS->identifier());
string toCmp = string(origS->identifier());
//TODO: extend
if (currArray && currArray->GetLocation().first == DIST::l_PARAMETER)
{
auto it = arrayLinksByFuncCalls.find(currArray);
if (it != arrayLinksByFuncCalls.end())
{
bool found = false;
for (auto &elem : it->second)
{
if (elem->GetLocation().first != DIST::l_PARAMETER)
{
if (elem->GetShortName() == string(symb->identifier()))
{
consistInAllocates++;
alloc = list->lhs()->lhs();
allocValues.insert(alloc->unparse());
found = true;
break;
}
}
}
if (found)
break;
}
}
else
{
if (toCmp == string(symb->identifier()))
{
consistInAllocates++;
alloc = list->lhs()->lhs();
allocValues.insert(alloc->unparse());
break;
}
}
}
list = list->rhs();
}
}
}
else // set next in list
alloc = alloc->rhs();
//TODO: dont check string representations of alloc expression!! check integer result, if all strings are equal
if (consistInAllocates != 1 && allocValues.size() != 1)
{
sizes.push_back(make_pair(-1, -1));
retVal.push_back(make_pair((Expression*)NULL, (Expression*)NULL));
}
else
{
SgExpression *result = ReplaceArrayBoundSizes(alloc->lhs()->copyPtr());
if (result->lhs())
{
err = CalculateInteger(result->lhs(), tmpRes);
if (err != -1)
result->setLhs(new SgValueExp(tmpRes));
}
if (result->rhs())
{
err = CalculateInteger(result->rhs(), tmpRes);
if (err != -1)
result->setRhs(new SgValueExp(tmpRes));
}
if (result->variant() == INT_VAL)
{
sizes.push_back(make_pair(1, result->valueInteger()));
retVal.push_back(make_pair((Expression*)NULL, new Expression(alloc->lhs())));
}
else if (result->variant() == DDOT)
{
retVal.push_back(getElem(alloc->lhs()));
int left = 0, right = 0;
bool ok = result->lhs() && result->rhs();
if (ok)
{
int err = fillSizes(result, left, right);
ok = (err == 0);
}
if (ok)
sizes.push_back(make_pair(left, right));
else
sizes.push_back(make_pair(-1, -1));
}
else
{
sizes.push_back(make_pair(-1, -1));
retVal.push_back(make_pair((Expression*)NULL, (Expression*)NULL));
}
}
}
}
else
{
sizes.push_back(make_pair(-1, -1));
retVal.push_back(make_pair((Expression*)NULL, (Expression*)NULL));
}
dimList = dimList->rhs();
}
}
return retVal;
}
void recalculateArraySizes(set<DIST::Array*> &arraysDone, const set<DIST::Array*> &allArrays,
const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls,
const map<string, vector<FuncInfo*>> &allFuncInfo)
{
for (auto& array : allArrays)
{
auto itF = arraysDone.find(array);
if (itF != arraysDone.end())
continue;
itF = arraysDone.insert(itF, array);
if (array->IsTemplate())
continue;
SgSymbol* symb = array->GetDeclSymbol()->GetOriginal();
if (!symb)
continue;
auto& sizeInfo = array->GetSizes();
bool needToUpdate = false;
for (auto& elem : sizeInfo)
{
if (elem.first == elem.second)
{
needToUpdate = true;
break;
}
}
if (!needToUpdate)
continue;
auto& declInfo = array->GetDeclInfo();
bool wasSelect = false;
vector<int> files;
pair<string, int> mainDecl;
for (auto& elem : declInfo)
{
int fileId = SgFile::switchToFile(elem.first);
if (fileId != -1)
{
files.push_back(fileId);
mainDecl = elem;
SgFile* tmpfile = &(CurrentProject->file(fileId));
wasSelect = true;
break;
}
}
if (!wasSelect)
{
//try to find in includes
for (int i = CurrentProject->numberOfFiles() - 1; i >= 0; --i)
{
SgFile* file = &(CurrentProject->file(i));
for (SgStatement* st = file->firstStatement(); st; st = st->lexNext())
{
for (auto& elem : declInfo)
{
if (make_pair(string(st->fileName()), st->lineNumber()) == elem)
{
wasSelect = true;
break;
}
}
if (wasSelect)
{
//wasSelect = false;
SgStatement* decl = declaratedInStmt(symb);
vector<pair<int, int>> sizes;
auto sizesEx = getArraySizes(sizes, symb, decl, arrayLinksByFuncCalls, allFuncInfo);
array->SetSizes(sizes);
array->SetSizesExpr(sizesEx);
}
}
if (wasSelect)
break;
}
if (!wasSelect)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
else
{
if (wasSelect)
{
if (array->GetLocation().first == DIST::l_MODULE)
{
files.clear();
for (int i = CurrentProject->numberOfFiles() - 1; i >= 0; --i)
files.push_back(i);
}
for (auto& file : files)
{
CurrentProject->file(file);
SgStatement* decl = NULL;
string currF = current_file->filename();
if (array->GetLocation().first == DIST::l_MODULE)
{
SgStatement* st = current_file->firstStatement();
while (st)
{
if (st->lineNumber() == mainDecl.second && st->fileName() == mainDecl.first)
{
decl = st;
symb = NULL;
SgExpression* ex = decl->expr(0);
while (ex)
{
if (ex->lhs() && isArrayRef(ex->lhs()))
{
auto s = ex->lhs()->symbol();
if (s && s->identifier() == array->GetShortName())
{
symb = s;
break;
}
}
ex = ex->rhs();
}
break;
}
st = st->lexNext();
}
}
else
{
if (symb->getFileId() != current_file_id)
{
SgStatement* st = current_file->firstStatement();
int lastLine = 1;
while (st)
{
if (st->lineNumber() > lastLine)
lastLine = st->lineNumber();
st = st->lexNext();
}
symb = array->GetDeclSymbol(currF, make_pair(1, lastLine), getAllFilesInProject())->GetOriginal();
}
decl = declaratedInStmt(symb, NULL, false);
}
if (decl == NULL)
continue;
if (symb == NULL)
{
decl->unparsestdout();
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
vector<pair<int, int>> sizes;
auto sizesEx = getArraySizes(sizes, symb, decl, arrayLinksByFuncCalls, allFuncInfo);
if (array->GetDimSize() != sizes.size())
{
sizes.clear();
auto sizesEx = getArraySizes(sizes, symb, decl, arrayLinksByFuncCalls, allFuncInfo);
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
array->SetSizes(sizes);
array->SetSizesExpr(sizesEx);
bool needToContinue = false;
for (auto& elem : sizes)
{
if (elem.first == elem.second)
{
needToContinue = true;
break;
}
}
if (!needToContinue)
break;
}
}
else
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
}
}
bool isIntrinsic(const char *funName)
{
if (intrinsicF.find(funName) == intrinsicF.end())
return false;
else
return true;
}
static set<string> getPrivatesFromModule(SgStatement *mod,
const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
const map<SgStatement*, set<tuple<int, string, string>>> &declaratedArraysSt,
const map<string, SgStatement*> &modulesByName)
{
set<string> privates;
SgStatement *end = mod->lastNodeOfStmt();
while (mod != end && mod->lineNumber() > 0)
{
if (mod->variant() == CONTAINS_STMT)
break;
if (mod->variant() == USE_STMT)
{
auto itF = modulesByName.find(mod->symbol()->identifier());
if (itF == modulesByName.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
const set<string> recPrivates = getPrivatesFromModule(itF->second, declaredArrays, declaratedArraysSt, modulesByName);
for (auto it = recPrivates.begin(); it != recPrivates.end(); ++it)
privates.insert(*it);
}
else
{
tryToFindPrivateInAttributes(mod, privates);
fillNonDistrArraysAsPrivate(mod, declaredArrays, declaratedArraysSt, privates);
}
mod = mod->lexNext();
}
return privates;
}
extern map<DIST::Array*, std::tuple<int, string, string>> tableOfUniqNamesByArray;
static void convertOneLoop(LoopGraph *currLoop, map<LoopGraph*, map<DIST::Array*, ArrayInfo*>> &outInfo,
const map<SgSymbol*, ArrayInfo> &toConvert,
const set<string> &privateArrays,
const map<string, vector<SgExpression*>> &commonBlocks,
const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls,
map<tuple<int, string, string>, DIST::Array*> &createdArrays,
bool freeArrays = false)
{
map<DIST::Array*, ArrayInfo*> toAdd;
for (auto& conv : toConvert)
{
SgSymbol *currentArray = OriginalSymbol(conv.first);
ArrayInfo *currentInfo = (ArrayInfo*)(&conv.second);
DIST::Array *arrayToAdd;
SgStatement *decl = declaratedInStmt(currentArray);
const char *symbIdent = currentArray->identifier();
if (privateArrays.find(symbIdent) == privateArrays.end() || sharedMemoryParallelization)
2023-09-14 19:43:13 +03:00
{
const tuple<int, string, string> uniqKey = getUniqName(commonBlocks, decl, currentArray);
auto itFound = createdArrays.find(uniqKey);
if (itFound == createdArrays.end())
{
auto itArray = declaredArrays.find(uniqKey);
if (itArray == declaredArrays.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
arrayToAdd = itArray->second.first;
itFound = createdArrays.insert(itFound, make_pair(uniqKey, arrayToAdd));
}
else
arrayToAdd = itFound->second;
if (!sharedMemoryParallelization && arrayToAdd->IsNotDistribute() == true)
2023-09-14 19:43:13 +03:00
continue;
set<DIST::Array*> links;
getRealArrayRefs(arrayToAdd, arrayToAdd, links, arrayLinksByFuncCalls);
int countOflinks = 0;
for (auto &linkedArray : links)
{
if (arrayToAdd == linkedArray)
continue;
++countOflinks;
auto key = tableOfUniqNamesByArray[linkedArray];
auto value = declaredArrays.find(key)->second;
if (value.second == 0 && createdArrays.find(key) == createdArrays.end())
createdArrays.insert(make_pair(key, linkedArray));
}
if (freeArrays)
if (countOflinks == 0)
continue;
toAdd[arrayToAdd] = currentInfo;
for (int z = 0; z < currentInfo->getDimSize(); ++z)
{
if (currentInfo->readOps[z].coefficients.size() || currentInfo->writeOps[z].coefficients.size())
{
arrayToAdd->SetMappedDim(z);
for (auto &realRef : links)
realRef->SetMappedDim(z);
}
}
}
}
outInfo[currLoop] = toAdd;
}
static map<LoopGraph*, map<DIST::Array*, ArrayInfo*>>
convertLoopInfo(const map<SgForStmt*, map<SgSymbol*, ArrayInfo>> &loopInfo,
const map<int, LoopGraph*> &sortedLoopGraph,
const set<string> &privateArrays,
const map<string, vector<SgExpression*>> &commonBlocks,
const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls,
map<tuple<int, string, string>, DIST::Array*> &createdArrays)
{
map<LoopGraph*, map<DIST::Array*, ArrayInfo*>> outInfo;
for (auto it = loopInfo.begin(); it != loopInfo.end(); ++it)
{
auto itGraph = sortedLoopGraph.find(it->first->lineNumber());
if (itGraph == sortedLoopGraph.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
convertOneLoop(itGraph->second, outInfo, it->second, privateArrays, commonBlocks, declaredArrays, arrayLinksByFuncCalls, createdArrays);
}
return outInfo;
}
inline static void fillPrivatesFromDecl(SgExpression *ex, set<SgSymbol*> &delcsSymbViewed, set<SgStatement*> &delcsStatViewed,
const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
const map<SgStatement*, set<tuple<int, string, string>>> &declaratedArraysSt,
set<string> &privatesVars)
{
if (!ex)
return;
if (isArrayRef(ex))
{
SgSymbol *symb = ex->symbol();
if (symb->type())
{
if (symb->type()->variant() == T_ARRAY)
{
SgSymbol *s = ex->symbol();
auto it = delcsSymbViewed.find(s);
if (it == delcsSymbViewed.end())
{
delcsSymbViewed.insert(it, s);
SgStatement *decl = declaratedInStmt(s);
auto itD = delcsStatViewed.find(decl);
if (itD == delcsStatViewed.end())
{
delcsStatViewed.insert(itD, decl);
tryToFindPrivateInAttributes(decl, privatesVars);
fillNonDistrArraysAsPrivate(decl, declaredArrays, declaratedArraysSt, privatesVars);
}
}
}
}
}
fillPrivatesFromDecl(ex->rhs(), delcsSymbViewed, delcsStatViewed, declaredArrays, declaratedArraysSt, privatesVars);
fillPrivatesFromDecl(ex->lhs(), delcsSymbViewed, delcsStatViewed, declaredArrays, declaratedArraysSt, privatesVars);
}
static void changeLoopWeight(double &currentWeight, const map<int, LoopGraph*> &sortedLoopGraph, const int line, bool increase = true)
2023-09-14 19:43:13 +03:00
{
auto loopIt = sortedLoopGraph.find(line);
if (loopIt == sortedLoopGraph.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (increase)
currentWeight *= loopIt->second->countOfIters;
else
currentWeight /= loopIt->second->countOfIters;
}
static bool hasNonPureFunctions(SgExpression *ex, LoopGraph *loopRef, vector<Messages> &messagesForFile, const int line, const map<string, FuncInfo*> &funcByName)
2023-09-14 19:43:13 +03:00
{
bool retVal = false;
if (ex == NULL)
return retVal;
if (ex->variant() == FUNC_CALL)
{
if (isIntrinsicFunctionName(ex->symbol()->identifier()) == 0)
{
auto itF = funcByName.find(ex->symbol()->identifier());
bool isPure = false;
if (itF != funcByName.end())
isPure = itF->second->isPure;
if (!isPure)
{
retVal = true;
loopRef->hasNonPureProcedures = true;
messagesForFile.push_back(Messages(WARR, line, R79, L"Only pure procedures were supported", 1044));
}
}
}
bool retL = false, retR = false;
if (ex->lhs())
retL = hasNonPureFunctions(ex->lhs(), loopRef, messagesForFile, line, funcByName);
if (ex->rhs())
retR = hasNonPureFunctions(ex->rhs(), loopRef, messagesForFile, line, funcByName);
return retVal || retL || retR;
}
void fillFromModule(SgSymbol* s, const map<string, set<string>>& privatesByModule, set<string>& privates)
{
if (s)
{
auto it = privatesByModule.find(s->identifier());
if (it != privatesByModule.end())
privates.insert(it->second.begin(), it->second.end());
}
}
static SgStatement* takeOutConditions(stack<SgExpression*>& conditions, stack<SgStatement*>& ifBlocks, SgStatement* st)
2023-09-14 19:43:13 +03:00
{
auto res = createIfConditions(conditions, ifBlocks, st);
auto before = st->lexPrev();
for (auto& elem : res)
if (elem)
st->insertStmtBefore(*elem, *st->controlParent());
SgLabel* lab = st->label();
if (lab) // move lab to first condition
{
st->deleteLabel(true);
if (res.size() == 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
res[0]->setLabel(*lab);
}
return before;
}
extern void createMapLoopGraph(map<int, LoopGraph*> &sortedLoopGraph, const vector<LoopGraph*> *loopGraph);
void loopAnalyzer(SgFile *file, vector<ParallelRegion*> &regions, map<tuple<int, string, string>, DIST::Array*> &createdArrays,
vector<Messages> &messagesForFile, REGIME regime, const map<string, vector<FuncInfo*>> &AllfuncInfo,
const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
const map<SgStatement*, set<tuple<int, string, string>>> &declaratedArraysSt,
const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls,
const map<SgStatement*, vector<DefUseList>> &defUseByPlace,
bool skipDeps, vector<LoopGraph*> *loopGraph)
{
currMessages = &messagesForFile;
currRegime = regime;
map<string, vector<SgExpression*>> commonBlocks;
map<int, LoopGraph*> sortedLoopGraph;
map<int, pair<SgForStmt*, pair<set<string>, set<string>>>> allLoops;
createMapLoopGraph(sortedLoopGraph, loopGraph);
int funcNum = file->numberOfFunctions();
__spf_print(PRINT_PROF_INFO,"functions num in file = %d\n", funcNum);
vector<SgStatement*> modules;
findModulesInFile(file, modules);
map<string, SgStatement*> modulesByName;
for (int i = 0; i < modules.size(); ++i)
modulesByName[modules[i]->symbol()->identifier()] = modules[i];
map<string, set<string>> privatesByModule;
if(!sharedMemoryParallelization)
for (int i = 0; i < modules.size(); ++i)
privatesByModule[modules[i]->symbol()->identifier()] = getPrivatesFromModule(modules[i], declaredArrays, declaratedArraysSt, modulesByName);
2023-09-14 19:43:13 +03:00
map<string, FuncInfo*> funcByName;
createMapOfFunc(AllfuncInfo, funcByName);
const vector<FuncInfo*> &funcInfo = AllfuncInfo.find(file->filename())->second;
for (int i = 0; i < funcNum; ++i)
{
createNeededException();
string fName = file->functions(i)->symbol()->identifier();
#if _WIN32
if (file->functions(i)->variant() != MODULE_STMT)
2024-11-14 15:28:51 +03:00
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"'");
2023-09-14 19:43:13 +03:00
else
2024-11-14 15:28:51 +03:00
sendMessage_2lvl(wstring(L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '") + wstring(fName.begin(), fName.end()) + L"'");
2023-09-14 19:43:13 +03:00
#else
if (file->functions(i)->variant() != MODULE_STMT)
sendMessage_2lvl(wstring(L"processing function '") + wstring(fName.begin(), fName.end()) + L"'");
else
sendMessage_2lvl(wstring(L"processing module '") + wstring(fName.begin(), fName.end()) + L"'");
#endif
set<SgSymbol*> delcsSymbViewed;
set<SgStatement*> delcsStatViewed;
if (funcInfo[i]->doNotAnalyze)
continue;
map<SgForStmt*, map<SgSymbol*, ArrayInfo>> loopInfo;
set<int> loopWithOutArrays;
set<string> privatesVars;
SgStatement *st = file->functions(i);
string funcName = "";
if (st->variant() == PROG_HEDR)
{
SgProgHedrStmt *progH = (SgProgHedrStmt*)st;
__spf_print(PRINT_PROF_INFO, "*** Program <%s> started at line %d / %s\n", progH->symbol()->identifier(), st->lineNumber(), st->fileName());
funcName = progH->symbol()->identifier();
}
else if (st->variant() == PROC_HEDR)
{
SgProcHedrStmt *procH = (SgProcHedrStmt*)st;
__spf_print(PRINT_PROF_INFO, "*** Function <%s> started at line %d / %s\n", procH->symbol()->identifier(), st->lineNumber(), st->fileName());
funcName = procH->symbol()->identifier();
}
else if (st->variant() == FUNC_HEDR)
{
SgFuncHedrStmt *funcH = (SgFuncHedrStmt*)st;
__spf_print(PRINT_PROF_INFO, "*** Function <%s> started at line %d / %s\n", funcH->symbol()->identifier(), st->lineNumber(), st->fileName());
funcName = funcH->symbol()->identifier();
}
vector<LoopGraph*> loopsForFunction;
for (auto& loop : *loopGraph)
{
auto fStat = getFuncStat(loop->loop->GetOriginal());
if (fStat->symbol()->identifier() == funcName)
loopsForFunction.push_back(loop);
}
if(!sharedMemoryParallelization)
2023-09-14 19:43:13 +03:00
{
SgStatement* tmpModFind = st;
while (tmpModFind->variant() != GLOBAL)
{
tmpModFind = tmpModFind->controlParent();
if (tmpModFind->variant() == MODULE_STMT)
fillFromModule(tmpModFind->symbol(), privatesByModule, privatesVars);
}
2023-09-14 19:43:13 +03:00
}
2023-09-14 19:43:13 +03:00
commonBlocks.clear();
getCommonBlocksRef(commonBlocks, st, st->lastNodeOfStmt());
__spf_print(PRINT_PROF_INFO, " number of common blocks %d\n", (int)commonBlocks.size());
SgStatement *lastNode = st->lastNodeOfStmt();
vector<SgForStmt*> parentLoops;
vector<set<string>> privatesVarsForLoop;
//For remote access
pair<SgForStmt*, LoopGraph*> *under_dvm_dir = NULL;
map<string, pair<SgSymbol*, SgStatement*>> notMappedDistributedArrays;
set<string> mappedDistrbutedArrays;
double currentWeight = 1.0;
while (st != lastNode)
{
createNeededException();
if (st == NULL)
{
currMessages->push_back(Messages(ERROR, 1, R128, L"internal error in analysis, parallel directives will not be generated for this file!", 3008));
__spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n");
break;
}
if (st->variant() == CONTAINS_STMT)
break;
if (!__gcov_doesThisLineExecuted(st->fileName(), st->lineNumber()))
{
st = st->lexNext();
continue;
}
const int currentLine = st->lineNumber() < -1 ? st->localLineNumber() : st->lineNumber();
ParallelRegion *currReg = getRegionByLine(regions, st->fileName(), currentLine);
if (currReg == NULL)
{
st = st->lexNext();
continue;
}
if (isSgExecutableStatement(st) == NULL)
delcsStatViewed.insert(st);
else if (!sharedMemoryParallelization &&
!isDVM_stat(st) && !isSPF_stat(st))
2023-09-14 19:43:13 +03:00
for (int i = 0; i < 3; ++i)
fillPrivatesFromDecl(st->expr(i), delcsSymbViewed, delcsStatViewed, declaredArrays, declaratedArraysSt, privatesVars);
//printf("new st with var = %d, on line %d\n", st->variant(), st->lineNumber());
const int currV = st->variant();
if (currV == FOR_NODE)
{
if(!sharedMemoryParallelization)
{
tryToFindPrivateInAttributes(st, privatesVars);
fillNonDistrArraysAsPrivate(st, declaredArrays, declaratedArraysSt, privatesVars);
}
2023-09-14 19:43:13 +03:00
set<string> toAdd;
tryToFindPrivateInAttributes(st, toAdd);
if (PRINT_LOOP_STRUCT)
printBlanks(2, (int)parentLoops.size());
__spf_print(PRINT_LOOP_STRUCT, "FOR NODE on line %d\n", st->lineNumber());
parentLoops.push_back((SgForStmt*)st);
changeLoopWeight(currentWeight, sortedLoopGraph, st->lineNumber());
privatesVarsForLoop.push_back(toAdd);
if (regime == REMOTE_ACC)
{
SgStatement *prev = st->lexPrev();
if (prev)
{
if (prev->variant() == DVM_PARALLEL_ON_DIR)
{
auto it = sortedLoopGraph.find(st->lineNumber());
if (it == sortedLoopGraph.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
under_dvm_dir = new pair<SgForStmt*, LoopGraph*>((SgForStmt*)st, it->second);
}
}
}
}
else if (currV == CONTROL_END)
{
SgStatement *contrlParent = st->controlParent();
if (contrlParent)
{
if (contrlParent->variant() == FOR_NODE)
{
changeLoopWeight(currentWeight, sortedLoopGraph, contrlParent->lineNumber(), false);
if (loopInfo.find((SgForStmt*)contrlParent) == loopInfo.end() && !sortedLoopGraph[contrlParent->lineNumber()]->hasUnknownDistributedMap)
loopWithOutArrays.insert(contrlParent->lineNumber());
set<string> unitedPrivates;
for (int p = 0; p < parentLoops.size(); ++p)
for (auto &privVar : privatesVarsForLoop[p])
unitedPrivates.insert(privVar);
set<string> setDiff;
if(!sharedMemoryParallelization)
for (auto &privVars : privatesVars)
if (unitedPrivates.find(privVars) == unitedPrivates.end())
setDiff.insert(privVars);
2023-09-14 19:43:13 +03:00
allLoops[contrlParent->lineNumber()] = make_pair((SgForStmt*)contrlParent, make_pair(unitedPrivates, setDiff));
parentLoops.pop_back();
privatesVarsForLoop.pop_back();
if (regime == REMOTE_ACC)
{
if (under_dvm_dir)
{
if (contrlParent == under_dvm_dir->first && under_dvm_dir->second->userDvmDirective == NULL)
{
ParallelRegion *currReg = getRegionByLine(regions, under_dvm_dir->first->fileName(), under_dvm_dir->first->lineNumber());
if (currReg)
{
const DIST::Arrays<int> &allArrays = currReg->GetAllArrays();
DIST::GraphCSR<int, double, attrType> &reducedG = currReg->GetReducedGraphToModify();
const DataDirective &data = currReg->GetDataDir();
const vector<int> &currVar = currReg->GetCurrentVariant();
const pair<LoopGraph*, const ParallelDirective*> currDir = make_pair(under_dvm_dir->second, under_dvm_dir->second->directive);
auto convertedLoopInfo = convertLoopInfo(loopInfo, sortedLoopGraph, privatesVars, commonBlocks, declaredArrays, arrayLinksByFuncCalls, createdArrays);
auto uniqRemotes = createRemoteInParallel(currDir, allArrays, convertedLoopInfo, reducedG, data, currVar, messagesForFile, currReg->GetId(), arrayLinksByFuncCalls, funcByName);
addRemotesToDir(under_dvm_dir, uniqRemotes);
}
delete under_dvm_dir;
under_dvm_dir = NULL;
}
}
}
}
}
else
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
else if (currV == ASSIGN_STAT)
{
if (st->expr(0))
findArrayRef(parentLoops, st->expr(0), st->lineNumber(), LEFT, loopInfo, privatesVars, privatesVarsForLoop,
sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays,
mappedDistrbutedArrays, st, currReg, currentWeight, arrayLinksByFuncCalls);
if (st->expr(1))
findArrayRef(parentLoops, st->expr(1), st->lineNumber(), RIGHT, loopInfo, privatesVars, privatesVarsForLoop,
sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays,
mappedDistrbutedArrays, st, currReg, currentWeight, arrayLinksByFuncCalls);
if (regime == REMOTE_ACC)
{
if (st->expr(1))
{
bool cond = true;
if (st->expr(1)->variant() == FUNC_CALL)
{
string fName = ((SgFunctionCallExp*)st->expr(1))->funName()->identifier();
cond = (fName != "allocated");
}
// detect copy operator: A(:, :, :) = B(:, :, :)
if (st->expr(1)->variant() == ARRAY_REF && st->expr(0)->variant() == ARRAY_REF)
{
set<SgSymbol*> ddots;
vector<SgExpression*> dummy;
fillVars(st->expr(0), { DDOT }, ddots, dummy);
fillVars(st->expr(1), { DDOT }, ddots, dummy);
if (ddots.size() != 0)
cond = false;
}
// detect copy operator: A = B
if (st->expr(1)->variant() == ARRAY_REF && st->expr(0)->variant() == ARRAY_REF)
{
SgExpression *left = st->expr(0);
SgExpression *right = st->expr(1);
if (left->lhs() == NULL && left->rhs() == NULL &&
right->lhs() == NULL && right->rhs() == NULL)
cond = false;
}
// detect operator: A[(:,:,:)] = F(X[(:,:,:)], Y[(:,:,:)], Z[(:,:,:)], ...)
//TODO: check right part
if (st->expr(0)->variant() == ARRAY_REF)
{
SgExpression *left = st->expr(0);
set<SgSymbol*> ddots;
vector<SgExpression*> dummy;
fillVars(st->expr(0), { DDOT }, ddots, dummy);
if ((left->lhs() == NULL && left->rhs() == NULL ) || ddots.size() != 0)
cond = false;
}
if (cond)
{
const DIST::Arrays<int> &allArrays = currReg->GetAllArrays();
if (under_dvm_dir == NULL)
createRemoteDir<1>(st, funcByName, sortedLoopGraph, allArrays, currReg->GetDataDir(), currReg->GetCurrentVariant(), currReg->GetId(), *currMessages, arrayLinksByFuncCalls);
}
}
if (st->expr(0))
{
const DIST::Arrays<int>& allArrays = currReg->GetAllArrays();
if (under_dvm_dir == NULL)
createRemoteDir<0>(st, funcByName, sortedLoopGraph, allArrays, currReg->GetDataDir(), currReg->GetCurrentVariant(), currReg->GetId(), *currMessages, arrayLinksByFuncCalls);
}
}
}
else if (currV == IF_NODE || currV == ELSEIF_NODE || currV == LOGIF_NODE || currV == SWITCH_NODE)
{
SgStatement* before = NULL;
// convert IF conditions if access to dist array appears
if (regime == REMOTE_ACC && under_dvm_dir == NULL)
{
stack<SgExpression*> conditions;
stack<SgStatement*> ifBlocks;
bool needToConv = false;
bool prevWithSameLine = (st->lexPrev()->lineNumber() == st->lineNumber());
if (currV == IF_NODE)
{
needToConv = isNeedToConvertIfCondition(st->expr(0));
conditions.push(st->expr(0));
ifBlocks.push(st);
SgIfStmt* ifS = (SgIfStmt*)st;
auto body = ifS->falseBody();
while (body)
{
if (body->variant() == ELSEIF_NODE)
{
needToConv = needToConv || isNeedToConvertIfCondition(body->expr(0)->copyPtr());
conditions.push(body->expr(0));
ifBlocks.push(body);
}
else
break;
body = body->lastNodeOfStmt();
}
needToConv = needToConv && !prevWithSameLine;
}
else if (currV == LOGIF_NODE)
{
needToConv = isNeedToConvertIfCondition(st->expr(0)) && !prevWithSameLine;
conditions.push(st->expr(0));
ifBlocks.push(st);
}
else if (currV == SWITCH_NODE)
{
needToConv = isNeedToConvertIfCondition(st->expr(0)) && !prevWithSameLine;
conditions.push(st->expr(0));
ifBlocks.push(st);
}
if (needToConv && !conditions.empty())
st = before = takeOutConditions(conditions, ifBlocks, st);
}
if (st->expr(0))
{
findArrayRef(parentLoops, st->expr(0), st->lineNumber(), RIGHT, loopInfo, privatesVars, privatesVarsForLoop,
sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays,
mappedDistrbutedArrays, st, currReg, currentWeight, arrayLinksByFuncCalls);
if (regime == REMOTE_ACC)
if (under_dvm_dir == NULL)
createRemoteDir<0>(st, funcByName, sortedLoopGraph, currReg->GetAllArrays(), currReg->GetDataDir(), currReg->GetCurrentVariant(), currReg->GetId(), *currMessages, arrayLinksByFuncCalls);
}
if (regime == REMOTE_ACC && before)
st = before;
}
else if (currV == PROC_STAT)
{
auto func = isUserFunctionInProject(st->symbol()->identifier());
if (func != NULL)
{
SgExpression *parList = st->expr(0);
set<DIST::Array*> toRedistr;
if (parList)
{
SgExprListExp *list = isSgExprListExp(parList);
for (int z = 0; z < list->length(); ++z)
{
SgExpression *par = list->elem(z);
if ((func->funcParams.inout_types[z] & OUT_BIT) != 0)
findArrayRef(parentLoops, par, st->lineNumber(), LEFT, loopInfo, privatesVars, privatesVarsForLoop,
sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays,
mappedDistrbutedArrays, st, currReg, currentWeight, arrayLinksByFuncCalls);
else
findArrayRef(parentLoops, par, st->lineNumber(), RIGHT, loopInfo, privatesVars, privatesVarsForLoop,
sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays,
mappedDistrbutedArrays, st, currReg, currentWeight, arrayLinksByFuncCalls);
if (regime == REMOTE_ACC)
{
if (isArrayRef(par) && isPassFullArray(par))
{
SgSymbol *s = OriginalSymbol(par->symbol());
DIST::Array *inPar = getArrayFromDeclarated(declaratedInStmt(s), s->identifier());
if (inPar && !inPar->IsNotDistribute())
{
if (func->funcParams.parametersT[z] != ARRAY_T)
toRedistr.insert(inPar->GetTemplateArray(currReg->GetId()));
else
{
if (inPar->GetDimSize() != ((DIST::Array*)func->funcParams.parameters[z])->GetDimSize())
toRedistr.insert(inPar->GetTemplateArray(currReg->GetId()));
}
}
}
}
}
if (regime == REMOTE_ACC && list->length())
if (under_dvm_dir == NULL)
createRemoteDir<0>(st, funcByName, sortedLoopGraph, currReg->GetAllArrays(), currReg->GetDataDir(), currReg->GetCurrentVariant(), currReg->GetId(), *currMessages, arrayLinksByFuncCalls);
}
if (regime == REMOTE_ACC)
{
const DataDirective &dataDirectives = currReg->GetDataDir();
const vector<int> &currentVariant = currReg->GetCurrentVariant();
auto &tmp = dataDirectives.distrRules;
std::vector<std::pair<DIST::Array*, const DistrVariant*>> currentVar;
for (int z1 = 0; z1 < currentVariant.size(); ++z1)
currentVar.push_back(make_pair(tmp[z1].first, &tmp[z1].second[currentVariant[z1]]));
for (auto &toRed : toRedistr)
{
auto cp = st->controlParent();
auto redist = new SgStatement(DVM_REDISTRIBUTE_DIR);
auto newRule = new SgExprListExp();
newRule->setLhs(*new SgExpression(KEYWORD_VAL, "*"));
for (int z = 1; z < toRed->GetDimSize(); ++z)
newRule->append(*new SgExpression(KEYWORD_VAL, "*"));
auto templS = new SgSymbol(VARIABLE_NAME, toRed->GetShortName().c_str());
redist->setExpression(0, *new SgVarRefExp(*templS));
redist->setExpression(1, *newRule);
st->insertStmtBefore(*redist, *cp);
redist = new SgStatement(DVM_REDISTRIBUTE_DIR);
newRule = new SgExprListExp();
const DistrVariant *varD = NULL;
for (auto &elem : currentVar)
{
if (elem.first == toRed)
{
varD = elem.second;
break;
}
}
if (!varD)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (int z = 0; z < toRed->GetDimSize(); ++z)
{
char *type = "*";
if (varD->distRule[z] == distType::BLOCK)
type = "BLOCK";
if (z == 0)
newRule->setLhs(*new SgExpression(KEYWORD_VAL, type));
else
newRule->append(*new SgExpression(KEYWORD_VAL, type));
}
redist->setExpression(0, *new SgVarRefExp(*templS));
redist->setExpression(1, *newRule);
st->insertStmtAfter(*redist, *cp);
}
}
}
}
else if (currV == USE_STMT)
{
if (st->lineNumber() > 0 && !sharedMemoryParallelization)
2023-09-14 19:43:13 +03:00
{
auto itF = privatesByModule.find(st->symbol()->identifier());
if (itF == privatesByModule.end())
{
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Module with name '%s' must be placed in current file", to_wstring(st->symbol()->identifier()).c_str());
__spf_printToLongBuf(messageR, R62, to_wstring(st->symbol()->identifier()).c_str());
currMessages->push_back(Messages(ERROR, st->lineNumber(), messageR, messageE, 1028));
__spf_print(1, "Module at line %d with name '%s' must be placed in current file\n", st->lineNumber(), st->symbol()->identifier());
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
2023-09-14 19:43:13 +03:00
for (auto it = itF->second.begin(); it != itF->second.end(); ++it)
privatesVars.insert(*it);
}
}
else
{
if(!sharedMemoryParallelization)
{
tryToFindPrivateInAttributes(st, privatesVars);
fillNonDistrArraysAsPrivate(st, declaredArrays, declaratedArraysSt, privatesVars);
}
2023-09-14 19:43:13 +03:00
if (isDVM_stat(st) == false && isSgExecutableStatement(st))
{
if (regime == REMOTE_ACC)
{
if (st->expr(0) &&
(currV == SWITCH_NODE || currV == FORALL_STAT || currV == WHILE_NODE ||
currV == WHERE_NODE || currV == ALLDO_NODE || currV == ARITHIF_NODE ||
currV == ASSGOTO_NODE || currV == COMGOTO_NODE))
{
const DIST::Arrays<int> &allArrays = currReg->GetAllArrays();
if (under_dvm_dir == NULL)
createRemoteDir<0>(st, funcByName, sortedLoopGraph, allArrays, currReg->GetDataDir(), currReg->GetCurrentVariant(), currReg->GetId(), *currMessages, arrayLinksByFuncCalls);
}
}
else
{
int const var = st->variant();
int side = (var == READ_STAT || var == WRITE_STAT || var == PRINT_STAT) ? LEFT : RIGHT;
for (int z = 0; z < 3; ++z)
if (st->expr(z))
findArrayRef(parentLoops, st->expr(z), st->lineNumber(), side, loopInfo, privatesVars, privatesVarsForLoop,
sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays,
mappedDistrbutedArrays, st, currReg, currentWeight, arrayLinksByFuncCalls);
}
}
}
st = st->lexNext();
}
auto convertedLoopInfo = convertLoopInfo(loopInfo, sortedLoopGraph, privatesVars, commonBlocks, declaredArrays, arrayLinksByFuncCalls, createdArrays);
if (regime == DATA_DISTR || regime == SHARED_MEMORY_PAR)
2023-09-14 19:43:13 +03:00
{
processLoopInformationForFunction(convertedLoopInfo);
//find dependencies for loops in function
initAnnotationsSysExt(0);
set<SgStatement*> funcWasInit;
map<SgExpression*, string> collection;
int idx = 0;
for (auto &loop : convertedLoopInfo)
{
++idx;
createNeededException();
if (!skipDeps)
{
string fName = file->functions(i)->symbol()->identifier();
#ifdef _WIN32
2024-11-14 15:28:51 +03:00
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()));
2023-09-14 19:43:13 +03:00
#else
sendMessage_2lvl(wstring(L"processing loop ") + std::to_wstring(idx) + L"/" + std::to_wstring(convertedLoopInfo.size()));
#endif
tryToFindDependencies(loop.first, allLoops, funcWasInit, file, regions, currMessages, collection, funcByName, defUseByPlace);
}
}
vector<LoopGraph*> tmpLoops;
map<SgSymbol*, ArrayInfo> tmpToConvert;
if (file->functions(i)->variant() != PROG_HEDR)
{
for (auto &notMapped : notMappedDistributedArrays)
{
if (mappedDistrbutedArrays.find(notMapped.first) == mappedDistrbutedArrays.end())
{
auto reg = getRegionByLine(regions, notMapped.second.second->fileName(), notMapped.second.second->lineNumber());
if (reg)
{
LoopGraph *tmpLoop = new LoopGraph();
tmpLoop->region = reg;
tmpLoop->isFor = true;
tmpLoops.push_back(tmpLoop);
ArrayInfo toAdd;
SgSymbol *arrayS = notMapped.second.first;
toAdd.setDimSize(((SgArrayType*)arrayS->type())->dimension());
for (int z = 0; z < toAdd.getDimSize(); ++z)
toAdd.readOps[z] = ArrayOp(make_pair(make_pair(1, 0), 1.0));
tmpToConvert[arrayS] = toAdd;
convertOneLoop(tmpLoop, convertedLoopInfo, tmpToConvert, privatesVars, commonBlocks, declaredArrays, arrayLinksByFuncCalls, createdArrays, true);
}
}
}
}
if(!sharedMemoryParallelization)
addToDistributionGraph(convertedLoopInfo, arrayLinksByFuncCalls);
2023-09-14 19:43:13 +03:00
for (auto &toDel : tmpLoops)
{
convertedLoopInfo.erase(toDel);
2023-09-14 19:43:13 +03:00
delete toDel;
}
2023-09-14 19:43:13 +03:00
tmpToConvert.clear();
if (!skipDeps)
{
for (auto &loopLine : loopWithOutArrays)
{
if (loopLine > 0)
{
tryToFindDependencies(sortedLoopGraph[loopLine], allLoops, funcWasInit, file, regions, currMessages, collection, funcByName, defUseByPlace);
sortedLoopGraph[loopLine]->withoutDistributedArrays = true;
}
}
// TODO: add messages!
for (auto &loopLine : loopWithOutArrays)
{
if (sortedLoopGraph[loopLine]->withoutDistributedArrays && loopLine > 0)
{
//TODO: enable linear writes to non distr arrays for CONSISTENT
bool hasWritesToArray = false;
//TODO: add IPA for non pure
bool hasNonPureProcedures = false;
auto loopRef = sortedLoopGraph[loopLine];
SgStatement *loopSt = loopRef->loop;
map<string, set<Symbol*>> reductions;
map<string, set<tuple<Symbol*, Symbol*, int>>> reductionsLoc;
set<Symbol*> privatesS;
for (auto &data : getAttributes<SgStatement*, SgStatement*>(loopSt, set<int>{ SPF_ANALYSIS_DIR, SPF_PARALLEL_DIR }))
{
Statement *dataSt = new Statement(data);
fillReductionsFromComment(dataSt, reductions);
fillReductionsFromComment(dataSt, reductionsLoc);
fillPrivatesFromComment(dataSt, privatesS);
}
for (auto &red : reductions)
privatesS.insert(red.second.begin(), red.second.end());
for (auto &red : reductionsLoc)
{
for (auto &elem : red.second)
{
privatesS.insert(get<0>(elem));
privatesS.insert(get<1>(elem));
}
}
set<string> privates;
for (auto& elem : privatesS)
privates.insert(elem->GetOriginal()->identifier());
for (SgStatement *start = loopSt->lexNext(); start != loopSt->lastNodeOfStmt(); start = start->lexNext())
{
//TODO: detect write in proc calls
if (start->variant() == ASSIGN_STAT)
{
if (start->expr(0)->variant() == ARRAY_REF || start->expr(0)->variant() == ARRAY_OP)
{
SgSymbol* s = NULL;
if (start->expr(0)->variant() == ARRAY_REF)
s = start->expr(0)->symbol();
else if (start->expr(0)->variant() == ARRAY_OP)
s = start->expr(0)->lhs()->symbol();
if (s && privates.find(s->identifier()) == privates.end())
if (sharedMemoryParallelization == 0)
2023-09-14 19:43:13 +03:00
hasWritesToArray = true;
}
}
if (start->variant() == PROC_STAT && isIntrinsicFunctionName(start->symbol()->identifier()) == 0)
{
checkNull(isSgCallStmt(start), convertFileName(__FILE__).c_str(), __LINE__);
auto itF = funcByName.find(isSgCallStmt(start)->name()->identifier());
bool isPure = false;
if (itF != funcByName.end())
isPure = itF->second->isPure;
if (!isPure)
{
hasNonPureProcedures = true;
loopRef->hasNonPureProcedures = true;
messagesForFile.push_back(Messages(WARR, start->lineNumber(), R80, L"Only pure procedures were supported", 1044));
}
}
for (int z = 1; z < 3; ++z)
if (hasNonPureFunctions(start->expr(z), loopRef, messagesForFile, start->lineNumber(), funcByName))
hasNonPureProcedures = true;
}
if (hasWritesToArray || hasNonPureProcedures)
loopRef->withoutDistributedArrays = false;
}
}
if (parallizeFreeLoops)
selectFreeLoopsForParallelization(loopsForFunction, funcName, (regime == DATA_DISTR), regions, messagesForFile);
}
sendMessage_2lvl(L"");
}
else if (regime == COMP_DISTR)
{
createParallelDirectives(convertedLoopInfo, regions, arrayLinksByFuncCalls, messagesForFile);
if (parallizeFreeLoops)
selectFreeLoopsForParallelization(loopsForFunction, funcName, (regime == DATA_DISTR), regions, messagesForFile);
}
if(regime == SHARED_MEMORY_PAR)
createParallelDirectives(convertedLoopInfo, regions, arrayLinksByFuncCalls, messagesForFile);
2023-09-14 19:43:13 +03:00
__spf_print(PRINT_PROF_INFO, "Function ended\n");
}
}
void arrayAccessAnalyzer(SgFile *file, vector<Messages> &messagesForFile, const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays, REGIME regime)
{
currMessages = &messagesForFile;
currRegime = regime;
map<string, vector<SgExpression*>> commonBlocks;
map<int, LoopGraph*> sortedLoopGraph;
map<int, pair<SgForStmt*, pair<set<string>, set<string>>>> allLoops;
map<string, pair<SgSymbol*, SgStatement*>> notMappedDistributedArrays;
set<string> mappedDistrbutedArrays;
int funcNum = file->numberOfFunctions();
__spf_print(PRINT_PROF_INFO, "functions num in file = %d\n", funcNum);
const map<DIST::Array*, set<DIST::Array*>> arrayLinksByFuncCalls;
for (int i = 0; i < funcNum; ++i)
{
map<SgForStmt*, map<SgSymbol*, ArrayInfo>> loopInfo;
set<string> privatesVars;
vector<set<string>> privatesVarsForLoop;
SgStatement *st = file->functions(i);
string funcName = "";
if (st->variant() == PROG_HEDR)
{
SgProgHedrStmt *progH = (SgProgHedrStmt*)st;
__spf_print(PRINT_PROF_INFO, "*** Program <%s> started at line %d / %s\n", progH->symbol()->identifier(), st->lineNumber(), st->fileName());
funcName = progH->symbol()->identifier();
}
else if (st->variant() == PROC_HEDR)
{
SgProcHedrStmt *procH = (SgProcHedrStmt*)st;
__spf_print(PRINT_PROF_INFO, "*** Function <%s> started at line %d / %s\n", procH->symbol()->identifier(), st->lineNumber(), st->fileName());
funcName = procH->symbol()->identifier();
}
else if (st->variant() == FUNC_HEDR)
{
SgFuncHedrStmt *funcH = (SgFuncHedrStmt*)st;
__spf_print(PRINT_PROF_INFO, "*** Function <%s> started at line %d / %s\n", funcH->symbol()->identifier(), st->lineNumber(), st->fileName());
funcName = funcH->symbol()->identifier();
}
commonBlocks.clear();
getCommonBlocksRef(commonBlocks, st, st->lastNodeOfStmt());
__spf_print(PRINT_PROF_INFO, " number of common blocks %d\n", (int)commonBlocks.size());
SgStatement *lastNode = st->lastNodeOfStmt();
vector<SgForStmt*> parentLoops;
double currentWeight = 1.0;
while (st != lastNode)
{
createNeededException();
if (st == NULL)
{
currMessages->push_back(Messages(ERROR, 1, R128, L"internal error in analysis, parallel directives will not be generated for this file!", 3008));
__spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n");
break;
}
if (st->variant() == CONTAINS_STMT)
break;
const int currV = st->variant();
if (currV == FOR_NODE)
{
if (PRINT_LOOP_STRUCT)
printBlanks(2, (int)parentLoops.size());
__spf_print(PRINT_LOOP_STRUCT, "FOR NODE on line %d\n", st->lineNumber());
parentLoops.push_back((SgForStmt*)st);
sortedLoopGraph[st->lineNumber()] = new LoopGraph();
privatesVarsForLoop.push_back(set<string>());
}
else if (currV == CONTROL_END)
{
SgStatement *contrlParent = st->controlParent();
if (contrlParent)
{
if (contrlParent->variant() == FOR_NODE)
{
parentLoops.pop_back();
delete sortedLoopGraph[contrlParent->lineNumber()];
sortedLoopGraph.erase(contrlParent->lineNumber());
privatesVarsForLoop.pop_back();
}
}
else
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
else if (currV == ASSIGN_STAT)
{
if (st->expr(0))
findArrayRef(parentLoops, st->expr(0), st->lineNumber(), LEFT, loopInfo, privatesVars, privatesVarsForLoop,
sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays,
mappedDistrbutedArrays, st, NULL, currentWeight, arrayLinksByFuncCalls);
if (st->expr(1))
findArrayRef(parentLoops, st->expr(1), st->lineNumber(), RIGHT, loopInfo, privatesVars, privatesVarsForLoop,
sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays,
mappedDistrbutedArrays, st, NULL, currentWeight, arrayLinksByFuncCalls);
}
else if (currV == IF_NODE || currV == ELSEIF_NODE || currV == LOGIF_NODE || currV == SWITCH_NODE)
{
if (st->expr(0))
findArrayRef(parentLoops, st->expr(0), st->lineNumber(), RIGHT, loopInfo, privatesVars, privatesVarsForLoop,
sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays,
mappedDistrbutedArrays, st, NULL, currentWeight, arrayLinksByFuncCalls);
}
else if (currV == PROC_STAT)
{
if (st->expr(0))
{
if (isIntrinsicFunctionName(st->symbol()->identifier()))
findArrayRef(parentLoops, st->expr(0), st->lineNumber(), RIGHT, loopInfo, privatesVars, privatesVarsForLoop,
sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays,
mappedDistrbutedArrays, st, NULL, currentWeight, arrayLinksByFuncCalls);
else
{
SgExpression *listEx = st->expr(0);
while (listEx)
{
findArrayRef(parentLoops, listEx->lhs(), st->lineNumber(), LEFT, loopInfo, privatesVars, privatesVarsForLoop,
sortedLoopGraph, commonBlocks, declaredArrays, false, notMappedDistributedArrays,
mappedDistrbutedArrays, st, NULL, currentWeight, arrayLinksByFuncCalls);
listEx = listEx->rhs();
}
}
}
}
st = st->lexNext();
}
__spf_print(PRINT_PROF_INFO, "Function ended\n");
}
}
//TODO: copy all functions from FDVM and fix them
static inline int getStructureSize(SgSymbol *s)
{
return 0;
//printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
static inline int getNumericTypeLength(SgType *t)
{
SgExpression *le;
SgValueExp *ve;
if (t->variant() == T_STRING)
return (0);
if (TYPE_RANGES(t->thetype))
{
le = t->length();
if (ve = isSgValueExp(le))
return ve->intValue();
else
return 0;
}
if (TYPE_KIND_LEN(t->thetype))
{
le = t->selector()->lhs();
if (ve = isSgValueExp(le))
if (t->variant() == T_COMPLEX || t->variant() == T_DCOMPLEX)
return 2 * ve->intValue();
else
return ve->intValue();
else
return 0;
}
return 0;
}
static inline int getIntrinsicTypeSize(SgType *t)
{
const int default_real_size = 4;
const int default_integer_size = 4;
switch (t->variant())
{
case T_INT:
case T_BOOL:
return default_integer_size;
case T_FLOAT:
return default_real_size;
case T_COMPLEX:
return 2 * default_real_size;
case T_DOUBLE:
return 2 * default_real_size;
case T_DCOMPLEX:
return 4 * default_real_size;
case T_STRING:
case T_CHAR:
return 1;
default:
return 0;
}
}
static SgExpression* getLengthOfKindExpr(SgType *t, SgExpression *se, SgExpression *le)
{
switch (t->variant())
{
case T_INT:
case T_FLOAT:
case T_BOOL:
case T_DOUBLE:
return se->lhs();
case T_COMPLEX:
case T_DCOMPLEX:
return &(*new SgValueExp(2) * (*(se->lhs())));
case T_CHAR:
case T_STRING:
{
SgExpression *length, *kind;
if (se->rhs() && se->rhs()->variant() == LENGTH_OP)
{
length = se->rhs()->lhs();
kind = se->lhs()->lhs();
}
else if (se->rhs() && se->rhs()->variant() != LENGTH_OP)
{
length = se->lhs()->lhs();
kind = se->rhs()->lhs();
}
else
{
length = se->lhs();
kind = NULL;
}
length = le ? le : length;
if (kind)
return &(*length * (*kind));
else
return length;
}
default:
return(NULL);
}
}
SgExpression* getTypeLengthExpr(SgType *t)
{
SgExpression *len;
SgExpression *selector;
if (t->variant() == T_DERIVED_TYPE)
return new SgValueExp(getStructureSize(t->symbol()));
len = TYPE_RANGES(t->thetype) ? t->length() : NULL;
selector = TYPE_KIND_LEN(t->thetype) ? t->selector() : NULL;
if (!len && !selector) //the number of bytes is not specified in type declaration statement
return (new SgValueExp(getIntrinsicTypeSize(t)));
else if (len && !selector) //INTEGER*2,REAL*8,CHARACTER*(N+1)
2024-04-09 11:51:21 +03:00
return CalculateInteger(len->copyPtr());
2023-09-14 19:43:13 +03:00
else
2024-04-09 11:51:21 +03:00
return CalculateInteger(getLengthOfKindExpr(t, selector, len)->copyPtr()); //specified kind or/and len
2023-09-14 19:43:13 +03:00
}
int getSizeOfType(SgType *t)
{
int len = -1;
if (IS_INTRINSIC_TYPE(t))
return getIntrinsicTypeSize(t);
if (t->variant() == T_DERIVED_TYPE)
return getStructureSize(t->symbol());
if (len = getNumericTypeLength(t))
return len;
SgExpression *le = getTypeLengthExpr(t);
if (le->isInteger())
{
len = le->valueInteger();
len = len < 0 ? 0 : len; //according to standard F90
}
else
len = -1; //may be error situation
return len;
}
void insertSpfAnalysisBeforeParalleLoops(const vector<LoopGraph*> &loops)
{
for (auto &loop : loops)
{
SgStatement *spfStat = new SgStatement(SPF_ANALYSIS_DIR);
spfStat->setlineNumber(loop->lineNum);
spfStat->setLocalLineNumber(0);
spfStat->setFileName((char*)current_file->filename());
if (!loop->hasLimitsToParallel())
{
loop->loop->addAttribute(SPF_ANALYSIS_DIR, spfStat, sizeof(SgStatement));
//uncomment it to debug private analysis
2024-07-24 12:07:29 +03:00
//loop->loop->insertStmtBefore(*spfStat, *loop->loop->controlParent());
2023-09-14 19:43:13 +03:00
}
insertSpfAnalysisBeforeParalleLoops(loop->children);
}
}
#undef PRINT_ARRAY_ARCS
#undef PRINT_LOOP_STRUCT
#undef PRINT_PROF_INFO
#undef FIRST
#undef SECOND
#undef THIRD