#include "leak_detector.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dvm.h" #include "../LoopAnalyzer/loop_analyzer.h" #include "types.h" #include "errors.h" #include "SgUtils.h" #include "../Distribution/Arrays.h" #include "graph_calls.h" #include "graph_calls_func.h" #include "graph_loops_func.h" #include "remote_access.h" using std::vector; using std::pair; using std::tuple; using std::map; using std::set; using std::make_pair; using std::make_tuple; using std::get; using std::string; using std::wstring; void fillRemoteFromDir(SgExpression* ex, vector& remotes) { if (ex) { if (ex->variant() == ARRAY_REF) remotes.push_back(ex); else { fillRemoteFromDir(ex->lhs(), remotes); fillRemoteFromDir(ex->rhs(), remotes); } } } SgExpression* remoteAggregation(SgExpression* remote, const vector* newRemotes) { vector remotes; fillRemoteFromDir(remote, remotes); if (newRemotes) for (auto elem : *newRemotes) fillRemoteFromDir(elem, remotes); if (remotes.size() == 0) return NULL; map> remByName; for (auto& rem : remotes) remByName[rem->symbol()->identifier()].push_back(rem); set existsRemotes; vector list; for (auto& byName : remByName) { SgExpression* fullDot = NULL; for (auto& rem : byName.second) { SgExpression* list = rem->lhs(); int countDim = 0; int countDD = 0; while (list) { countDim++; if (list->lhs()->variant() == DDOT) countDD++; list = list->rhs(); } if (countDim == countDD && countDD != 0) fullDot = rem; if (fullDot) break; } if (fullDot) list.push_back(fullDot); else { //TODO: group by the same parts, eg. A(:,N,:) + A(1,N,:) -> A(:,N,:) for (auto& rem : byName.second) { const string curr = rem->unparse(); auto exist = existsRemotes.find(curr); if (exist == existsRemotes.end()) { existsRemotes.insert(exist, curr); list.push_back(rem); } } } } if (isSgExprListExp(remote)) remote = makeExprList(list); else remote->setLhs(makeExprList(list)); return remote; } static DIST::Array* GetArrayByShortName(const DIST::Arrays &allArrays, SgSymbol *name) { auto uniqKey = getFromUniqTable(name); string nameFromUniq = getShortName(uniqKey); return allArrays.GetArrayByName(nameFromUniq); } static SgExpression* getArrayRefCopyFromAttribute(SgExpression* ex) { SgExpression* copy = ex; if (isArrayRef(ex)) { for (int i = 0; i < ex->numberOfAttributes(); ++i) if (ex->attributeType(i) == ARRAY_REF) copy = (SgExpression*)(ex->getAttribute(i)->getAttributeData()); } return copy; } static bool checkArrayRef(SgExpression* arrayRef, vector>& remotes, const DIST::Arrays& allArrays, const DataDirective& data, const vector& currVar, const uint64_t regionID, const map>& arrayLinksByFuncCalls) { bool retVal = false; DIST::Array* currArray = GetArrayByShortName(allArrays, OriginalSymbol(arrayRef->symbol())); set realRefs; getRealArrayRefs(currArray, currArray, realRefs, arrayLinksByFuncCalls); for (auto array : realRefs) { if (array != NULL) { // find distributed dims DIST::Array* templ = array->GetTemplateArray(regionID); checkNull(templ, convertFileName(__FILE__).c_str(), __LINE__); auto links = array->GetLinksWithTemplate(regionID); bool needToAdd = false; for (int i = 0; i < data.distrRules.size(); ++i) { if (data.distrRules[i].first == templ) { const vector& rule = data.distrRules[i].second[currVar[i]].distRule; for (int k = 0; k < links.size(); ++k) { const int idx = links[k]; if (idx >= 0) { if (rule[idx] == BLOCK) { needToAdd = true; break; } } } break; } } //and add, if found any distributed dim if (needToAdd) { remotes.push_back(make_pair(arrayRef->copyPtr(), getArrayRefCopyFromAttribute(arrayRef))); retVal = true; break; } } } return retVal; } static bool findAllArraysForRemote(SgStatement* st, SgExpression* expr, vector>& remotes, const DIST::Arrays& allArrays, const DataDirective& data, const vector& currVar, const uint64_t regionID, const map>& arrayLinksByFuncCalls) { bool retVal = false; if (expr == NULL) return retVal; bool isProcCall = st->variant() == PROC_STAT && st->expr(0) == expr; if (expr->variant() == FUNC_CALL || isProcCall) { SgExpression* list = isProcCall ? expr : expr->lhs(); while (list) { auto arg = list->lhs(); if (isArrayRef(arg) && isSgArrayRefExp(arg)->numberOfSubscripts() != 0) { bool tmp = checkArrayRef(arg, remotes, allArrays, data, currVar, regionID, arrayLinksByFuncCalls); retVal = retVal || tmp; } if (arg->lhs()) { bool tmp = findAllArraysForRemote(st, arg->lhs(), remotes, allArrays, data, currVar, regionID, arrayLinksByFuncCalls); retVal = retVal || tmp; } if (arg->rhs()) { bool tmp = findAllArraysForRemote(st, arg->rhs(), remotes, allArrays, data, currVar, regionID, arrayLinksByFuncCalls); retVal = retVal || tmp; } list = list->rhs(); } return retVal; } else if (isArrayRef(expr)) { bool tmp = checkArrayRef(expr, remotes, allArrays, data, currVar, regionID, arrayLinksByFuncCalls); retVal = retVal || tmp; } if (expr->lhs()) { bool tmp = findAllArraysForRemote(st, expr->lhs(), remotes, allArrays, data, currVar, regionID, arrayLinksByFuncCalls); retVal = retVal || tmp; } if (expr->rhs()) { bool tmp = findAllArraysForRemote(st, expr->rhs(), remotes, allArrays, data, currVar, regionID, arrayLinksByFuncCalls); retVal = retVal || tmp; } return retVal; } static bool checkExpr(SgExpression *ex, const set& noSimpleVars, const set& writeVars) { bool retVal = true; if (ex == NULL) return true; const int var = ex->variant(); if (noSimpleVars.find(var) != noSimpleVars.end()) { if (var == VAR_REF) { if (writeVars.find(OriginalSymbol(ex->symbol())->identifier()) != writeVars.end()) return false; else return true; } return false; } if (ex->lhs()) retVal = retVal && checkExpr(ex->lhs(), noSimpleVars, writeVars); if (ex->rhs()) retVal = retVal && checkExpr(ex->rhs(), noSimpleVars, writeVars); return retVal; } static void checkFuncCalls(SgExpression* ex, set& writeVars, const map& funcMap, SgStatement* st, vector& retVal) { if (ex) { if (ex->variant() == FUNC_CALL && !isIntrinsicFunctionName(ex->symbol()->identifier())) { auto it = funcMap.find(ex->symbol()->identifier()); if (it == funcMap.end()) { __spf_print(1, "can not find func '%s' in %s:%d\n", ex->symbol()->identifier(), st->fileName(), st->lineNumber()); //printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (int z = 0; z < retVal.size(); ++z) retVal[z] = false; return; } int num = 0; for (auto fPar = ex->lhs(); fPar; fPar = fPar->rhs(), ++num) if (fPar->lhs() && fPar->lhs()->variant() == VAR_REF && it->second->funcParams.isArgOut(num)) writeVars.insert(OriginalSymbol(fPar->lhs()->symbol())->identifier()); } checkFuncCalls(ex->lhs(), writeVars, funcMap, st, retVal); checkFuncCalls(ex->rhs(), writeVars, funcMap, st, retVal); } } //TODO: check VAR_REF declaration in common block / module vector isSimpleRef(SgStatement* stS, SgStatement* stE, SgExpression *subs, const set noSimpleVars, const map& funcMap, const set& usedVars) { vector retVal; SgExpression* tmp = subs; while (tmp) { retVal.push_back(true); tmp = tmp->rhs(); } set writeVars = usedVars; if (noSimpleVars.find(VAR_REF) != noSimpleVars.end() && stS && stE) { if (stE == stS) stE = stE->lexNext(); for (auto st = stS; st != stE; st = st->lexNext()) { if (st->variant() == ASSIGN_STAT) if (st->expr(0)->variant() == VAR_REF) writeVars.insert(OriginalSymbol(st->expr(0)->symbol())->identifier()); if (st->variant() == PROC_STAT && !isIntrinsicFunctionName(st->symbol()->identifier())) { auto it = funcMap.find(st->symbol()->identifier()); if (it == funcMap.end()) { __spf_print(1, "can not find proc '%s' in %s:%d\n", st->symbol()->identifier(), st->fileName(), st->lineNumber()); //printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (int z = 0; z < retVal.size(); ++z) retVal[z] = false; break; } int num = 0; for (auto ex = st->expr(0); ex; ex = ex->rhs(), ++num) if (ex->lhs() && ex->lhs()->variant() == VAR_REF && it->second->funcParams.isArgOut(num)) writeVars.insert(OriginalSymbol(ex->lhs()->symbol())->identifier()); } if (st->variant() == FOR_NODE) writeVars.insert(OriginalSymbol(isSgForStmt(st)->doName())->identifier()); for (int z = 0; z < 3; ++z) checkFuncCalls(st->expr(z), writeVars, funcMap, st, retVal); } } int z = 0; tmp = subs; while (tmp) { if (retVal[z]) retVal[z] = checkExpr(tmp->lhs(), noSimpleVars, writeVars); ++z; tmp = tmp->rhs(); } return retVal; } static bool inline hasDirs(SgStatement *st, const int var) { SgStatement *last = st->lastNodeOfStmt(); for ( ;st != last; st = st->lexNext()) if (st->variant() == var) return true; return false; } static bool isDistributed(SgSymbol *in) { SgSymbol *s = OriginalSymbol(in); DIST::Array *decl = getArrayFromDeclarated(declaratedInStmt(s), s->identifier()); if (!decl) return false; else return !(decl->IsNotDistribute()); } //TODO: need to add IPA (functions) static void fillRead(SgExpression *ex, SgStatement *cp, SgStatement *st, map, set>>> &readArrays) { if (ex) { if (ex->variant() == ARRAY_REF) if (isDistributed(ex->symbol())) { readArrays[ex->symbol()->identifier()][string(ex->unparse())].first.insert(cp); readArrays[ex->symbol()->identifier()][string(ex->unparse())].second.insert(st); } fillRead(ex->lhs(), cp, st, readArrays); fillRead(ex->rhs(), cp, st, readArrays); } } bool isNeedToConvertIfCondition(SgExpression *ex) { map, set>>> readArrays; fillRead(ex, NULL, NULL, readArrays); return (readArrays.size() != 0); } static bool inline hasGoTo(SgStatement* stIn) { SgStatement* last = stIn->lastNodeOfStmt(); for (auto st = stIn; st != last; st = st->lexNext()) { if (isSgGotoStmt(st) || isSgAssignedGotoStmt(st) || isSgComputedGotoStmt(st) || isSgExitStmt(st) || isSgCycleStmt(st)) return true; } return false; } static bool inline hasSpecialIfCond(SgStatement* stIn) { if (stIn->variant() != IF_NODE) return false; auto ex = stIn->expr(0); if (!ex) return false; if (ex->variant() == NOT_OP) { ex = ex->lhs(); if (ex->variant() == VAR_REF && !ex->lhs() && !ex->rhs()) { if (string(ex->symbol()->identifier()).find("spf_If_C") != string::npos) return true; } } return false; } static bool inline hasAssignsToArray(SgStatement *stIn) { // array -> unparse access -> pair [ control par, original stat] map, set>>> arrayAccessWrite; map, set>>> arrayAccessRead; SgStatement *last = stIn->lastNodeOfStmt(); if (stIn->variant() == IF_NODE) { while (last->variant() != CONTROL_END) last = last->lastNodeOfStmt(); } for (auto st = stIn; st != last; st = st->lexNext()) { if (st->variant() == ASSIGN_STAT) { SgExpression *ex = st->expr(0); if (ex->variant() == ARRAY_REF) { SgSymbol *s = ex->symbol(); if (isDistributed(s)) { arrayAccessWrite[s->identifier()][string(ex->unparse())].first.insert(st->controlParent()); arrayAccessWrite[s->identifier()][string(ex->unparse())].second.insert(st); } } } } for (auto st = stIn; st != last; st = st->lexNext()) { SgStatement *cp = st->controlParent(); if (st->variant() != ASSIGN_STAT) { for (int z = 0; z < 3; ++z) fillRead(st->expr(z), cp, st, arrayAccessRead); } else { for (int z = 1; z < 3; ++z) fillRead(st->expr(z), cp, st, arrayAccessRead); SgExpression *left = st->expr(0); fillRead(left->lhs(), cp, st, arrayAccessRead); fillRead(left->rhs(), cp, st, arrayAccessRead); } } for (auto &readPair : arrayAccessRead) { string arrayName = readPair.first; auto it = arrayAccessWrite.find(arrayName); //TODO: if (it != arrayAccessWrite.end()) { return true; /*for (auto &read : readPair.second) { auto mapW = it->second.find(read.first); if (mapW == it->second.end()) return true; else { for (auto &cpW : mapW->second.first) { for (auto &cpR : read.second.first) if (cpW != cpR && cpW->variant() == FOR_NODE) return true; } for (auto &cpW : mapW->second.second) if (read.second.second.find(cpW) == read.second.second.end()) return true; } }*/ } } return false; } static bool converToDDOT(const vector& checkResult, SgExpression *spec) { bool done = false; int currIdx = 0; while (spec) { if (currIdx >= checkResult.size() && checkResult.size() > 0) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (checkResult.size() == 0 || !checkResult[currIdx]) { spec->setLhs(new SgExpression(DDOT)); done = true; } ++currIdx; spec = spec->rhs(); } return done; } static void getAllSymbols(SgExpression *ex, set &symbs) { if (ex) { if (ex->variant() == VAR_REF) symbs.insert(ex->symbol()->identifier()); getAllSymbols(ex->lhs(), symbs); getAllSymbols(ex->rhs(), symbs); } } static bool ifRange(SgExpression* spec) { while (spec) { if (spec->lhs()->variant() == DDOT) { if (!spec->lhs()->lhs() || !spec->lhs()->rhs()) return true; if (string(spec->lhs()->lhs()->unparse()) != string(spec->lhs()->rhs()->unparse())) return true; } spec = spec->rhs(); } return false; } static bool isAlloc(SgStatement* st) { return st->variant() == ALLOCATE_STMT || st->variant() == DEALLOCATE_STMT; } static int numOfOperators(SgIfStmt* st) { int num = 0; if (st && st->falseBody() == NULL) { for (auto it = st->lexNext(); it != st->lastNodeOfStmt(); it = it->lexNext()) num++; return num; } return num; } template bool createRemoteDir(SgStatement *st, const map& funcMap, const map &sortedLoopGraph, const DIST::Arrays &allArrays, const DataDirective &data, const vector &currVar, const uint64_t regionId, vector &currMessages, const map> &arrayLinksByFuncCalls) { //for parallel loops after vector assign convertion if (st->lexPrev()->variant() == DVM_PARALLEL_ON_DIR) return false; if (isAlloc(st)) return false; if (st->variant() == LOGIF_NODE) if (((SgLogIfStmt*)st)->body()) if (isAlloc(((SgLogIfStmt*)st)->body())) return false; vector> remotes; // string leftPartOfAssign = ""; if (st->variant() == ASSIGN_STAT) leftPartOfAssign = getArrayRefCopyFromAttribute(st->expr(0))->unparse(); if (findAllArraysForRemote(st, st->expr(NUM), remotes, allArrays, data, currVar, regionId, arrayLinksByFuncCalls)) { SgStatement *remoteDir = new SgStatement(DVM_REMOTE_ACCESS_DIR); SgExpression *exprList = new SgExpression(EXPR_LIST); remoteDir->setExpression(0, *exprList); //exclude left part of assign: A(i,j,k) = A(i,j,k) + 5 if (leftPartOfAssign != "") { int z = 0; while (z != remotes.size()) { if (leftPartOfAssign == string(remotes[z].second->unparse())) remotes.erase(remotes.begin() + z); else z++; } } vector allSubs; for (auto &rem : remotes) allSubs.push_back(rem.first->lhs()); if (remotes.size() > 0) { //TODO: use CFG and RD analysis set usedSymbols; for (auto &access : remotes) getAllSymbols(access.first, usedSymbols); SgStatement *toInsert = st; vector allToInsert = { toInsert }; int lvlUp = 0; bool througthForNode = false; //find the uppest control parent do { SgStatement *parent = toInsert->controlParent(); const int var = parent->variant(); if (var == FUNC_HEDR || var == PROC_HEDR || var == PROG_HEDR || hasDirs(parent, DVM_PARALLEL_ON_DIR) || hasDirs(parent, DVM_REMOTE_ACCESS_DIR) || hasAssignsToArray(parent) || hasSpecialIfCond(parent) || hasGoTo(parent)) { break; } toInsert = parent; allToInsert.push_back(toInsert); if (toInsert->variant() == FOR_NODE) througthForNode = true; ++lvlUp; } while (1); for (int idx = allToInsert.size() - 1; idx >= 0; --idx) { const int var = allToInsert[idx]->variant(); if (var == ELSEIF_NODE) { if (idx != 0) toInsert = allToInsert[idx - 1]; else break; } else break; --lvlUp; } if (toInsert->variant() == FOR_NODE || toInsert->variant() == WHILE_NODE) { for (auto &elem : allSubs) { const vector checkRes = isSimpleRef(toInsert, toInsert->lastNodeOfStmt(), elem, { ARRAY_OP, ARRAY_REF, VAR_REF }, funcMap, set()); converToDDOT(checkRes, elem); } } else { const int cpV = toInsert->controlParent()->variant(); const int varI = toInsert->variant(); for (auto& elem : allSubs) { set varsToCheck = { ARRAY_OP, ARRAY_REF }; if (througthForNode) varsToCheck.insert(VAR_REF); const vector checkRes = isSimpleRef(toInsert, toInsert->lastNodeOfStmt(), elem, varsToCheck, funcMap, set()); bool isSimple = true; for (auto res : checkRes) isSimple &= res; if (ifRange(elem) || !isSimple) converToDDOT(checkRes, elem); } } //create remote dir with uniq expressions set exist; int add = 0; for (int z = 0; z < remotes.size(); ++z, ++add) { string currRem = remotes[z].first->unparse(); auto itR = exist.find(currRem); if (itR == exist.end()) { if (add != 0) { exprList->setRhs(new SgExpression(EXPR_LIST)); exprList = exprList->rhs(); } exprList->setLhs(remotes[z].first); exist.insert(itR, currRem); } } exist.clear(); SgStatement *prev = toInsert->lexPrev(); if (prev) { if (prev->variant() != DVM_REMOTE_ACCESS_DIR) { remoteDir->setExpression(0, remoteAggregation(remoteDir->expr(0), NULL)); toInsert->insertStmtBefore(*remoteDir, *toInsert->controlParent()); } else // aggregate this { vector tmpR; for (auto& rem : remotes) tmpR.push_back(rem.first); prev->setExpression(0, remoteAggregation(prev->expr(0), &tmpR)); } } else { remoteDir->setExpression(0, remoteAggregation(remoteDir->expr(0), NULL)); toInsert->insertStmtBefore(*remoteDir, *toInsert->controlParent()); } } return true; } return false; } template bool createRemoteDir<0>(SgStatement*, const map&, const map&, const DIST::Arrays&, const DataDirective&, const vector&, const uint64_t, vector&, const map>&); template bool createRemoteDir<1>(SgStatement*, const map&, const map&, const DIST::Arrays&, const DataDirective&, const vector&, const uint64_t, vector&, const map>&); void addRemoteLink(const LoopGraph* loop, const map& funcMap, ArrayRefExp *expr, map &uniqRemotes, const set& remotesInParallel, set &addedRemotes, const vector& mapToLoop, vector &messages, const int line, bool bindToLoopDistribution) { SgArrayRefExp* copyExpr = NULL; bool isConv = false; if (bindToLoopDistribution) { const LoopGraph* withDir = loop; while (withDir && withDir->loop->GetOriginal()->lexPrev()->variant() != DVM_PARALLEL_ON_DIR) withDir = withDir->parent; checkNull(withDir, convertFileName(__FILE__).c_str(), __LINE__); set loopVars; for (auto& elem : withDir->directive->parallel) if (elem != "*") loopVars.insert(elem); copyExpr = (SgArrayRefExp*)(expr->copyPtr()); SgExpression* subs = copyExpr->subscripts(); set tmp; checkNull(loop->loop, convertFileName(__FILE__).c_str(), __LINE__); //get uppest nested loop const LoopGraph* UppestNested = loop; while (UppestNested->parent && UppestNested->parent->children.size() == 1 && UppestNested->loop->GetOriginal()->lexPrev()->variant() != DVM_PARALLEL_ON_DIR) UppestNested = UppestNested->parent; vector isSimple = isSimpleRef(UppestNested->loop->GetOriginal(), UppestNested->loop->GetOriginal()->lastNodeOfStmt(), subs, {ARRAY_OP, ARRAY_REF, VAR_REF}, funcMap, loopVars); SgExpression* ex = subs; for (int z = 0; z < isSimple.size(); ++z, ex = ex->rhs()) { if (!isSimple[z] && mapToLoop.size() && mapToLoop[z] != "") { // check for A*x + B SgExpression* list = ex->lhs(); if (!list->lhs() && !list->rhs()) // I { if (list->variant() == VAR_REF && list->symbol() && list->symbol()->identifier() == mapToLoop[z]) isSimple[z] = true; } else if (list->variant() == ADD_OP) // I + B or B + I { if (list->lhs() && list->rhs()) { SgExpression* left = list->lhs(); SgExpression* right = list->rhs(); if (right->variant() == VAR_REF && left->variant() != VAR_REF) std::swap(left, right); if (left->variant() == VAR_REF && right->variant() != VAR_REF) { if (left->variant() == VAR_REF && left->symbol() && left->symbol()->identifier() == mapToLoop[z]) { int const rVar = right->variant(); if (rVar == CONST_REF || isSgValueExp(right)) isSimple[z] = true; } } } } } } isConv = converToDDOT(isSimple, subs); } else { set loopVars; copyExpr = (SgArrayRefExp*)(expr->copyPtr()); SgExpression* subs = copyExpr->subscripts(); vector isSimple = isSimpleRef(loop->loop->GetOriginal(), loop->loop->GetOriginal()->lastNodeOfStmt(), subs, { ARRAY_OP, ARRAY_REF, VAR_REF }, funcMap, loopVars); isConv = converToDDOT(isSimple, subs); } string remoteExp(copyExpr->unparse()); auto rem = uniqRemotes.find(remoteExp); if (rem == uniqRemotes.end() && remotesInParallel.find(remoteExp) == remotesInParallel.end()) { rem = uniqRemotes.insert(rem, make_pair(remoteExp, new ArrayRefExp(copyExpr))); addedRemotes.insert(new ArrayRefExp(copyExpr)); if (line > 0 && !isConv) { string remoteExp(expr->unparse()); __spf_print(1, "WARN: added remote access for array ref '%s' on line %d can significantly reduce performance\n", remoteExp.c_str(), line); wstring bufE, bufR; __spf_printToLongBuf(bufE, L"Added remote access for array ref '%s' can significantly reduce performance", to_wstring(remoteExp).c_str()); __spf_printToLongBuf(bufR, R129, to_wstring(remoteExp).c_str()); messages.push_back(Messages(WARR, line, bufR, bufE, 3009)); } } } ArrayRefExp* createRemoteLink(const LoopGraph* currLoop, const DIST::Array* forArray) { SgFile* file = current_file; const set allFiles = getAllFilesInProject(); SgStatement* realStat = (SgStatement*)currLoop->getRealStat(file->filename()); SgExpression* ex = new SgExpression(EXPR_LIST); SgExpression* p = ex; for (int z = 0; z < forArray->GetDimSize(); ++z) { p->setLhs(new SgExpression(DDOT)); if (z != forArray->GetDimSize() - 1) { p->setRhs(new SgExpression(EXPR_LIST)); p = p->rhs(); } } SgArrayRefExp* newRem = new SgArrayRefExp(*((SgSymbol*)forArray->GetNameInLocationS(realStat)), *ex); return new ArrayRefExp(newRem); } void addRemotesToDir(const pair *under_dvm_dir, const map &uniqRemotes) { SgStatement *dir = under_dvm_dir->first->lexPrev(); if (!dir) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (dir->variant() != DVM_PARALLEL_ON_DIR) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); SgExpression* list = NULL; for (auto& rem : uniqRemotes) { list = dir->expr(1); SgExpression *remoteList = NULL; while (list) { if (list->lhs()) { if (list->lhs()->variant() == REMOTE_ACCESS_OP) { remoteList = list->lhs(); break; } } list = list->rhs(); } list = dir->expr(1); SgExpression *toAdd = new SgExpression(EXPR_LIST, rem.second, NULL, NULL); if (!remoteList) { remoteList = new SgExpression(REMOTE_ACCESS_OP, toAdd, NULL, NULL); dir->setExpression(1, *new SgExpression(EXPR_LIST, remoteList, list, NULL)); } else { SgExpression *lastLhs = remoteList->lhs(); remoteList->setLhs(toAdd); toAdd->setRhs(lastLhs); } } list = dir->expr(1); while (list) { if (list->lhs()) { if (list->lhs()->variant() == REMOTE_ACCESS_OP) { remoteAggregation(list->lhs(), NULL); break; } } list = list->rhs(); } } static set addedDummyIf; void groupActualAndRemote(SgFile *file, bool revert) { if (revert) { for (auto& dummyIf : addedDummyIf) { SgStatement* end = dummyIf->lastNodeOfStmt(); SgStatement* st = dummyIf->lexNext(); while (st != end) { SgStatement* toMove = st; st = st->lexNext(); toMove = toMove->extractStmt(); dummyIf->insertStmtBefore(*toMove, *dummyIf->controlParent()); } dummyIf->extractStmt(); } addedDummyIf.clear(); } else { SgStatement* st = file->firstStatement(); while (st) { if (st->variant() == DVM_REMOTE_ACCESS_DIR) { auto next = st->lexNext(); auto nnext = next->lexNext(); if (next->expr(0) && next->expr(0)->variant() == ARRAY_REF && next->expr(0)->lhs()->lhs()->variant() == ARRAY_REF) { const string ref = next->expr(0)->unparse(); if (nnext && nnext->variant() == ACC_ACTUAL_DIR) { bool ifFullActual = false; SgExpression* ex = nnext->expr(0); while (ex) { if (ex->lhs() && ex->lhs()->unparse() == ref) { ifFullActual = true; break; } ex = ex->rhs(); } bool ifRemote = false; ex = st->expr(0); while (ex) { if (ex->lhs() && ref.find(ex->lhs()->unparse()) != string::npos) { ifRemote = true; break; } ex = ex->rhs(); } if (ifRemote && ifFullActual) { SgStatement* op = next->extractStmt(); SgStatement* act = nnext->extractStmt(); SgIfStmt* dummyIf = new SgIfStmt(*new SgValueExp(true), *act); st->insertStmtAfter(*dummyIf, *st->controlParent()); dummyIf->insertStmtAfter(*op, *dummyIf); addedDummyIf.insert(dummyIf); st = dummyIf->lastNodeOfStmt(); } } } } st = st->lexNext(); } } }