|
|
|
|
@@ -25,6 +25,21 @@ struct RegularExpr {
|
|
|
|
|
string var;
|
|
|
|
|
|
|
|
|
|
RegularExpr(): coefA(0), coefB(0), var("") {}
|
|
|
|
|
|
|
|
|
|
string toString() const
|
|
|
|
|
{
|
|
|
|
|
string result = var;
|
|
|
|
|
|
|
|
|
|
if (coefA != 1)
|
|
|
|
|
result = std::to_string(coefA) + "*" + var;
|
|
|
|
|
|
|
|
|
|
if (coefB > 0)
|
|
|
|
|
result += " + " + std::to_string(coefB);
|
|
|
|
|
else if (coefB < 0)
|
|
|
|
|
result += " - " + std::to_string((-1) * coefB);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static bool operator==(const RegularExpr& left, const RegularExpr& right)
|
|
|
|
|
@@ -52,13 +67,38 @@ struct ArraySubscript {
|
|
|
|
|
RegularExpr regExprStart;
|
|
|
|
|
RegularExpr regExprEnd;
|
|
|
|
|
|
|
|
|
|
ArraySubscript() {
|
|
|
|
|
ArraySubscript()
|
|
|
|
|
{
|
|
|
|
|
isFixed = false;
|
|
|
|
|
value = 0;
|
|
|
|
|
isRegIndex = false;
|
|
|
|
|
regExprStart = RegularExpr{};
|
|
|
|
|
regExprEnd = RegularExpr{};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string toStringStart() const
|
|
|
|
|
{
|
|
|
|
|
if (isFixed)
|
|
|
|
|
return std::to_string(value);
|
|
|
|
|
|
|
|
|
|
return regExprStart.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string toStringEnd() const
|
|
|
|
|
{
|
|
|
|
|
if (isFixed)
|
|
|
|
|
return std::to_string(value);
|
|
|
|
|
|
|
|
|
|
return regExprEnd.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string toString() const
|
|
|
|
|
{
|
|
|
|
|
if (regExprStart == regExprEnd)
|
|
|
|
|
return this->toStringStart();
|
|
|
|
|
|
|
|
|
|
return this->toStringStart() + ":" + this->toStringEnd();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// DefUseStmtsPair represents pair of DEF and USE statements for private variable
|
|
|
|
|
@@ -337,15 +377,17 @@ static void fillIterationVars(SgStatement* stmt, SgStatement* outerLoopStmt, vec
|
|
|
|
|
* Block of creating messages functions: *
|
|
|
|
|
* ************************************* */
|
|
|
|
|
|
|
|
|
|
static void addMessageRemoveLoop(vector<Messages>& messages, int loopLineNum)
|
|
|
|
|
static void addMessageVarNotAlignedWithLoop(vector<Messages>& messages, string varName, int loopLineNum)
|
|
|
|
|
{
|
|
|
|
|
__spf_print(1, "NOTE: loop on line %d was removed\n", loopLineNum);
|
|
|
|
|
__spf_print(1, "WARR: cannot remove private var '%s' - its references have different alignment with the loop %d\n",
|
|
|
|
|
varName.c_str(), loopLineNum);
|
|
|
|
|
|
|
|
|
|
wstring messageE, messageR;
|
|
|
|
|
__spf_printToLongBuf(messageE, L"Loop on line %d was removed", loopLineNum);
|
|
|
|
|
__spf_printToLongBuf(messageR, R198, loopLineNum);
|
|
|
|
|
__spf_printToLongBuf(messageE, L"Cannot remove private var '%s' - its references have different alignment with the loop",
|
|
|
|
|
to_wstring(varName).c_str());
|
|
|
|
|
__spf_printToLongBuf(messageR, R198, to_wstring(varName).c_str());
|
|
|
|
|
|
|
|
|
|
messages.push_back(Messages(typeMessage::NOTE, loopLineNum, messageR, messageE, 2024));
|
|
|
|
|
messages.push_back(Messages(typeMessage::WARR, loopLineNum, messageR, messageE, 2024));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addMessageRemovePrivateVar(vector<Messages>& messages, string varName, int loopLineNum)
|
|
|
|
|
@@ -385,19 +427,19 @@ static void addMessageCannotFindRD(vector<Messages>& messages, string varName, i
|
|
|
|
|
messages.push_back(Messages(typeMessage::WARR, loopLineNum, messageR, messageE, 2021));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: unused:
|
|
|
|
|
//static void addMessageMoreThanOneRD(vector<Messages>& messages, string varName, int loopLineNum)
|
|
|
|
|
//{
|
|
|
|
|
// __spf_print(1, "WARR: cannot remove private var '%s' - more than one definition reaches the statement in line %d\n",
|
|
|
|
|
// varName.c_str(), loopLineNum);
|
|
|
|
|
//
|
|
|
|
|
// wstring messageE, messageR;
|
|
|
|
|
// __spf_printToLongBuf(messageE, L"Cannot remove private var '%s' - more than one definition reaches the statement",
|
|
|
|
|
// to_wstring(varName).c_str());
|
|
|
|
|
// __spf_printToLongBuf(messageR, R193, to_wstring(varName).c_str());
|
|
|
|
|
//
|
|
|
|
|
// messages.push_back(Messages(typeMessage::WARR, loopLineNum, messageR, messageE, 2020));
|
|
|
|
|
//}
|
|
|
|
|
static void addMessagePossibleDifferentAssumption(vector<Messages>& messages, string varName,
|
|
|
|
|
string ref1, string ref2, int loopLineNum)
|
|
|
|
|
{
|
|
|
|
|
__spf_print(1, "WARR: removing of private var '%s' was made with assumption that references '%s' and '%s' are different in line %d\n",
|
|
|
|
|
varName.c_str(), ref1.c_str(), ref2.c_str(), loopLineNum);
|
|
|
|
|
|
|
|
|
|
wstring messageE, messageR;
|
|
|
|
|
__spf_printToLongBuf(messageE, L"Removing of private var '%s' was made with assumption that references '%s' and '%s' are different",
|
|
|
|
|
to_wstring(varName).c_str(), to_wstring(ref1).c_str(), to_wstring(ref2).c_str());
|
|
|
|
|
__spf_printToLongBuf(messageR, R192, to_wstring(varName).c_str(), to_wstring(ref1).c_str(), to_wstring(ref2).c_str());
|
|
|
|
|
|
|
|
|
|
messages.push_back(Messages(typeMessage::WARR, loopLineNum, messageR, messageE, 2019));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addMessageRecursiveDependency(vector<Messages>& messages, string varName, int lineNum)
|
|
|
|
|
{
|
|
|
|
|
@@ -963,6 +1005,126 @@ static vector<int> getShortFixedSubscriptsVector(Context* ctx, SgArrayRefExp* ar
|
|
|
|
|
return getShortFixedSubscriptsVector(arrayRef, ctx->fixedDimensionsMask, ctx->regime, iterationVars);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// getLoopsInfo return vector of pair (string, int) - doName and level for each loop
|
|
|
|
|
// from stmt up to outerLoop (not only closely nested). Loop levels start from 1
|
|
|
|
|
static void getLoopsInfo(SgStatement* stmt, SgStatement* outerLoop,
|
|
|
|
|
vector<pair<string, int>>& loopsInfo)
|
|
|
|
|
{
|
|
|
|
|
if (stmt == nullptr)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
if (stmt->variant() == FOR_NODE)
|
|
|
|
|
{
|
|
|
|
|
string doName = ((SgForStmt*)stmt)->doName()->identifier();
|
|
|
|
|
loopsInfo.push_back(make_pair(doName, 0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (stmt == outerLoop)
|
|
|
|
|
{
|
|
|
|
|
int levelsNum = loopsInfo.size();
|
|
|
|
|
for (int i = 0; i < levelsNum; ++i)
|
|
|
|
|
loopsInfo[i].second = levelsNum - i;
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getLoopsInfo(stmt->controlParent(), outerLoop, loopsInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// checkLoopAlignmentMatching checks if all array references in loop has the same alignment
|
|
|
|
|
// with nested loops
|
|
|
|
|
static bool checkLoopAlignmentMatching(Context* ctx)
|
|
|
|
|
{
|
|
|
|
|
// Loop alignment is a pair of loop alignment vector
|
|
|
|
|
// and a number of nested loops for current statement context (not only closely nested).
|
|
|
|
|
// Loop alignment vector is a vector of ctx->dimensionsNum length of loop levels
|
|
|
|
|
// or -1, if dimension is not aligned with any loop.
|
|
|
|
|
// Dimension is aligned with loop, if subscript expression has iteration var of this loop
|
|
|
|
|
// (and only of this loop).
|
|
|
|
|
set<pair<vector<int>, int>> loopAlignmentSet;
|
|
|
|
|
|
|
|
|
|
for (SgStatement* st = ctx->loopStmt; st != ctx->loopStmt->lastNodeOfStmt(); st = st->lexNext())
|
|
|
|
|
{
|
|
|
|
|
vector<SgArrayRefExp*> arrayRefs = getDirectArrayRefsFromSingleStmt(st, ctx->arraySymbol);
|
|
|
|
|
if (arrayRefs.empty())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
vector<pair<string, int>> loopsInfoVector;
|
|
|
|
|
getLoopsInfo(st, ctx->loopStmt, loopsInfoVector);
|
|
|
|
|
|
|
|
|
|
for (SgArrayRefExp* arrayRef : arrayRefs)
|
|
|
|
|
{
|
|
|
|
|
vector<int> arrayRefLoopAlignment;
|
|
|
|
|
for (int i = 0; i < ctx->dimensionsNum; ++i)
|
|
|
|
|
{
|
|
|
|
|
bool foundIterationVar = false;
|
|
|
|
|
|
|
|
|
|
set<string> vars;
|
|
|
|
|
getVariables(arrayRef->subscript(i), vars, { VAR_REF });
|
|
|
|
|
for (string var : vars)
|
|
|
|
|
{
|
|
|
|
|
for (auto& loopInfo : loopsInfoVector)
|
|
|
|
|
{
|
|
|
|
|
if (loopInfo.first != var)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// There are two iteration vars in subscript expression
|
|
|
|
|
// or one var is iteration var for more than one loop:
|
|
|
|
|
if (foundIterationVar)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
foundIterationVar = true;
|
|
|
|
|
arrayRefLoopAlignment.push_back(loopInfo.second);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!foundIterationVar)
|
|
|
|
|
arrayRefLoopAlignment.push_back(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
loopAlignmentSet.insert(make_pair(arrayRefLoopAlignment, loopsInfoVector.size()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if all loop alignments has similar alignment diff.
|
|
|
|
|
// Alignment diff is a difference between the number of nested loops (size of loopInfoVector)
|
|
|
|
|
// and the number of aligned dimensions (alignment counter).
|
|
|
|
|
int alignmentDiff = -1;
|
|
|
|
|
for (auto& loopAlignment : loopAlignmentSet)
|
|
|
|
|
{
|
|
|
|
|
int currentAlignmentCounter = ctx->dimensionsNum;
|
|
|
|
|
for (int i = 0; i < ctx->dimensionsNum; ++i)
|
|
|
|
|
if (loopAlignment.first[i] == -1) // if dimension is not aligned
|
|
|
|
|
currentAlignmentCounter--;
|
|
|
|
|
|
|
|
|
|
int currentAlignmentDiff = loopAlignment.second - currentAlignmentCounter;
|
|
|
|
|
if (alignmentDiff == -1)
|
|
|
|
|
alignmentDiff = currentAlignmentDiff;
|
|
|
|
|
else if (alignmentDiff != currentAlignmentDiff)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if there are any different loop alignments.
|
|
|
|
|
// Two loop alignments are different if they have different loop level alignments
|
|
|
|
|
// in the same dimension. The case when one of two different loop level is -1
|
|
|
|
|
// (there is no loop alignment) is not a problem
|
|
|
|
|
for (int i = 0; i < ctx->dimensionsNum; ++i)
|
|
|
|
|
{
|
|
|
|
|
int currentLoopLevel = -1;
|
|
|
|
|
for (auto& loopAlignment : loopAlignmentSet)
|
|
|
|
|
{
|
|
|
|
|
if (loopAlignment.first[i] != -1) // if loop alignment is not empty
|
|
|
|
|
{
|
|
|
|
|
if (currentLoopLevel == -1)
|
|
|
|
|
currentLoopLevel = loopAlignment.first[i];
|
|
|
|
|
else if (currentLoopLevel != loopAlignment.first[i])
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// matchesFixedDimensionsMask checks if all array references have INT_VAL value in fixed dimension
|
|
|
|
|
static bool checkFixedDimensionsMaskMatching(Context* ctx)
|
|
|
|
|
@@ -1848,9 +2010,8 @@ static bool fixedSubscriptLess(const ArraySubscript& left, const ArraySubscript&
|
|
|
|
|
|
|
|
|
|
// fixedSubscriptLess checks if left and right FixedSubscripts are different,
|
|
|
|
|
// using empirical methods
|
|
|
|
|
static bool possibleDifferent(ArraySubscript left, ArraySubscript right)
|
|
|
|
|
static bool arePossibleDifferent(ArraySubscript left, ArraySubscript right)
|
|
|
|
|
{
|
|
|
|
|
// TODO: add warning?
|
|
|
|
|
if (left.isFixed && right.isRegIndex && right.regExprStart == right.regExprEnd) {
|
|
|
|
|
return true; // in general, this is not true
|
|
|
|
|
}
|
|
|
|
|
@@ -1858,9 +2019,9 @@ static bool possibleDifferent(ArraySubscript left, ArraySubscript right)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// isDifferentRefs checks if exp (var reference) is different from var. Refs are different
|
|
|
|
|
// if they has at least one different fixed subscript: arr(i, 1) is different from arr(j, 2)
|
|
|
|
|
static bool isDifferentRefs(SgExpression* exp, const pair<string, vector<ArraySubscript>>& var, SgStatement* stmt)
|
|
|
|
|
// areDifferentRefs checks if exp (var reference) is different from var
|
|
|
|
|
static bool areDifferentRefs(Context* ctx, SgExpression* exp, const pair<string, vector<ArraySubscript>>& var,
|
|
|
|
|
SgStatement* stmt)
|
|
|
|
|
{
|
|
|
|
|
if (exp->symbol()->identifier() != var.first)
|
|
|
|
|
return true;
|
|
|
|
|
@@ -1876,11 +2037,26 @@ static bool isDifferentRefs(SgExpression* exp, const pair<string, vector<ArraySu
|
|
|
|
|
for (int i = 0; i < leftVec.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
if (fixedSubscriptLess(leftVec[i], var.second[i])
|
|
|
|
|
|| fixedSubscriptLess(var.second[i], leftVec[i])
|
|
|
|
|
|| possibleDifferent(leftVec[i], var.second[i]))
|
|
|
|
|
|| fixedSubscriptLess(var.second[i], leftVec[i]))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (arePossibleDifferent(leftVec[i], var.second[i]))
|
|
|
|
|
{
|
|
|
|
|
string varRefStr = var.first + "(";
|
|
|
|
|
for (int i = 0; i < var.second.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
varRefStr += var.second[i].toString();
|
|
|
|
|
if (i != var.second.size() - 1)
|
|
|
|
|
varRefStr += ",";
|
|
|
|
|
}
|
|
|
|
|
varRefStr += ")";
|
|
|
|
|
|
|
|
|
|
addMessagePossibleDifferentAssumption(ctx->messages, ctx->arraySymbol->identifier(),
|
|
|
|
|
exp->sunparse(), varRefStr, stmt->lineNumber());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
@@ -1972,7 +2148,7 @@ static bool checkDefUsePair(Context* ctx, const DefUseStmtsPair& defUse, const C
|
|
|
|
|
auto useLoopStmt = getScopeLoopStmt(defUse.second);
|
|
|
|
|
|
|
|
|
|
LoopGraph* loop = ctx->loop;
|
|
|
|
|
while (loop->perfectLoop != 1) // (what is it? - TODO: may be remove it)
|
|
|
|
|
while (loop->perfectLoop != 1)
|
|
|
|
|
loop = loop->children[0];
|
|
|
|
|
|
|
|
|
|
LoopGraph* defLoop = findLoop(loop, defLoopStmt);
|
|
|
|
|
@@ -2022,7 +2198,7 @@ static bool checkDefUsePair(Context* ctx, const DefUseStmtsPair& defUse, const C
|
|
|
|
|
{
|
|
|
|
|
if (st == defUse.second)
|
|
|
|
|
continue;
|
|
|
|
|
if (st->variant() == ASSIGN_STAT && !isDifferentRefs(st->expr(0), var, st))
|
|
|
|
|
if (st->variant() == ASSIGN_STAT && !areDifferentRefs(ctx, st->expr(0), var, st))
|
|
|
|
|
{
|
|
|
|
|
addMessageDependOnNonInvariant(ctx->messages, arrayName,
|
|
|
|
|
var.first, defUse.first->lineNumber());
|
|
|
|
|
@@ -2179,6 +2355,13 @@ void removePrivatesAnalysis(string filename,
|
|
|
|
|
if (context.explicitArrayRefs.empty())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!checkLoopAlignmentMatching(&context))
|
|
|
|
|
{
|
|
|
|
|
addMessageVarNotAlignedWithLoop(messages, context.arraySymbol->identifier(),
|
|
|
|
|
context.loop->lineNum);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
context.fixedDimensionsMask = getFixedDimensionsMask(&context);
|
|
|
|
|
|
|
|
|
|
if (!context.fixedDimensionsMask.empty() &&
|
|
|
|
|
@@ -2194,10 +2377,16 @@ void removePrivatesAnalysis(string filename,
|
|
|
|
|
removePrivateAnalyze(&context);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
addMessageDoesNotMatchMask(messages, context.arraySymbol->identifier(), context.loop->lineNum);
|
|
|
|
|
{
|
|
|
|
|
addMessageDoesNotMatchMask(messages, context.arraySymbol->identifier(),
|
|
|
|
|
context.loop->lineNum);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (LoopGraph* loop : loopGraphs)
|
|
|
|
|
removePrivatesAnalysis(filename, loop->children, messages, usersDirectives, commonBlocks, allFuncInfo);
|
|
|
|
|
{
|
|
|
|
|
removePrivatesAnalysis(filename, loop->children, messages,
|
|
|
|
|
usersDirectives, commonBlocks, allFuncInfo);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|