From 1e9e1db084fc0b0498f19cbe3b61c7c8e4b95ecf Mon Sep 17 00:00:00 2001 From: Grigorii Gusev Date: Sat, 24 Feb 2024 18:11:28 +0300 Subject: [PATCH 1/2] private_removing: bugreport_1703086913 --- .../_src/Transformations/private_removing.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.cpp b/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.cpp index c5d94f7..96e4ba3 100644 --- a/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.cpp +++ b/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.cpp @@ -1474,7 +1474,8 @@ static vector buildDefUsePairs(Context* ctx, const CFG_Type& CF set RD_defArgs = RD_forUseArg->second; // make copy - // delete recursive definition from RD def args: + // delete recursive and uninit definition from RD def args: + set tmpRD_defArgs; for (int defArgNum : RD_defArgs) { if (defArgNum == SAPFOR::CFG_VAL::UNINIT) @@ -1487,11 +1488,11 @@ static vector buildDefUsePairs(Context* ctx, const CFG_Type& CF SgStatement* defStmt = defInsAndBlock.first->getOperator(); auto defInsertedStmt = findInsertedStmt(insertedStmts, defStmt); if (useInsertedStmt.relatedToStmt == defInsertedStmt->relatedToStmt) - { - RD_defArgs.erase(defArgNum); - break; - } + continue; + + tmpRD_defArgs.insert(defArgNum); } + RD_defArgs.swap(tmpRD_defArgs); if (RD_defArgs.size() == 0) // argument is not initialized { @@ -1551,6 +1552,9 @@ static vector buildDefUsePairs(Context* ctx, const CFG_Type& CF else { auto defInsAndBlock = getInstructionAndBlockByNumber(CFGraph, *RD_defArgs.begin()); + if (defInsAndBlock.first == nullptr) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + defStmt = defInsAndBlock.first->getOperator(); } -- 2.49.1 From 0d61856cefda25a8b7ea0c3ec1e4610b2bc33b58 Mon Sep 17 00:00:00 2001 From: Grigorii Gusev Date: Sat, 24 Feb 2024 21:26:05 +0300 Subject: [PATCH 2/2] private_removing: update for LU test --- sapfor/experts/Sapfor_2017/_src/Sapfor.cpp | 6 +- .../_src/Transformations/private_removing.cpp | 323 +++++++++++++----- .../_src/Transformations/private_removing.h | 5 +- 3 files changed, 254 insertions(+), 80 deletions(-) diff --git a/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp b/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp index 0dcb946..3b2f0d3 100644 --- a/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp +++ b/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp @@ -1106,11 +1106,13 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne { auto itFound = loopGraph.find(file->filename()); if (itFound != loopGraph.end()) - removePrivatesAnalysis(itFound->second, getObjectForFileFromMap(file_name, SPF_messages), usersDirectives, commonBlocks, allFuncInfo); + removePrivatesAnalysis(itFound->second, getObjectForFileFromMap(file_name, SPF_messages), + usersDirectives, commonBlocks, allFuncInfo); } else if (curr_regime == PRIVATE_REMOVING) { - removePrivates(file, getObjectForFileFromMap(file_name, SPF_messages), countOfTransform); + removePrivates(file, getObjectForFileFromMap(file_name, SPF_messages), + commonBlocks, allFuncInfo, countOfTransform); } else if (curr_regime == CREATE_INTER_TREE) { diff --git a/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.cpp b/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.cpp index 96e4ba3..c1d87e3 100644 --- a/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.cpp +++ b/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.cpp @@ -4,6 +4,7 @@ #include "../Utils/SgUtils.h" #include "../Utils/utils.h" #include "../ExpressionTransform/expr_transform.h" +#include "dead_code.h" using std::make_pair; using std::map; @@ -16,17 +17,48 @@ using std::wstring; using CFG_Type = map>; using UsersDirectives = map, set>; +// RegularExpr represents expressions like ( coefA * I + coefB ), +// where I is a variable and coefA or coefB can be equal to zero +struct RegularExpr { + int coefA = 0; + int coefB; + string var; + + RegularExpr(): coefA(0), coefB(0), var("") {} +}; + +static bool operator==(const RegularExpr& left, const RegularExpr& right) +{ + return left.var == right.var && left.coefA == right.coefA && left.coefB == right.coefB; +} + +static bool operator<(const RegularExpr& left, const RegularExpr& right) +{ + if (left.var == right.var && left.coefA < right.coefA && left.coefB <= right.coefB) + return true; + + if (left.var == right.var && left.coefA == right.coefA && left.coefB < right.coefB) + return true; + + return false; +} + // FixedSubscript represents subscript of array. Subscript is fixed if it is INT_VAL value struct FixedSubscript { bool isFixed; int value; -}; -// RegularExpr represents expressions like ( coefA * I + coefB ), -// where I is a variable and coefA or coefB can be equal to zero -struct RegularExpr { - int coefA; - int coefB; + bool isRegIndex; + RegularExpr regExprStart; + RegularExpr regExprEnd; + + FixedSubscript() { + isFixed = false; + value = 0; + isRegIndex = false; + regExprStart = RegularExpr{}; + regExprEnd = RegularExpr{}; + } }; // DefUseStmtsPair represents pair of DEF and USE statements for private variable @@ -106,15 +138,50 @@ static bool isArrayRefInVector(SgArrayRefExp* ref, const vector& return false; } +// findAnyVar returns first found VAR_REF in expr +static SgSymbol* findAnyVar(SgExpression* expr) +{ + if (expr == nullptr) + return nullptr; + + if (expr->variant() == VAR_REF) + return expr->symbol(); + + SgSymbol* res = findAnyVar(expr->lhs()); + if (res != nullptr) + return res; + + return findAnyVar(expr->rhs()); +} + // checkAndFillRegularExpr checks if expr is regular and fills regularExpr struct // with info about expr static bool checkAndFillRegularExpr(SgExpression* expr, RegularExpr& regularExpr, SgSymbol* iterationVar) { + if (expr == nullptr) + return false; + + // hack for cases when iterationVar doesn't matter: + if (iterationVar == nullptr) + iterationVar = findAnyVar(expr); + + bool deleteTmpVar = false; + if (iterationVar == nullptr) + { + iterationVar = new SgSymbol(VARIABLE_NAME, "tmp"); + deleteTmpVar = true; + } + pair retCoefs; getCoefsOfSubscript(retCoefs, expr, iterationVar); regularExpr.coefA = retCoefs.first; regularExpr.coefB = retCoefs.second; + if (!deleteTmpVar) + regularExpr.var = iterationVar->identifier(); + + if (deleteTmpVar) + delete iterationVar; if (retCoefs.first != 0 || retCoefs.second != 0) return true; @@ -218,6 +285,33 @@ static bool isSymbolInExpression(SgSymbol* symbol, SgExpression* exp) isSymbolInExpression(symbol, exp->rhs()); } +static FuncInfo* findFunc(string fileName, string funcName, const map>& allFuncInfo) +{ + auto fileInfo = allFuncInfo.find(fileName); + if (fileInfo == allFuncInfo.end()) + return nullptr; + + for (auto funcInfo : fileInfo->second) + if (funcInfo->funcName == funcName) + return funcInfo; + + return nullptr; +} + +static FuncInfo* getCurrectFunc(SgStatement* stmt, const map>& allFuncInfo) +{ + auto fileInfo = allFuncInfo.find(stmt->fileName()); + if (fileInfo == allFuncInfo.end()) + return nullptr; + + int stmtLine = stmt->lineNumber(); + for (auto funcInfo : fileInfo->second) + if (funcInfo->linesNum.first <= stmtLine && stmtLine <= funcInfo->linesNum.second) + return funcInfo; + + return nullptr; +} + /* ************************************** * * End of block of common used functions: * * ************************************** */ @@ -735,7 +829,10 @@ static set> removeArray(string filename, const PrivateToRemove& arra return removedFixedSubscripts; } -void removePrivates(SgFile* file, vector& messages, int& countOfTransform) +void removePrivates(SgFile* file, vector& messages, + const map& commonBlocks, + const map>& allFuncInfo, + int& countOfTransform) { for (auto& varToRemove : privatesToRemoveGlobal) { @@ -747,9 +844,16 @@ void removePrivates(SgFile* file, vector& messages, int& countOfTransf //removeDeadCodeFromLoop(varToRemove.loop); // TODO: problem with reverting substitution removeExcessiveDefs(varToRemove); - removeEmptyLoops(varToRemove.loop, messages); + removeEmptyLoops(varToRemove.loop, messages); // removing is made by REMOVE_DEAD_CODE pass SgForStmt* loopStmt = (SgForStmt*)varToRemove.loop->loop->GetOriginal(); + FuncInfo* currFunc = getCurrectFunc(loopStmt, allFuncInfo); + if (currFunc == nullptr) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + // TODO: problem with removing dead code before reverting substitution + //removeDeadCode(currFunc->funcPointer, allFuncInfo, commonBlocks); + vector varRefs = getDirectArrayRefs(loopStmt, varToRemove.varSymbol); int loopLineNum = varToRemove.loop->lineNum; string varName = varToRemove.varSymbol->identifier(); @@ -780,7 +884,7 @@ void removePrivates(SgFile* file, vector& messages, int& countOfTransf { varName = getDimensionVarName(varToRemove.varSymbol, removedDimension, fixedDimensions, varToRemove.regime); - addMessageRemovePrivateVarPart(messages, varName, loopLineNum); + addMessageRemovePrivateVar(messages, varName, loopLineNum); } } } @@ -1042,9 +1146,35 @@ static vector getFixedDimensionsMask(Context* ctx) return resultMask; } +// getScopeLoopStmt returns least outer scope loop statement +static SgForStmt* getScopeLoopStmt(SgStatement* stmt) +{ + while (stmt != nullptr && stmt->variant() != FOR_NODE) + stmt = stmt->controlParent(); + + return (SgForStmt*)stmt; +} + +// getLoopStmtForVar searches for loop with iteration var equal loopVar starting from from stmt +static SgForStmt* getLoopStmtForVar(SgStatement* stmt, string loopVar) +{ + while (stmt != nullptr) + { + SgForStmt* loopStmt = getScopeLoopStmt(stmt); + + if (loopStmt->doName()->identifier() == loopVar) + return loopStmt; + + stmt = stmt->controlParent(); + } + + return nullptr; +} + // getFixedSubscriptsVector returns vector of fixed INT_VAL subscripts of arrayRef // true - subscript is fixed, false - it isn't -static vector getFixedSubscriptsVector(SgArrayRefExp* arrayRef, int dimensionsNum = 0) +static vector getFixedSubscriptsVector(SgArrayRefExp* arrayRef, int dimensionsNum = 0, + SgStatement* stmt = nullptr) { if (arrayRef->numberOfSubscripts() == 0) return vector(dimensionsNum); @@ -1052,42 +1182,50 @@ static vector getFixedSubscriptsVector(SgArrayRefExp* arrayRef, vector subscriptsVector; for (int i = 0; i < arrayRef->numberOfSubscripts(); ++i) { - if (arrayRef->subscript(i)->variant() == INT_VAL) - subscriptsVector.push_back(FixedSubscript{ true, arrayRef->subscript(i)->valueInteger() }); - else - subscriptsVector.push_back(FixedSubscript{ false, 0 }); + SgExpression* subscriptExpr = arrayRef->subscript(i); + FixedSubscript sub; + + if (subscriptExpr->variant() == INT_VAL) + { + sub.isFixed = true; + sub.value = subscriptExpr->valueInteger(); + } + else if (stmt != nullptr && subscriptExpr->variant() == VAR_REF) + { + SgForStmt* loopStmt = getLoopStmtForVar(stmt, subscriptExpr->symbol()->identifier()); + if (loopStmt != nullptr) + { + RegularExpr regExprStep; + SgExpression* step = loopStmt->step(); + if (step == nullptr || checkAndFillRegularExpr(step, regExprStep, nullptr) && regExprStep.coefA == 0) + { + SgExpression* start = loopStmt->start(); + SgExpression* end = loopStmt->end(); + if (regExprStep.coefB < 0) + std::swap(start, end); + + bool isRegular = true; + isRegular = isRegular && checkAndFillRegularExpr(start, sub.regExprStart, nullptr); + isRegular = isRegular && checkAndFillRegularExpr(end, sub.regExprEnd, nullptr); + sub.isRegIndex = isRegular; + } + } + } + else { + RegularExpr regExpr; + if (checkAndFillRegularExpr(subscriptExpr, regExpr, nullptr)) { + sub.isRegIndex = true; + sub.regExprStart = regExpr; + sub.regExprEnd = regExpr; + } + } + + subscriptsVector.push_back(sub); } return subscriptsVector; } -static FuncInfo* findFunc(string fileName, string funcName, const map>& allFuncInfo) -{ - auto fileInfo = allFuncInfo.find(fileName); - if (fileInfo == allFuncInfo.end()) - return nullptr; - - for (auto funcInfo : fileInfo->second) - if (funcInfo->funcName == funcName) - return funcInfo; - - return nullptr; -} - -static FuncInfo* getCurrectFunc(SgStatement* stmt, const map>& allFuncInfo) -{ - auto fileInfo = allFuncInfo.find(stmt->fileName()); - if (fileInfo == allFuncInfo.end()) - return nullptr; - - int stmtLine = stmt->lineNumber(); - for (auto funcInfo : fileInfo->second) - if (funcInfo->linesNum.first <= stmtLine && stmtLine <= funcInfo->linesNum.second) - return funcInfo; - - return nullptr; -} - // checkImplicitDirectUsage returns masks of array implicit usage (as out argument) // in any function call in exp and writes message about each usage static void checkImplicitDirectUsage(Context* ctx, SgExpression* exp, int stmtLineNum, @@ -1580,14 +1718,14 @@ static vector buildDefUsePairs(Context* ctx, const CFG_Type& CF return defUsePairs; } -// getScopeLoopStmt returns least outer scope loop statement -static SgForStmt* getScopeLoopStmt(SgStatement* stmt) -{ - while (stmt != nullptr && stmt->variant() != FOR_NODE) - stmt = stmt->controlParent(); - - return (SgForStmt*)stmt; -} +//// getScopeLoopStmt returns least outer scope loop statement +//static SgForStmt* getScopeLoopStmt(SgStatement* stmt) +//{ +// while (stmt != nullptr && stmt->variant() != FOR_NODE) +// stmt = stmt->controlParent(); +// +// return (SgForStmt*)stmt; +//} // findChildLoop returns LoopGraph for provided loop statement static LoopGraph* findLoop(LoopGraph* outerLoop, SgForStmt* loopStmt) @@ -1653,7 +1791,8 @@ static LoopGraph* leastCommonAncestor(LoopGraph* a, LoopGraph* b, LoopGraph* par // fillFullFixedSubscriptsVectorsOfAllVars return vector of pairs (name of var, its fixed subscripts vector) // of all VAR_REF and ARRAY_REF vars in exp static void fillFixedSubscriptsVectorsOfAllVars(SgExpression* exp, - vector>>& vec) + vector>>& vec, + SgStatement* stmt = nullptr) { if (exp == nullptr) return; @@ -1671,22 +1810,54 @@ static void fillFixedSubscriptsVectorsOfAllVars(SgExpression* exp, else if (exp->variant() == ARRAY_REF) { vec.push_back(make_pair(exp->symbol()->identifier(), - getFixedSubscriptsVector((SgArrayRefExp*)exp))); + getFixedSubscriptsVector((SgArrayRefExp*)exp, 0, stmt))); SgExprListExp* exprList = (SgExprListExp*)exp->lhs(); for (int i = 0; i < exprList->length(); ++i) - fillFixedSubscriptsVectorsOfAllVars(exprList->elem(i), vec); + fillFixedSubscriptsVectorsOfAllVars(exprList->elem(i), vec, stmt); } return; } - fillFixedSubscriptsVectorsOfAllVars(exp->lhs(), vec); - fillFixedSubscriptsVectorsOfAllVars(exp->rhs(), vec); + fillFixedSubscriptsVectorsOfAllVars(exp->lhs(), vec, stmt); + fillFixedSubscriptsVectorsOfAllVars(exp->rhs(), vec, stmt); +} + +// fixedSubscriptLess checks if left FixedSubscript is less than right +static bool fixedSubscriptLess(const FixedSubscript& left, const FixedSubscript& right) +{ + if (left.isFixed && right.isFixed && left.value < right.value) + return true; + + if (left.isFixed && right.isRegIndex + && right.regExprStart.coefA == 0 && left.value < right.regExprStart.coefB) + return true; + + if (left.isRegIndex && right.isFixed + && left.regExprEnd.coefA == 0 && left.regExprEnd.coefB < right.value) + return true; + + if (left.isRegIndex && right.isRegIndex) + return left.regExprEnd < right.regExprStart; + + return false; +} + +// fixedSubscriptLess checks if left and right FixedSubscripts are different, +// using empirical methods +static bool possibleDifferent(FixedSubscript left, FixedSubscript right) +{ + // TODO: add warning? + if (left.isFixed && right.isRegIndex && right.regExprStart == right.regExprEnd) { + return true; // in general, this is not true + } + + 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>& var) +static bool isDifferentRefs(SgExpression* exp, const pair>& var, SgStatement* stmt) { if (exp->symbol()->identifier() != var.first) return true; @@ -1694,16 +1865,25 @@ static bool isDifferentRefs(SgExpression* exp, const pairvariant() == VAR_REF) return false; - vector leftVec = getFixedSubscriptsVector((SgArrayRefExp*)exp); + vector leftVec = getFixedSubscriptsVector((SgArrayRefExp*)exp, 0, stmt); + + if (leftVec.size() != var.second.size()) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (int i = 0; i < leftVec.size(); i++) - if (leftVec[i].isFixed && var.second[i].isFixed && leftVec[i].value != var.second[i].value) + { + if (fixedSubscriptLess(leftVec[i], var.second[i]) + || fixedSubscriptLess(var.second[i], leftVec[i]) + || possibleDifferent(leftVec[i], var.second[i])) + { return true; + } + } return false; } -pair> findVarInRDSet(map> RD_In, string var) +static pair> findVarInRDSet(const map> RD_In, string var) { for (auto& RD_InElem : RD_In) { @@ -1721,7 +1901,7 @@ pair> findVarInRDSet(map // checkDefUsePair checks if def statement from pair can be substituted into use statement // and creates messages -static bool checkDefUsePair(Context* ctx, DefUseStmtsPair defUse, const CFG_Type& CFGraph) +static bool checkDefUsePair(Context* ctx, const DefUseStmtsPair& defUse, const CFG_Type& CFGraph) { if (defUse.first->lineNumber() > defUse.second->lineNumber()) return false; @@ -1737,7 +1917,7 @@ static bool checkDefUsePair(Context* ctx, DefUseStmtsPair defUse, const CFG_Type SgExpression* expToSubst = defUse.first->rhs()->copyPtr(); expToSubst = replaceVarsWithExps(expToSubst, varToExpMap); - fillFixedSubscriptsVectorsOfAllVars(expToSubst, dependOnVars); + fillFixedSubscriptsVectorsOfAllVars(expToSubst, dependOnVars, defUse.second); } vector iterationVars{}; @@ -1784,29 +1964,16 @@ static bool checkDefUsePair(Context* ctx, DefUseStmtsPair defUse, const CFG_Type } } - return true; - // TODO: ^^^^^ - // проверка массивов отключена, поскольку является слишком консервативной и не позволяет - // выполнить удаление массива RTMP в функции RHS теста LU. - // требуется выполнять более сложный анализ, с определением границ циклов, - // чтобы отличать, что все присваивания в переменную rsd в этом примере - // являются присваиваниями в разные элементы массива: - // rsd(1,i,j,2) = ... - // do k = 4, nz - 3 - // rsd(1, i, j, k) = ... - // enddo - // rsd(1, i, j, nz - 2) = ... - // checking arrays: auto defLoopStmt = getScopeLoopStmt(defUse.first); auto useLoopStmt = getScopeLoopStmt(defUse.second); LoopGraph* loop = ctx->loop; - while (loop->perfectLoop != 1) // (what is it? - может быть это не нужно) + while (loop->perfectLoop != 1) // (what is it? - TODO: may be remove it) loop = loop->children[0]; - auto defLoop = findLoop(loop, defLoopStmt); - auto useLoop = findLoop(loop, useLoopStmt); + LoopGraph* defLoop = findLoop(loop, defLoopStmt); + LoopGraph* useLoop = findLoop(loop, useLoopStmt); if (!defLoopStmt || !useLoopStmt || !defLoop || !useLoop) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); @@ -1850,7 +2017,9 @@ static bool checkDefUsePair(Context* ctx, DefUseStmtsPair defUse, const CFG_Type { for (SgStatement* st = startStmt; st != endStmt; st = st->lexNext()) { - if (st->variant() == ASSIGN_STAT && !isDifferentRefs(st->expr(0), var)) + if (st == defUse.second) + continue; + if (st->variant() == ASSIGN_STAT && !isDifferentRefs(st->expr(0), var, st)) { addMessageDependOnNonInvariant(ctx->messages, arrayName, var.first, defUse.first->lineNumber()); diff --git a/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.h b/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.h index 84c0584..63fe5c3 100644 --- a/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.h +++ b/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.h @@ -22,7 +22,10 @@ struct PrivateToRemove { // removePrivates removes all privates from vector privatesToRemoveGloval // and add info messages -void removePrivates(SgFile* file, std::vector& messages, int& countOfTransform); +void removePrivates(SgFile* file, std::vector& messages, + const std::map& commonBlocks, + const std::map>& allFuncInfo, + int& countOfTransform); // removePrivatesAnalysis checks all private variables in loopGraphs specified by usersDirectives // if they can be removed, and adds those that can to vector privatesToRemoveGloval. -- 2.49.1