Files
SAPFOR/src/ParallelizationRegions/resolve_par_reg_conflicts.cpp

2117 lines
92 KiB
C++
Raw Normal View History

#include "leak_detector.h"
2023-09-14 19:43:13 +03:00
#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"
2025-06-04 13:08:38 +03:00
#include "graph_calls_func.h"
#include "graph_loops_func.h"
2023-09-14 19:43:13 +03:00
#include "../LoopAnalyzer/loop_analyzer.h"
#include "../DirectiveProcessing/directive_creator.h"
#include "../DirectiveProcessing/insert_directive.h"
2025-06-04 13:08:38 +03:00
#include "SgUtils.h"
#include "expr_transform.h"
2025-07-05 20:49:23 +03:00
#include "FunctionPurifying/function_purifying.h"
2023-09-14 19:43:13 +03:00
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();
2024-04-09 11:51:21 +03:00
auto res = CalculateInteger(stat->expr(0)->copyPtr());
2023-09-14 19:43:13 +03:00
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*> &regions,
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 &region : regions)
{
for (auto &fileLines : region->GetAllLines())
{
// switch to current file
if (SgFile::switchToFile(fileLines.first) != -1)
{
for (auto &regionLines : 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*> &regions, 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)
2023-09-14 19:43:13 +03:00
{
auto& callFrom = callInfo.detailCallsFrom;
auto line = callFrom.second;
auto call = callFrom.first;
2023-09-14 19:43:13 +03:00
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*> &regions)
{
if (regions.size() == 1 && regions[0]->GetName() == "DEFAULT") // only default
return;
for (auto &region : 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*> &regions,
const map<string, vector<FuncInfo*>> &allFuncInfo,
map<string, vector<Messages>> &SPF_messages)
{
bool noError = true;
// check if region includes itself
for (auto &region : 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 &region : 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 &region : 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 &regionLines, 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)
2023-09-14 19:43:13 +03:00
{
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*> &regions,
const map<string, vector<FuncInfo*>> &allFuncInfo,
const map<string, CommonBlock*> &commonBlocks,
map<string, vector<Messages>> &SPF_messages, bool sharedMemoryParallelization)
2023-09-14 19:43:13 +03:00
{
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 &regId : 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 &regId : 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)
2023-09-14 19:43:13 +03:00
return error;
// check local arrays
for (auto &reg : 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 &regLines : 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 &reg : 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 &reg : 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 &reg : 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*> &regions, const map<string, vector<FuncInfo*>> &allFuncInfo,
map<string, vector<Messages>> &SPF_messages, bool sharedMemoryParallelization,
2023-09-14 19:43:13 +03:00
map<string, map<int, set<string>>> &newDeclsToInclude)
{
bool error = false;
map<string, FuncInfo*> funcMap;
createMapOfFunc(allFuncInfo, funcMap);
if (sharedMemoryParallelization == 0)
2023-09-14 19:43:13 +03:00
{
map<string, map<int, set<string>>> copied;
for (auto& region : regions)
{
2023-11-28 12:58:22 +03:00
__spf_print(1, "[%s]: create local arrays\n", region->GetName().c_str());
2023-09-14 19:43:13 +03:00
// 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());
}
}
}
2023-11-28 12:58:22 +03:00
__spf_print(1, "[%s]: create common arrays\n", region->GetName().c_str());
2023-09-14 19:43:13 +03:00
// 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;
}
}
}
2023-11-28 12:58:22 +03:00
__spf_print(1, "create functions\n");
2023-09-14 19:43:13 +03:00
// 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 &regionId : 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 &region : 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)
2023-09-14 19:43:13 +03:00
{
2023-11-28 12:58:22 +03:00
__spf_print(1, "insert DVM intervals\n");
2023-09-14 19:43:13 +03:00
// 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*> &regions, const map<string, vector<FuncInfo*>> &allFuncInfo)
{
map<string, FuncInfo*> funcMap;
createMapOfFunc(allFuncInfo, funcMap);
string outText = "";
string elems = "";
for (auto &region : regions)
{
outText += "*** REGION '" + region->GetName() + "'\n";
for (auto &nameFunc : funcMap)
{
if (nameFunc.second->callRegions.size() > 1)
{
for (auto &regId : 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;
}