2650 lines
112 KiB
C++
2650 lines
112 KiB
C++
#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 "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 "errors.h"
|
|
#include "../DirectiveProcessing/directive_parser.h"
|
|
#include "../DirectiveProcessing/directive_creator.h"
|
|
|
|
#include "SgUtils.h"
|
|
#include "AstWrapper.h"
|
|
|
|
#include "graph_calls_func.h"
|
|
#include "graph_loops_func.h"
|
|
#include "../ParallelizationRegions/ParRegions_func.h"
|
|
#include "../DynamicAnalysis/gCov_parser_func.h"
|
|
|
|
#include "expr_transform.h"
|
|
#include "../SageAnalysisTool/depInterfaceExt.h"
|
|
|
|
#include "../VisualizerCalls/get_information.h"
|
|
#include "../VisualizerCalls/SendMessage.h"
|
|
|
|
#include "../Transformations/LoopEndDoConverter/enddo_loop_converter.h"
|
|
|
|
#include "../DirectiveProcessing/remote_access.h"
|
|
#include "../DirectiveProcessing/directive_omp_parser.h"
|
|
|
|
#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;
|
|
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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,
|
|
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())
|
|
{
|
|
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))
|
|
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))
|
|
{
|
|
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,
|
|
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);
|
|
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,
|
|
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*>> ¬MappedDistributedArrays,
|
|
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())
|
|
{
|
|
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;
|
|
}
|
|
mapArrayRef(currentSt, currExp, parentLoops, privatesVarsForLoop, side, lineNum, loopInfo, sortedLoopGraph,
|
|
notMappedDistributedArrays, mappedDistrbutedArrays, reg, currentW, arrayLinksByFuncCalls);
|
|
}
|
|
else
|
|
{
|
|
wasDistributedArrayRef = true;
|
|
mapArrayRef(currentSt, currExp, parentLoops, privatesVarsForLoop, side, lineNum, loopInfo, sortedLoopGraph,
|
|
notMappedDistributedArrays, mappedDistrbutedArrays, reg, currentW, arrayLinksByFuncCalls);
|
|
}
|
|
}
|
|
else if (currRegime == DATA_DISTR && side == LEFT)
|
|
{
|
|
auto symb = OriginalSymbol(currExp->symbol());
|
|
SgStatement *decl = declaratedInStmt(symb);
|
|
auto uniqKey = getUniqName(commonBlocks, decl, symb);
|
|
|
|
auto itFound = declaredArrays.find(uniqKey);
|
|
if (itFound == declaredArrays.end())
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
//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;
|
|
|
|
|
|
for (int z = 0; z < parentLoops.size(); ++z)
|
|
{
|
|
auto& loop = parentLoops[z];
|
|
for (auto &data : getAttributes<SgStatement*, SgStatement*>(loop, set<int>{ SPF_ANALYSIS_DIR }))
|
|
{
|
|
fillPrivatesFromComment(new Statement(data), loopsPrivatesS);
|
|
for (auto& elem : loopsPrivatesS)
|
|
loopsPrivates.insert(elem->GetOriginal()->identifier());
|
|
fillReductionsFromComment(new Statement(data), loopsReductions);
|
|
fillReductionsFromComment(new Statement(data), loopsReductionsLoc);
|
|
}
|
|
}
|
|
|
|
for (auto &elem : loopsReductions)
|
|
{
|
|
for (auto &setElem : elem.second)
|
|
{
|
|
loopsPrivates.insert(setElem->GetOriginal()->identifier());
|
|
loopsRedUnited.insert(setElem->GetOriginal()->identifier());
|
|
}
|
|
}
|
|
|
|
for (auto &elem : loopsReductionsLoc)
|
|
{
|
|
for (auto &setElem : elem.second)
|
|
{
|
|
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());
|
|
}
|
|
}
|
|
|
|
const string key = string(OriginalSymbol(currExp->symbol())->identifier());
|
|
if (loopsPrivates.find(key) == loopsPrivates.end())
|
|
{
|
|
for (auto& loop : parentLoops)
|
|
{
|
|
__spf_print(1, "WARN: write to non distributed array '%s' in loop on line %d\n", symb->identifier(), loop->lineNumber());
|
|
|
|
wstring messageE, messageR;
|
|
__spf_printToLongBuf(messageE, L"write to non distributed array '%s' in this loop", to_wstring(symb->identifier()).c_str());
|
|
|
|
__spf_printToLongBuf(messageR, R61, to_wstring(symb->identifier()).c_str());
|
|
|
|
if (loop->lineNumber() > 0)
|
|
currMessages->push_back(Messages(WARR, loop->lineNumber(), messageR, messageE, 1026));
|
|
sortedLoopGraph[loop->lineNumber()]->hasWritesToNonDistribute = true;
|
|
}
|
|
}
|
|
|
|
if (loopsPrivates.find(key) != loopsPrivates.end() || loopsRedUnited.find(key) != loopsRedUnited.end())
|
|
{
|
|
auto currOrigArrayS = OriginalSymbol(currExp->symbol());
|
|
if (currOrigArrayS->type()->variant() == T_ARRAY)
|
|
{
|
|
DIST::Array* currArray = getArrayFromDeclarated(declaratedInStmt(currOrigArrayS), currOrigArrayS->identifier());
|
|
checkNull(currArray, convertFileName(__FILE__).c_str(), __LINE__);
|
|
{
|
|
set<DIST::Array*> realArrayRefs;
|
|
getRealArrayRefs(currArray, currArray, realArrayRefs, arrayLinksByFuncCalls);
|
|
|
|
for (auto& array : realArrayRefs)
|
|
array->SetPrivateInLoopStatus(true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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)
|
|
{
|
|
if (callOfThis->callsFromDetailed[p].detailCallsFrom.first == procN)
|
|
{
|
|
for (auto& par : idxFound)
|
|
{
|
|
auto parType = callOfThis->callsFromDetailed[p].actualParams.parametersT[par];
|
|
if (parType != SCALAR_INT_T)
|
|
return dimList;
|
|
else
|
|
{
|
|
if (callOfThis->callsFromDetailed[p].actualParams.parameters[par] == NULL)
|
|
return dimList;
|
|
values[par].insert(((int*)(callOfThis->callsFromDetailed[p].actualParams.parameters[par]))[0]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (auto& elem : values)
|
|
if (elem.second.size() != 1)
|
|
return dimList;
|
|
|
|
doReplacement(dimList, idsToIdx, values);
|
|
return dimList;
|
|
}
|
|
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
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 ¤tWeight, const map<int, LoopGraph*> &sortedLoopGraph, const int line, bool increase = true)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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*> ®ions, 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);
|
|
|
|
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();
|
|
sendMessage_2lvl(0, (file->functions(i)->variant() != MODULE_STMT), fName);
|
|
|
|
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)
|
|
{
|
|
SgStatement* tmpModFind = st;
|
|
while (tmpModFind->variant() != GLOBAL)
|
|
{
|
|
tmpModFind = tmpModFind->controlParent();
|
|
if (tmpModFind->variant() == MODULE_STMT)
|
|
fillFromModule(tmpModFind->symbol(), privatesByModule, privatesVars);
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
const ParallelRegionLines* prevParLines = NULL;
|
|
double prevLinesWeight = 1.0;
|
|
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();
|
|
auto regAndLines = getRegionAndLinesByLine(regions, st->fileName(), currentLine);
|
|
|
|
auto *currReg = regAndLines.first;
|
|
auto *parLines = regAndLines.second;
|
|
if (currReg == NULL)
|
|
{
|
|
st = st->lexNext();
|
|
continue;
|
|
}
|
|
|
|
if (parLines != prevParLines)
|
|
{
|
|
prevParLines = parLines;
|
|
auto newParLinesWeight = parLines ? parLines->weight : 1.0;
|
|
|
|
if (prevParLines)
|
|
currentWeight /= prevLinesWeight;
|
|
|
|
if (parLines)
|
|
currentWeight *= newParLinesWeight;
|
|
|
|
prevLinesWeight = newParLinesWeight;
|
|
prevParLines = parLines;
|
|
}
|
|
|
|
if (isSgExecutableStatement(st) == NULL)
|
|
delcsStatViewed.insert(st);
|
|
else if (!sharedMemoryParallelization &&
|
|
!isDVM_stat(st) && !isSPF_stat(st))
|
|
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);
|
|
}
|
|
|
|
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);
|
|
|
|
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> ¤tVariant = 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)
|
|
{
|
|
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__);
|
|
}
|
|
|
|
|
|
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);
|
|
}
|
|
|
|
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)
|
|
{
|
|
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();
|
|
sendMessage_2lvl(1, idx, (int)convertedLoopInfo.size());
|
|
|
|
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 ¬Mapped : 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);
|
|
|
|
for (auto &toDel : tmpLoops)
|
|
{
|
|
convertedLoopInfo.erase(toDel);
|
|
delete toDel;
|
|
}
|
|
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)
|
|
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(2);
|
|
}
|
|
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);
|
|
|
|
__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)
|
|
return CalculateInteger(len->copyPtr());
|
|
else
|
|
return CalculateInteger(getLengthOfKindExpr(t, selector, len)->copyPtr()); //specified kind or/and len
|
|
}
|
|
|
|
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
|
|
//loop->loop->insertStmtBefore(*spfStat, *loop->loop->controlParent());
|
|
}
|
|
insertSpfAnalysisBeforeParalleLoops(loop->children);
|
|
}
|
|
}
|
|
#undef PRINT_ARRAY_ARCS
|
|
#undef PRINT_LOOP_STRUCT
|
|
#undef PRINT_PROF_INFO
|
|
#undef FIRST
|
|
#undef SECOND
|
|
#undef THIRD
|