improved function analysis
This commit is contained in:
@@ -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<arrayLocation, STRING> &locationPos,
|
||||
Symbol *declSymbol, bool inOmpThreadPriv, bool privateInLoop, bool inEquivalence,
|
||||
const VECTOR<STRING> ®ions, const int typeSize) :
|
||||
const VECTOR<STRING> ®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)
|
||||
{
|
||||
|
||||
@@ -12,13 +12,14 @@
|
||||
#include <stack>
|
||||
|
||||
#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<string, vector<SgExpres
|
||||
currParams.init(numOfParams);
|
||||
|
||||
if (numOfParams > 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<string, vector<SgExpression*>> &commonBlocks, SgStatement *entryHeader)
|
||||
@@ -341,13 +350,11 @@ static void processActualParams(SgExpression *parList, const map<string, vector<
|
||||
}
|
||||
}
|
||||
|
||||
static void findFuncCalls(SgStatement *parent, SgExpression *curr, vector<FuncInfo*> &entryProcs, const int line,
|
||||
static void findFuncCalls(SgStatement *parent, SgExpression *curr, FuncInfo* procInfo, const int line,
|
||||
const map<string, vector<SgExpression*>> &commonBlocks, const set<string> ¯oNames,
|
||||
const vector<SgStatement*> &containsFunctions, const string &prefix)
|
||||
{
|
||||
if (curr->variant() == FUNC_CALL && macroNames.find(curr->symbol()->identifier()) == macroNames.end())
|
||||
{
|
||||
for (auto &proc : entryProcs)
|
||||
{
|
||||
vector<string> nameOfCallFunc;
|
||||
nameOfCallFunc.push_back(curr->symbol()->identifier());
|
||||
@@ -356,7 +363,7 @@ static void findFuncCalls(SgStatement *parent, SgExpression *curr, vector<FuncIn
|
||||
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
|
||||
@@ -364,15 +371,14 @@ static void findFuncCalls(SgStatement *parent, SgExpression *curr, vector<FuncIn
|
||||
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<string,
|
||||
}
|
||||
}
|
||||
|
||||
static void fillInOut(FuncInfo *currF, SgStatement *start, SgStatement *last)
|
||||
static void fillInOut(FuncInfo *currF, SgStatement *start, SgStatement *last, const set<SgStatement*>& 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<Messages> &messagesForFile)
|
||||
static void fillFunctionPureStatus(SgStatement *header, FuncInfo *currInfo, vector<Messages> &messagesForFile, const set<SgStatement*>& activeOps)
|
||||
{
|
||||
if (!currInfo->isMain)
|
||||
{
|
||||
set<int> 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,99 +961,67 @@ static void fillCommons(FuncInfo *currInfo, const map<string, vector<SgExpressio
|
||||
}
|
||||
}
|
||||
|
||||
void functionAnalyzer(SgFile *file, map<string, vector<FuncInfo*>> &allFuncInfo, vector<LoopGraph*> &loops, vector<Messages> &messagesForFile, bool dontFillFuncParam)
|
||||
static FuncInfo* createNewFuction(const string& funcName, SgStatement *st, SgStatement* entry,
|
||||
vector<Messages>& messagesForFile,
|
||||
const map<string, vector<SgExpression*>>& commonBlocks,
|
||||
const set<SgStatement*>& activeOps)
|
||||
{
|
||||
map<int, LoopGraph*> mapLoopGraph;
|
||||
createMapLoopGraph(loops, mapLoopGraph);
|
||||
|
||||
int funcNum = file->numberOfFunctions();
|
||||
__spf_print(DEBUG, "functions num in file = %d\n", funcNum);
|
||||
vector<SgStatement*> containsFunctions;
|
||||
|
||||
for (int i = 0; i < funcNum; ++i)
|
||||
{
|
||||
SgStatement *st = file->functions(i);
|
||||
string containsPrefix = "";
|
||||
|
||||
SgStatement *st_cp = st->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)
|
||||
{
|
||||
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());
|
||||
}
|
||||
else if (st->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());
|
||||
}
|
||||
else if (st->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());
|
||||
}
|
||||
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<FuncInfo*>()));
|
||||
|
||||
map<string, vector<SgExpression*>> 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 });
|
||||
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);
|
||||
fillFunctionPureStatus(st, currInfo, messagesForFile, activeOps);
|
||||
|
||||
if (st->variant() != PROG_HEDR)
|
||||
{
|
||||
SgProgHedrStmt* procFuncHedr = ((SgProgHedrStmt*)st);
|
||||
|
||||
if (st == entry)
|
||||
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());
|
||||
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", currFunc.c_str());
|
||||
__spf_print(1, "set NOINLINE attribute for function '%s'\n", funcName.c_str());
|
||||
currInfo->doNotInline = true;
|
||||
}
|
||||
|
||||
it->second.push_back(currInfo);
|
||||
return currInfo;
|
||||
}
|
||||
|
||||
vector<FuncInfo*> entryProcs;
|
||||
entryProcs.push_back(currInfo);
|
||||
static void analyzeFunction(const string& funcName, const string& containsPrefix,
|
||||
SgStatement *function, SgStatement* entry, map<string, vector<FuncInfo*>>& allFuncInfo,
|
||||
const map<int, LoopGraph*>& mapLoopGraph, vector<Messages>& messagesForFile,
|
||||
vector<SgStatement*>& containsFunctions,
|
||||
const set<SgStatement*>& 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<FuncInfo*>()));
|
||||
|
||||
map<string, vector<SgExpression*>> 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<SgStatement*> macroStats;
|
||||
set<string> macroNames;
|
||||
|
||||
while (st != lastNode)
|
||||
{
|
||||
if (st->variant() == CONTAINS_STMT)
|
||||
@@ -1052,7 +1034,7 @@ void functionAnalyzer(SgFile *file, map<string, vector<FuncInfo*>> &allFuncInfo,
|
||||
{
|
||||
if (st->variant() == PROC_HEDR || st->variant() == FUNC_HEDR)
|
||||
{
|
||||
currInfo->interfaceBlocks[st->symbol()->identifier()] = NULL;
|
||||
procInfo->interfaceBlocks[st->symbol()->identifier()] = NULL;
|
||||
st = st->lastNodeOfStmt();
|
||||
}
|
||||
st = st->lexNext();
|
||||
@@ -1078,8 +1060,9 @@ void functionAnalyzer(SgFile *file, map<string, vector<FuncInfo*>> &allFuncInfo,
|
||||
st = st->lexNext();
|
||||
}
|
||||
|
||||
SgStatement* origStart = NULL;
|
||||
origStart = st = file->functions(i);
|
||||
st = function;
|
||||
const string file = st->fileName();
|
||||
|
||||
while (st != lastNode)
|
||||
{
|
||||
if (st == NULL)
|
||||
@@ -1091,19 +1074,32 @@ void functionAnalyzer(SgFile *file, map<string, vector<FuncInfo*>> &allFuncInfo,
|
||||
if (st->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
if (!__gcov_doesThisLineExecuted(st->fileName(), st->lineNumber()))
|
||||
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())
|
||||
currInfo->externalCalls.insert(ex->lhs()->symbol()->identifier());
|
||||
procInfo->externalCalls.insert(ex->lhs()->symbol()->identifier());
|
||||
|
||||
const string prefix = containsPrefix == "" ? currFunc + "." : containsPrefix;
|
||||
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)
|
||||
{
|
||||
@@ -1114,12 +1110,10 @@ void functionAnalyzer(SgFile *file, map<string, vector<FuncInfo*>> &allFuncInfo,
|
||||
for (auto& elem : pureNameOfCallFunc)
|
||||
correctNameIfContains(st, NULL, elem, containsFunctions, prefix);
|
||||
|
||||
for (auto &proc : entryProcs)
|
||||
{
|
||||
if (hasRecCall(proc, pureNameOfCallFunc))
|
||||
if (hasRecCall(procInfo, pureNameOfCallFunc))
|
||||
continue;
|
||||
|
||||
proc->callsFrom.insert(pureNameOfCallFunc.begin(), pureNameOfCallFunc.end());
|
||||
procInfo->callsFrom.insert(pureNameOfCallFunc.begin(), pureNameOfCallFunc.end());
|
||||
|
||||
FuncInfoCallFrom newCall;
|
||||
newCall.detailCallsFrom = make_pair(pureNameOfCallFunc[1], st->lineNumber()); // original name of call
|
||||
@@ -1127,15 +1121,15 @@ void functionAnalyzer(SgFile *file, map<string, vector<FuncInfo*>> &allFuncInfo,
|
||||
newCall.parentForPointer = st;
|
||||
newCall.actualParams = FuncParam();
|
||||
|
||||
processActualParams(st->expr(0), commonBlocks, newCall.actualParams, proc->externalCalls);
|
||||
proc->callsFromDetailed.push_back(newCall);
|
||||
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]);
|
||||
proc->funcsCalledFromThis.push_back(funcCall);
|
||||
procInfo->funcsCalledFromThis.push_back(funcCall);
|
||||
|
||||
// search for using pars of cur func in pars of called
|
||||
throughParams(st->expr(0), *proc, containsFunctions, prefix);
|
||||
throughParams(st->expr(0), *procInfo, containsFunctions, prefix);
|
||||
|
||||
//find external calls
|
||||
for (SgExpression* par = st->expr(0); par != NULL; par = par->rhs())
|
||||
@@ -1146,7 +1140,7 @@ void functionAnalyzer(SgFile *file, map<string, vector<FuncInfo*>> &allFuncInfo,
|
||||
if (curr->variant() == VAR_REF)
|
||||
{
|
||||
auto s = curr->symbol();
|
||||
if (currInfo->externalCalls.find(s->identifier()) != currInfo->externalCalls.end() ||
|
||||
if (procInfo->externalCalls.find(s->identifier()) != procInfo->externalCalls.end() ||
|
||||
(s->attributes() & EXTERNAL_BIT))
|
||||
{
|
||||
vector<string> nameOfCallFunc;
|
||||
@@ -1156,7 +1150,7 @@ void functionAnalyzer(SgFile *file, map<string, vector<FuncInfo*>> &allFuncInfo,
|
||||
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], st->lineNumber()); // original name of call
|
||||
@@ -1164,8 +1158,7 @@ void functionAnalyzer(SgFile *file, map<string, vector<FuncInfo*>> &allFuncInfo,
|
||||
newCall.parentForPointer = st;
|
||||
newCall.actualParams = FuncParam();
|
||||
|
||||
proc->callsFromDetailed.push_back(newCall);
|
||||
}
|
||||
procInfo->callsFromDetailed.push_back(newCall);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1173,53 +1166,26 @@ void functionAnalyzer(SgFile *file, map<string, vector<FuncInfo*>> &allFuncInfo,
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto &proc : entryProcs)
|
||||
for (int i = 0; i < 3; ++i)
|
||||
if (st->expr(i))
|
||||
findParamUsedInFuncCalls(st->expr(i), *proc, containsFunctions, prefix);
|
||||
findParamUsedInFuncCalls(st->expr(i), *procInfo, 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());
|
||||
}
|
||||
findFuncCalls(st, st->expr(i), procInfo, st->lineNumber(), commonBlocks, macroNames, containsFunctions, prefix);
|
||||
|
||||
if (isSgExecutableStatement(st))
|
||||
{
|
||||
for (auto &proc : entryProcs)
|
||||
if (proc->isParamUsedAsIndex.size())
|
||||
if (procInfo->isParamUsedAsIndex.size())
|
||||
for (int i = 0; i < 3; i++)
|
||||
findArrayRef(st->expr(i), *proc, st->variant() == ASSIGN_STAT && i == 0);
|
||||
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())
|
||||
{
|
||||
for (auto &proc : entryProcs)
|
||||
proc->loopsInFunc.push_back(itL->second);
|
||||
}
|
||||
procInfo->loopsInFunc.push_back(itL->second);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1227,6 +1193,136 @@ void functionAnalyzer(SgFile *file, map<string, vector<FuncInfo*>> &allFuncInfo,
|
||||
}
|
||||
}
|
||||
|
||||
static set<SgStatement*> fillActiveOperators(const vector<SAPFOR::BasicBlock*>& blocks)
|
||||
{
|
||||
if (blocks.size() == 0)
|
||||
return set<SgStatement*>();
|
||||
|
||||
set<SgStatement*> active;
|
||||
set<SAPFOR::BasicBlock*> 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<string, vector<FuncInfo*>> &allFuncInfo, const vector<LoopGraph*> &loops, vector<Messages> &messagesForFile,
|
||||
map<FuncInfo*, vector<SAPFOR::BasicBlock*>> &fullIR)
|
||||
{
|
||||
map<int, LoopGraph*> mapLoopGraph;
|
||||
createMapLoopGraph(loops, mapLoopGraph);
|
||||
|
||||
map<SgStatement*, FuncInfo*> 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<SgStatement*> containsFunctions;
|
||||
|
||||
vector<SgStatement*> functions;
|
||||
for (int i = 0; i < funcNum; ++i)
|
||||
{
|
||||
auto func = file->functions(i);
|
||||
functions.push_back(func);
|
||||
|
||||
//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 funcName = "";
|
||||
if (function->variant() == PROG_HEDR)
|
||||
{
|
||||
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 (function->variant() == PROC_HEDR)
|
||||
{
|
||||
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 (function->variant() == FUNC_HEDR)
|
||||
{
|
||||
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__);
|
||||
|
||||
set<SgStatement*> activeOps;
|
||||
if (fullIR.size())
|
||||
{
|
||||
if (tmpInfoInIR.count(function) == 0)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
activeOps = fillActiveOperators(fullIR[tmpInfoInIR[function]]);
|
||||
activeOps.insert(function);
|
||||
if (isEntry)
|
||||
activeOps.insert(function->controlParent());
|
||||
}
|
||||
|
||||
analyzeFunction(funcName, containsPrefix, isEntry ? function->controlParent() : function, function, allFuncInfo, mapLoopGraph, messagesForFile, containsFunctions, activeOps);
|
||||
}
|
||||
|
||||
//fill INTERFACE block from modules
|
||||
vector<SgStatement*> modules;
|
||||
findModulesInFile(file, modules);
|
||||
@@ -1275,6 +1371,30 @@ void functionAnalyzer(SgFile *file, map<string, vector<FuncInfo*>> &allFuncInfo,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto it = allFuncInfo.find(file->filename());
|
||||
if (it == allFuncInfo.end())
|
||||
return;
|
||||
|
||||
if (fullIR.size() == 0)
|
||||
return;
|
||||
|
||||
vector<FuncInfo*> 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)
|
||||
|
||||
@@ -14,6 +14,11 @@ namespace Distribution
|
||||
}
|
||||
namespace DIST = Distribution;
|
||||
|
||||
namespace SAPFOR
|
||||
{
|
||||
class BasicBlock;
|
||||
}
|
||||
|
||||
int CreateCallGraphViz(const char *fileName, const std::map<std::string, std::vector<FuncInfo*>> &funcByFile, std::map<std::string, CallV> &V, std::vector<std::string> &E);
|
||||
int CreateFuncInfo(const char *fileName, const std::map<std::string, std::vector<FuncInfo*>> &funcByFile);
|
||||
std::string removeString(const std::string &toRemove, const std::string &inStr);
|
||||
@@ -32,7 +37,7 @@ void updateFuncInfo(const std::map<std::string, std::vector<FuncInfo*>> &allFunc
|
||||
void excludeArraysFromDistribution(const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls, const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>> declaredArrays, std::map<std::string, std::vector<LoopGraph*>>& loopGraph, std::vector<ParallelRegion*> parallelRegions, std::map<std::string, std::vector<Messages>>& SPF_messages, std::map<std::tuple<int, std::string, std::string>, DIST::Array*>& createdArrays, int mpiProgram = 0);
|
||||
|
||||
#if __SPF
|
||||
void functionAnalyzer(SgFile *file, std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo, std::vector<LoopGraph*> &loops, std::vector<Messages> &messagesForFile, bool dontFillFuncParam = false);
|
||||
void functionAnalyzer(SgFile *file, std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo, const std::vector<LoopGraph*> &loops, std::vector<Messages> &messagesForFile, std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& fullIR);
|
||||
int CheckFunctionsToInline(SgProject *proj, const std::map<std::string, int> &files, const char *fileName,
|
||||
std::map<std::string, std::vector<FuncInfo*>> &funcByFile, const std::map<std::string, std::vector<LoopGraph*>> &loopGraph,
|
||||
std::map<std::string, std::vector<Messages>> &allMessages, bool needToAddErrors,
|
||||
|
||||
@@ -318,24 +318,32 @@ bool checkRegionEntries(SgStatement *begin,
|
||||
return noError;
|
||||
}
|
||||
|
||||
bool hasThisIds(SgStatement *start, set<int> &lines, const set<int> &IDs)
|
||||
bool hasThisIds(SgStatement *start, set<int> &lines, const set<int> &IDs, const std::set<SgStatement*>* 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*> &loopGraph, const vector<SpfInterval*> &intervalTree, vector<Messages> &messages, int mpiProgram)
|
||||
{
|
||||
map<int, SpfInterval*> mapIntervals;
|
||||
@@ -653,6 +695,7 @@ void loopGraphAnalyzer(SgFile *file, vector<LoopGraph*> &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);
|
||||
|
||||
@@ -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<LoopGraph*> children;
|
||||
std::vector<LoopGraph*> funcChildren;
|
||||
|
||||
@@ -12,7 +12,7 @@ void findAllRefsToLables(SgStatement *st, std::map<int, std::vector<int>> &label
|
||||
std::map<LoopGraph*, ParallelDirective*> findAllDirectives(SgFile *file, const std::vector<LoopGraph*> &loops, const uint64_t regId);
|
||||
std::vector<std::tuple<DIST::Array*, std::vector<long>, std::pair<std::string, int>>> findAllSingleRemotes(SgFile *file, const uint64_t regId, std::vector<ParallelRegion*> ®ions);
|
||||
std::map<DIST::Array*, std::vector<long>> fillRemoteInParallel(Statement *st);
|
||||
bool hasThisIds(SgStatement *loop, std::set<int> &lines, const std::set<int> &IDs);
|
||||
bool hasThisIds(SgStatement *loop, std::set<int> &lines, const std::set<int> &IDs, const std::set<SgStatement*>* activeOps = NULL);
|
||||
bool checkRegionEntries(SgStatement *begin, SgStatement *end, const std::map<std::string, FuncInfo*> &funcMap, const std::vector<ParallelRegion*> ¶llelRegions, std::map<std::string, std::vector<Messages>> &SPF_messages);
|
||||
bool recSymbolFind(SgExpression *ex, const std::string &symb, const int var);
|
||||
void completeFillOfArrayUsageBetweenProc(const std::map<std::string, std::vector<LoopGraph*>>& loopGraph, const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);
|
||||
|
||||
@@ -2776,7 +2776,7 @@ static void findArrayRefs(SgExpression *ex, SgStatement *st, string fName, int p
|
||||
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);
|
||||
inRegion, typeSize, mpiProgram ? DIST::NO_DISTR : DIST::DISTR);
|
||||
|
||||
itNew = declaredArrays.insert(itNew, make_pair(uniqKey, make_pair(arrayToAdd, new DIST::ArrayAccessInfo())));
|
||||
|
||||
|
||||
@@ -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<LoopGraph*> tmp;
|
||||
functionAnalyzer(file, allFuncInfo_IR, tmp, getObjectForFileFromMap(file_name, SPF_messages), true);
|
||||
map<FuncInfo*, vector<SAPFOR::BasicBlock*>> 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<FuncInfo*, vector<SAPFOR::BasicBlock*>> 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;
|
||||
|
||||
@@ -1553,7 +1553,9 @@ void constructDefUseStep1(SgFile *file, map<string, vector<DefUseList>> &defUseB
|
||||
{
|
||||
map<string, vector<FuncInfo*>> curFileFuncInfo;
|
||||
vector<LoopGraph*> tmpL;
|
||||
functionAnalyzer(file, curFileFuncInfo, tmpL, messages);
|
||||
map<FuncInfo*, vector<SAPFOR::BasicBlock*>> tmpIR;
|
||||
|
||||
functionAnalyzer(file, curFileFuncInfo, tmpL, messages, tmpIR);
|
||||
|
||||
//functions not found
|
||||
if (curFileFuncInfo.size() == 0)
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#define VERSION_SPF "2329"
|
||||
#define VERSION_SPF "2330"
|
||||
|
||||
Reference in New Issue
Block a user