#include "../Utils/leak_detector.h" #include #include #include #include #include #include #include #include #include #include #include "directive_parser.h" #include "../Utils/SgUtils.h" #include "../LoopAnalyzer/loop_analyzer.h" #include "../Utils/AstWrapper.h" #include "../Utils/errors.h" using std::string; using std::vector; using std::set; using std::tuple; using std::map; using std::make_pair; using std::pair; bool isSPF_NoInline(Statement *stIn) { if (stIn) { SgStatement *st = stIn->GetOriginal(); for (auto &data : getAttributes(st, set{ SPF_TRANSFORM_DIR })) { SgExpression *exprList = data->expr(0); while (exprList) { if (exprList->lhs()->variant() == SPF_NOINLINE_OP) { //__spf_print(1, "found no inline\n"); return true; } exprList = exprList->rhs(); } } } return false; } static map dictCreated; static inline string getSymbol(const string& s) { return s; } static inline string getSymbol(SgSymbol* s) { return s->identifier(); } static inline string getData(SgExpression *symb, string*, bool moduleNameAdd = false) { SgSymbol* base = symb->symbol(); SgSymbol* symbOr = OriginalSymbol(symb->symbol()); if (symbOr == base) return symbOr->identifier(); else { SgStatement* scope = symbOr->scope(); checkNull(scope, convertFileName(__FILE__).c_str(), __LINE__); if (scope->variant() != MODULE_STMT) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return string(scope->symbol()->identifier()) + "::" + symbOr->identifier(); } } static inline Expression* getData(SgExpression *symb, Expression**, bool moduleNameAdd = false) { return new Expression(symb); } static inline Symbol* getData(SgExpression *symb, Symbol**, bool moduleNameAdd = false) { SgSymbol *symbOr = OriginalSymbol(symb->symbol()); auto it = dictCreated.find(symbOr); if (it == dictCreated.end()) it = dictCreated.insert(it, make_pair(symbOr, new Symbol(symbOr))); return it->second; } template void fillPrivatesFromComment(Statement *stIn, set &privates, int type) { if (stIn) { SgStatement *st = stIn->GetOriginal(); if (st->variant() == SPF_ANALYSIS_DIR) { SgExpression *exprList = st->expr(0); while (exprList) { const int var = exprList->lhs()->variant(); if ( ((var == ACC_PRIVATE_OP || var == SPF_PROCESS_PRIVATE_OP) && type == -1) || (var == ACC_PRIVATE_OP && var == type) || (var == SPF_PROCESS_PRIVATE_OP && var == type) ) { SgExpression *list = exprList->lhs()->lhs(); while (list) { fillType *dummy = NULL; privates.insert(getData(list->lhs(), dummy)); list = list->rhs(); } break; } exprList = exprList->rhs(); } } } } template void fillPrivatesFromComment(Statement *st, set &privates, int type); template void fillPrivatesFromComment(Statement *st, set &privates, int type); //XXX: need to remove message and to add implementation extern map> SPF_messages; //for simple reduction template void fillReductionsFromComment(Statement *stIn, map> &reduction, bool moduleNameAdd, int type) { bool error = false; if (stIn) { SgStatement *st = stIn->GetOriginal(); if (st->variant() == type) { SgExpression* exprList = NULL; if (type == SPF_ANALYSIS_DIR) exprList = st->expr(0); else if (type == DVM_PARALLEL_ON_DIR) exprList = st->expr(1); while (exprList) { if (exprList->lhs()->variant() == REDUCTION_OP) { SgExpression *list = exprList->lhs()->lhs(); while (list) { SgExpression *currRed = list->lhs(); // with variant ARRAY_OP fillType redSymb, *dummy = NULL; //minloc/maxloc if (currRed->rhs()->variant() == EXPR_LIST) redSymb = getData(currRed->rhs()->lhs(), dummy, moduleNameAdd); else { redSymb = getData(currRed->rhs(), dummy, moduleNameAdd); if (currRed->rhs()->variant() == ARRAY_REF) { SgExpression* ref = currRed->rhs(); if (ref->lhs() != NULL || ref->rhs() != NULL) { //XXX std::wstring messageE, messageR; __spf_printToLongBuf(messageE, L"Reduction by element of array '%s' is not supported", to_wstring(getSymbol(redSymb)).c_str()); __spf_printToLongBuf(messageR, R182, to_wstring(getSymbol(redSymb)).c_str()); SPF_messages[current_file->filename()].push_back(Messages(ERROR, stIn->lineNumber(), messageR, messageE, 1059)); error = true; } } } string oper = ((SgKeywordValExp *)(currRed->lhs()))->value(); auto it = reduction.find(oper); if (oper == "minloc" || oper == "maxloc") { //skip //__spf_print(1, " MAXLOC/MINLOC operation from SPF not supported yet, ignored\n"); } else { if (it == reduction.end()) it = reduction.insert(it, make_pair(oper, set())); it->second.insert(redSymb); } list = list->rhs(); } } exprList = exprList->rhs(); } } } if (error) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } template void fillReductionsFromComment(Statement *st, map> &reduction, bool, int); template void fillReductionsFromComment(Statement *st, map> &reduction, bool, int); //for min/max loc reduction template void fillReductionsFromComment(Statement *stIn, map>> &reduction, bool moduleNameAdd, int type) { if (stIn) { SgStatement *st = stIn->GetOriginal(); if (st->variant() == type) { SgExpression* exprList = NULL; if (type == SPF_ANALYSIS_DIR) exprList = st->expr(0); else if (type == DVM_PARALLEL_ON_DIR) exprList = st->expr(1); while (exprList) { if (exprList->lhs()->variant() == REDUCTION_OP) { SgExpression *list = exprList->lhs()->lhs(); while (list) { SgExpression *currRed = list->lhs(); fillType redSymb, *dummy = NULL; //minloc/maxloc if (currRed->rhs()->variant() == EXPR_LIST) redSymb = getData(currRed->rhs()->lhs(), dummy, moduleNameAdd); else redSymb = getData(currRed->rhs(), dummy, moduleNameAdd); string oper = ((SgKeywordValExp *)(currRed->lhs()))->value(); auto it = reduction.find(oper); if (oper == "minloc" || oper == "maxloc") { fillType arraySymb = getData(currRed->rhs()->rhs()->lhs(), dummy); int dim = currRed->rhs()->rhs()->rhs()->lhs()->valueInteger(); if (it == reduction.end()) it = reduction.insert(it, make_pair(oper, set>())); it->second.insert(std::make_tuple(redSymb, arraySymb, dim)); } else { //skip } list = list->rhs(); } } exprList = exprList->rhs(); } } } } template void fillReductionsFromComment(Statement *st, map>> &reduction, bool, int); template void fillReductionsFromComment(Statement *st, map>> &reduction, bool, int); void fillParameterFromComment(Statement *stIn, vector> &assigns) { if (stIn) { SgStatement *st = stIn->GetOriginal(); if (st->variant() == SPF_ANALYSIS_DIR) { SgExpression *exprList = st->expr(0); while (exprList) { if (exprList->lhs() && exprList->lhs()->variant() == SPF_PARAMETER_OP) { auto paramList = exprList->lhs()->lhs(); while (paramList) { assigns.push_back(make_pair(new Expression(paramList->lhs()->lhs()), new Expression(paramList->lhs()->rhs()))); paramList = paramList->rhs(); } } exprList = exprList->rhs(); } } } } template static void fillShadowAcross(const int type, Statement *stIn, vector, vector>>> &data, set *corner = NULL) { if (stIn) { SgStatement *st = stIn->GetOriginal(); for (int list = 0; list < 3; ++list) { SgExpression *exprList = st->expr(list); while (exprList) { if (exprList->lhs()->variant() == type) { SgExpression *listExp = exprList->lhs()->lhs(); while (listExp) { SgExpression *list = listExp; bool needCornerAdd = false; if (list->lhs()->variant() == ARRAY_OP) { list = list->lhs(); needCornerAdd = true; } SgSymbol *symb = OriginalSymbol(list->lhs()->symbol()); fillType arrayName, *dummy = NULL; arrayName = getData(list->lhs(), dummy); bool cond = false; if (corner && needCornerAdd) corner->insert(arrayName); pair, vector>> *toAdd; for (int i = 0; i < data.size(); ++i) { if (data[i].first.first == arrayName) { toAdd = &data[i]; cond = true; break; } } if (!cond) { auto uniqKey = getFromUniqTable(symb); data.push_back(make_pair(make_pair(arrayName, getShortName(uniqKey)), vector>())); toAdd = &data.back(); } SgExpression *listEx = list->lhs()->lhs(); int idx = 0; while (listEx) { SgExpression *width = listEx->lhs(); const int left = width->lhs()->valueInteger(); const int right = width->rhs()->valueInteger(); if (toAdd->second.size() <= idx) toAdd->second.push_back(make_pair(left, right)); else { toAdd->second[idx].first = std::max(toAdd->second[idx].first, left); toAdd->second[idx].second = std::max(toAdd->second[idx].second, right); } idx++; listEx = listEx->rhs(); } listExp = listExp->rhs(); } } exprList = exprList->rhs(); } } } } template void fillShadowAcrossFromComment(const int type, Statement *stIn, vector, vector>>> &data) { if (stIn) if (stIn->GetOriginal()->variant() == SPF_PARALLEL_DIR) fillShadowAcross(type, stIn, data); } template void fillShadowAcrossFromComment(const int type, Statement *st, vector, vector>>> &data); template void fillShadowAcrossFromComment(const int type, Statement *st, vector, vector>>> &data); template void fillShadowAcrossFromParallel(const int type, Statement *stIn, vector, vector>>> &data, set &corner) { if (stIn) if (stIn->GetOriginal()->variant() == DVM_PARALLEL_ON_DIR) fillShadowAcross(type, stIn, data, &corner); } template void fillShadowAcrossFromParallel(const int type, Statement *st, vector, vector>>> &data, set &corner); template void fillShadowAcrossFromParallel(const int type, Statement* st, vector, vector>>>& data, set &corner); template void fillRemoteFromComment(Statement *stIn, map, Expression*> &remote, bool isFull, int type) { if (stIn) { SgStatement *st = stIn->GetOriginal(); if (st->variant() == type) { SgExpression *exprList = NULL; if (type == SPF_PARALLEL_DIR || type == DVM_REMOTE_ACCESS_DIR) exprList = st->expr(0); else if (type == DVM_PARALLEL_ON_DIR) exprList = st->expr(1); while (exprList) { if (exprList->lhs()->variant() == REMOTE_ACCESS_OP || type == DVM_REMOTE_ACCESS_DIR) { SgExpression *list; if (type == DVM_REMOTE_ACCESS_DIR) list = exprList; else list = exprList->lhs()->lhs(); while (list) { fillType arrayName, *dummy = NULL; arrayName = getData(list->lhs(), dummy); char *str; if (list->lhs()->lhs()) str = list->lhs()->lhs()->unparse(); else str = ""; if (isFull) remote.insert(make_pair(make_pair(arrayName, string(str)), new Expression(list->lhs()))); else { if (list->lhs()->lhs()) remote.insert(make_pair(make_pair(arrayName, string(str)), new Expression(list->lhs()->lhs()))); else remote.insert(make_pair(make_pair(arrayName, string(str)), new Expression(new SgExprListExp()))); } list = list->rhs(); } } if (type == DVM_REMOTE_ACCESS_DIR) break; exprList = exprList->rhs(); } } } } template void fillRemoteFromComment(Statement *st, map, Expression*> &remote, bool isFull, int type); template void fillRemoteFromComment(Statement *st, map, Expression*> &remote, bool isFull, int type); template void fillRemoteFromComment(Statement *st, map, Expression*> &remote, bool isFull, int type); void fillAcrossInfoFromDirectives(const LoopGraph *loopInfo, vector, vector>>> &acrossInfo) { SgForStmt *currentLoop = (SgForStmt*)loopInfo->loop; for (auto &data : getAttributes(currentLoop, set{ SPF_ANALYSIS_DIR, SPF_PARALLEL_DIR, SPF_TRANSFORM_DIR })) fillShadowAcrossFromComment(ACROSS_OP, new Statement(data), acrossInfo); } void fillFissionPrivatesExpansionFromComment(Statement *stIn, vector &vars) { if (stIn) { SgStatement *st = stIn->GetOriginal(); if (st->variant() == SPF_TRANSFORM_DIR) { SgExpression *exprList = st->expr(0); while (exprList) { if (exprList->lhs() && (exprList->lhs()->variant() == SPF_FISSION_OP || exprList->lhs()->variant() == SPF_EXPAND_OP)) { SgExpression *list = exprList->lhs()->lhs(); while (list) { if (list->lhs()->variant() == VAR_REF) vars.push_back(list->lhs()->symbol()->identifier()); list = list->rhs(); } } exprList = exprList->rhs(); } } } } template void fillShrinkFromComment(Statement *stIn, vector>> &varDims) { if (stIn) { SgStatement *st = stIn->GetOriginal(); if (st->variant() == SPF_TRANSFORM_DIR) { SgExpression *exprList = st->expr(0); while (exprList) { if (exprList->lhs() && (exprList->lhs()->variant() == SPF_SHRINK_OP)) { SgExpression *list = exprList->lhs()->lhs(); while (list) { // get identifier fillType var, *dummy = NULL; var = getData(list->lhs(), dummy); vector dims; SgExpression *dimList = list->lhs()->lhs(); while (dimList) { // filling dimensions dimList->lhs()->isInteger() ? dims.push_back(dimList->lhs()->valueInteger()) : dims.push_back(-1); dimList = dimList->rhs(); } varDims.push_back(make_pair(var, dims)); list = list->rhs(); } } exprList = exprList->rhs(); } } } } template void fillShrinkFromComment(Statement *stIn, vector>> &varDims); template void fillShrinkFromComment(Statement *stIn, vector>> &varDims); template void fillCheckpointFromComment(Statement *stIn, map &clauses, set &vars, set &expt) { if (stIn) { SgStatement *st = stIn->GetOriginal(); if (st->variant() == SPF_CHECKPOINT_DIR) { SgExpression *exprList= st->expr(0); while (exprList) { if (exprList->lhs()) { SgExpression *toInsert = NULL; if (exprList->lhs()->variant() == SPF_INTERVAL_OP) toInsert = new SgExpression(EXPR_LIST, exprList->lhs(), NULL); else if (exprList->lhs()->variant() == SPF_FILES_COUNT_OP) toInsert = new SgExpression(EXPR_LIST, exprList->lhs()->lhs(), NULL); else toInsert = exprList->lhs()->lhs(); auto it = clauses.find(exprList->lhs()->variant()); if (it == clauses.end()) it = clauses.insert(it, make_pair(exprList->lhs()->variant(), new Expression(toInsert))); else { auto expr = it->second->GetOriginal(); while (expr && expr->rhs()) expr = expr->rhs(); expr->setRhs(toInsert); } if (exprList->lhs()->variant() == SPF_VARLIST_OP || exprList->lhs()->variant() == SPF_EXCEPT_OP) { auto expr = exprList->lhs()->lhs(); while (expr) { // get identifier fillType var, *dummy = NULL; var = getData(expr->lhs(), dummy); if (exprList->lhs()->variant() == SPF_VARLIST_OP) { auto it = vars.find(var); if (it == vars.end()) vars.insert(var); } else { auto it = expt.find(var); if (it == expt.end()) expt.insert(var); } expr = expr->rhs(); } } } exprList = exprList->rhs(); } } } } template void fillCheckpointFromComment(Statement *stIn, map &clauses, set &vars, set &expt); template void fillCheckpointFromComment(Statement *stIn, map &clauses, set &vars, set &expt); void fillInfoFromDirectives(const LoopGraph *loopInfo, ParallelDirective *directive) { SgForStmt *currentLoop = (SgForStmt*)loopInfo->loop; for (auto &data : getAttributes(currentLoop, set{ SPF_ANALYSIS_DIR, SPF_PARALLEL_DIR, SPF_TRANSFORM_DIR })) { Statement *sData = new Statement(data); fillPrivatesFromComment(sData, directive->privates); fillReductionsFromComment(sData, directive->reduction, true); fillReductionsFromComment(sData, directive->reductionLoc, true); fillShadowAcrossFromComment(SHADOW_OP, sData, directive->shadowRenew); fillShadowAcrossFromComment(ACROSS_OP, sData, directive->across); map, Expression*> remotes; fillRemoteFromComment(sData, remotes); for (auto& elem : remotes) { SgSymbol* symb = OriginalSymbol(elem.first.first->GetOriginal()); auto uniqKey = getFromUniqTable(symb); directive->remoteAccess[make_pair(make_pair(elem.first.first->GetOriginal()->identifier(), getShortName(uniqKey)), elem.first.second)] = new Expression(elem.second->GetOriginal()); } } } void fillInfoFromDirective(Statement* parallel_on, DvmDirective& directive) { Statement* sData = parallel_on; fillReductionsFromComment(sData, directive.reduction, true, DVM_PARALLEL_ON_DIR); fillReductionsFromComment(sData, directive.reductionLoc, true, DVM_PARALLEL_ON_DIR); fillShadowAcrossFromParallel(SHADOW_RENEW_OP, sData, directive.shadowRenew, directive.corners); fillShadowAcrossFromParallel(ACROSS_OP, sData, directive.across, directive.corners); //TODO: /*map, Expression*> remotes; fillRemoteFromComment(sData, remotes, false, DVM_PARALLEL_ON_DIR); for (auto& elem : remotes) { SgSymbol* symb = OriginalSymbol(elem.first.first->GetOriginal()); auto uniqKey = getFromUniqTable(symb); directive.remoteAccess[make_pair(make_pair(elem.first.first->GetOriginal()->identifier(), getShortName(uniqKey)), elem.first.second)] = new Expression(elem.second->GetOriginal()); }*/ } int getCoverPropertyFromComment(Statement* stIn) { if (stIn) { SgStatement* st = stIn->GetOriginal(); if (st->variant() == SPF_ANALYSIS_DIR) { SgExpression* exprList = st->expr(0); while (exprList) { if (exprList->lhs() && exprList->lhs()->variant() == SPF_COVER_OP) { auto value = exprList->lhs()->lhs(); if (value->isInteger()) return value->valueInteger(); else return -1; } exprList = exprList->rhs(); } } } return 0; }