Merge pull request 'private_remoing: add loop alignment check and fix messages' (#44) from private_removing into master

This commit was merged in pull request #44.
This commit is contained in:
2024-04-16 14:39:33 +00:00
3 changed files with 226 additions and 37 deletions

View File

@@ -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);
}
}

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"
// 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";

View File

@@ -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"