diff --git a/sapfor/experts/Sapfor_2017/_src/DirectiveProcessing/directive_creator_base_nodist.cpp b/sapfor/experts/Sapfor_2017/_src/DirectiveProcessing/directive_creator_base_nodist.cpp index f30b02d..9febb79 100644 --- a/sapfor/experts/Sapfor_2017/_src/DirectiveProcessing/directive_creator_base_nodist.cpp +++ b/sapfor/experts/Sapfor_2017/_src/DirectiveProcessing/directive_creator_base_nodist.cpp @@ -68,7 +68,7 @@ void createParallelDirectivesNoDist(const maphasLimitsToParallel() && + if (!currLoop->hasLimitsToParallel() && (currLoop->lineNum > 0 || (currLoop->lineNum < 0 && currLoop->altLineNum > 0))) { ParallelDirective* parDir = new ParallelDirective(); diff --git a/sapfor/experts/Sapfor_2017/_src/Distribution/Array.h b/sapfor/experts/Sapfor_2017/_src/Distribution/Array.h index f29c7f1..7dd823e 100644 --- a/sapfor/experts/Sapfor_2017/_src/Distribution/Array.h +++ b/sapfor/experts/Sapfor_2017/_src/Distribution/Array.h @@ -158,10 +158,10 @@ namespace Distribution Array(const STRING &name, const STRING &shortName, const int dimSize, const unsigned id, const STRING &declFile, const int declLine, const PAIR &locationPos, Symbol *declSymbol, bool inOmpThreadPriv, bool privateInLoop, bool inEquivalence, - const VECTOR ®ions, const int typeSize) : + const VECTOR ®ions, const int typeSize, const distFlag flag = DISTR) : name(name), dimSize(dimSize), id(id), shortName(shortName), - isTemplFlag(false), isNonDistribute(DISTR), isLoopArrayFlag(false), + isTemplFlag(false), isNonDistribute(flag), isLoopArrayFlag(false), locationPos(locationPos), declSymbol(declSymbol), typeSize(typeSize), ompThreadPrivate(inOmpThreadPriv), privateInLoop(privateInLoop), inEquivalence(inEquivalence) { diff --git a/sapfor/experts/Sapfor_2017/_src/GraphCall/graph_calls.cpp b/sapfor/experts/Sapfor_2017/_src/GraphCall/graph_calls.cpp index 74ddd52..e20ed1f 100644 --- a/sapfor/experts/Sapfor_2017/_src/GraphCall/graph_calls.cpp +++ b/sapfor/experts/Sapfor_2017/_src/GraphCall/graph_calls.cpp @@ -12,13 +12,14 @@ #include #include "dvm.h" -#include "../GraphLoop/graph_loops_func.h" #include "graph_calls_func.h" + +#include "../CFGraph/CFGraph.h" +#include "../GraphLoop/graph_loops_func.h" #include "../DirectiveProcessing/directive_parser.h" #include "../Utils/SgUtils.h" #include "../ParallelizationRegions/ParRegions_func.h" #include "../DynamicAnalysis/gCov_parser_func.h" -#include "acc_analyzer.h" #include "../ExpressionTransform/expr_transform.h" #include "../LoopAnalyzer/loop_analyzer.h" #include "../VerificationCode/verifications.h" @@ -203,8 +204,16 @@ static void fillFuncParams(FuncInfo *currInfo, const map 0) + { for (int i = 0; i < numOfParams; ++i) fillParam(i, procHeader->parameter(i), currParams, commonBlocks, false); + + for (int i = 0; i < procHeader->numberOfParameters(); ++i) + { + currInfo->funcParams.identificators.push_back((procHeader->parameter(i))->identifier()); + currInfo->isParamUsedAsIndex.push_back(false); + } + } } static void fillFuncParams(FuncInfo *currInfo, const map> &commonBlocks, SgStatement *entryHeader) @@ -341,38 +350,35 @@ static void processActualParams(SgExpression *parList, const map &entryProcs, const int line, +static void findFuncCalls(SgStatement *parent, SgExpression *curr, FuncInfo* procInfo, const int line, const map> &commonBlocks, const set ¯oNames, const vector &containsFunctions, const string &prefix) { if (curr->variant() == FUNC_CALL && macroNames.find(curr->symbol()->identifier()) == macroNames.end()) { - for (auto &proc : entryProcs) - { - vector nameOfCallFunc; - nameOfCallFunc.push_back(curr->symbol()->identifier()); - nameOfCallFunc.push_back(OriginalSymbol(curr->symbol())->identifier()); + vector nameOfCallFunc; + nameOfCallFunc.push_back(curr->symbol()->identifier()); + nameOfCallFunc.push_back(OriginalSymbol(curr->symbol())->identifier()); - for (auto& elem : nameOfCallFunc) - correctNameIfContains(NULL, curr, elem, containsFunctions, prefix); + for (auto& elem : nameOfCallFunc) + correctNameIfContains(NULL, curr, elem, containsFunctions, prefix); - proc->callsFrom.insert(nameOfCallFunc.begin(), nameOfCallFunc.end()); + procInfo->callsFrom.insert(nameOfCallFunc.begin(), nameOfCallFunc.end()); - FuncInfoCallFrom newCall; - newCall.detailCallsFrom = make_pair(nameOfCallFunc[1], line); // original name of call - newCall.pointerDetailCallsFrom = make_pair(curr, FUNC_CALL); - newCall.parentForPointer = parent; - newCall.actualParams = FuncParam(); + FuncInfoCallFrom newCall; + newCall.detailCallsFrom = make_pair(nameOfCallFunc[1], line); // original name of call + newCall.pointerDetailCallsFrom = make_pair(curr, FUNC_CALL); + newCall.parentForPointer = parent; + newCall.actualParams = FuncParam(); - processActualParams(curr->lhs(), commonBlocks, newCall.actualParams, proc->externalCalls); - proc->callsFromDetailed.push_back(newCall); - } + processActualParams(curr->lhs(), commonBlocks, newCall.actualParams, procInfo->externalCalls); + procInfo->callsFromDetailed.push_back(newCall); } if (curr->lhs()) - findFuncCalls(parent, curr->lhs(), entryProcs, line, commonBlocks, macroNames, containsFunctions, prefix); + findFuncCalls(parent, curr->lhs(), procInfo, line, commonBlocks, macroNames, containsFunctions, prefix); if (curr->rhs()) - findFuncCalls(parent, curr->rhs(), entryProcs, line, commonBlocks, macroNames, containsFunctions, prefix); + findFuncCalls(parent, curr->rhs(), procInfo, line, commonBlocks, macroNames, containsFunctions, prefix); } static void findReplaceSymbolByExpression(SgExpression *parentEx, SgExpression *findIn, int pos, @@ -763,7 +769,7 @@ static void checkSpecList(SgExpression *spec, FuncInfo* currF, const map& activeOps) { if (currF->funcParams.countOfPars == 0) return; @@ -786,6 +792,12 @@ static void fillInOut(FuncInfo *currF, SgStatement *start, SgStatement *last) if (isSgExecutableStatement(st) == NULL || st->lineNumber() <= 0) continue; + if (activeOps.size() && activeOps.find(st) == activeOps.end()) + { + st = st->lastNodeOfStmt(); + continue; + } + if (st->variant() == ASSIGN_STAT) { SgExpression *left = st->expr(0); @@ -894,12 +906,12 @@ static void fillInOut(FuncInfo *currF, SgStatement *start, SgStatement *last) } //TODO: check common block and module use -static void fillFunctionPureStatus(SgStatement *header, FuncInfo *currInfo, vector &messagesForFile) +static void fillFunctionPureStatus(SgStatement *header, FuncInfo *currInfo, vector &messagesForFile, const set& activeOps) { if (!currInfo->isMain) { set lines; - bool hasIntent = hasThisIds(header, lines, { INTENT_STMT }); + bool hasIntent = hasThisIds(header, lines, { INTENT_STMT }, &activeOps); bool declaratedAsPure = (header->symbol()->attributes() & PURE_BIT); if (declaratedAsPure && !hasIntent && ((SgProgHedrStmt*)header)->numberOfParameters()) @@ -913,7 +925,9 @@ static void fillFunctionPureStatus(SgStatement *header, FuncInfo *currInfo, vect lines.clear(); bool has = hasThisIds(header, lines, { DATA_DECL, SAVE_DECL, USE_STMT, WRITE_STAT, READ_STAT, OPEN_STAT, CLOSE_STAT, - PRINT_STAT, STOP_STAT, PAUSE_NODE }); + PRINT_STAT, STOP_STAT, PAUSE_NODE }, + &activeOps); + if (!has || declaratedAsPure) currInfo->isPure = true; else @@ -947,284 +961,366 @@ static void fillCommons(FuncInfo *currInfo, const map> &allFuncInfo, vector &loops, vector &messagesForFile, bool dontFillFuncParam) +static FuncInfo* createNewFuction(const string& funcName, SgStatement *st, SgStatement* entry, + vector& messagesForFile, + const map>& commonBlocks, + const set& activeOps) +{ + SgStatement* lastNode = st->lastNodeOfStmt(); + + FuncInfo* currInfo = new FuncInfo(funcName, make_pair(entry->lineNumber(), lastNode->lineNumber()), new Statement(entry)); + hasThisIds(st, currInfo->linesOfIO, { WRITE_STAT, READ_STAT, OPEN_STAT, CLOSE_STAT, PRINT_STAT }, &activeOps); + hasThisIds(st, currInfo->linesOfStop, { STOP_STAT, PAUSE_NODE }, &activeOps); + currInfo->isMain = (st->variant() == PROG_HEDR); + fillCommons(currInfo, commonBlocks); + fillFunctionPureStatus(st, currInfo, messagesForFile, activeOps); + + if (st->variant() != PROG_HEDR) + { + SgProgHedrStmt* procFuncHedr = ((SgProgHedrStmt*)st); + + if (st == entry) + fillFuncParams(currInfo, commonBlocks, procFuncHedr); + else + fillFuncParams(currInfo, commonBlocks, entry); + fillInOut(currInfo, st, lastNode, activeOps); + } + + if (isSPF_NoInline(new Statement(st->lexNext()))) + { + __spf_print(1, "set NOINLINE attribute for function '%s'\n", funcName.c_str()); + currInfo->doNotInline = true; + } + + return currInfo; +} + +static void analyzeFunction(const string& funcName, const string& containsPrefix, + SgStatement *function, SgStatement* entry, map>& allFuncInfo, + const map& mapLoopGraph, vector& messagesForFile, + vector& containsFunctions, + const set& activeOps) +{ + SgStatement* st = function; + SgStatement* lastNode = st->lastNodeOfStmt(); + + const string fileName = function->fileName(); + auto it = allFuncInfo.find(fileName); + if (it == allFuncInfo.end()) + it = allFuncInfo.insert(it, make_pair(fileName, vector())); + + map> commonBlocks; + getCommonBlocksRef(commonBlocks, function, lastNode); + + if (function->controlParent()->variant() == GLOBAL) + containsFunctions.clear(); + + findContainsFunctions(function, containsFunctions); + auto procInfo = createNewFuction(funcName, function, entry, messagesForFile, commonBlocks, activeOps); + it->second.push_back(procInfo); + + vector macroStats; + set macroNames; + + while (st != lastNode) + { + if (st->variant() == CONTAINS_STMT) + break; + + if (st->variant() == INTERFACE_STMT) + { + st = st->lexNext(); + while (st && !(st->controlParent()->variant() == INTERFACE_STMT && st->variant() == CONTROL_END)) + { + if (st->variant() == PROC_HEDR || st->variant() == FUNC_HEDR) + { + procInfo->interfaceBlocks[st->symbol()->identifier()] = NULL; + st = st->lastNodeOfStmt(); + } + st = st->lexNext(); + } + } + + if (st == NULL) + { + __spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n"); + break; + } + + if (!isSgExecutableStatement(st)) + { + if (st->variant() == STMTFN_STAT) + { + macroStats.push_back(st); + macroNames.insert(st->expr(0)->symbol()->identifier()); + } + } + else + break; + st = st->lexNext(); + } + + st = function; + const string file = st->fileName(); + + while (st != lastNode) + { + if (st == NULL) + { + __spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n"); + break; + } + + if (st->variant() == CONTAINS_STMT) + break; + + if (!__gcov_doesThisLineExecuted(st->fileName(), st->lineNumber()) || + st->variant() == ENTRY_STAT) + { + st = st->lexNext(); + continue; + } + + if (activeOps.size()) + { + if (st->fileName() == file && + isSgExecutableStatement(st) && + activeOps.find(st) == activeOps.end()) + { + st = st->lastNodeOfStmt(); + st = st->lexNext(); + continue; + } + } + + // check for external calls + if (st->variant() == EXTERN_STAT) + for (SgExpression* ex = st->expr(0); ex; ex = ex->rhs()) + if (ex->lhs()->symbol()) + procInfo->externalCalls.insert(ex->lhs()->symbol()->identifier()); + + const string prefix = containsPrefix == "" ? string(function->symbol()->identifier()) + "." : containsPrefix; + //printf("var %d, line %d, file %s\n", st->variant(), st->lineNumber(), st->fileName()); + if (st->variant() == PROC_STAT) + { + vector pureNameOfCallFunc; + pureNameOfCallFunc.push_back(removeString("call ", st->symbol()->identifier())); + pureNameOfCallFunc.push_back(removeString("call ", OriginalSymbol(st->symbol())->identifier())); + + for (auto& elem : pureNameOfCallFunc) + correctNameIfContains(st, NULL, elem, containsFunctions, prefix); + + if (hasRecCall(procInfo, pureNameOfCallFunc)) + continue; + + procInfo->callsFrom.insert(pureNameOfCallFunc.begin(), pureNameOfCallFunc.end()); + + FuncInfoCallFrom newCall; + newCall.detailCallsFrom = make_pair(pureNameOfCallFunc[1], st->lineNumber()); // original name of call + newCall.pointerDetailCallsFrom = make_pair(st, PROC_STAT); + newCall.parentForPointer = st; + newCall.actualParams = FuncParam(); + + processActualParams(st->expr(0), commonBlocks, newCall.actualParams, procInfo->externalCalls); + procInfo->callsFromDetailed.push_back(newCall); + + // Add func call which we've just found + NestedFuncCall funcCall(pureNameOfCallFunc[1]); + procInfo->funcsCalledFromThis.push_back(funcCall); + + // search for using pars of cur func in pars of called + throughParams(st->expr(0), *procInfo, containsFunctions, prefix); + + //find external calls + for (SgExpression* par = st->expr(0); par != NULL; par = par->rhs()) + { + SgExpression* curr = par->lhs(); + if (curr) + { + if (curr->variant() == VAR_REF) + { + auto s = curr->symbol(); + if (procInfo->externalCalls.find(s->identifier()) != procInfo->externalCalls.end() || + (s->attributes() & EXTERNAL_BIT)) + { + vector nameOfCallFunc; + nameOfCallFunc.push_back(s->identifier()); + nameOfCallFunc.push_back(OriginalSymbol(s)->identifier()); + + for (auto& elem : nameOfCallFunc) + correctNameIfContains(NULL, curr, elem, containsFunctions, prefix); + + procInfo->callsFrom.insert(nameOfCallFunc.begin(), nameOfCallFunc.end()); + + FuncInfoCallFrom newCall; + newCall.detailCallsFrom = make_pair(nameOfCallFunc[1], st->lineNumber()); // original name of call + newCall.pointerDetailCallsFrom = make_pair(curr, VAR_REF); + newCall.parentForPointer = st; + newCall.actualParams = FuncParam(); + + procInfo->callsFromDetailed.push_back(newCall); + } + } + } + } + } + else + { + for (int i = 0; i < 3; ++i) + if (st->expr(i)) + findParamUsedInFuncCalls(st->expr(i), *procInfo, containsFunctions, prefix); + } + + for (int i = 0; i < 3; ++i) + if (st->expr(i)) + findFuncCalls(st, st->expr(i), procInfo, st->lineNumber(), commonBlocks, macroNames, containsFunctions, prefix); + + if (isSgExecutableStatement(st)) + { + if (procInfo->isParamUsedAsIndex.size()) + for (int i = 0; i < 3; i++) + findArrayRef(st->expr(i), *procInfo, st->variant() == ASSIGN_STAT && i == 0); + + if (st->variant() == FOR_NODE) + { + auto itL = mapLoopGraph.find(st->lineNumber()); + if (itL != mapLoopGraph.end()) + procInfo->loopsInFunc.push_back(itL->second); + } + } + + st = st->lexNext(); + } +} + +static set fillActiveOperators(const vector& blocks) +{ + if (blocks.size() == 0) + return set(); + + set active; + set activeBlocks; + + activeBlocks.insert(blocks[0]); + bool added = true; + while (added) + { + added = false; + for (auto& block : activeBlocks) + { + for (auto& next : block->getNext()) + { + if (activeBlocks.find(next) == activeBlocks.end()) + { + activeBlocks.insert(next); + added = true; + } + } + } + } + + for (auto& block : activeBlocks) + { + for (auto& instr : block->getInstructions()) + { + auto op = instr->getInstruction()->getOperator(); + if (op) + active.insert(op); + } + } + + return active; +} + +//if fullIR not empty -> call this function from CALL_GRAPH2 +void functionAnalyzer(SgFile *file, map> &allFuncInfo, const vector &loops, vector &messagesForFile, + map> &fullIR) { map mapLoopGraph; createMapLoopGraph(loops, mapLoopGraph); + map tmpInfoInIR; + for (auto& elem : fullIR) + { + SgStatement* func = elem.first->funcPointer->GetOriginal(); + if (tmpInfoInIR.count(func) != 0) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + tmpInfoInIR[func] = elem.first; + } + int funcNum = file->numberOfFunctions(); __spf_print(DEBUG, "functions num in file = %d\n", funcNum); vector containsFunctions; + vector functions; for (int i = 0; i < funcNum; ++i) { - SgStatement *st = file->functions(i); - string containsPrefix = ""; + auto func = file->functions(i); + functions.push_back(func); - SgStatement *st_cp = st->controlParent(); + //find entry points + for (auto st = func->lexNext(); st != func->lastNodeOfStmt(); st = st->lexNext()) + { + if (st->variant() == ENTRY_STAT) + functions.push_back(st); + } + } + + for (auto& function : functions) + { + bool isEntry = (function->variant() == ENTRY_STAT); + + const int line = function->lineNumber(); + const char* file = function->fileName(); + + string containsPrefix = ""; + SgStatement* st_cp = isEntry ? function->controlParent()->controlParent() : function->controlParent(); if (st_cp->variant() == PROC_HEDR || st_cp->variant() == PROG_HEDR || st_cp->variant() == FUNC_HEDR) containsPrefix = st_cp->symbol()->identifier() + string("."); else if (st_cp->variant() == INTERFACE_STMT) continue; - string currFunc = ""; - if (st->variant() == PROG_HEDR) + string funcName = ""; + if (function->variant() == PROG_HEDR) { - SgProgHedrStmt *progH = (SgProgHedrStmt*)st; - currFunc = progH->nameWithContains(); - __spf_print(DEBUG, "*** Program <%s> started at line %d / %s\n", progH->symbol()->identifier(), st->lineNumber(), st->fileName()); + SgProgHedrStmt* progH = (SgProgHedrStmt*)function; + funcName = progH->nameWithContains(); + __spf_print(DEBUG, "*** Program <%s> started at line %d / %s\n", progH->symbol()->identifier(), line, file); } - else if (st->variant() == PROC_HEDR) + else if (function->variant() == PROC_HEDR) { - SgProcHedrStmt *procH = (SgProcHedrStmt*)st; - currFunc = procH->nameWithContains(); - __spf_print(DEBUG, "*** Function <%s> started at line %d / %s\n", procH->symbol()->identifier(), st->lineNumber(), st->fileName()); + SgProcHedrStmt* procH = (SgProcHedrStmt*)function; + funcName = procH->nameWithContains(); + __spf_print(DEBUG, "*** Function <%s> started at line %d / %s\n", procH->symbol()->identifier(), line, file); } - else if (st->variant() == FUNC_HEDR) + else if (function->variant() == FUNC_HEDR) { - SgFuncHedrStmt *funcH = (SgFuncHedrStmt*)st; - currFunc = funcH->nameWithContains(); - __spf_print(DEBUG, "*** Function <%s> started at line %d / %s\n", funcH->symbol()->identifier(), st->lineNumber(), st->fileName()); + SgFuncHedrStmt* funcH = (SgFuncHedrStmt*)function; + funcName = funcH->nameWithContains(); + __spf_print(DEBUG, "*** Function <%s> started at line %d / %s\n", funcH->symbol()->identifier(), line, file); + } + else if (function->variant() == ENTRY_STAT) + { + funcName = function->symbol()->identifier(); + __spf_print(DEBUG, "*** Entry function <%s> started at line %d / %s\n", funcName.c_str(), line, file); } else printInternalError(convertFileName(__FILE__).c_str(), __LINE__); - SgStatement *lastNode = st->lastNodeOfStmt(); - - const string fileName = st->fileName(); - auto it = allFuncInfo.find(fileName); - if (it == allFuncInfo.end()) - it = allFuncInfo.insert(it, make_pair(fileName, vector())); - - map> commonBlocks; - getCommonBlocksRef(commonBlocks, st, lastNode); - - if (st->controlParent()->variant() == GLOBAL) - containsFunctions.clear(); - - findContainsFunctions(st, containsFunctions); - - FuncInfo *currInfo = new FuncInfo(currFunc, make_pair(st->lineNumber(), lastNode->lineNumber()), new Statement(st)); - hasThisIds(st, currInfo->linesOfIO, { WRITE_STAT, READ_STAT, OPEN_STAT, CLOSE_STAT, PRINT_STAT }); - hasThisIds(st, currInfo->linesOfStop, { STOP_STAT, PAUSE_NODE }); - currInfo->isMain = (st->variant() == PROG_HEDR); - fillCommons(currInfo, commonBlocks); - fillFunctionPureStatus(st, currInfo, messagesForFile); - - if (st->variant() != PROG_HEDR) + set activeOps; + if (fullIR.size()) { - SgProgHedrStmt *procFuncHedr = ((SgProgHedrStmt*)st); + if (tmpInfoInIR.count(function) == 0) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); - fillFuncParams(currInfo, commonBlocks, procFuncHedr); - - // Fill in names of function parameters - for (int i = 0; i < procFuncHedr->numberOfParameters(); ++i) - { - currInfo->funcParams.identificators.push_back((procFuncHedr->parameter(i))->identifier()); - currInfo->isParamUsedAsIndex.push_back(false); - } - - fillInOut(currInfo, st, st->lastNodeOfStmt()); + activeOps = fillActiveOperators(fullIR[tmpInfoInIR[function]]); + activeOps.insert(function); + if (isEntry) + activeOps.insert(function->controlParent()); } - if (isSPF_NoInline(new Statement(st->lexNext()))) - { - __spf_print(1, "set NOINLINE attribute for function '%s'\n", currFunc.c_str()); - currInfo->doNotInline = true; - } - - it->second.push_back(currInfo); - - vector entryProcs; - entryProcs.push_back(currInfo); - - vector macroStats; - set macroNames; - while (st != lastNode) - { - if (st->variant() == CONTAINS_STMT) - break; - - if (st->variant() == INTERFACE_STMT) - { - st = st->lexNext(); - while (st && !(st->controlParent()->variant() == INTERFACE_STMT && st->variant() == CONTROL_END)) - { - if (st->variant() == PROC_HEDR || st->variant() == FUNC_HEDR) - { - currInfo->interfaceBlocks[st->symbol()->identifier()] = NULL; - st = st->lastNodeOfStmt(); - } - st = st->lexNext(); - } - } - - if (st == NULL) - { - __spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n"); - break; - } - - if (!isSgExecutableStatement(st)) - { - if (st->variant() == STMTFN_STAT) - { - macroStats.push_back(st); - macroNames.insert(st->expr(0)->symbol()->identifier()); - } - } - else - break; - st = st->lexNext(); - } - - SgStatement* origStart = NULL; - origStart = st = file->functions(i); - while (st != lastNode) - { - if (st == NULL) - { - __spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n"); - break; - } - - if (st->variant() == CONTAINS_STMT) - break; - - if (!__gcov_doesThisLineExecuted(st->fileName(), st->lineNumber())) - { - st = st->lexNext(); - continue; - } - - // check for external calls - if (st->variant() == EXTERN_STAT) - for (SgExpression* ex = st->expr(0); ex; ex = ex->rhs()) - if (ex->lhs()->symbol()) - currInfo->externalCalls.insert(ex->lhs()->symbol()->identifier()); - - const string prefix = containsPrefix == "" ? currFunc + "." : containsPrefix; - //printf("var %d, line %d, file %s\n", st->variant(), st->lineNumber(), st->fileName()); - if (st->variant() == PROC_STAT) - { - vector pureNameOfCallFunc; - pureNameOfCallFunc.push_back(removeString("call ", st->symbol()->identifier())); - pureNameOfCallFunc.push_back(removeString("call ", OriginalSymbol(st->symbol())->identifier())); - - for (auto& elem : pureNameOfCallFunc) - correctNameIfContains(st, NULL, elem, containsFunctions, prefix); - - for (auto &proc : entryProcs) - { - if (hasRecCall(proc, pureNameOfCallFunc)) - continue; - - proc->callsFrom.insert(pureNameOfCallFunc.begin(), pureNameOfCallFunc.end()); - - FuncInfoCallFrom newCall; - newCall.detailCallsFrom = make_pair(pureNameOfCallFunc[1], st->lineNumber()); // original name of call - newCall.pointerDetailCallsFrom = make_pair(st, PROC_STAT); - newCall.parentForPointer = st; - newCall.actualParams = FuncParam(); - - processActualParams(st->expr(0), commonBlocks, newCall.actualParams, proc->externalCalls); - proc->callsFromDetailed.push_back(newCall); - - // Add func call which we've just found - NestedFuncCall funcCall(pureNameOfCallFunc[1]); - proc->funcsCalledFromThis.push_back(funcCall); - - // search for using pars of cur func in pars of called - throughParams(st->expr(0), *proc, containsFunctions, prefix); - - //find external calls - for (SgExpression* par = st->expr(0); par != NULL; par = par->rhs()) - { - SgExpression* curr = par->lhs(); - if (curr) - { - if (curr->variant() == VAR_REF) - { - auto s = curr->symbol(); - if (currInfo->externalCalls.find(s->identifier()) != currInfo->externalCalls.end() || - (s->attributes() & EXTERNAL_BIT)) - { - vector nameOfCallFunc; - nameOfCallFunc.push_back(s->identifier()); - nameOfCallFunc.push_back(OriginalSymbol(s)->identifier()); - - for (auto& elem : nameOfCallFunc) - correctNameIfContains(NULL, curr, elem, containsFunctions, prefix); - - proc->callsFrom.insert(nameOfCallFunc.begin(), nameOfCallFunc.end()); - - FuncInfoCallFrom newCall; - newCall.detailCallsFrom = make_pair(nameOfCallFunc[1], st->lineNumber()); // original name of call - newCall.pointerDetailCallsFrom = make_pair(curr, VAR_REF); - newCall.parentForPointer = st; - newCall.actualParams = FuncParam(); - - proc->callsFromDetailed.push_back(newCall); - } - } - } - } - } - } - else - { - for (auto &proc : entryProcs) - for (int i = 0; i < 3; ++i) - if (st->expr(i)) - findParamUsedInFuncCalls(st->expr(i), *proc, containsFunctions, prefix); - } - - for (int i = 0; i < 3; ++i) - if (st->expr(i)) - findFuncCalls(st, st->expr(i), entryProcs, st->lineNumber(), commonBlocks, macroNames, containsFunctions, prefix); - - if (st->variant() == ENTRY_STAT) - { - string entryName = st->symbol()->identifier(); - FuncInfo *entryInfo = new FuncInfo(entryName, make_pair(st->lineNumber(), lastNode->lineNumber()), new Statement(st)); - hasThisIds(st, entryInfo->linesOfIO, { WRITE_STAT, READ_STAT, OPEN_STAT, CLOSE_STAT, PRINT_STAT }); - hasThisIds(st, entryInfo->linesOfStop, { STOP_STAT, PAUSE_NODE }); - fillCommons(entryInfo, commonBlocks); - fillFunctionPureStatus(st, entryInfo, messagesForFile); - - fillFuncParams(entryInfo, commonBlocks, st); - - if (isSPF_NoInline(new Statement(st->lexNext()))) - { - __spf_print(1, "set NOINLINE attribute for function '%s'\n", entryName.c_str()); - entryInfo->doNotInline = true; - } - it->second.push_back(entryInfo); - entryProcs.push_back(entryInfo); - - fillInOut(entryInfo, origStart, origStart->lastNodeOfStmt()); - } - - if (isSgExecutableStatement(st)) - { - for (auto &proc : entryProcs) - if (proc->isParamUsedAsIndex.size()) - for (int i = 0; i < 3; i++) - findArrayRef(st->expr(i), *proc, st->variant() == ASSIGN_STAT && i == 0); - - if (st->variant() == FOR_NODE) - { - auto itL = mapLoopGraph.find(st->lineNumber()); - if (itL != mapLoopGraph.end()) - { - for (auto &proc : entryProcs) - proc->loopsInFunc.push_back(itL->second); - } - } - } - - st = st->lexNext(); - } + analyzeFunction(funcName, containsPrefix, isEntry ? function->controlParent() : function, function, allFuncInfo, mapLoopGraph, messagesForFile, containsFunctions, activeOps); } //fill INTERFACE block from modules @@ -1275,6 +1371,30 @@ void functionAnalyzer(SgFile *file, map> &allFuncInfo, } } } + + auto it = allFuncInfo.find(file->filename()); + if (it == allFuncInfo.end()) + return; + + if (fullIR.size() == 0) + return; + + vector toRemove; + for (auto& func : it->second) + { + SgStatement* pointer = func->funcPointer->GetOriginal(); + if (tmpInfoInIR.find(pointer) != tmpInfoInIR.end()) + { + auto key = tmpInfoInIR[pointer]; + toRemove.push_back(key); + + fullIR[func] = fullIR[key]; + fullIR.erase(key); + } + } + + for (auto& func : toRemove) + delete func; } static bool findLoopVarInParameter(SgExpression *ex, const string &loopSymb) diff --git a/sapfor/experts/Sapfor_2017/_src/GraphCall/graph_calls_func.h b/sapfor/experts/Sapfor_2017/_src/GraphCall/graph_calls_func.h index b7ba94d..94c5b56 100644 --- a/sapfor/experts/Sapfor_2017/_src/GraphCall/graph_calls_func.h +++ b/sapfor/experts/Sapfor_2017/_src/GraphCall/graph_calls_func.h @@ -14,6 +14,11 @@ namespace Distribution } namespace DIST = Distribution; +namespace SAPFOR +{ + class BasicBlock; +} + int CreateCallGraphViz(const char *fileName, const std::map> &funcByFile, std::map &V, std::vector &E); int CreateFuncInfo(const char *fileName, const std::map> &funcByFile); std::string removeString(const std::string &toRemove, const std::string &inStr); @@ -32,7 +37,7 @@ void updateFuncInfo(const std::map> &allFunc void excludeArraysFromDistribution(const std::map>& arrayLinksByFuncCalls, const std::map, std::pair> declaredArrays, std::map>& loopGraph, std::vector parallelRegions, std::map>& SPF_messages, std::map, DIST::Array*>& createdArrays, int mpiProgram = 0); #if __SPF -void functionAnalyzer(SgFile *file, std::map> &allFuncInfo, std::vector &loops, std::vector &messagesForFile, bool dontFillFuncParam = false); +void functionAnalyzer(SgFile *file, std::map> &allFuncInfo, const std::vector &loops, std::vector &messagesForFile, std::map>& fullIR); int CheckFunctionsToInline(SgProject *proj, const std::map &files, const char *fileName, std::map> &funcByFile, const std::map> &loopGraph, std::map> &allMessages, bool needToAddErrors, diff --git a/sapfor/experts/Sapfor_2017/_src/GraphLoop/graph_loops.cpp b/sapfor/experts/Sapfor_2017/_src/GraphLoop/graph_loops.cpp index 9393b87..077fe4f 100644 --- a/sapfor/experts/Sapfor_2017/_src/GraphLoop/graph_loops.cpp +++ b/sapfor/experts/Sapfor_2017/_src/GraphLoop/graph_loops.cpp @@ -318,24 +318,32 @@ bool checkRegionEntries(SgStatement *begin, return noError; } -bool hasThisIds(SgStatement *start, set &lines, const set &IDs) +bool hasThisIds(SgStatement *start, set &lines, const set &IDs, const std::set* activeOps) { bool has = false; SgStatement *end = start->lastNodeOfStmt(); SgStatement *curr = start; - while (curr != end) + for ( ; curr != end; curr = curr->lexNext()) { const int var = curr->variant(); - if (var == CONTAINS_STMT || var == ENTRY_STAT) + if (var == CONTAINS_STMT) break; + if (var == ENTRY_STAT) + continue; + + if (activeOps && activeOps->size() && activeOps->find(curr) == activeOps->end()) + { + curr = curr->lastNodeOfStmt(); + continue; + } + if (IDs.find(var) != IDs.end()) { has = true; lines.insert(curr->lineNumber()); } - curr = curr->lexNext(); } return has; @@ -564,6 +572,40 @@ static bool isLoopStat(SgStatement* st) return (var == FOR_NODE || var == WHILE_NODE); } +static bool hasSubstringRef(SgExpression* ex) +{ + bool res = false; + if (ex) + { + if (ex->variant() == ARRAY_OP) + return true; + + if (ex->lhs()) + res |= hasSubstringRef(ex->lhs()); + if (ex->rhs()) + res |= hasSubstringRef(ex->rhs()); + } + return res; +} + +static bool hasSubstringRef(SgStatement* loop) +{ + for (SgStatement* st = loop->lexNext(); st != loop->lastNodeOfStmt(); st = st->lexNext()) + { + if (isSgExecutableStatement(st) && !isDVM_stat(st) && !isSPF_stat(st)) + { + for (int z = 0; z < 3; ++z) + { + bool res = hasSubstringRef(st->expr(z)); + if (res) + return true; + } + } + } + + return false; +} + void loopGraphAnalyzer(SgFile *file, vector &loopGraph, const vector &intervalTree, vector &messages, int mpiProgram) { map mapIntervals; @@ -653,6 +695,7 @@ void loopGraphAnalyzer(SgFile *file, vector &loopGraph, const vector newLoop->hasDvmIntervals = hasThisIds(st, tmpLines, { DVM_INTERVAL_DIR, DVM_ENDINTERVAL_DIR, DVM_EXIT_INTERVAL_DIR }); newLoop->isFor = isSgForStmt(st) ? true : false; newLoop->inCanonicalFrom = isSgForStmt(st) ? true : false; + newLoop->hasSubstringRefs = hasSubstringRef(st); if (isSgForStmt(st)) newLoop->hasNonRectangularBounds = hasNonRect(((SgForStmt*)st), parentLoops, messages); diff --git a/sapfor/experts/Sapfor_2017/_src/GraphLoop/graph_loops.h b/sapfor/experts/Sapfor_2017/_src/GraphLoop/graph_loops.h index c56e832..6faef07 100644 --- a/sapfor/experts/Sapfor_2017/_src/GraphLoop/graph_loops.h +++ b/sapfor/experts/Sapfor_2017/_src/GraphLoop/graph_loops.h @@ -73,6 +73,7 @@ public: isFor = false; inCanonicalFrom = false; hasAccessToSubArray = false; + hasSubstringRefs = false; } ~LoopGraph() @@ -112,7 +113,7 @@ public: { return hasUnknownArrayDep || hasUnknownScalarDep || hasGoto || hasPrints || (hasConflicts.size() != 0) || hasStops || hasNonPureProcedures || hasUnknownArrayAssigns || hasNonRectangularBounds || hasIndirectAccess || hasWritesToNonDistribute || hasDifferentAlignRules || hasDvmIntervals || - !isFor || lastprivateScalars.size() || hasAccessToSubArray; + !isFor || lastprivateScalars.size() || hasAccessToSubArray || hasSubstringRefs; } bool hasLimitsToSplit() const @@ -440,12 +441,15 @@ public: bool hasNonPureProcedures; bool hasDvmIntervals; + // make sense only for NODIST regime + bool hasAccessToSubArray; + + bool hasSubstringRefs; bool isFor; bool inCanonicalFrom; - // make sense only for NODIST regime - bool hasAccessToSubArray; + std::vector children; std::vector funcChildren; diff --git a/sapfor/experts/Sapfor_2017/_src/GraphLoop/graph_loops_func.h b/sapfor/experts/Sapfor_2017/_src/GraphLoop/graph_loops_func.h index 35b249b..99cfa0b 100644 --- a/sapfor/experts/Sapfor_2017/_src/GraphLoop/graph_loops_func.h +++ b/sapfor/experts/Sapfor_2017/_src/GraphLoop/graph_loops_func.h @@ -12,7 +12,7 @@ void findAllRefsToLables(SgStatement *st, std::map> &label std::map findAllDirectives(SgFile *file, const std::vector &loops, const uint64_t regId); std::vector, std::pair>> findAllSingleRemotes(SgFile *file, const uint64_t regId, std::vector ®ions); std::map> fillRemoteInParallel(Statement *st); -bool hasThisIds(SgStatement *loop, std::set &lines, const std::set &IDs); +bool hasThisIds(SgStatement *loop, std::set &lines, const std::set &IDs, const std::set* activeOps = NULL); bool checkRegionEntries(SgStatement *begin, SgStatement *end, const std::map &funcMap, const std::vector ¶llelRegions, std::map> &SPF_messages); bool recSymbolFind(SgExpression *ex, const std::string &symb, const int var); void completeFillOfArrayUsageBetweenProc(const std::map>& loopGraph, const std::map>& allFuncInfo); diff --git a/sapfor/experts/Sapfor_2017/_src/LoopAnalyzer/loop_analyzer.cpp b/sapfor/experts/Sapfor_2017/_src/LoopAnalyzer/loop_analyzer.cpp index fa4476d..393f234 100644 --- a/sapfor/experts/Sapfor_2017/_src/LoopAnalyzer/loop_analyzer.cpp +++ b/sapfor/experts/Sapfor_2017/_src/LoopAnalyzer/loop_analyzer.cpp @@ -2774,9 +2774,9 @@ static void findArrayRefs(SgExpression *ex, SgStatement *st, string fName, int p { DIST::Array* arrayToAdd = new DIST::Array(getShortName(uniqKey), symb->identifier(), ((SgArrayType*)(symb->type()))->dimension(), - getUniqArrayId(), decl->fileName(), decl->lineNumber(), arrayLocation, new Symbol(symb), - findOmpThreadPrivDecl(scope, ompThreadPrivate, symb), false, false, - inRegion, typeSize); + getUniqArrayId(), decl->fileName(), decl->lineNumber(), arrayLocation, new Symbol(symb), + findOmpThreadPrivDecl(scope, ompThreadPrivate, symb), false, false, + inRegion, typeSize, mpiProgram ? DIST::NO_DISTR : DIST::DISTR); itNew = declaredArrays.insert(itNew, make_pair(uniqKey, make_pair(arrayToAdd, new DIST::ArrayAccessInfo()))); diff --git a/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp b/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp index 8d8bb8a..ada72a4 100644 --- a/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp +++ b/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp @@ -497,7 +497,7 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne { auto it = allFuncInfo.find(file_name); if (it == allFuncInfo.end()) - functionAnalyzer(file, allFuncInfo, getObjectForFileFromMap(file_name, loopGraph), getObjectForFileFromMap(file_name, SPF_messages)); + functionAnalyzer(file, allFuncInfo, getObjectForFileFromMap(file_name, loopGraph), getObjectForFileFromMap(file_name, SPF_messages), fullIR); } else if (curr_regime == CALL_GRAPH2) { @@ -905,7 +905,9 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne if (it == allFuncInfo_IR.end()) { vector tmp; - functionAnalyzer(file, allFuncInfo_IR, tmp, getObjectForFileFromMap(file_name, SPF_messages), true); + map> tmp1; + + functionAnalyzer(file, allFuncInfo_IR, tmp, getObjectForFileFromMap(file_name, SPF_messages), tmp1); } } else if (curr_regime == ADD_TEMPL_TO_USE_ONLY) @@ -1293,30 +1295,6 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne removeDistrStateFromDeadFunctions(allFuncInfo, declaredArrays); propagateArrayFlags(arrayLinksByFuncCalls, declaredArrays, SPF_messages); - - //replaced FuncInfo fullIR - map> fullIR_new; - if (allFuncInfo_IR.size() != allFuncInfo.size()) - printInternalError(convertFileName(__FILE__).c_str(), __LINE__); - - for (auto& byFile : allFuncInfo_IR) - { - auto itByFileReal = allFuncInfo.find(byFile.first); - if (itByFileReal == allFuncInfo.end()) - printInternalError(convertFileName(__FILE__).c_str(), __LINE__); - - for (auto& func : byFile.second) - { - if (func->isInterface) - continue; - - auto itOld = fullIR.find(func); - if (itOld == fullIR.end()) - printInternalError(convertFileName(__FILE__).c_str(), __LINE__); - fullIR_new[itOld->first] = itOld->second; - } - } - fullIR_new = fullIR; } else if (curr_regime == CALL_GRAPH2) { @@ -2605,8 +2583,10 @@ int main(int argc, char **argv) pppaAnalyzer(argc - i, argv + i); else if (string(curr_arg) == "-fdvm") convertFiles(argc - i, argv + i); - else if (string(curr_arg) == "-mpi") + else if (string(curr_arg) == "-mpi") { mpiProgram = 1; + ignoreArrayDistributeState = true; + } else if (string(curr_arg) == "-client") { runAsClient = true; diff --git a/sapfor/experts/Sapfor_2017/_src/Utils/SgUtils.cpp b/sapfor/experts/Sapfor_2017/_src/Utils/SgUtils.cpp index 7bb33a6..2b41882 100644 --- a/sapfor/experts/Sapfor_2017/_src/Utils/SgUtils.cpp +++ b/sapfor/experts/Sapfor_2017/_src/Utils/SgUtils.cpp @@ -1553,7 +1553,9 @@ void constructDefUseStep1(SgFile *file, map> &defUseB { map> curFileFuncInfo; vector tmpL; - functionAnalyzer(file, curFileFuncInfo, tmpL, messages); + map> tmpIR; + + functionAnalyzer(file, curFileFuncInfo, tmpL, messages, tmpIR); //functions not found if (curFileFuncInfo.size() == 0) diff --git a/sapfor/experts/Sapfor_2017/_src/Utils/version.h b/sapfor/experts/Sapfor_2017/_src/Utils/version.h index d767411..b37bdf6 100644 --- a/sapfor/experts/Sapfor_2017/_src/Utils/version.h +++ b/sapfor/experts/Sapfor_2017/_src/Utils/version.h @@ -1,3 +1,3 @@ #pragma once -#define VERSION_SPF "2329" +#define VERSION_SPF "2330"