improved ROUTINE insertion
This commit is contained in:
@@ -104,7 +104,7 @@ void DvmhRegionInserter::parFuncsInNode(LoopGraph *loop, bool isParallel)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
else
|
||||
parallel_functions.insert(it->second);
|
||||
parallel_functions[it->second].insert(loop);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -133,23 +133,36 @@ void DvmhRegionInserter::updateParallelFunctions(const map<string, vector<LoopGr
|
||||
while (changes_done)
|
||||
{
|
||||
changes_done = false;
|
||||
set<FuncInfo*> newList;
|
||||
map<FuncInfo*, set<LoopGraph*>> newList;
|
||||
for (auto& funcPair : allFunctions)
|
||||
{
|
||||
FuncInfo* func = funcPair.second;
|
||||
for (auto& callsTo : func->callsTo)
|
||||
{
|
||||
if (parallel_functions.find(callsTo) != parallel_functions.end() &&
|
||||
parallel_functions.find(func) == parallel_functions.end())
|
||||
auto itF = parallel_functions.find(func);
|
||||
|
||||
set<LoopGraph*> added;
|
||||
if (itF != parallel_functions.end())
|
||||
added = itF->second;
|
||||
|
||||
auto itTo = parallel_functions.find(callsTo);
|
||||
if (itTo != parallel_functions.end())
|
||||
{
|
||||
newList.insert(func);
|
||||
changes_done = true;
|
||||
for (auto& loop : itTo->second)
|
||||
{
|
||||
if (added.find(loop) == added.end())
|
||||
{
|
||||
changes_done = true;
|
||||
newList[func].insert(loop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& newElem : newList)
|
||||
parallel_functions.insert(newElem);
|
||||
for (auto& loop : newElem.second)
|
||||
parallel_functions[newElem.first].insert(loop);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1040,7 +1053,156 @@ static void insertInterface(SgStatement* func, const string& iface, const string
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
static void insertRoutine(SgStatement* func)
|
||||
static LoopGraph* getParallelLoop(LoopGraph* loop)
|
||||
{
|
||||
auto prev_st = loop->loop->lexPrev();
|
||||
|
||||
while (prev_st && isDVM_stat(prev_st))
|
||||
{
|
||||
if (prev_st->variant() == DVM_PARALLEL_ON_DIR)
|
||||
return loop;
|
||||
prev_st = prev_st->lexPrev();
|
||||
loop = loop->parent;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static set<LoopGraph*> getParallelLoops(const std::set<LoopGraph*>& loops)
|
||||
{
|
||||
set<LoopGraph*> retVal;
|
||||
for (auto& elem : loops)
|
||||
{
|
||||
string oldFile = current_file->filename();
|
||||
if (!elem->loop->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
auto parLoop = getParallelLoop(elem);
|
||||
checkNull(parLoop, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
retVal.insert(parLoop);
|
||||
|
||||
if (SgFile::switchToFile(oldFile) == -1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static set<DIST::Array*> getPrivateArrays(const set<LoopGraph*>& parLoops,
|
||||
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls)
|
||||
{
|
||||
set<DIST::Array*> retVal;
|
||||
|
||||
for (auto& loop : parLoops)
|
||||
{
|
||||
string oldFile = current_file->filename();
|
||||
if (!loop->loop->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
for (auto& priv : loop->directive->privates)
|
||||
{
|
||||
bool isArray = false;
|
||||
if (isArrayType(priv->type()))
|
||||
{
|
||||
auto type = isSgArrayType(priv->type());
|
||||
if (type && type->dimension())
|
||||
isArray = true;
|
||||
}
|
||||
|
||||
if (!isArray)
|
||||
continue;
|
||||
|
||||
DIST::Array* arr = getArrayFromDeclarated(declaratedInStmt(priv), priv->identifier());
|
||||
checkNull(arr, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
set<DIST::Array*> realArrayRefs;
|
||||
getRealArrayRefs(arr, arr, realArrayRefs, arrayLinksByFuncCalls);
|
||||
|
||||
for (auto& elem : realArrayRefs)
|
||||
retVal.insert(elem);
|
||||
}
|
||||
|
||||
if (SgFile::switchToFile(oldFile) == -1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static SgExpression* getPrivateArraysInPar(const FuncInfo* funcInfo, const std::set<LoopGraph*>& inLoops,
|
||||
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls,
|
||||
SgExpression* addedPrivList)
|
||||
{
|
||||
if (!funcInfo)
|
||||
return NULL;
|
||||
|
||||
map<string, SgExpression*> addedPriv;
|
||||
SgExpression* ex = addedPrivList;
|
||||
while (ex)
|
||||
{
|
||||
if (ex->lhs() && ex->lhs()->variant() == ACC_PRIVATE_OP)
|
||||
{
|
||||
ex = ex->lhs()->lhs();
|
||||
while (ex)
|
||||
{
|
||||
if (ex->lhs() && ex->lhs()->variant() == VAR_REF)
|
||||
addedPriv[ex->lhs()->symbol()->identifier()] = ex->lhs();
|
||||
ex = ex->rhs();
|
||||
}
|
||||
break;
|
||||
}
|
||||
ex = ex->rhs();
|
||||
}
|
||||
|
||||
SgStatement* func = funcInfo->funcPointer->GetOriginal();
|
||||
auto prog = isSgProgHedrStmt(func);
|
||||
checkNull(prog, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
set<LoopGraph*> inParLoops = getParallelLoops(inLoops);
|
||||
set<DIST::Array*> privArrays = getPrivateArrays(inLoops, arrayLinksByFuncCalls);
|
||||
|
||||
for (int z = 0; z < prog->numberOfParameters(); ++z)
|
||||
{
|
||||
SgSymbol* par = prog->parameter(z);
|
||||
bool isArray = false;
|
||||
if (isArrayType(par->type()))
|
||||
{
|
||||
auto type = isSgArrayType(par->type());
|
||||
if (type && type->dimension())
|
||||
isArray = true;
|
||||
}
|
||||
|
||||
if (isArray && addedPriv.count(par->identifier()) == 0)
|
||||
{
|
||||
DIST::Array* arr = getArrayFromDeclarated(declaratedInStmt(par), par->identifier());
|
||||
checkNull(arr, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
set<DIST::Array*> realArrayRefs;
|
||||
getRealArrayRefs(arr, arr, realArrayRefs, arrayLinksByFuncCalls);
|
||||
|
||||
bool found = false;
|
||||
for (auto& elem : realArrayRefs)
|
||||
if (privArrays.find(elem) != privArrays.end())
|
||||
found = true;
|
||||
|
||||
if (found)
|
||||
addedPriv[par->identifier()] = new SgVarRefExp(par);
|
||||
}
|
||||
}
|
||||
|
||||
if (addedPriv.size())
|
||||
{
|
||||
vector<SgExpression*> list;
|
||||
for (auto& elem : addedPriv)
|
||||
list.push_back(elem.second);
|
||||
|
||||
return makeExprList(list, false);
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void insertRoutine(SgStatement* func, const FuncInfo* funcInfo, const std::set<LoopGraph*>& inLoops,
|
||||
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls)
|
||||
{
|
||||
string oldFile = current_file->filename();
|
||||
if (!func->switchToFile())
|
||||
@@ -1048,26 +1210,34 @@ static void insertRoutine(SgStatement* func)
|
||||
|
||||
SgStatement* st = func->lexNext();
|
||||
SgStatement* last = func->lastNodeOfStmt();
|
||||
bool has = false;
|
||||
|
||||
SgStatement* routine = NULL;
|
||||
while (st != last)
|
||||
{
|
||||
if (st->variant() == ACC_ROUTINE_DIR)
|
||||
{
|
||||
has = true;
|
||||
routine = st;
|
||||
break;
|
||||
}
|
||||
st = st->lexNext();
|
||||
}
|
||||
|
||||
if (has == false)
|
||||
|
||||
if (!routine)
|
||||
{
|
||||
st = func->lexNext();
|
||||
st->insertStmtBefore(*new SgStatement(ACC_ROUTINE_DIR), *st->controlParent());
|
||||
routine = new SgStatement(ACC_ROUTINE_DIR);
|
||||
st->insertStmtBefore(*routine, *st->controlParent());
|
||||
}
|
||||
|
||||
SgExpression* list = getPrivateArraysInPar(funcInfo, inLoops, arrayLinksByFuncCalls, routine->expr(0));
|
||||
if (list)
|
||||
{
|
||||
list = new SgExpression(EXPR_LIST, new SgExpression(ACC_PRIVATE_OP, list));
|
||||
routine->setExpression(0, list);
|
||||
}
|
||||
|
||||
if (SgFile::switchToFile(oldFile) == -1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
}
|
||||
|
||||
static bool isPure(SgStatement* func)
|
||||
@@ -1089,15 +1259,23 @@ void DvmhRegionInserter::createInterfaceBlockForOutCall(FuncInfo* func, FuncInfo
|
||||
insertInterface(func->funcPointer, getInterfaceBlock(callFrom->funcPointer->GetOriginal(), callFrom->funcParams), callFrom->funcName);
|
||||
}
|
||||
|
||||
void DvmhRegionInserter::createInterfaceBlockForParallelFunctions()
|
||||
void DvmhRegionInserter::createInterfaceBlockForParallelFunctions(bool onlyRoutine)
|
||||
{
|
||||
for (auto& parF : parallel_functions)
|
||||
{
|
||||
for (auto& func_pair : parallel_functions)
|
||||
{
|
||||
const auto& parF = func_pair.first;
|
||||
const auto& inLoops = func_pair.second;
|
||||
|
||||
for (auto& callTo : parF->callsTo)
|
||||
{
|
||||
if (callTo->fileName != parF->fileName && isPure(parF->funcPointer->GetOriginal()))
|
||||
{
|
||||
insertRoutine(parF->funcPointer->GetOriginal());
|
||||
if (onlyRoutine)
|
||||
{
|
||||
insertRoutine(parF->funcPointer->GetOriginal(), parF, inLoops, arrayLinksByFuncCalls);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto it = callTo->interfaceBlocks.find(parF->funcName);
|
||||
if (it == callTo->interfaceBlocks.end())
|
||||
{
|
||||
@@ -1124,7 +1302,7 @@ void DvmhRegionInserter::createInterfaceBlockForParallelFunctions()
|
||||
st->symbol()->identifier() == parF->funcName)
|
||||
{
|
||||
iface = st;
|
||||
insertRoutine(iface);
|
||||
insertRoutine(iface, parF, inLoops, arrayLinksByFuncCalls);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1362,15 +1540,16 @@ void insertDvmhRegions(SgProject& project, int files, const vector<ParallelRegio
|
||||
for (int i = files - 1, k = 0; i >= 0; --i, ++k)
|
||||
{
|
||||
SgFile* file = &(project.file(i));
|
||||
|
||||
DvmhRegionInserter* regionInserter = inserters[k];
|
||||
|
||||
for (auto& func : regionInserter->getParallelFunctions())
|
||||
createInterfacesForOutCalls(func);
|
||||
|
||||
// create interface for 'parallel' functions and
|
||||
// insert ROUTINE directive if needed
|
||||
regionInserter->createInterfaceBlockForParallelFunctions();
|
||||
inserters[k]->createInterfaceBlockForParallelFunctions();
|
||||
}
|
||||
|
||||
for (int i = files - 1, k = 0; i >= 0; --i, ++k)
|
||||
{
|
||||
SgFile* file = &(project.file(i));
|
||||
|
||||
// create interface for 'parallel' functions
|
||||
inserters[k]->createInterfaceBlockForParallelFunctions(false);
|
||||
}
|
||||
|
||||
for (auto& regionInserter : inserters)
|
||||
|
||||
@@ -30,7 +30,7 @@ class DvmhRegionInserter
|
||||
bool isMpiProgram;
|
||||
|
||||
ReadWriteAnalyzer& rw_analyzer;
|
||||
std::set<FuncInfo*> parallel_functions;
|
||||
std::map<FuncInfo*, std::set<LoopGraph*>> parallel_functions;
|
||||
std::set<DIST::Array*> writesToArraysInParallelLoops;
|
||||
std::set<DIST::Array*> usedArraysInParallelLoops;
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls;
|
||||
@@ -76,7 +76,7 @@ public:
|
||||
void insertActualDirectives(const std::vector<ParallelRegion*>* regs);
|
||||
|
||||
void updateParallelFunctions(const std::map<std::string, std::vector<LoopGraph*>>& loopGraphs);
|
||||
void createInterfaceBlockForParallelFunctions();
|
||||
void createInterfaceBlockForParallelFunctions(bool onlyRoutine = true);
|
||||
void removePrivatesFromParallelLoops();
|
||||
void addPrivatesToParallelLoops();
|
||||
void addUsedArrays(std::set<DIST::Array*>& arrays);
|
||||
@@ -95,7 +95,12 @@ public:
|
||||
usedArraysInParallelLoops = newSet;
|
||||
}
|
||||
|
||||
const std::set<FuncInfo*>& getParallelFunctions() const { return parallel_functions; }
|
||||
const std::set<FuncInfo*> getParallelFunctions() const {
|
||||
std::set<FuncInfo*> retVal;
|
||||
for (auto& elem : parallel_functions)
|
||||
retVal.insert(elem.first);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static void createInterfaceBlockForOutCall(FuncInfo* func, FuncInfo* callFrom);
|
||||
static void createInterfaceBlockForOutCalls(FuncInfo* func);
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#define VERSION_SPF "2375"
|
||||
#define VERSION_SPF "2379"
|
||||
|
||||
Reference in New Issue
Block a user