2117 lines
92 KiB
C++
2117 lines
92 KiB
C++
#include "leak_detector.h"
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
#include <set>
|
|
#include <map>
|
|
#include <stack>
|
|
#include <string.h>
|
|
|
|
#include "ParRegions_func.h"
|
|
#include "resolve_par_reg_conflicts.h"
|
|
|
|
#include "graph_calls_func.h"
|
|
#include "graph_loops_func.h"
|
|
#include "../LoopAnalyzer/loop_analyzer.h"
|
|
#include "../DirectiveProcessing/directive_creator.h"
|
|
#include "../DirectiveProcessing/insert_directive.h"
|
|
#include "SgUtils.h"
|
|
#include "expr_transform.h"
|
|
#include "../Transformations/FunctionPurifying/function_purifying.h"
|
|
|
|
using std::map;
|
|
using std::pair;
|
|
using std::set;
|
|
using std::vector;
|
|
using std::stack;
|
|
using std::string;
|
|
using std::wstring;
|
|
using std::to_string;
|
|
using std::make_pair;
|
|
|
|
static inline int getRegionExplicitLine(SgStatement *startR)
|
|
{
|
|
checkNull(startR, convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
const string saveName = current_file->filename();
|
|
startR->switchToFile();
|
|
|
|
SgStatement *regSt = startR->lexPrev();
|
|
checkNull(regSt, convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
SgFile::switchToFile(saveName);
|
|
return regSt->lineNumber();
|
|
}
|
|
|
|
static int getIntervalNumber(const int fileId, const int lineNumber, const uint64_t regionId)
|
|
{
|
|
int fileMask = 0xFF;
|
|
int lineMask = 0x7FFFF;
|
|
int regionMask = 0xF;
|
|
|
|
int filePart = fileMask & fileId;
|
|
int linePart = lineMask & lineNumber;
|
|
int regionPart = regionMask & regionId;
|
|
|
|
filePart = filePart << 4;
|
|
linePart = linePart << 12;
|
|
int number = 1 << 31;
|
|
|
|
number = number | filePart | linePart | regionPart;
|
|
|
|
return number;
|
|
}
|
|
|
|
// array -> common-block
|
|
static map<DIST::Array*, const CommonBlock*> allUsedCommonArrays;
|
|
|
|
static bool isSPF_reg(SgStatement *st)
|
|
{
|
|
return st->variant() == SPF_PARALLEL_REG_DIR || st->variant() == SPF_END_PARALLEL_REG_DIR;
|
|
}
|
|
|
|
static const vector<const Variable*> getArraySynonyms(DIST::Array *array)
|
|
{
|
|
auto arrayBlock = allUsedCommonArrays.find(array);
|
|
if (arrayBlock == allUsedCommonArrays.end())
|
|
{
|
|
auto location = array->GetLocation();
|
|
if (location.first != DIST::l_COMMON)
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
//try to find synonym
|
|
for (auto& elem : allUsedCommonArrays)
|
|
{
|
|
if (elem.second->getName() == location.second)
|
|
{
|
|
arrayBlock = allUsedCommonArrays.find(elem.first);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (arrayBlock == allUsedCommonArrays.end())
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
|
|
// find array position
|
|
int pos = -1;
|
|
for (auto &var : arrayBlock->second->getVariables())
|
|
{
|
|
if (var->getName() == arrayBlock->first->GetShortName() && var->getType() == ARRAY)
|
|
pos = var->getPosition();
|
|
}
|
|
|
|
// get all variables with this position
|
|
return arrayBlock->second->getVariables(pos);
|
|
}
|
|
|
|
static string getStringDeclaration(SgSymbol *symb)
|
|
{
|
|
string decl;
|
|
SgFile *oldFile = current_file;
|
|
|
|
if (SgFile::switchToFile(symb->getFile()->filename()) != -1)
|
|
{
|
|
auto stat = symb->makeVarDeclStmt();
|
|
auto res = CalculateInteger(stat->expr(0)->copyPtr());
|
|
stat->setExpression(0, res);
|
|
decl = stat->unparse();
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
if (SgFile::switchToFile(oldFile->filename()) == -1)
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
return decl;
|
|
}
|
|
|
|
static void insertStringDeclarations(SgStatement *insertPlace, DIST::Array *array)
|
|
{
|
|
auto varsOnPos = getArraySynonyms(array);
|
|
if (varsOnPos.size() && varsOnPos[0]->getName() == array->GetShortName())
|
|
{
|
|
SgSymbol *varSymb = varsOnPos[0]->getSymbol();
|
|
string varName = varSymb->identifier();
|
|
string newName = varName + "_c";
|
|
varSymb->changeName(newName.c_str());
|
|
string decl = getStringDeclaration(varsOnPos[0]->getSymbol());
|
|
varSymb->changeName(varName.c_str());
|
|
insertPlace->addComment(decl.c_str());
|
|
}
|
|
}
|
|
|
|
static void createSetOfCalledFuncs(const string &funcName, const map<string, FuncInfo*> &funcMap, set<FuncInfo*> &callSet)
|
|
{
|
|
set<string> queue;
|
|
|
|
queue.insert(funcName);
|
|
|
|
while (queue.size())
|
|
{
|
|
auto it = queue.begin();
|
|
FuncInfo *func = getFuncInfo(funcMap, *it);
|
|
queue.erase(it);
|
|
|
|
for (auto &call : func->callsFrom)
|
|
{
|
|
FuncInfo *callFunc = getFuncInfo(funcMap, call);
|
|
auto it2 = callSet.find(callFunc);
|
|
if (it2 == callSet.end() && callFunc)
|
|
{
|
|
callSet.insert(it2, callFunc);
|
|
queue.insert(call);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void fillRegionCover(FuncInfo *func, const map<string, FuncInfo*> &funcMap)
|
|
{
|
|
if (func->funcPointer->variant() != ENTRY_STAT)
|
|
{
|
|
if (SgFile::switchToFile(func->fileName) != -1)
|
|
{
|
|
SgStatement *iterator = func->funcPointer->GetOriginal();
|
|
FuncInfo *entry = NULL;
|
|
bool isFuncCovered = true;
|
|
bool isEntryCovered = false;
|
|
bool isRegion = false;
|
|
|
|
for (; !isSgExecutableStatement(iterator) && !isSPF_reg(iterator) && iterator->variant() != ENTRY_STAT; iterator = iterator->lexNext())
|
|
{
|
|
// skip not executable and not necessary statements
|
|
}
|
|
|
|
for (; iterator->lineNumber() < func->linesNum.second; iterator = iterator->lexNext())
|
|
{
|
|
switch (iterator->variant())
|
|
{
|
|
case SPF_PARALLEL_REG_DIR:
|
|
isRegion = true;
|
|
break;
|
|
case SPF_END_PARALLEL_REG_DIR:
|
|
isRegion = false;
|
|
break;
|
|
case ENTRY_STAT:
|
|
entry = getFuncInfo(funcMap, string(iterator->symbol()->identifier()));
|
|
isEntryCovered = true;
|
|
break;
|
|
default:
|
|
if (isSPF_stat(iterator) || isDVM_stat(iterator))
|
|
break;
|
|
|
|
if (!isRegion)
|
|
{
|
|
isFuncCovered = false;
|
|
isEntryCovered = false;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
}
|
|
|
|
static void recursiveFill(SgStatement *st,
|
|
SgExpression *exp,
|
|
ParallelRegion *region,
|
|
const string &fileName,
|
|
const string &funcName,
|
|
const ParallelRegionLines &lines,
|
|
const map<string, FuncInfo*> &funcMap,
|
|
const map<string, CommonBlock*> &commonBlocks)
|
|
{
|
|
if (exp)
|
|
{
|
|
if (exp->variant() == ARRAY_REF)
|
|
{
|
|
SgArrayRefExp *arrayRef = isSgArrayRefExp(exp);
|
|
SgType *type = exp->symbol()->type();
|
|
if (isArrayRef(arrayRef))
|
|
{
|
|
SgSymbol *arraySymbol = exp->symbol();
|
|
string arrayName = string(arraySymbol->identifier());
|
|
DIST::Array *array = getArrayFromDeclarated(declaratedInStmt(arraySymbol), arrayName);
|
|
FuncInfo *func = getFuncInfo(funcMap, funcName);
|
|
|
|
checkNull(array, convertFileName(__FILE__).c_str(), __LINE__);
|
|
checkNull(func, convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
if (!array->IsNotDistribute() || array->GetLocation().first == DIST::l_PARAMETER)
|
|
{
|
|
auto commonBlock = isArrayInCommon(commonBlocks, array);
|
|
if (commonBlock)
|
|
{
|
|
array = commonBlock->getFirstSynonym(array);
|
|
|
|
if (isSgExecutableStatement(st))
|
|
region->AddUsedCommonArray(func, array, lines);
|
|
|
|
allUsedCommonArrays.insert(make_pair(array, commonBlock));
|
|
}
|
|
else if (!lines.isImplicit())
|
|
region->AddUsedLocalArray(func, array, lines);
|
|
}
|
|
}
|
|
}
|
|
|
|
recursiveFill(st, exp->rhs(), region, fileName, funcName, lines, funcMap, commonBlocks);
|
|
recursiveFill(st, exp->lhs(), region, fileName, funcName, lines, funcMap, commonBlocks);
|
|
}
|
|
}
|
|
|
|
void fillRegionArrays(vector<ParallelRegion*> ®ions,
|
|
const map<string, vector<FuncInfo*>> &allFuncInfo,
|
|
const map<string, CommonBlock*> &commonBlocks)
|
|
{
|
|
if (regions.size() == 1 && regions[0]->GetName() == "DEFAULT") // only default
|
|
return;
|
|
|
|
map<string, FuncInfo*> funcMap;
|
|
createMapOfFunc(allFuncInfo, funcMap);
|
|
|
|
for (auto ®ion : regions)
|
|
{
|
|
for (auto &fileLines : region->GetAllLines())
|
|
{
|
|
// switch to current file
|
|
if (SgFile::switchToFile(fileLines.first) != -1)
|
|
{
|
|
for (auto ®ionLines : fileLines.second)
|
|
{
|
|
SgStatement *iterator = NULL;
|
|
SgStatement *end = NULL;
|
|
string funcName = "";
|
|
|
|
// implicit lines
|
|
if (regionLines.isImplicit())
|
|
{
|
|
iterator = SgStatement::getStatementByFileAndLine(fileLines.first, regionLines.lines.first);
|
|
end = SgStatement::getStatementByFileAndLine(fileLines.first, regionLines.lines.second);
|
|
}
|
|
else
|
|
{
|
|
iterator = regionLines.stats.first->GetOriginal();
|
|
end = regionLines.stats.second->GetOriginal();
|
|
}
|
|
|
|
iterator = getFuncStat(iterator);
|
|
string containsPrefix = "";
|
|
SgStatement *st_cp = iterator->controlParent();
|
|
if (st_cp->variant() == PROC_HEDR || st_cp->variant() == PROG_HEDR || st_cp->variant() == FUNC_HEDR)
|
|
containsPrefix = st_cp->symbol()->identifier() + string(".");
|
|
funcName = containsPrefix + iterator->symbol()->identifier();
|
|
|
|
if (regionLines.isImplicit())
|
|
iterator = SgStatement::getStatementByFileAndLine(fileLines.first, regionLines.lines.first);
|
|
else
|
|
iterator = regionLines.stats.first->GetOriginal();
|
|
|
|
for (; iterator && iterator != end->lexNext(); iterator = iterator->lexNext())
|
|
{
|
|
if (isSPF_stat(iterator) || isDVM_stat(iterator))
|
|
continue;
|
|
|
|
if (iterator->variant() == ALLOCATE_STMT || iterator->variant() == DEALLOCATE_STMT)
|
|
continue;
|
|
|
|
for (int i = 0; i < 3; ++i)
|
|
recursiveFill(iterator, iterator->expr(i), region, fileLines.first, funcName, regionLines, funcMap, commonBlocks);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
}
|
|
}
|
|
|
|
void fillRegionFunctions(vector<ParallelRegion*> ®ions, const map<string, vector<FuncInfo*>> &allFuncInfo)
|
|
{
|
|
if (regions.size() == 1 && regions[0]->GetName() == "DEFAULT") // only default
|
|
return;
|
|
|
|
// funcName -> funcInfo
|
|
map<string, FuncInfo*> funcMap;
|
|
createMapOfFunc(allFuncInfo, funcMap);
|
|
|
|
for (auto &nameFunc : funcMap)
|
|
{
|
|
auto func = nameFunc.second;
|
|
|
|
fillRegionCover(func, funcMap);
|
|
|
|
// add DEFAULT region (regionId == 0)
|
|
if (func->isIndirect())
|
|
{
|
|
for (auto &callInfo : func->callsFromDetailed)
|
|
{
|
|
auto& callFrom = callInfo.detailCallsFrom;
|
|
|
|
auto line = callFrom.second;
|
|
auto call = callFrom.first;
|
|
auto callF = getFuncInfo(funcMap, call);
|
|
auto regs = getAllRegionsByLine(regions, func->fileName, line).size();
|
|
if (callF && !getAllRegionsByLine(regions, func->fileName, line).size())
|
|
callF->callRegions.insert(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
// move DEFAULT region (regionId == 0)
|
|
bool changes = true;
|
|
while (changes)
|
|
{
|
|
changes = false;
|
|
for (auto &nameFunc : funcMap)
|
|
{
|
|
auto func = nameFunc.second;
|
|
if (func->callRegions.size() > 1 && func->callRegions.find(0) != func->callRegions.end())
|
|
{
|
|
for (auto &call : func->callsFrom)
|
|
{
|
|
auto callF = getFuncInfo(funcMap, call);
|
|
if (callF && callF->callRegions.find(0) == callF->callRegions.end())
|
|
{
|
|
changes = true;
|
|
callF->callRegions.insert(0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void fillRegionIntervals(vector<ParallelRegion*> ®ions)
|
|
{
|
|
if (regions.size() == 1 && regions[0]->GetName() == "DEFAULT") // only default
|
|
return;
|
|
|
|
for (auto ®ion : regions)
|
|
{
|
|
for (auto &fileLines : region->GetAllLinesToModify())
|
|
{
|
|
// switch to current file
|
|
if (SgFile::switchToFile(fileLines.first) != -1)
|
|
{
|
|
for (auto &lines : fileLines.second)
|
|
{
|
|
// explicit lines
|
|
if (!lines.isImplicit())
|
|
{
|
|
SgStatement *start = NULL;
|
|
SgStatement *end = NULL;
|
|
|
|
// try to find interval before explicit lines
|
|
end = lines.stats.first->GetOriginal()->lexPrev()->lexPrev(); // before SPF_PARALLEL_REG_DIR
|
|
if (end && end->variant() == DVM_ENDINTERVAL_DIR)
|
|
{
|
|
for (auto st = end; st; st = st->lexPrev())
|
|
{
|
|
if (st->variant() == DVM_INTERVAL_DIR)
|
|
{
|
|
start = st;
|
|
|
|
Statement *intervalStart = new Statement(start);
|
|
Statement *intervalEnd = new Statement(end);
|
|
lines.intervalBefore = make_pair(intervalStart, intervalEnd);
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// try to find interval after explicit lines
|
|
start = lines.stats.second->GetOriginal()->lexNext()->lexNext(); // after SPF_END_PARALLEL_REG_DIR
|
|
if (start && start->variant() == DVM_INTERVAL_DIR)
|
|
{
|
|
for (auto st = start; st; st = st->lexNext())
|
|
{
|
|
if (st->variant() == DVM_ENDINTERVAL_DIR)
|
|
{
|
|
end = st;
|
|
|
|
Statement *intervalStart = new Statement(start);
|
|
Statement *intervalEnd = new Statement(end);
|
|
lines.intervalAfter = make_pair(intervalStart, intervalEnd);
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool checkRegions(const vector<ParallelRegion*> ®ions,
|
|
const map<string, vector<FuncInfo*>> &allFuncInfo,
|
|
map<string, vector<Messages>> &SPF_messages)
|
|
{
|
|
bool noError = true;
|
|
|
|
// check if region includes itself
|
|
for (auto ®ion : regions)
|
|
{
|
|
for (auto &fileLines : region->GetAllLines())
|
|
{
|
|
for (auto &lines : fileLines.second)
|
|
{
|
|
if (!lines.isImplicit())
|
|
{
|
|
for (auto &lines2 : fileLines.second)
|
|
{
|
|
if (lines2.isImplicit() && lines2.lines.first <= lines.lines.first && lines2.lines.second >= lines.lines.second)
|
|
{
|
|
__spf_print(1, "parallel region '%s' is included in file '%s' on line %d\n", region->GetName().c_str(),
|
|
fileLines.first.c_str(), lines2.lines.first);
|
|
wstring messageE, messageR;
|
|
__spf_printToLongBuf(messageE, L"parallel region '%s' is included in file '%s'",
|
|
to_wstring(region->GetName()).c_str(), to_wstring(fileLines.first).c_str());
|
|
|
|
__spf_printToLongBuf(messageR, R65,
|
|
to_wstring(region->GetName()).c_str(), to_wstring(fileLines.first).c_str());
|
|
|
|
getObjectForFileFromMap(fileLines.first.c_str(), SPF_messages).push_back(Messages(ERROR, lines2.lines.first, messageR, messageE, 1033));
|
|
noError = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// check if explicit region lines are included by another region
|
|
for (auto ®ion : regions)
|
|
{
|
|
for (auto &fileLines : region->GetAllLines())
|
|
{
|
|
for (auto &lines : fileLines.second)
|
|
{
|
|
if (!lines.isImplicit())
|
|
{
|
|
for (auto line = lines.lines.first; line <= lines.lines.second; ++line)
|
|
{
|
|
auto inRegs = getAllRegionsByLine(regions, fileLines.first, line);
|
|
if (inRegs.size() > 1)
|
|
{
|
|
__spf_print(1, "parallel region '%s' has line included in another region on line %d\n", region->GetName().c_str(), line);
|
|
|
|
wstring messageE, messageR;
|
|
__spf_printToLongBuf(messageE, L"parallel region '%s' has line included in another region, try to run Region conflict resolving pass", to_wstring(region->GetName()).c_str());
|
|
__spf_printToLongBuf(messageR, R74, to_wstring(region->GetName()).c_str());
|
|
|
|
getObjectForFileFromMap(fileLines.first.c_str(), SPF_messages).push_back(Messages(ERROR, line, messageR, messageE, 1041));
|
|
|
|
noError = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// check if there are several entries in each fragment
|
|
map<string, FuncInfo*> funcMap;
|
|
createMapOfFunc(allFuncInfo, funcMap);
|
|
|
|
for (auto ®ion : regions)
|
|
{
|
|
for (auto &fileLines : region->GetAllLines())
|
|
{
|
|
if (SgFile::switchToFile(fileLines.first) != -1)
|
|
{
|
|
for (auto &lines : fileLines.second)
|
|
{
|
|
if (!lines.isImplicit())
|
|
{
|
|
noError = noError && checkRegionEntries(lines.stats.first->GetOriginal()->lexPrev(), lines.stats.second->GetOriginal()->lexNext(), funcMap, regions, SPF_messages);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
}
|
|
|
|
return noError;
|
|
}
|
|
|
|
static void recursiveReplace(SgStatement *st, SgExpression *exp, const string &from, SgSymbol *to)
|
|
{
|
|
if (exp)
|
|
{
|
|
if (exp->variant() == ARRAY_REF || exp->variant() == VAR_REF || exp->variant() == FUNC_CALL)
|
|
if (exp->symbol() && exp->symbol()->identifier() == from)
|
|
exp->setSymbol(to);
|
|
|
|
recursiveReplace(st, exp->lhs(), from, to);
|
|
recursiveReplace(st, exp->rhs(), from, to);
|
|
}
|
|
}
|
|
|
|
static void replaceSymbol(const string &fileName, const ParallelRegionLines &lines, const string &origSymbName, SgSymbol *newSymb, bool replaceFunc = false)
|
|
{
|
|
if (SgFile::switchToFile(fileName) != -1)
|
|
{
|
|
// explicit lines
|
|
if (!lines.isImplicit())
|
|
{
|
|
SgStatement *iterator = lines.stats.first->GetOriginal();
|
|
SgStatement *end = lines.stats.second->GetOriginal()->lexNext();
|
|
|
|
for (; iterator != end; iterator = iterator->lexNext())
|
|
{
|
|
// skip not executable statements and change symbols only in executable section
|
|
if (!isSgExecutableStatement(iterator) && (iterator->variant() != VAR_DECL && iterator->variant() != EXTERN_STAT))
|
|
continue;
|
|
|
|
if (iterator->symbol() && iterator->symbol()->identifier() == origSymbName)
|
|
iterator->setSymbol(*newSymb);
|
|
|
|
for (int i = 0; i < 3; ++i)
|
|
recursiveReplace(iterator, iterator->expr(i), origSymbName, newSymb);
|
|
|
|
if (replaceFunc && isSgExecutableStatement(iterator))
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
|
|
static inline string getContains(SgStatement *funcSt)
|
|
{
|
|
string containsName;
|
|
SgStatement *st_cp = funcSt->controlParent();
|
|
if (st_cp->variant() == PROC_HEDR || st_cp->variant() == PROG_HEDR || st_cp->variant() == FUNC_HEDR)
|
|
containsName = st_cp->symbol()->identifier() + std::string(".");
|
|
return containsName;
|
|
}
|
|
|
|
static void recReplaceFuncCalls(SgStatement *st, SgExpression *exp, const ParallelRegionLines &lines, const map<string, FuncInfo*> &funcMap, const uint64_t regionId)
|
|
{
|
|
if (exp)
|
|
{
|
|
if (exp->variant() == FUNC_CALL)
|
|
{
|
|
SgStatement *externFuncSt = getFuncStat(st);
|
|
SgProcHedrStmt *procH = (SgProcHedrStmt*)externFuncSt;
|
|
string contains = getContains(procH);
|
|
|
|
string funcName = exp->symbol()->identifier();
|
|
string fullFuncName = contains + funcName;
|
|
FuncInfo *func = getFuncInfo(funcMap, fullFuncName);
|
|
|
|
if (func)
|
|
{
|
|
string newFuncName = func->getFuncNameByRegion(funcName, regionId);
|
|
SgSymbol *newSymb = new SgSymbol(exp->symbol()->variant());
|
|
newSymb->changeName(newFuncName.c_str());
|
|
exp->setSymbol(*newSymb);
|
|
|
|
// for extern
|
|
replaceSymbol(current_file->filename(), lines, funcName, newSymb, true);
|
|
}
|
|
}
|
|
|
|
recReplaceFuncCalls(st, exp->rhs(), lines, funcMap, regionId);
|
|
recReplaceFuncCalls(st, exp->lhs(), lines, funcMap, regionId);
|
|
}
|
|
}
|
|
|
|
static void replaceFuncCalls(const ParallelRegionLines &lines, const map<string, FuncInfo*> &funcMap, uint64_t regionId = 0)
|
|
{
|
|
for (auto st = lines.stats.first->GetOriginal();
|
|
st != lines.stats.second->GetOriginal()->lexNext();
|
|
st = st->lexNext())
|
|
{
|
|
if (st->variant() == PROC_STAT)
|
|
{
|
|
SgStatement *externFuncSt = getFuncStat(st);
|
|
SgProcHedrStmt *procH = (SgProcHedrStmt*)externFuncSt;
|
|
string contains = getContains(procH);
|
|
|
|
string funcName = st->symbol()->identifier();
|
|
string fullFuncName = contains + funcName;
|
|
FuncInfo *func = getFuncInfo(funcMap, fullFuncName);
|
|
|
|
if (func)
|
|
{
|
|
string newFuncName = func->getFuncNameByRegion(funcName, regionId);
|
|
SgSymbol *newSymb = new SgSymbol(st->symbol()->variant());
|
|
newSymb->changeName(newFuncName.c_str());
|
|
st->setSymbol(*newSymb);
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < 3; ++i)
|
|
recReplaceFuncCalls(st, st->expr(i), lines, funcMap, regionId);
|
|
}
|
|
}
|
|
|
|
static map<string, map<DIST::Array*, SgStatement*>> createdCommonBlocks; // file -> array -> new common statement
|
|
static map<string, map<DIST::Array*, pair<SgSymbol*, SgSymbol*>>> createdCommonArrays; // file -> array -> (orig, copy)
|
|
|
|
static SgStatement* createCommonBlock(SgFile *file, DIST::Array *array)
|
|
{
|
|
auto varsOnPos = getArraySynonyms(array);
|
|
if (!varsOnPos.size())
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
string fileName = file->filename();
|
|
|
|
if (SgFile::switchToFile(fileName) != -1)
|
|
{
|
|
auto fileArrayBlock = createdCommonBlocks.find(fileName);
|
|
if (fileArrayBlock == createdCommonBlocks.end())
|
|
fileArrayBlock = createdCommonBlocks.insert(fileArrayBlock, make_pair(fileName, map<DIST::Array*, SgStatement*>()));
|
|
|
|
auto arrayBlock = fileArrayBlock->second.find(array);
|
|
if (arrayBlock == fileArrayBlock->second.end())
|
|
{
|
|
// new common-block is not created for array at this file, so create it
|
|
// creating new common-block statement
|
|
//TODO: consistence with declaration
|
|
//string commBlockName = checkSymbNameAndCorrect(array->GetShortName() + "_r");
|
|
string commBlockName = array->GetShortName() + "_r";
|
|
SgStatement *commDecl = new SgStatement(COMM_STAT);
|
|
|
|
SgSymbol *commSymb = new SgSymbol(VARIABLE_NAME, commBlockName.c_str());
|
|
SgExprListExp *commList = new SgExprListExp(COMM_LIST);
|
|
SgExprListExp *curNode = NULL;
|
|
commDecl->setExpression(0, *commList);
|
|
commList->setSymbol(commSymb);
|
|
|
|
// need to add
|
|
// check if need to create new common array symbol
|
|
SgSymbol *newArrSymb = NULL;
|
|
|
|
auto it = createdCommonArrays.find(fileName);
|
|
if (it == createdCommonArrays.end())
|
|
it = createdCommonArrays.insert(it, make_pair(fileName, map<DIST::Array*, pair<SgSymbol*, SgSymbol*>>()));
|
|
|
|
auto itt = it->second.find(array);
|
|
if (itt == it->second.end()) // need to create symbol
|
|
{
|
|
//TODO: consistence with declaration
|
|
//string newArrName = checkSymbNameAndCorrect(varsOnPos[0]->getName() + "_c");
|
|
string newArrName = varsOnPos[0]->getName() + "_c";
|
|
|
|
newArrSymb = new SgSymbol(VARIABLE_NAME, newArrName.c_str(), file->firstStatement());
|
|
SgType *type = new SgType(T_ARRAY);
|
|
newArrSymb->setType(type);
|
|
|
|
itt = it->second.insert(itt, make_pair(array, make_pair((SgSymbol*)NULL, newArrSymb)));
|
|
}
|
|
else
|
|
// just use previous created symbol
|
|
newArrSymb = itt->second.second;
|
|
|
|
checkNull(newArrSymb, convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
// inserting newArrSymb to COMM_STAT
|
|
if (!curNode)
|
|
{
|
|
curNode = new SgExprListExp();
|
|
commList->setLhs(curNode);
|
|
}
|
|
else
|
|
{
|
|
SgExprListExp *newNode = new SgExprListExp();
|
|
curNode->setRhs(newNode);
|
|
curNode = (SgExprListExp*)curNode->rhs();
|
|
}
|
|
|
|
SgExpression *arrNode = new SgExpression(VAR_REF, NULL, NULL, newArrSymb);
|
|
curNode->setLhs(arrNode);
|
|
|
|
fileArrayBlock->second.insert(make_pair(array, commDecl));
|
|
|
|
return commDecl;
|
|
}
|
|
|
|
return arrayBlock->second;
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// func -> arrays; funcs where new common statement inserted
|
|
static map<FuncInfo*, set<DIST::Array*>> insertedCommonBlocks;
|
|
|
|
static void insertCommonBlock(FuncInfo *func, DIST::Array *array)
|
|
{
|
|
SgFile *file = func->funcPointer->GetOriginal()->getFile();
|
|
SgStatement *insertPlace = NULL;
|
|
|
|
for (auto iterator = func->funcPointer->GetOriginal()->lexNext();
|
|
!isSgExecutableStatement(iterator) || isSPF_stat(iterator) && !isSPF_reg(iterator);
|
|
iterator = iterator->lexNext())
|
|
{
|
|
insertPlace = iterator;
|
|
}
|
|
|
|
//NULL - no decl stats in function!
|
|
if (!insertPlace)
|
|
insertPlace = func->funcPointer->GetOriginal();
|
|
|
|
SgStatement *commDecl = createCommonBlock(file, array);
|
|
SgStatement *copyDecl = commDecl->copyPtr();
|
|
|
|
auto st = insertPlace->controlParent();
|
|
if (st->variant() == GLOBAL)
|
|
st = insertPlace;
|
|
|
|
const int nextLine = insertPlace->lexNext()->lineNumber();
|
|
insertPlace->insertStmtAfter(*copyDecl, *st);
|
|
insertPlace->lexNext()->setlineNumber(nextLine);
|
|
|
|
// create declaration via comment
|
|
insertStringDeclarations(insertPlace->lexNext(), array);
|
|
}
|
|
|
|
// file -> lines -> arrays; lines where arrays copying is inserted
|
|
static map<string, map<ParallelRegionLines, set<string>>> copiedArrays;
|
|
|
|
static void insertArrayCopying(const string &fileName, const ParallelRegionLines ®ionLines, SgSymbol *origSymb, SgSymbol *newSymb)
|
|
{
|
|
if (SgFile::switchToFile(fileName) != -1)
|
|
{
|
|
if (regionLines.isImplicit())
|
|
return;
|
|
|
|
auto it = copiedArrays.find(fileName);
|
|
if (it == copiedArrays.end())
|
|
it = copiedArrays.insert(it, make_pair(fileName, map<ParallelRegionLines, set<string>>()));
|
|
|
|
auto it2 = it->second.find(regionLines);
|
|
if (it2 == it->second.end())
|
|
it2 = it->second.insert(it2, make_pair(regionLines, set<string>()));
|
|
|
|
const string arrName = origSymb->identifier();
|
|
auto it3 = it2->second.find(arrName);
|
|
|
|
if (it3 == it2->second.end())
|
|
{
|
|
// A_reg = A
|
|
SgAssignStmt* assign = new SgAssignStmt(*new SgArrayRefExp(*newSymb), *new SgArrayRefExp(*origSymb));
|
|
assign->setlineNumber(getNextNegativeLineNumber()); // before region
|
|
regionLines.stats.first->GetOriginal()->lexPrev()->insertStmtBefore(*assign, *regionLines.stats.first->GetOriginal()->controlParent());
|
|
|
|
// A = A_reg
|
|
assign = new SgAssignStmt(*new SgArrayRefExp(*origSymb), *new SgArrayRefExp(*newSymb));
|
|
//TODO: bug with insertion
|
|
//assign->setlineNumber(getNextNegativeLineNumber()); // after region
|
|
regionLines.stats.second->GetOriginal()->lexNext()->insertStmtAfter(*assign, *regionLines.stats.first->GetOriginal()->controlParent());
|
|
|
|
it2->second.insert(arrName);
|
|
// TODO: SPF_ANALYSIS(decl)
|
|
|
|
if ((origSymb->attributes() & IN_BIT) || (origSymb->attributes() & OUT_BIT))
|
|
{
|
|
auto func = getFuncStat(regionLines.stats.first->GetOriginal());
|
|
auto fromIntent = fillFromIntent(func);
|
|
|
|
//TODO:
|
|
if (fromIntent.size())
|
|
{
|
|
for (auto& elem : fromIntent)
|
|
{
|
|
string ident = origSymb->identifier();
|
|
if (elem.second.find(ident) != elem.second.end())
|
|
{
|
|
if (elem.first->variant() == INTENT_STMT)
|
|
{
|
|
SgIntentStmt* stat = (SgIntentStmt*)elem.first;
|
|
if (stat->numberOfArgs() == 1)
|
|
stat->deleteStmt();
|
|
else
|
|
{
|
|
SgExpression* par = NULL;
|
|
SgExpression* ex = stat->expr(0);
|
|
while (ex)
|
|
{
|
|
if (ex->lhs()->symbol()->identifier() == ident)
|
|
{
|
|
if (par)
|
|
par->setRhs(ex->rhs());
|
|
else
|
|
stat->setExpression(0, ex->rhs());
|
|
break;
|
|
}
|
|
|
|
par = ex;
|
|
ex = ex->rhs();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
|
|
// return true if error exists
|
|
static bool replaceCommonArray(const string &fileName,
|
|
const set<string> &arraySynonymNames,
|
|
const ParallelRegionLines &lines,
|
|
map<string, vector<Messages>> &SPF_messages,
|
|
const bool needInsertCopying = false)
|
|
{
|
|
auto it = createdCommonArrays.find(fileName);
|
|
if (it == createdCommonArrays.end())
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
SgStatement *begin = getFuncStat(lines.stats.first->GetOriginal());
|
|
SgStatement *end = begin->lastNodeOfStmt();
|
|
|
|
if (begin->symbol() == NULL)
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
const string fName = begin->symbol()->identifier();
|
|
|
|
// get common-blocks ref
|
|
DIST::Array *array = NULL;
|
|
map<string, vector<SgExpression*>> commonBlocksRef;
|
|
getCommonBlocksRef(commonBlocksRef, begin, end);
|
|
|
|
for (auto &commonBlockRef : commonBlocksRef)
|
|
{
|
|
for (auto &commExp : commonBlockRef.second)
|
|
{
|
|
for (auto exp = commExp->lhs(); exp; exp = exp->rhs())
|
|
{
|
|
SgSymbol *varSymb = exp->lhs()->symbol();
|
|
string varName = varSymb->identifier();
|
|
|
|
if (arraySynonymNames.find(varName) != arraySynonymNames.end())
|
|
{
|
|
array = getArrayFromDeclarated(declaratedInStmt(varSymb), varName);
|
|
|
|
if (array)
|
|
{
|
|
auto varsOnPos = getArraySynonyms(array);
|
|
|
|
if (!varsOnPos.size())
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
auto var = varsOnPos[0];
|
|
|
|
if (SgFile::switchToFile(var->getSymbol()->getFile()->filename()) != -1)
|
|
{
|
|
DIST::Array *commArr = getArrayFromDeclarated(declaratedInStmt(var->getSymbol()), var->getName());
|
|
checkNull(commArr, convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
auto itt = it->second.find(commArr);
|
|
if (itt == it->second.end())
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
replaceSymbol(fileName, lines, varName, itt->second.second);
|
|
if (needInsertCopying)
|
|
insertArrayCopying(fileName, lines, varSymb, itt->second.second);
|
|
|
|
// no error
|
|
return false;
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!array)
|
|
{
|
|
string toPrint;
|
|
for (auto &arrayName : arraySynonymNames)
|
|
toPrint += " '" + arrayName + '\'';
|
|
__spf_print(1, "wrong parallel region position, there is no common-block in current function '%s' with any of such arrays:%s on line %d\n",
|
|
fName.c_str(), toPrint.c_str(), lines.lines.first);
|
|
|
|
wstring messageE, messageR;
|
|
__spf_printToLongBuf(messageE, L"wrong parallel region position, there is no common-block in current function '%s' with any of such arrays:%s",
|
|
to_wstring(fName).c_str(), to_wstring(toPrint).c_str());
|
|
__spf_printToLongBuf(messageR, R66, to_wstring(fName).c_str(), to_wstring(toPrint).c_str());
|
|
|
|
getObjectForFileFromMap(fileName.c_str(), SPF_messages).push_back(Messages(ERROR, lines.lines.first, messageR, messageE, 1034));
|
|
// error
|
|
return true;
|
|
}
|
|
|
|
// no error
|
|
return false;
|
|
}
|
|
|
|
pair<SgSymbol*, SgSymbol*> copyArray(const pair<string, int> &place,
|
|
const DIST::Array *array,
|
|
const vector<ParallelRegionLines>& lines,
|
|
const string &suffix,
|
|
string& filename,
|
|
map<string, map<int, set<string>>>& newDeclsToInclude,
|
|
map<string, map<int, set<string>>>& copied)
|
|
{
|
|
string fileName = place.first;
|
|
int switchRes = SgFile::switchToFile(fileName);
|
|
bool isIncludeFile = false;
|
|
if (switchRes == -1)
|
|
{
|
|
isIncludeFile = true;
|
|
set<string> files;
|
|
for (auto& elem : lines)
|
|
{
|
|
if (elem.stats.first)
|
|
files.insert(elem.stats.first->fileName());
|
|
else if (elem.stats.second)
|
|
files.insert(elem.stats.second->fileName());
|
|
}
|
|
|
|
if (files.size() != 1)
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
else
|
|
{
|
|
switchRes = SgFile::switchToFile(*files.begin());
|
|
if (switchRes != -1)
|
|
filename = *files.begin();
|
|
}
|
|
}
|
|
|
|
if (switchRes != -1)
|
|
{
|
|
//TODO: consistence with declaration
|
|
//string newArrName = checkSymbNameAndCorrect(array->GetShortName() + suffix);
|
|
string newArrName = array->GetShortName() + suffix;
|
|
SgStatement* decl = SgStatement::getStatementByFileAndLine(place.first, place.second);
|
|
checkNull(decl, convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
SgStatement* func = getFuncStat(decl, { MODULE_STMT });
|
|
const auto range = make_pair(func->lineNumber(), func->lastNodeOfStmt()->lineNumber());
|
|
|
|
SgSymbol *arrSymb = array->GetDeclSymbol(fileName, range, getAllFilesInProject())->GetOriginal();
|
|
|
|
SgSymbol *newArrSymb = NULL;
|
|
SgStatement *newDecl = NULL;
|
|
|
|
// for what? to skip .h stats?
|
|
if (decl->fileName() != fileName)
|
|
{
|
|
while (!isSgExecutableStatement(decl) || isSPF_stat(decl) && !isSPF_reg(decl))
|
|
decl = decl->lexNext();
|
|
decl = decl->lexPrev();
|
|
}
|
|
|
|
newArrSymb = &arrSymb->copy();
|
|
newArrSymb->changeName(newArrName.c_str());
|
|
newDecl = makeDeclaration(NULL, { newArrSymb });
|
|
|
|
if (IS_ALLOCATABLE(arrSymb))
|
|
{
|
|
newArrSymb->setAttribute(newArrSymb->attributes() | ALLOCATABLE_BIT);
|
|
if (((SgVarDeclStmt*)newDecl)->addAttributeExpression(new SgExpression(ALLOCATABLE_OP)) == false)
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
// add allocate/deallocate operators
|
|
for (auto &data : getAttributes<SgStatement*, SgStatement*>(decl, set<int>{ ALLOCATE_STMT, DEALLOCATE_STMT }))
|
|
{
|
|
SgExpression *list = data->expr(0);
|
|
|
|
set<string> allocated;
|
|
while (list)
|
|
{
|
|
SgArrayRefExp* arrayRef = isSgArrayRefExp(list->lhs());
|
|
if (arrayRef != NULL)
|
|
allocated.insert(string(OriginalSymbol(arrayRef->symbol())->identifier()));
|
|
list = list->rhs();
|
|
}
|
|
|
|
list = data->expr(0);
|
|
while (list)
|
|
{
|
|
SgArrayRefExp *arrayRef = isSgArrayRefExp(list->lhs());
|
|
if (arrayRef != NULL)
|
|
{
|
|
if (string(OriginalSymbol(arrayRef->symbol())->identifier()) == arrSymb->identifier() &&
|
|
allocated.find(newArrSymb->identifier()) == allocated.end())
|
|
{
|
|
// add parameter to allocate() operator
|
|
if (data->variant() == ALLOCATE_STMT)
|
|
{
|
|
while (list->rhs())
|
|
list = list->rhs();
|
|
|
|
auto copy = arrayRef->copyPtr();
|
|
copy->setSymbol(newArrSymb);
|
|
|
|
list->setRhs(new SgExpression(EXPR_LIST, copy));
|
|
}
|
|
// add parameter to deallocate() operator
|
|
else if (data->variant() == DEALLOCATE_STMT)
|
|
{
|
|
SgExprListExp* newNode = new SgExprListExp();
|
|
newNode->setLhs(new SgArrayRefExp(*newArrSymb));
|
|
newNode->setRhs(data->expr(0));
|
|
data->setExpression(0, *newNode);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
list = list->rhs();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!isIncludeFile)
|
|
{
|
|
if (!(copied.count(decl->fileName()) &&
|
|
copied[decl->fileName()].count(decl->lineNumber()) &&
|
|
copied[decl->fileName()][decl->lineNumber()].count(newDecl->unparse())))
|
|
{
|
|
decl->insertStmtAfter(*newDecl, *decl->controlParent());
|
|
copied[decl->fileName()][decl->lineNumber()].insert(newDecl->unparse());
|
|
}
|
|
}
|
|
else
|
|
newDeclsToInclude[decl->fileName()][decl->lineNumber()].insert(newDecl->unparse());
|
|
|
|
return make_pair(arrSymb, newArrSymb);
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
|
|
static void copyFunction(ParallelRegion *region,
|
|
FuncInfo *func,
|
|
const map<string, FuncInfo*> &funcMap,
|
|
const string &suffix = "")
|
|
{
|
|
if (SgFile::switchToFile(func->fileName) != -1)
|
|
{
|
|
SgStatement *funcStat = func->funcPointer->GetOriginal();
|
|
SgStatement *newFuncStat = NULL;
|
|
SgSymbol *funcSymb = func->funcPointer->GetOriginal()->symbol();
|
|
SgSymbol *newFuncSymb = NULL;
|
|
SgFile *file = func->funcPointer->GetOriginal()->getFile();
|
|
string newFuncName = string(funcSymb->identifier()) + suffix;
|
|
|
|
// create copy function symbol and copy function for original function
|
|
SgStatement* copyFunc = duplicateProcedure(funcStat, &newFuncName, false, false, false);
|
|
newFuncSymb = copyFunc->symbol();
|
|
|
|
if (SgFile::switchToFile(func->fileName) == -1)
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
// set line numbers
|
|
for (auto origStat = funcStat, copyStat = copyFunc;
|
|
origStat != funcStat->lastNodeOfStmt()->lexNext();
|
|
origStat = origStat->lexNext(), copyStat = copyStat->lexNext())
|
|
{
|
|
if (copyStat->variant() != origStat->variant())
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
copyStat->setlineNumber(origStat->lineNumber());
|
|
BIF_FILE_NAME(copyStat->thebif) = BIF_FILE_NAME(origStat->thebif);
|
|
}
|
|
|
|
// replace all func calls in copy function
|
|
Statement *begin = new Statement(copyFunc);
|
|
Statement *end = new Statement(copyFunc->lastNodeOfStmt());
|
|
pair<Statement*, Statement*> beginEnd = make_pair(begin, end);
|
|
pair<int, int> newLines = make_pair(beginEnd.first->lineNumber(), beginEnd.second->lineNumber());
|
|
ParallelRegionLines newFuncLines(newLines, beginEnd);
|
|
replaceFuncCalls(newFuncLines, funcMap, region->GetId());
|
|
|
|
if (funcStat->variant() == FUNC_HEDR)
|
|
replaceSymbol(current_file->filename(), newFuncLines, func->funcName, newFuncSymb);
|
|
|
|
// try to find common-block and add new if common-block exists
|
|
for (auto origStat = funcStat, copyStat = copyFunc;
|
|
origStat && (!isSgExecutableStatement(origStat) || isSPF_stat(origStat));
|
|
origStat = origStat->lexNext(), copyStat = copyStat->lexNext())
|
|
{
|
|
if (origStat->variant() == COMM_STAT)
|
|
{
|
|
for (auto &arrayBlock : allUsedCommonArrays)
|
|
createCommonBlock(file, arrayBlock.first);
|
|
|
|
auto usedCommonArrays = region->GetUsedCommonArrays().find(func);
|
|
if (usedCommonArrays != region->GetUsedCommonArrays().end())
|
|
{
|
|
for (auto &arrayLines : usedCommonArrays->second)
|
|
{
|
|
SgStatement *commDecl = createCommonBlock(file, arrayLines.first);
|
|
SgStatement *copyDecl = commDecl->copyPtr();
|
|
|
|
while (!isSgExecutableStatement(copyStat) || isSPF_stat(copyStat))
|
|
copyStat = copyStat->lexNext();
|
|
|
|
copyStat = copyStat->lexPrev();
|
|
copyStat->insertStmtAfter(*copyDecl, *copyStat->controlParent());
|
|
|
|
// making declaration of new common array symbol via comment through files
|
|
insertStringDeclarations(copyStat->lexNext(), arrayLines.first);
|
|
}
|
|
|
|
auto it = createdCommonArrays.find(file->filename());
|
|
if (it == createdCommonArrays.end())
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
// replace common arrays to new common arrays in executable code section
|
|
SgStatement *iterator = begin->GetOriginal();
|
|
|
|
for (; iterator != end->GetOriginal() && (!isSgExecutableStatement(iterator) || isSPF_stat(iterator)); iterator = iterator->lexNext())
|
|
;
|
|
|
|
Statement *start = new Statement(iterator);
|
|
ParallelRegionLines lines(make_pair(start->lineNumber(), end->lineNumber()), make_pair(start, end));
|
|
|
|
// get common-blocks ref
|
|
map<string, vector<SgExpression*>> commonBlocksRef;
|
|
getCommonBlocksRef(commonBlocksRef, func->funcPointer->GetOriginal(), func->funcPointer->GetOriginal()->lastNodeOfStmt());
|
|
|
|
for (auto &commonBlockRef : commonBlocksRef)
|
|
{
|
|
for (auto &commExp : commonBlockRef.second)
|
|
{
|
|
for (auto exp = commExp->lhs(); exp; exp = exp->rhs())
|
|
{
|
|
SgSymbol *varSymb = exp->lhs()->symbol();
|
|
string varName = varSymb->identifier();
|
|
DIST::Array *array = getArrayFromDeclarated(declaratedInStmt(varSymb), varName);
|
|
|
|
if (array && !array->IsNotDistribute())
|
|
{
|
|
auto varsOnPos = getArraySynonyms(array);
|
|
|
|
if (!varsOnPos.size())
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
auto var = varsOnPos[0];
|
|
|
|
if (SgFile::switchToFile(var->getSymbol()->getFile()->filename()) != -1)
|
|
{
|
|
DIST::Array *commArr = getArrayFromDeclarated(declaratedInStmt(var->getSymbol()), var->getName());
|
|
checkNull(commArr, convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
auto itt = it->second.find(commArr);
|
|
if (itt == it->second.end())
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
replaceSymbol(func->fileName, lines, varName, itt->second.second);
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
|
|
void fillUsedArraysInExp(const pair<Statement*, Statement*> &interval, const int exp, set<DIST::Array*> &varSet)
|
|
{
|
|
if (exp > 2 || exp < 0)
|
|
return;
|
|
|
|
for (auto st = interval.first->GetOriginal()->lexNext(); st != interval.second->GetOriginal(); st = st->lexNext())
|
|
{
|
|
// after CONVERT_ASSIGN_TO_LOOP
|
|
if (st->variant() == ASSIGN_STAT)
|
|
{
|
|
auto varSymb = st->expr(exp)->symbol();
|
|
checkNull(varSymb, convertFileName(__FILE__).c_str(), __LINE__);
|
|
auto array = getArrayFromDeclarated(declaratedInStmt(varSymb), varSymb->identifier());
|
|
checkNull(array, convertFileName(__FILE__).c_str(), __LINE__);
|
|
varSet.insert(array);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool checkRegionsResolving(const vector<ParallelRegion*> ®ions,
|
|
const map<string, vector<FuncInfo*>> &allFuncInfo,
|
|
const map<string, CommonBlock*> &commonBlocks,
|
|
map<string, vector<Messages>> &SPF_messages, bool sharedMemoryParallelization)
|
|
{
|
|
bool error = false;
|
|
|
|
if (regions.size())
|
|
{
|
|
map<string, FuncInfo*> funcMap;
|
|
createMapOfFunc(allFuncInfo, funcMap);
|
|
|
|
// check functions
|
|
for (auto &nameFunc : funcMap)
|
|
{
|
|
auto func = nameFunc.second;
|
|
if (func->callRegions.size() > 1)
|
|
{
|
|
string outText = "";
|
|
for (auto ®Id : func->callRegions)
|
|
{
|
|
auto reg = getRegionById(regions, regId);
|
|
if (!reg && regId)
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
if (regId)
|
|
outText += "'" + reg->GetName() + "' ";
|
|
else
|
|
outText += "'DEFAULT' ";
|
|
}
|
|
__spf_print(1, "parallel regions %shave common function '%s' which is used inside them\n", outText.c_str(), nameFunc.first.c_str());
|
|
|
|
wstring messageE, messageR;
|
|
__spf_printToLongBuf(messageE, L"parallel regions %shave common function '%s' which is used inside them",
|
|
to_wstring(outText).c_str(), to_wstring(nameFunc.first).c_str());
|
|
__spf_printToLongBuf(messageR, R133, to_wstring(outText).c_str(), to_wstring(nameFunc.first).c_str());
|
|
|
|
ParallelRegion *reg = NULL;
|
|
for (auto ®Id : func->callRegions)
|
|
{
|
|
if (regId)
|
|
{
|
|
reg = getRegionById(regions, regId);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!reg)
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
auto lines = reg->GetAllLines();
|
|
bool ok = false;
|
|
for (auto &linePair : lines)
|
|
{
|
|
for (auto &line : linePair.second)
|
|
{
|
|
if (line.stats.first && line.stats.second)
|
|
{
|
|
getObjectForFileFromMap(linePair.first.c_str(), SPF_messages).push_back(Messages(ERROR, getRegionExplicitLine(line.stats.first), messageR, messageE, 3012));
|
|
error = true;
|
|
ok = true;
|
|
break;
|
|
}
|
|
}
|
|
if (ok)
|
|
break;
|
|
}
|
|
if (ok == false)
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
}
|
|
|
|
if (sharedMemoryParallelization)
|
|
return error;
|
|
|
|
// check local arrays
|
|
for (auto ® : regions)
|
|
{
|
|
for (auto &funcArrays : reg->GetUsedLocalArrays())
|
|
{
|
|
if (SgFile::switchToFile(funcArrays.first->fileName) != -1)
|
|
{
|
|
for (auto &arrayLines : funcArrays.second)
|
|
{
|
|
auto regsByArr = arrayLines.first->GetRegionsName();
|
|
bool notResolved = false;
|
|
|
|
if (regsByArr.size() > 1)
|
|
{
|
|
// check if array is used only in region and its related interval
|
|
if (regsByArr.size() == 2 && regsByArr.find("default") != regsByArr.end())
|
|
{
|
|
auto array = arrayLines.first;
|
|
for (auto &line : array->GetUsagePlaces(funcArrays.first->fileName, &funcArrays.first->linesNum))
|
|
{
|
|
auto inRegs = getAllRegionsByLine(regions, funcArrays.first->fileName, line);
|
|
if (!inRegs.size())
|
|
{
|
|
bool inInterval = false;
|
|
for (auto ®Lines : arrayLines.second)
|
|
{
|
|
// check interval existing
|
|
if (regLines.intervalBefore.first && regLines.intervalBefore.second && regLines.intervalAfter.first && regLines.intervalAfter.second)
|
|
{
|
|
if (line > regLines.intervalBefore.first->lineNumber() && line < regLines.intervalAfter.second->lineNumber())
|
|
inInterval = true;
|
|
}
|
|
}
|
|
|
|
if (!inInterval)
|
|
notResolved = true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
notResolved = true;
|
|
}
|
|
|
|
if (notResolved)
|
|
{
|
|
|
|
string regions = "";
|
|
for (auto ® : regsByArr)
|
|
regions += "'" + reg + "' ";
|
|
__spf_print(1, "parallel regions %shave local array '%s' which is used inside them\n",
|
|
regions.c_str(), arrayLines.first->GetShortName().c_str());
|
|
|
|
wstring messageE, messageR;
|
|
if (arrayLines.first->GetLocation().first == DIST::l_MODULE)
|
|
__spf_printToLongBuf(messageE, L"parallel regions %shave module array '%s' which is used inside them, try to run Region conflict resolving pass",
|
|
to_wstring(regions).c_str(), to_wstring(arrayLines.first->GetShortName()).c_str());
|
|
else
|
|
__spf_printToLongBuf(messageE, L"parallel regions %shave local array '%s' which is used inside them, try to run Region conflict resolving pass",
|
|
to_wstring(regions).c_str(), to_wstring(arrayLines.first->GetShortName()).c_str());
|
|
|
|
if (arrayLines.first->GetLocation().first == DIST::l_MODULE)
|
|
__spf_printToLongBuf(messageR, R152, to_wstring(regions).c_str(), to_wstring(arrayLines.first->GetShortName()).c_str());
|
|
else
|
|
__spf_printToLongBuf(messageR, R134, to_wstring(regions).c_str(), to_wstring(arrayLines.first->GetShortName()).c_str());
|
|
|
|
|
|
auto lines = reg->GetAllLines();
|
|
bool ok = false;
|
|
for (auto &linePair : lines)
|
|
{
|
|
for (auto &line : linePair.second)
|
|
{
|
|
if (line.stats.first && line.stats.second)
|
|
{
|
|
getObjectForFileFromMap(linePair.first.c_str(), SPF_messages).push_back(Messages(ERROR, getRegionExplicitLine(line.stats.first), messageR, messageE, 3013));
|
|
error = true;
|
|
ok = true;
|
|
break;
|
|
}
|
|
}
|
|
if (ok)
|
|
break;
|
|
}
|
|
if (ok == false)
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
}
|
|
|
|
// check common arrays
|
|
for (auto ® : regions)
|
|
{
|
|
for (auto &funcArrays : reg->GetUsedCommonArrays())
|
|
{
|
|
for (auto &arrayLines : funcArrays.second)
|
|
{
|
|
auto commonBlock = isArrayInCommon(commonBlocks, arrayLines.first);
|
|
checkNull(commonBlock, convertFileName(__FILE__).c_str(), __LINE__);
|
|
if (!arrayLines.second.size())
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
// check common block name and variables count
|
|
auto lines = arrayLines.second[0].lines;
|
|
string commonBlockName = commonBlock->getName();
|
|
auto pos = commonBlockName.rfind("_r");
|
|
if (!arrayLines.second[0].isImplicit() && (pos != commonBlockName.length() - 2 || commonBlock->getVariables().size() != 1))
|
|
{
|
|
__spf_print(1, "parallel region '%s' has common array '%s' which is used inside and outside region on lines %d-%d\n",
|
|
reg->GetName().c_str(), arrayLines.first->GetShortName().c_str(), lines.first, lines.second);
|
|
|
|
wstring messageE, messageR;
|
|
__spf_printToLongBuf(messageE, L"parallel region '%s' has common array '%s' which is used inside and outside region, try to run Region conflict resolving pass",
|
|
to_wstring(reg->GetName()).c_str(), to_wstring(arrayLines.first->GetShortName()).c_str());
|
|
|
|
__spf_printToLongBuf(messageR, R135, to_wstring(reg->GetName()).c_str(), to_wstring(arrayLines.first->GetShortName()).c_str());
|
|
|
|
|
|
getObjectForFileFromMap(funcArrays.first->fileName.c_str(), SPF_messages).push_back(Messages(ERROR, getRegionExplicitLine(arrayLines.second[0].stats.first), messageR, messageE, 3014));
|
|
error = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// check intervals and arrays copying
|
|
for (auto ® : regions)
|
|
{
|
|
for (auto &fileLines : reg->GetAllLines())
|
|
{
|
|
if (SgFile::switchToFile(fileLines.first) != -1)
|
|
{
|
|
// check array copying existing
|
|
for (auto &lines : fileLines.second)
|
|
{
|
|
if (!lines.isImplicit())
|
|
{
|
|
// check interval existing
|
|
if (!lines.intervalBefore.first || !lines.intervalBefore.second || !lines.intervalAfter.first || !lines.intervalAfter.second)
|
|
{
|
|
__spf_print(1, "parallel region '%s' does not have DVM interval for fragment on line %d\n",
|
|
reg->GetName().c_str(), lines.lines.first);
|
|
|
|
wstring messageE, messageR;
|
|
__spf_printToLongBuf(messageE, L"parallel region '%s' does not have DVM interval for fragment, try to run Region conflict resolving pass", to_wstring(reg->GetName()).c_str());
|
|
__spf_printToLongBuf(messageR, R136, to_wstring(reg->GetName()).c_str());
|
|
|
|
getObjectForFileFromMap(fileLines.first.c_str(), SPF_messages).push_back(Messages(ERROR, getRegionExplicitLine(lines.stats.first), messageR, messageE, 3015));
|
|
error = true;
|
|
}
|
|
// check arrays
|
|
else
|
|
{
|
|
set<DIST::Array*> leftBefore;
|
|
set<DIST::Array*> rightAfter;
|
|
|
|
fillUsedArraysInExp(lines.intervalBefore, 0, leftBefore);
|
|
fillUsedArraysInExp(lines.intervalAfter, 1, rightAfter);
|
|
|
|
// check left and right sets if common array is used at this lines
|
|
for (auto funcArrays : reg->GetUsedCommonArrays())
|
|
{
|
|
if (funcArrays.first->fileName == fileLines.first)
|
|
{
|
|
for (auto &arrayLines : funcArrays.second)
|
|
{
|
|
for (auto &lines2 : arrayLines.second)
|
|
{
|
|
if (lines == lines2)
|
|
{
|
|
if (leftBefore.find(arrayLines.first) == leftBefore.end() || rightAfter.find(arrayLines.first) == rightAfter.end())
|
|
{
|
|
__spf_print(1, "parallel region '%s' does not have copying of array '%s' in DVM interval on line %d\n",
|
|
reg->GetName().c_str(), arrayLines.first->GetShortName().c_str(), lines.lines.first);
|
|
|
|
wstring messageE, messageR;
|
|
__spf_printToLongBuf(messageE, L"parallel region '%s' does not have copying of array '%s' in DVM interval, try to run Region conflict resolving pass",
|
|
to_wstring(reg->GetName()).c_str(), to_wstring(arrayLines.first->GetShortName()).c_str());
|
|
|
|
__spf_printToLongBuf(messageR, R139, to_wstring(reg->GetName()).c_str(), to_wstring(arrayLines.first->GetShortName()).c_str());
|
|
|
|
getObjectForFileFromMap(fileLines.first.c_str(), SPF_messages).push_back(Messages(ERROR, lines.lines.first, messageR, messageE, 3018));
|
|
error = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// check left and right sets if local array is used at this lines
|
|
for (auto funcArrays : reg->GetUsedLocalArrays())
|
|
{
|
|
if (funcArrays.first->fileName == fileLines.first)
|
|
{
|
|
for (auto &arrayLines : funcArrays.second)
|
|
{
|
|
for (auto &lines2 : arrayLines.second)
|
|
{
|
|
if (lines == lines2)
|
|
{
|
|
if (leftBefore.find(arrayLines.first) == leftBefore.end() || rightAfter.find(arrayLines.first) == rightAfter.end())
|
|
{
|
|
__spf_print(1, "parallel region '%s' does not have copying of array '%s' in DVM interval on line %d\n",
|
|
reg->GetName().c_str(), arrayLines.first->GetShortName().c_str(), lines.lines.first);
|
|
|
|
wstring messageE, messageR;
|
|
__spf_printToLongBuf(messageE, L"parallel region '%s' does not have copying of array '%s' in DVM interval, try to run Region conflict resolving pass",
|
|
to_wstring(reg->GetName()).c_str(), to_wstring(arrayLines.first->GetShortName()).c_str());
|
|
|
|
__spf_printToLongBuf(messageR, R138, to_wstring(reg->GetName()).c_str(), to_wstring(arrayLines.first->GetShortName()).c_str());
|
|
|
|
getObjectForFileFromMap(fileLines.first.c_str(), SPF_messages).push_back(Messages(ERROR, lines.lines.first, messageR, messageE, 3017));
|
|
error = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
}
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
//check: A = B
|
|
static bool isArrayAssign(SgStatement *st)
|
|
{
|
|
if (st->variant() != ASSIGN_STAT)
|
|
return false;
|
|
if (st->expr(0)->variant() != ARRAY_REF)
|
|
return false;
|
|
if (st->expr(1)->variant() != ARRAY_REF)
|
|
return false;
|
|
|
|
if (st->expr(0)->lhs() != NULL || st->expr(0)->rhs() != NULL)
|
|
return false;
|
|
if (st->expr(1)->lhs() != NULL || st->expr(1)->rhs() != NULL)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
static void compliteUseOnlyList(SgStatement *func, const string &location, const string &s)
|
|
{
|
|
if (isSgProgHedrStmt(func) == NULL)
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
for (SgStatement* st = func->lexNext(); st; st = st->lexNext())
|
|
{
|
|
if (isSgExecutableStatement(st))
|
|
break;
|
|
if (st->variant() == CONTAINS_STMT)
|
|
break;
|
|
|
|
if (st->variant() == USE_STMT)
|
|
{
|
|
if (st->symbol()->identifier() == location)
|
|
{
|
|
SgExpression* ex = st->expr(0);
|
|
|
|
if (ex && ex->variant() == ONLY_NODE)
|
|
{
|
|
SgExpression* toInsert = new SgExpression(RENAME_NODE);
|
|
SgExpression* list = new SgExpression(EXPR_LIST);
|
|
|
|
toInsert->setLhs(new SgVarRefExp(findSymbolOrCreate(st->getFile(), s)));
|
|
|
|
list->setRhs(ex->lhs());
|
|
list->setLhs(toInsert);
|
|
ex->setLhs(list);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int resolveParRegions(vector<ParallelRegion*> ®ions, const map<string, vector<FuncInfo*>> &allFuncInfo,
|
|
map<string, vector<Messages>> &SPF_messages, bool sharedMemoryParallelization,
|
|
map<string, map<int, set<string>>> &newDeclsToInclude)
|
|
{
|
|
bool error = false;
|
|
|
|
map<string, FuncInfo*> funcMap;
|
|
createMapOfFunc(allFuncInfo, funcMap);
|
|
|
|
if (sharedMemoryParallelization == 0)
|
|
{
|
|
map<string, map<int, set<string>>> copied;
|
|
|
|
for (auto& region : regions)
|
|
{
|
|
__spf_print(1, "[%s]: create local arrays\n", region->GetName().c_str());
|
|
|
|
// creating new local arrays
|
|
for (auto& funcArrays : region->GetUsedLocalArrays())
|
|
{
|
|
for (auto& arrayLines : funcArrays.second)
|
|
{
|
|
if (arrayLines.first->GetRegionsName().size() > 1)
|
|
{
|
|
bool fromModule = (arrayLines.first->GetLocation().first == DIST::l_MODULE);
|
|
const string locationName = arrayLines.first->GetLocation().second;
|
|
|
|
auto place = *arrayLines.first->GetDeclInfo().begin();
|
|
string fileName = place.first;
|
|
string suffix = "_l";
|
|
|
|
if (fromModule)
|
|
{
|
|
fileName = funcArrays.first->fileName;
|
|
suffix = "_m";
|
|
}
|
|
|
|
auto origCopy = copyArray(place, arrayLines.first, arrayLines.second, suffix + to_string(region->GetId()), fileName, newDeclsToInclude, copied);
|
|
for (auto& lines : arrayLines.second)
|
|
{
|
|
replaceSymbol(fileName, lines, origCopy.first->identifier(), origCopy.second);
|
|
insertArrayCopying(fileName, lines, origCopy.first, origCopy.second);
|
|
}
|
|
|
|
// complete USE ONLY list
|
|
if (fromModule)
|
|
compliteUseOnlyList(funcArrays.first->funcPointer, locationName, origCopy.second->identifier());
|
|
}
|
|
}
|
|
}
|
|
|
|
__spf_print(1, "[%s]: create common arrays\n", region->GetName().c_str());
|
|
|
|
// creating new common-blocks for files with explicit lines
|
|
for (auto& fileLines : region->GetAllLines())
|
|
{
|
|
if (SgFile::switchToFile(fileLines.first) != -1)
|
|
{
|
|
for (auto& lines : fileLines.second)
|
|
{
|
|
if (!lines.isImplicit())
|
|
{
|
|
SgStatement* iterator = getFuncStat(lines.stats.first->GetOriginal());
|
|
string funcName = iterator->symbol()->identifier();
|
|
FuncInfo* func = getFuncInfo(funcMap, funcName);
|
|
|
|
auto it = insertedCommonBlocks.find(func);
|
|
if (it == insertedCommonBlocks.end())
|
|
it = insertedCommonBlocks.insert(it, make_pair(func, set<DIST::Array*>()));
|
|
|
|
for (auto& arrayBlock : allUsedCommonArrays)
|
|
{
|
|
auto varsOnPos = getArraySynonyms(arrayBlock.first);
|
|
auto itt = it->second.find(arrayBlock.first);
|
|
// insert only one of all array synonyms
|
|
if (itt == it->second.end() && arrayBlock.first->GetShortName() == varsOnPos[0]->getName())
|
|
{
|
|
// need to insert common-block
|
|
insertCommonBlock(func, arrayBlock.first);
|
|
it->second.insert(arrayBlock.first);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
|
|
// insert array copying in explicit lines (and replace common arrays in this lines)
|
|
for (auto& funcArrays : region->GetUsedCommonArrays())
|
|
{
|
|
for (auto& arrayLines : funcArrays.second)
|
|
{
|
|
for (auto& lines : arrayLines.second)
|
|
{
|
|
// get all synonyms for array
|
|
set<string> arraySynonyms;
|
|
auto varsOnPos = getArraySynonyms(arrayLines.first);
|
|
for (auto& var : varsOnPos)
|
|
arraySynonyms.insert(var->getName());
|
|
|
|
// replace common arrays to new common arrays and insert copying in explicit lines
|
|
if (lines.isImplicit())
|
|
{
|
|
// replace common arrays in explicit lines and insert copying
|
|
// finding explicit lines where implicit lines are called from
|
|
// forall lines, lines2: lines.isImplicit(), lines2.isExplicit ==>
|
|
// exists func, func2: lines in func, lines2 in func2, func2 calls func explicit or implicit ==>
|
|
// insert copying of common-arrays in lines2 used in lines
|
|
for (auto& fileLines : region->GetAllLines())
|
|
{
|
|
if (SgFile::switchToFile(fileLines.first) != -1)
|
|
{
|
|
for (auto& lines2 : fileLines.second)
|
|
{
|
|
if (!lines2.isImplicit())
|
|
{
|
|
SgStatement* iterator = getFuncStat(lines2.stats.first->GetOriginal());
|
|
string func2Name = iterator->symbol()->identifier();
|
|
set<FuncInfo*> callSet;
|
|
createSetOfCalledFuncs(func2Name, funcMap, callSet);
|
|
|
|
auto it = callSet.find(funcArrays.first);
|
|
if (it != callSet.end())
|
|
{
|
|
bool tempErr = replaceCommonArray(fileLines.first, arraySynonyms, lines2, SPF_messages, true);
|
|
error = error || tempErr;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (SgFile::switchToFile(funcArrays.first->fileName) != -1)
|
|
{
|
|
bool tempErr = replaceCommonArray(funcArrays.first->fileName, arraySynonyms, lines, SPF_messages, true);
|
|
error = error || tempErr;
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// creating new common-blocks for main program unit
|
|
for (auto& funcPair : funcMap)
|
|
{
|
|
auto func = funcPair.second;
|
|
if (func->isMain)
|
|
{
|
|
if (SgFile::switchToFile(func->fileName) != -1)
|
|
{
|
|
auto it = insertedCommonBlocks.find(func);
|
|
if (it == insertedCommonBlocks.end())
|
|
it = insertedCommonBlocks.insert(it, make_pair(func, set<DIST::Array*>()));
|
|
|
|
for (auto& arrayBlock : allUsedCommonArrays)
|
|
{
|
|
auto varsOnPos = getArraySynonyms(arrayBlock.first);
|
|
auto itt = it->second.find(arrayBlock.first);
|
|
// insert only one of all array synonyms
|
|
if (itt == it->second.end() && arrayBlock.first->GetShortName() == varsOnPos[0]->getName())
|
|
{
|
|
// need to insert common-block
|
|
insertCommonBlock(func, arrayBlock.first);
|
|
it->second.insert(arrayBlock.first);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
__spf_print(1, "create functions\n");
|
|
|
|
// creating new functions
|
|
for (auto &fileFuncs : allFuncInfo)
|
|
{
|
|
if (SgFile::switchToFile(fileFuncs.first) != -1)
|
|
{
|
|
for (auto &func : fileFuncs.second)
|
|
{
|
|
// callRegions = {i}, i = 1, 2, ...
|
|
if (func->callRegions.size() == 1 && *(func->callRegions.begin()) != 0)
|
|
{
|
|
// need just create new common-blocks and replace arrays
|
|
SgFile *file = func->funcPointer->GetOriginal()->getFile();
|
|
ParallelRegion *region = getRegionById(regions, *(func->callRegions.begin()));
|
|
|
|
auto usedCommonArrays = region->GetUsedCommonArrays().find(func);
|
|
if (usedCommonArrays != region->GetUsedCommonArrays().end())
|
|
{
|
|
for (auto &arrayBlock : allUsedCommonArrays)
|
|
createCommonBlock(file, arrayBlock.first);
|
|
|
|
auto it = insertedCommonBlocks.find(func);
|
|
if (it == insertedCommonBlocks.end())
|
|
it = insertedCommonBlocks.insert(it, make_pair(func, set<DIST::Array*>()));
|
|
|
|
for (auto &arrayLines : usedCommonArrays->second)
|
|
{
|
|
auto itt = it->second.find(arrayLines.first);
|
|
if (itt == it->second.end())
|
|
{
|
|
// need to insert common-block
|
|
insertCommonBlock(func, arrayLines.first);
|
|
it->second.insert(arrayLines.first);
|
|
|
|
// replace common arrays to new common arrays in executable code section
|
|
SgStatement *iterator = func->funcPointer->GetOriginal();
|
|
|
|
for (; iterator != func->funcPointer->GetOriginal()->lastNodeOfStmt() &&
|
|
(!isSgExecutableStatement(iterator) || isSPF_stat(iterator)); iterator = iterator->lexNext())
|
|
;
|
|
|
|
// get all synonyms for array
|
|
set<string> arraySynonyms;
|
|
auto varsOnPos = getArraySynonyms(arrayLines.first);
|
|
for (auto &var : varsOnPos)
|
|
arraySynonyms.insert(var->getName());
|
|
|
|
Statement *start = new Statement(iterator);
|
|
Statement *end = new Statement(func->funcPointer->GetOriginal()->lastNodeOfStmt());
|
|
pair<Statement*, Statement*> beginEnd = make_pair(start, end);
|
|
pair<int, int> funcLines = make_pair(beginEnd.first->GetOriginal()->lineNumber(), beginEnd.second->GetOriginal()->lineNumber());
|
|
ParallelRegionLines lines(funcLines, beginEnd);
|
|
bool tempErr = replaceCommonArray(fileFuncs.first, arraySynonyms, lines, SPF_messages);
|
|
error = error || tempErr;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// callRegions = {i1, i2, ...}
|
|
else if (func->callRegions.size() > 1)
|
|
{
|
|
// need copy function for every region, the exeption is defalut region
|
|
for (auto ®ionId : func->callRegions)
|
|
if (regionId)
|
|
copyFunction(getRegionById(regions, regionId), func, funcMap, string("_r") + to_string(regionId));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
|
|
// replace function calls in funcs with callRegions = {i}, i = 1, 2, ...
|
|
for (auto &fileFuncs : allFuncInfo)
|
|
{
|
|
if (SgFile::switchToFile(fileFuncs.first) != -1)
|
|
{
|
|
for (auto &func : fileFuncs.second)
|
|
{
|
|
if (func->callRegions.size() == 1 && *(func->callRegions.begin()))
|
|
{
|
|
int regionId = *(func->callRegions.begin());
|
|
Statement *begin = func->funcPointer;
|
|
Statement *end = new Statement(begin->GetOriginal()->lastNodeOfStmt());
|
|
ParallelRegionLines funcLines(make_pair(begin->GetOriginal()->lineNumber(), end->GetOriginal()->lineNumber()), make_pair(func->funcPointer, end));
|
|
replaceFuncCalls(funcLines, funcMap, regionId);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
|
|
// replace function calls in explicit lines
|
|
for (auto ®ion : regions)
|
|
{
|
|
for (auto &fileLines : region->GetAllLines())
|
|
{
|
|
if (SgFile::switchToFile(fileLines.first) != -1)
|
|
{
|
|
for (auto &lines : fileLines.second)
|
|
{
|
|
if (!lines.isImplicit())
|
|
replaceFuncCalls(lines, funcMap, region->GetId());
|
|
}
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
}
|
|
|
|
if (sharedMemoryParallelization == 0)
|
|
{
|
|
__spf_print(1, "insert DVM intervals\n");
|
|
|
|
// inserting dvm intervals
|
|
for (auto& region : regions)
|
|
{
|
|
for (auto& fileLines : region->GetAllLines())
|
|
{
|
|
if (SgFile::switchToFile(fileLines.first) != -1)
|
|
{
|
|
for (auto& lines : fileLines.second)
|
|
{
|
|
if (!lines.isImplicit())
|
|
{
|
|
// create DVM INTERVAL before region
|
|
SgStatement* start = NULL;
|
|
SgStatement* end = lines.stats.first->GetOriginal()->lexPrev()->lexPrev();
|
|
|
|
for (SgStatement* st = end; st && st->lineNumber() < 0 && isArrayAssign(st); st = st->lexPrev())
|
|
start = st;
|
|
|
|
// DVM END INTERVAL
|
|
SgStatement* interval = new SgStatement(DVM_ENDINTERVAL_DIR);
|
|
interval->setlineNumber(lines.stats.first->GetOriginal()->lineNumber());
|
|
end->insertStmtAfter(*interval, *end->controlParent());
|
|
|
|
// DVM INTERVAL N
|
|
interval = new SgStatement(DVM_INTERVAL_DIR);
|
|
SgExprListExp* newNode = new SgExprListExp();
|
|
int val = getIntervalNumber(current_file_id, lines.stats.first->GetOriginal()->lexPrev()->lineNumber(), region->GetId());
|
|
newNode->setLhs(new SgValueExp(val));
|
|
interval->setExpression(0, *newNode);
|
|
interval->setlineNumber(lines.stats.first->GetOriginal()->lineNumber());
|
|
if (start)
|
|
start->insertStmtBefore(*interval, *start->controlParent());
|
|
else
|
|
end->insertStmtAfter(*interval, *end->controlParent());
|
|
|
|
|
|
// create DVM INTERVAL after region
|
|
start = lines.stats.second->GetOriginal()->lexNext()->lexNext();
|
|
end = NULL;
|
|
|
|
for (SgStatement* st = start; st && !st->lineNumber() && isArrayAssign(st); st = st->lexNext())
|
|
end = st;
|
|
|
|
// DVM INTERVAL N
|
|
interval = new SgStatement(DVM_INTERVAL_DIR);
|
|
newNode = new SgExprListExp();
|
|
val = getIntervalNumber(current_file_id, lines.stats.second->GetOriginal()->lexNext()->lineNumber(), region->GetId());
|
|
newNode->setLhs(new SgValueExp(val));
|
|
interval->setExpression(0, *newNode);
|
|
interval->setlineNumber(lines.stats.second->GetOriginal()->lineNumber());
|
|
start->insertStmtBefore(*interval, *start->controlParent());
|
|
|
|
// DVM END INTERVAL
|
|
interval = new SgStatement(DVM_ENDINTERVAL_DIR);
|
|
interval->setlineNumber(lines.stats.second->GetOriginal()->lineNumber());
|
|
if (end)
|
|
end->insertStmtAfter(*interval, *end->controlParent());
|
|
else
|
|
start->insertStmtBefore(*interval, *start->controlParent());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (error ? 1 : 0);
|
|
}
|
|
|
|
int printCheckRegions(const char *fileName, const vector<ParallelRegion*> ®ions, const map<string, vector<FuncInfo*>> &allFuncInfo)
|
|
{
|
|
map<string, FuncInfo*> funcMap;
|
|
createMapOfFunc(allFuncInfo, funcMap);
|
|
|
|
string outText = "";
|
|
string elems = "";
|
|
|
|
for (auto ®ion : regions)
|
|
{
|
|
outText += "*** REGION '" + region->GetName() + "'\n";
|
|
for (auto &nameFunc : funcMap)
|
|
{
|
|
if (nameFunc.second->callRegions.size() > 1)
|
|
{
|
|
for (auto ®Id : nameFunc.second->callRegions)
|
|
if (region->GetId() == regId)
|
|
elems += " '" + nameFunc.first + '\'';
|
|
}
|
|
}
|
|
|
|
if (elems.size())
|
|
outText += " COMMON FUNCTIONS:" + elems + '\n';
|
|
|
|
set<string> arrays;
|
|
for (auto &funcArrays : region->GetUsedCommonArrays())
|
|
for (auto &arrayLines : funcArrays.second)
|
|
arrays.insert(arrayLines.first->GetShortName());
|
|
|
|
elems.clear();
|
|
for (auto &arrayName : arrays)
|
|
elems += " '" + arrayName + '\'';
|
|
|
|
if (elems.size())
|
|
outText += " COMMON ARRAYS:" + elems + '\n';
|
|
|
|
elems.clear();
|
|
for (auto &funcArrays : region->GetUsedLocalArrays())
|
|
{
|
|
for (auto &arrayLines : funcArrays.second)
|
|
{
|
|
string toPrint = "";
|
|
for (auto &lines : arrayLines.second)
|
|
{
|
|
toPrint += "[" + to_string(lines.lines.first);
|
|
toPrint += "-" + to_string(lines.lines.second);
|
|
toPrint += "]";
|
|
}
|
|
|
|
elems += " [" + funcArrays.first->funcName + ", " + arrayLines.first->GetShortName() + ", " + toPrint + "]\n";
|
|
}
|
|
}
|
|
|
|
if (elems.size())
|
|
outText += " LOCAL ARRAYS in [FUNC, ARRAY, [LINES]]:\n" + elems;
|
|
}
|
|
|
|
outText += "*** SUMMARY\n";
|
|
|
|
elems.clear();
|
|
for (auto &nameFunc : funcMap)
|
|
if (nameFunc.second->callRegions.size() > 1)
|
|
elems += " '" + nameFunc.first + '\'';
|
|
|
|
if (elems.size())
|
|
outText += " ALL COMMON FUNCTIONS : " + elems + '\n';
|
|
|
|
elems.clear();
|
|
for (auto &commonArrayCommonBlock : allUsedCommonArrays)
|
|
elems += " '" + commonArrayCommonBlock.first->GetShortName() + '\'';
|
|
|
|
if (elems.size())
|
|
outText += " ALL COMMON ARRAYS:" + elems + '\n';
|
|
|
|
if (fileName == NULL)
|
|
__spf_print(1, "%s", outText.c_str());
|
|
else
|
|
{
|
|
FILE *file = fopen(fileName, "w");
|
|
if (file == NULL)
|
|
{
|
|
__spf_print(1, "can not open file '%s'\n", fileName);
|
|
return -1;
|
|
}
|
|
fprintf(file, "%s", outText.c_str());
|
|
fclose(file);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void insertRealignsBeforeFragments(ParallelRegion *reg, SgFile *file, const set<DIST::Array*> &distrArrays, const map<DIST::Array*,
|
|
set<DIST::Array*>>& arrayLinksByFuncCalls)
|
|
{
|
|
auto currFile = new File(file);
|
|
|
|
if (distrArrays.size() == 0)
|
|
return;
|
|
if (reg->GetName() == "DEFAULT")
|
|
return;
|
|
|
|
auto lines = reg->GetLines(file->filename());
|
|
if (lines)
|
|
{
|
|
set<DIST::Array*> withoutTempl;
|
|
for (auto& elem : distrArrays)
|
|
if (elem->IsArray())
|
|
withoutTempl.insert(elem);
|
|
|
|
for (auto& elem : *lines)
|
|
{
|
|
if (!elem.isImplicit())
|
|
{
|
|
checkNull(elem.stats.first, convertFileName(__FILE__).c_str(), __LINE__);
|
|
checkNull(elem.stats.second, convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
checkNull(elem.intervalBefore.first, convertFileName(__FILE__).c_str(), __LINE__);
|
|
checkNull(elem.intervalBefore.second, convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
auto toRealign = createRealignRules(elem.intervalBefore.first, reg->GetId(), currFile, "", arrayLinksByFuncCalls, withoutTempl, make_pair(0, 0));
|
|
auto cp = elem.intervalBefore.first->controlParent();
|
|
|
|
if (toRealign.second.size() == 0)
|
|
break;
|
|
|
|
for (auto& rule : toRealign.second)
|
|
{
|
|
elem.intervalBefore.first->insertStmtBefore(*new SgStatement(DVM_NEW_VALUE_DIR), *cp);
|
|
elem.intervalBefore.first->insertStmtBefore(*createStatFromExprs(((CreatedDirective*)rule)->sageData), *cp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
delete currFile;
|
|
} |