private_remoing: add loop alignment check and fix messages

This commit is contained in:
2024-04-16 00:06:24 +03:00
parent b2693b655a
commit 93bcd1d8e1
3 changed files with 226 additions and 36 deletions

View File

@@ -25,6 +25,21 @@ struct RegularExpr {
string var; string var;
RegularExpr(): coefA(0), coefB(0), 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) static bool operator==(const RegularExpr& left, const RegularExpr& right)
@@ -52,13 +67,38 @@ struct ArraySubscript {
RegularExpr regExprStart; RegularExpr regExprStart;
RegularExpr regExprEnd; RegularExpr regExprEnd;
ArraySubscript() { ArraySubscript()
{
isFixed = false; isFixed = false;
value = 0; value = 0;
isRegIndex = false; isRegIndex = false;
regExprStart = RegularExpr{}; regExprStart = RegularExpr{};
regExprEnd = 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 // 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: * * 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; wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Loop on line %d was removed", loopLineNum); __spf_printToLongBuf(messageE, L"Cannot remove private var '%s' - its references have different alignment with the loop",
__spf_printToLongBuf(messageR, R198, loopLineNum); 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) 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)); messages.push_back(Messages(typeMessage::WARR, loopLineNum, messageR, messageE, 2021));
} }
// TODO: unused: static void addMessagePossibleDifferentAssumption(vector<Messages>& messages, string varName,
//static void addMessageMoreThanOneRD(vector<Messages>& messages, string varName, int loopLineNum) string ref1, string ref2, int loopLineNum)
//{ {
// __spf_print(1, "WARR: cannot remove private var '%s' - more than one definition reaches the statement in line %d\n", __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(), loopLineNum); varName.c_str(), ref1.c_str(), ref2.c_str(), loopLineNum);
//
// wstring messageE, messageR; wstring messageE, messageR;
// __spf_printToLongBuf(messageE, L"Cannot remove private var '%s' - more than one definition reaches the statement", __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(varName).c_str(), to_wstring(ref1).c_str(), to_wstring(ref2).c_str());
// __spf_printToLongBuf(messageR, R193, to_wstring(varName).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, 2020)); messages.push_back(Messages(typeMessage::WARR, loopLineNum, messageR, messageE, 2019));
//} }
static void addMessageRecursiveDependency(vector<Messages>& messages, string varName, int lineNum) 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); 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 // matchesFixedDimensionsMask checks if all array references have INT_VAL value in fixed dimension
static bool checkFixedDimensionsMaskMatching(Context* ctx) static bool checkFixedDimensionsMaskMatching(Context* ctx)
@@ -1848,7 +2010,7 @@ static bool fixedSubscriptLess(const ArraySubscript& left, const ArraySubscript&
// fixedSubscriptLess checks if left and right FixedSubscripts are different, // fixedSubscriptLess checks if left and right FixedSubscripts are different,
// using empirical methods // using empirical methods
static bool possibleDifferent(ArraySubscript left, ArraySubscript right) static bool arePossibleDifferent(ArraySubscript left, ArraySubscript right)
{ {
// TODO: add warning? // TODO: add warning?
if (left.isFixed && right.isRegIndex && right.regExprStart == right.regExprEnd) { if (left.isFixed && right.isRegIndex && right.regExprStart == right.regExprEnd) {
@@ -1858,9 +2020,9 @@ static bool possibleDifferent(ArraySubscript left, ArraySubscript right)
return false; return false;
} }
// isDifferentRefs checks if exp (var reference) is different from var. Refs are different // areDifferentRefs checks if exp (var reference) is different from var
// if they has at least one different fixed subscript: arr(i, 1) is different from arr(j, 2) static bool areDifferentRefs(Context* ctx, SgExpression* exp, const pair<string, vector<ArraySubscript>>& var,
static bool isDifferentRefs(SgExpression* exp, const pair<string, vector<ArraySubscript>>& var, SgStatement* stmt) SgStatement* stmt)
{ {
if (exp->symbol()->identifier() != var.first) if (exp->symbol()->identifier() != var.first)
return true; return true;
@@ -1876,11 +2038,26 @@ static bool isDifferentRefs(SgExpression* exp, const pair<string, vector<ArraySu
for (int i = 0; i < leftVec.size(); i++) for (int i = 0; i < leftVec.size(); i++)
{ {
if (fixedSubscriptLess(leftVec[i], var.second[i]) if (fixedSubscriptLess(leftVec[i], var.second[i])
|| fixedSubscriptLess(var.second[i], leftVec[i]) || fixedSubscriptLess(var.second[i], leftVec[i]))
|| possibleDifferent(leftVec[i], var.second[i]))
{ {
return true; 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; return false;
@@ -1972,7 +2149,7 @@ static bool checkDefUsePair(Context* ctx, const DefUseStmtsPair& defUse, const C
auto useLoopStmt = getScopeLoopStmt(defUse.second); auto useLoopStmt = getScopeLoopStmt(defUse.second);
LoopGraph* loop = ctx->loop; LoopGraph* loop = ctx->loop;
while (loop->perfectLoop != 1) // (what is it? - TODO: may be remove it) while (loop->perfectLoop != 1)
loop = loop->children[0]; loop = loop->children[0];
LoopGraph* defLoop = findLoop(loop, defLoopStmt); LoopGraph* defLoop = findLoop(loop, defLoopStmt);
@@ -2022,7 +2199,7 @@ static bool checkDefUsePair(Context* ctx, const DefUseStmtsPair& defUse, const C
{ {
if (st == defUse.second) if (st == defUse.second)
continue; 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, addMessageDependOnNonInvariant(ctx->messages, arrayName,
var.first, defUse.first->lineNumber()); var.first, defUse.first->lineNumber());
@@ -2179,6 +2356,13 @@ void removePrivatesAnalysis(string filename,
if (context.explicitArrayRefs.empty()) if (context.explicitArrayRefs.empty())
continue; continue;
if (!checkLoopAlignmentMatching(&context))
{
addMessageVarNotAlignedWithLoop(messages, context.arraySymbol->identifier(),
context.loop->lineNum);
continue;
}
context.fixedDimensionsMask = getFixedDimensionsMask(&context); context.fixedDimensionsMask = getFixedDimensionsMask(&context);
if (!context.fixedDimensionsMask.empty() && if (!context.fixedDimensionsMask.empty() &&
@@ -2194,10 +2378,16 @@ void removePrivatesAnalysis(string filename,
removePrivateAnalyze(&context); removePrivateAnalyze(&context);
} }
else else
addMessageDoesNotMatchMask(messages, context.arraySymbol->identifier(), context.loop->lineNum); {
addMessageDoesNotMatchMask(messages, context.arraySymbol->identifier(),
context.loop->lineNum);
}
} }
} }
for (LoopGraph* loop : loopGraphs) for (LoopGraph* loop : loopGraphs)
removePrivatesAnalysis(filename, loop->children, messages, usersDirectives, commonBlocks, allFuncInfo); {
removePrivatesAnalysis(filename, loop->children, messages,
usersDirectives, commonBlocks, allFuncInfo);
}
} }

View File

@@ -95,12 +95,12 @@ enum typeMessage { WARR, ERROR, NOTE };
// 16 "cannot remove private var '%s' - it doesn't match any fixed dimensions mask" // 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' // 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" // 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" // 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" // 21 "cannot remove private var '%s' - cannot find reaching definition for the statement"
// 22 "cannot transform ..." // 22 "cannot transform ..."
// 23 "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'" // 25 "Cannot remove private var '%s' - it is used in the call of function '%s'"
// 30xx PARALLEL GROUP // 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 *R191 = L"R191:%s";
static const wchar_t *R201 = L"R201:%s"; static const wchar_t *R201 = L"R201:%s";
//2019 //2019
static const wchar_t *R192 = L"R192:%s"; static const wchar_t *R192 = L"R192:%s#%s#%s";
//2020 //2020
static const wchar_t *R193 = L"R193:%s"; // static const wchar_t *R193 = L"R193:%s";
//2021 //2021
static const wchar_t *R194 = L"R194:%s"; static const wchar_t *R194 = L"R194:%s";
//2022 //2022
@@ -531,7 +531,7 @@ static const wchar_t *R196 = L"R196:";
//2023 //2023
static const wchar_t *R197 = L"R197:"; static const wchar_t *R197 = L"R197:";
//2024 //2024
static const wchar_t *R198 = L"R198:%d"; static const wchar_t *R198 = L"R198:%s";
//2025 //2025
static const wchar_t *R203 = L"R203:%s#%s"; static const wchar_t *R203 = L"R203:%s#%s";

View File

@@ -231,7 +231,7 @@ R190 = "Нельзя удалить приватную переменную '%s'
R191 = "Приватная переменная '%s' была удалена" R191 = "Приватная переменная '%s' была удалена"
R201 = "Приватная переменная '%s' была частично удалена" R201 = "Приватная переменная '%s' была частично удалена"
//2019 //2019
R192 = "Нельзя удалить приватную переменную '%s' - она не имеет фиксированных измерений" R192 = "Удаление приватной переменной '%s' было выполнено в предположении, что выражения '%s' и '%s' различны"
//2020 //2020
R193 = "Нельзя удалить приватную переменную '%s' - более одного определения достигают оператора" R193 = "Нельзя удалить приватную переменную '%s' - более одного определения достигают оператора"
//2021 //2021
@@ -241,7 +241,7 @@ R196 = "Невозможно выполнить преобразование ц
//2023 //2023
R197 = "Преобразование не может быть выполнено - не произошло никаких изменений в коде" R197 = "Преобразование не может быть выполнено - не произошло никаких изменений в коде"
//2024 //2024
R198 = "Цикл на строке %d был удалён" R198 = "Нельзя удалить приватную переменную '%s' - обращения к ней имеют разное выравнивание с циклом"
//2025 //2025
R203 = "Нельзя удалить приватную переменную '%s' - она используется в вызове функции %s" R203 = "Нельзя удалить приватную переменную '%s' - она используется в вызове функции %s"