private_remoing: add loop alignment check and fix messages
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,12 +95,12 @@ enum typeMessage { WARR, ERROR, NOTE };
|
||||
// 16 "cannot remove private var '%s' - it doesn't match any fixed dimensions mask"
|
||||
// 17 cannot remove private var '%s' - it has recursive dependency or it depends on non-invariant var '%s'
|
||||
// 18 "private variable '%s' was removed" or "private variable '%s' was partially removed"
|
||||
// 19 "cannot remove private var '%s' - it doesn't have any fixed dimensions"
|
||||
// 19 "Removing of private var '%s' was made with assumption that references '%s' and '%s' are different"
|
||||
// 20 "cannot remove private var '%s' - more than one definition reaches the statement"
|
||||
// 21 "cannot remove private var '%s' - cannot find reaching definition for the statement"
|
||||
// 22 "cannot transform ..."
|
||||
// 23 "cannot transform ..."
|
||||
// 24 "loop on line %d was removed"
|
||||
// 24 "Cannot remove private var '%s' - its references have different alignment with the loop"
|
||||
// 25 "Cannot remove private var '%s' - it is used in the call of function '%s'"
|
||||
|
||||
// 30xx PARALLEL GROUP
|
||||
@@ -521,9 +521,9 @@ static const wchar_t *R190 = L"R190:%s#%s";
|
||||
static const wchar_t *R191 = L"R191:%s";
|
||||
static const wchar_t *R201 = L"R201:%s";
|
||||
//2019
|
||||
static const wchar_t *R192 = L"R192:%s";
|
||||
static const wchar_t *R192 = L"R192:%s#%s#%s";
|
||||
//2020
|
||||
static const wchar_t *R193 = L"R193:%s";
|
||||
// static const wchar_t *R193 = L"R193:%s";
|
||||
//2021
|
||||
static const wchar_t *R194 = L"R194:%s";
|
||||
//2022
|
||||
@@ -531,7 +531,7 @@ static const wchar_t *R196 = L"R196:";
|
||||
//2023
|
||||
static const wchar_t *R197 = L"R197:";
|
||||
//2024
|
||||
static const wchar_t *R198 = L"R198:%d";
|
||||
static const wchar_t *R198 = L"R198:%s";
|
||||
//2025
|
||||
static const wchar_t *R203 = L"R203:%s#%s";
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@ R190 = "Нельзя удалить приватную переменную '%s'
|
||||
R191 = "Приватная переменная '%s' была удалена"
|
||||
R201 = "Приватная переменная '%s' была частично удалена"
|
||||
//2019
|
||||
R192 = "Нельзя удалить приватную переменную '%s' - она не имеет фиксированных измерений"
|
||||
R192 = "Удаление приватной переменной '%s' было выполнено в предположении, что выражения '%s' и '%s' различны"
|
||||
//2020
|
||||
R193 = "Нельзя удалить приватную переменную '%s' - более одного определения достигают оператора"
|
||||
//2021
|
||||
@@ -241,7 +241,7 @@ R196 = "Невозможно выполнить преобразование ц
|
||||
//2023
|
||||
R197 = "Преобразование не может быть выполнено - не произошло никаких изменений в коде"
|
||||
//2024
|
||||
R198 = "Цикл на строке %d был удалён"
|
||||
R198 = "Нельзя удалить приватную переменную '%s' - обращения к ней имеют разное выравнивание с циклом"
|
||||
//2025
|
||||
R203 = "Нельзя удалить приватную переменную '%s' - она используется в вызове функции %s"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user