diff --git a/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.cpp b/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.cpp index b2215fe..c5d94f7 100644 --- a/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.cpp +++ b/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.cpp @@ -3,6 +3,7 @@ #include "../Utils/errors.h" #include "../Utils/SgUtils.h" #include "../Utils/utils.h" +#include "../ExpressionTransform/expr_transform.h" using std::make_pair; using std::map; @@ -21,6 +22,13 @@ struct FixedSubscript { 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; +}; + // DefUseStmtsPair represents pair of DEF and USE statements for private variable using DefUseStmtsPair = pair; @@ -28,21 +36,6 @@ using DefUseStmtsPair = pair; // used in PRIVATE_REMOVING pass - private vars that can be removed static vector privatesToRemoveGlobal; -// Context stores general info about current loop and array to remove -struct Context { - const map>& allFuncInfo; - const map& commonBlocks; - vector& messages; - - LoopGraph* loop; - SgForStmt* loopStmt; - SgSymbol* arraySymbol; - int dimensionsNum; - // string arrayName; // TODO: может быть можно заменить arraySym на arrayName - vector explicitArrayRefs; - vector fixedDimensionsMask; -}; - /* ******************************* * * Block of common used functions: * @@ -64,7 +57,7 @@ static void fillDirectArrayRefs(SgExpression* exp, SgSymbol* arraySym, vectorrhs(), arraySym, refs); } -// getDirectArrayRefs returns all direct arraySym references in stmt, +// getDirectArrayRefs returns all direct arraySym references in compound stmt, // except VAR_DECL statements static vector getDirectArrayRefs(SgStatement* stmt, SgSymbol* arraySym) { @@ -88,6 +81,22 @@ static vector getDirectArrayRefs(SgStatement* stmt, SgSymbol* ar return arrayRefs; } +// getDirectArrayRefs returns all direct arraySym references in single stmt, +// except VAR_DECL statements +static vector getDirectArrayRefsFromSingleStmt(SgStatement* stmt, SgSymbol* arraySym) +{ + vector arrayRefs; + if (stmt == nullptr) + return arrayRefs; + + if (stmt->variant() != VAR_DECL && stmt->variant() != VAR_DECL_90) // skip var declaration stmt + for (int i = 0; i < 3; ++i) + fillDirectArrayRefs(stmt->expr(i), arraySym, arrayRefs); + + + return arrayRefs; +} + static bool isArrayRefInVector(SgArrayRefExp* ref, const vector& arrayRefs) { for (SgArrayRefExp* arrayRef : arrayRefs) @@ -97,28 +106,97 @@ static bool isArrayRefInVector(SgArrayRefExp* ref, const vector& return false; } +// checkAndFillRegularExpr checks if expr is regular and fills regularExpr struct +// with info about expr +static bool checkAndFillRegularExpr(SgExpression* expr, RegularExpr& regularExpr, SgSymbol* iterationVar) +{ + pair retCoefs; + getCoefsOfSubscript(retCoefs, expr, iterationVar); + + regularExpr.coefA = retCoefs.first; + regularExpr.coefB = retCoefs.second; + + if (retCoefs.first != 0 || retCoefs.second != 0) + return true; + + // check if expr is like ( 0 ), because we cannot separate zero const int expr from incorrect expr: + if (expr->variant() == INT_VAL) + return true; + + return false; +} + // getShortFixedSubscriptsVector returns vector of fixed INT_VAL subscripts of arrayRef static vector getShortFixedSubscriptsVector(SgArrayRefExp* arrayRef, - const vector& fixedDimensions) + const vector& fixedDimensionsMask, + Regime regime, vector iterationVars) { - vector subscriptsVector; - for (int i = 0; i < arrayRef->numberOfSubscripts(); ++i) - if (fixedDimensions[i]) - subscriptsVector.push_back(arrayRef->subscript(i)->valueInteger()); + if (regime == Regime::DEFLT) + { + vector subscriptsVector; + for (int i = 0; i < fixedDimensionsMask.size(); ++i) + if (fixedDimensionsMask[i]) + subscriptsVector.push_back(arrayRef->subscript(i)->valueInteger()); - return subscriptsVector; + return subscriptsVector; + } + else if (regime == Regime::REGULAR_INDEXES) + { + vector subscriptsVector; + SgExprListExp* indexExprList = (SgExprListExp*)arrayRef->lhs(); + if (iterationVars.size() < indexExprList->length()) + return vector{}; + + for (int i = 0; i < indexExprList->length(); ++i) + { + SgExpression* indexExpr = indexExprList->elem(i); + RegularExpr regularExpr; + if (!checkAndFillRegularExpr(indexExpr, regularExpr, iterationVars[i])) + return vector{}; + + subscriptsVector.push_back(regularExpr.coefA); + subscriptsVector.push_back(regularExpr.coefB); + } + + return subscriptsVector; + } + + return vector{}; +} + +static vector getShortFixedSubscriptsVector(SgArrayRefExp* arrayRef, const PrivateToRemove& varToRemove) +{ + vector iterationVars; + if (varToRemove.regime == Regime::REGULAR_INDEXES) + { + auto vars = varToRemove.arrayRefToIterationVarsMap.find(arrayRef); + if (vars != varToRemove.arrayRefToIterationVarsMap.end()) + iterationVars = vars->second; + } + return getShortFixedSubscriptsVector(arrayRef, varToRemove.fixedDimensions, + varToRemove.regime, iterationVars); } // removeDuplicateArrayRefs returns unique array refereces in fixed dimensions static vector removeDuplicateArrayRefs(const vector& arrayRefs, - const vector& fixedDimensions) + const vector& fixedDimensionsMask, + Regime regime, + const map>& arrayRefToIterVarsMap) { map, SgArrayRefExp*> uniqueRefs; - for (SgArrayRefExp* ref : arrayRefs) + for (SgArrayRefExp* arrayRef : arrayRefs) { - vector subscripts = getShortFixedSubscriptsVector(ref, fixedDimensions); + vector iterationVars; + if (regime == Regime::REGULAR_INDEXES) + { + auto vars = arrayRefToIterVarsMap.find(arrayRef); + if (vars != arrayRefToIterVarsMap.end()) + iterationVars = vars->second; + } + + vector subscripts = getShortFixedSubscriptsVector(arrayRef, fixedDimensionsMask, regime, iterationVars); if (uniqueRefs.find(subscripts) == uniqueRefs.end()) - uniqueRefs.insert(make_pair(subscripts, ref)); + uniqueRefs.insert(make_pair(subscripts, arrayRef)); } vector result; @@ -274,20 +352,52 @@ static void addMessageUsageInFunctionCall(vector& messages, string var // getDimensionVarName returns var name in style A(1, 2, *) static string getDimensionVarName(SgSymbol* var, const vector& subscripts, - const vector& fixedDimensions) + const vector& fixedDimensions, Regime regime) { string result = var->identifier(); result += "("; - for (int i = 0; i < fixedDimensions.size(); ++i) + if (regime == Regime::DEFLT) { - if (fixedDimensions[i]) - result += std::to_string(subscripts[i]); - else - result += "*"; + for (int i = 0; i < fixedDimensions.size(); ++i) + { + if (fixedDimensions[i]) + result += std::to_string(subscripts[i]); + else + result += "*"; - if (i != fixedDimensions.size() - 1) - result += ", "; + if (i != fixedDimensions.size() - 1) + result += ", "; + } + } + else if (regime == Regime::REGULAR_INDEXES) + { + for (int i = 0; i < subscripts.size(); i += 2) { + if (subscripts[i] == 0 && subscripts[(size_t)i + 1] == 0) + result += "0"; + else + { + if (subscripts[i] != 0) + { + if (subscripts[i] != 1) + result += "I_" + std::to_string(i / 2 + 1); + else + result += std::to_string(subscripts[i]) + " * I_" + std::to_string(i / 2 + 1); + + if (subscripts[(size_t)i + 1] > 0) + result += " + "; + else if (subscripts[(size_t)i + 1] < 0) + result += " - "; + } + + + if (subscripts[(size_t)i + 1] != 0) + result += std::to_string(std::abs(subscripts[(size_t)i + 1])); + } + + if (i != subscripts.size() - 2) + result += ", "; + } } result += ")"; @@ -358,10 +468,8 @@ static SgExpression* substituteExpressions(SgExpression* exp, if (exp->variant() == ARRAY_REF) { const auto& refToExp = refToExpMap.find(exp->unparse()); - if (refToExp == refToExpMap.end()) - return exp; - - return refToExp->second; + if (refToExp != refToExpMap.end()) + return refToExp->second; } exp->setLhs(substituteExpressions(exp->lhs(), refToExpMap)); @@ -386,6 +494,17 @@ static bool isVarReadInLoop(SgSymbol* var, SgForStmt* loopStmt) return false; } +// isVarChangedBetween checks if the var is changed between first and second statement +// by assignment to var (it doesn't check if the var is indirectly or implicitly by function call) +static bool isVarChangedBetween(string var, SgStatement* first, SgStatement* second) +{ + for (SgStatement* st = first->lexNext(); st != second; st = st->lexNext()) + if (st->variant() == ASSIGN_STAT && st->expr(0)->symbol()->identifier() == var) + return true; + + return false; +} + // removeDeadCodeFromLoop removes assign statements to private scalar vars which are not read in loop static void removeDeadCodeFromLoop(LoopGraph* loop) { @@ -421,7 +540,7 @@ static void removeDeadCodeFromLoop(LoopGraph* loop) // fillReadShortFixedSumscripts fills all short fixed subscripts vectors of array var, // which are used for reading from array var in exp -static void fillReadShortFixedSumscripts(SgExpression* exp, const PrivateToRemove& var, +static void fillReadShortFixedSubscripts(SgExpression* exp, const PrivateToRemove& var, set>& fixedSubscripts) { if (exp == nullptr) @@ -431,19 +550,19 @@ static void fillReadShortFixedSumscripts(SgExpression* exp, const PrivateToRemov { if (isEqSymbols(exp->symbol(), var.varSymbol)) { - auto subscripts = getShortFixedSubscriptsVector((SgArrayRefExp*)exp, var.fixedDimensions); + auto subscripts = getShortFixedSubscriptsVector((SgArrayRefExp*)exp, var); fixedSubscripts.insert(subscripts); return; } } - fillReadShortFixedSumscripts(exp->lhs(), var, fixedSubscripts); - fillReadShortFixedSumscripts(exp->rhs(), var, fixedSubscripts); + fillReadShortFixedSubscripts(exp->lhs(), var, fixedSubscripts); + fillReadShortFixedSubscripts(exp->rhs(), var, fixedSubscripts); } -// getReadShortFixedSumscripts return set of all short fixed subscripts vectors of array var from loop, +// getReadShortFixedSubscripts return set of all short fixed subscripts vectors of array var from loop, // which are used for reading from array var -static set> getReadShortFixedSumscripts(const PrivateToRemove& var, SgForStmt* loopStmt) +static set> getReadShortFixedSubscripts(const PrivateToRemove& var, SgForStmt* loopStmt) { set> fixedSubscripts; for (SgStatement* st = loopStmt->lexNext(); st != loopStmt->lastNodeOfStmt(); st = st->lexNext()) @@ -453,7 +572,7 @@ static set> getReadShortFixedSumscripts(const PrivateToRemove& var, i = 1; for (; i < 3; ++i) - fillReadShortFixedSumscripts(st->expr(i), var, fixedSubscripts); + fillReadShortFixedSubscripts(st->expr(i), var, fixedSubscripts); } return fixedSubscripts; @@ -464,7 +583,7 @@ static set> getReadShortFixedSumscripts(const PrivateToRemove& var, static void removeExcessiveDefs(const PrivateToRemove& var) { SgForStmt* loopStmt = (SgForStmt*)var.loop->loop->GetOriginal(); - set> usedFixedSubscripts = getReadShortFixedSumscripts(var, loopStmt); + set> usedFixedSubscripts = getReadShortFixedSubscripts(var, loopStmt); vector stmtsToRemove; for (SgStatement* st = loopStmt->lexNext(); st != loopStmt->lastNodeOfStmt(); st = st->lexNext()) @@ -475,7 +594,7 @@ static void removeExcessiveDefs(const PrivateToRemove& var) if (st->expr(0)->symbol() == nullptr || !isEqSymbols(st->expr(0)->symbol(), var.varSymbol)) continue; - auto subscripts = getShortFixedSubscriptsVector((SgArrayRefExp*) st->expr(0), var.fixedDimensions); + auto subscripts = getShortFixedSubscriptsVector((SgArrayRefExp*) st->expr(0), var); if (usedFixedSubscripts.find(subscripts) == usedFixedSubscripts.end()) stmtsToRemove.push_back(st); } @@ -576,7 +695,7 @@ static set> removeArray(string filename, const PrivateToRemove& arra SgStatement* useStmt = defUsePair.second; SgArrayRefExp* defRef = (SgArrayRefExp*)defStmt->lhs(); - vector defFixedSubscripts = getShortFixedSubscriptsVector(defRef, fixedDimensions); + vector defFixedSubscripts = getShortFixedSubscriptsVector(defRef, arrayToRemove); int startIndex = 0; if (useStmt->variant() == ASSIGN_STAT) @@ -591,7 +710,7 @@ static set> removeArray(string filename, const PrivateToRemove& arra for (SgArrayRefExp* useRef : arrayUseRefs) { - vector useFixedSubscripts = getShortFixedSubscriptsVector(useRef, fixedDimensions); + vector useFixedSubscripts = getShortFixedSubscriptsVector(useRef, arrayToRemove); if (defFixedSubscripts != useFixedSubscripts) continue; // because useRef and defRef can be different in subscripts of fixed dimensions @@ -626,7 +745,7 @@ void removePrivates(SgFile* file, vector& messages, int& countOfTransf auto removedDimensions = removeArray(file->filename(), varToRemove); countOfTransform++; - removeDeadCodeFromLoop(varToRemove.loop); + //removeDeadCodeFromLoop(varToRemove.loop); // TODO: problem with reverting substitution removeExcessiveDefs(varToRemove); removeEmptyLoops(varToRemove.loop, messages); @@ -642,13 +761,15 @@ void removePrivates(SgFile* file, vector& messages, int& countOfTransf } else { - varRefs = removeDuplicateArrayRefs(varRefs, fixedDimensions); + varRefs = removeDuplicateArrayRefs(varRefs, fixedDimensions, varToRemove.regime, + varToRemove.arrayRefToIterationVarsMap); for (auto& varRef : varRefs) { - vector subscripts = getShortFixedSubscriptsVector(varRef, fixedDimensions); + vector subscripts = getShortFixedSubscriptsVector(varRef, varToRemove); if (removedDimensions.find(subscripts) != removedDimensions.end()) { - varName = getDimensionVarName(varToRemove.varSymbol, subscripts, fixedDimensions); + varName = getDimensionVarName(varToRemove.varSymbol, subscripts, + fixedDimensions, varToRemove.regime); addMessageRemovePrivateVarPart(messages, varName, loopLineNum); } @@ -657,8 +778,9 @@ void removePrivates(SgFile* file, vector& messages, int& countOfTransf for (auto& removedDimension : removedDimensions) { - varName = getDimensionVarName(varToRemove.varSymbol, removedDimension, fixedDimensions); - addMessageRemovePrivateVar(messages, varName, loopLineNum); + varName = getDimensionVarName(varToRemove.varSymbol, removedDimension, + fixedDimensions, varToRemove.regime); + addMessageRemovePrivateVarPart(messages, varName, loopLineNum); } } } @@ -673,9 +795,25 @@ void removePrivates(SgFile* file, vector& messages, int& countOfTransf * PRIVATE_REMOVING_ANALYSIS block of functions: * * ********************************************* */ +// Context stores general info about current loop and array to remove +struct Context { + const map>& allFuncInfo; + const map& commonBlocks; + vector& messages; + + Regime regime; + LoopGraph* loop; + SgForStmt* loopStmt; + SgSymbol* arraySymbol; + int dimensionsNum; + vector explicitArrayRefs; + vector fixedDimensionsMask; + map> arrayRefToIterationVarsMap; +}; + // ReducedArrayVars represents mapping of array reference to reduced scalar var: // arr(1, i) -> pair, SgSymbol*>: [1], arr_1 -class ReducedArrayVars { +class ReducedArrayVarsMap { map, SgSymbol*> arrayMap; public: @@ -735,6 +873,33 @@ static vector::const_iterator findInsertedStmt(const vector getShortFixedSubscriptsVector(Context* ctx, SgArrayRefExp* arrayRef) +{ + vector iterationVars; + if (ctx->regime == Regime::REGULAR_INDEXES) + { + auto vars = ctx->arrayRefToIterationVarsMap.find(arrayRef); + if (vars != ctx->arrayRefToIterationVarsMap.end()) + iterationVars = vars->second; + } + + return getShortFixedSubscriptsVector(arrayRef, ctx->fixedDimensionsMask, ctx->regime, iterationVars); +} + +// fillIterationVariables fill vars set with iteration variables of all loops +// from stmt to outerLoopStmt +static void fillIterationVars(SgStatement* stmt, SgStatement* outerLoopStmt, vector& vars) +{ + if (stmt == nullptr) + return; + + if (stmt->variant() == FOR_NODE) + vars.push_back(((SgForStmt*)stmt)->doName()); + + if (stmt->id() != outerLoopStmt->id()) + fillIterationVars(stmt->controlParent(), outerLoopStmt, vars); +} + // matchesFixedDimensionsMask checks if all array references have INT_VAL value in fixed dimension static bool checkFixedDimensionsMaskMatching(Context* ctx) { @@ -750,13 +915,14 @@ static bool checkFixedDimensionsMaskMatching(Context* ctx) // and VAR_REF in non-fixed dimensions static bool checkDefStmtRefsMatchesMask(Context* ctx) { - // TODO: сделать проверку, что все VAR_REF - это итерационные переменные цикла - // потом переделать, что может быть выражение a * i + b, но i не используется в правой части for (SgStatement* st = ctx->loopStmt->lexNext(); st != ctx->loopStmt->lastNodeOfStmt(); st = st->lexNext()) { if (st->variant() != ASSIGN_STAT) continue; + vector iterationVars; + fillIterationVars(st, ctx->loopStmt, iterationVars); + if (isEqSymbols(st->expr(0)->symbol(), ctx->arraySymbol)) // DEF statement { SgArrayRefExp* ref = (SgArrayRefExp*)st->expr(0); @@ -764,8 +930,19 @@ static bool checkDefStmtRefsMatchesMask(Context* ctx) { if (ctx->fixedDimensionsMask[i] && ref->subscript(i)->variant() == INT_VAL) continue; + if (!ctx->fixedDimensionsMask[i] && ref->subscript(i)->variant() == VAR_REF) + { + bool isIterationVar = false; + for (auto iterationvVar : iterationVars) + if (isEqSymbols(ref->subscript(i)->symbol(), iterationvVar)) + isIterationVar = true; + + if (!isIterationVar) + return false; + continue; + } return false; } @@ -784,7 +961,7 @@ static vector getFixedDimensionsVector(SgArrayRefExp* arrayRef) if (arrayRef->subscript(i)->variant() == INT_VAL) fixedDimensions[i] = true; -return fixedDimensions; + return fixedDimensions; } // sunparseFixedDimensionsVector unparses fixed dimensions vector as string @@ -807,6 +984,45 @@ static string sunparseFixedDimensionsVector(const vector& fixedDimensions) return result; } +static bool checkRegularIndexRefs(Context* ctx) +{ + vector newArrayRefsVector; + for (SgStatement* st = ctx->loopStmt->lexNext(); st != ctx->loopStmt->lastNodeOfStmt(); st = st->lexNext()) + { + vector iterationVars; + fillIterationVars(st, ctx->loopStmt, iterationVars); + + vector arrayRefs = getDirectArrayRefsFromSingleStmt(st, ctx->arraySymbol); + for (auto arrayRef : arrayRefs) + { + if (!isArrayRefInVector(arrayRef, ctx->explicitArrayRefs)) + continue; + + SgExprListExp* indexExprList = (SgExprListExp*)arrayRef->lhs(); + if (iterationVars.size() < indexExprList->length()) + return false; + + for (int i = 0; i < indexExprList->length(); ++i) + { + SgExpression* indexExpr = indexExprList->elem(i); + RegularExpr regularExpr; + if (!checkAndFillRegularExpr(indexExpr, regularExpr, iterationVars[i])) + return false; + } + + if (st->variant() == ASSIGN_STAT && isEqSymbols(st->expr(0)->symbol(), ctx->arraySymbol)) + for (auto iterationVar : iterationVars) + if (isSymbolInExpression(iterationVar, st->expr(1))) + return false; + + iterationVars.resize(indexExprList->length()); + ctx->arrayRefToIterationVarsMap.insert(make_pair(arrayRef, iterationVars)); + } + } + + return true; +} + // getFixedDimensionsMask finds fixed dimensions vector with minimum number of fixed dimensions // and writes messages if array doesn't have fixed dimensions static vector getFixedDimensionsMask(Context* ctx) @@ -927,22 +1143,21 @@ static vector> checkImplicitDirectUsage(Context* ctx) SgCallStmt* callStmt = (SgCallStmt*)st; string procName = callStmt->name()->identifier(); FuncInfo* funcInfo = findFunc(callStmt->fileName(), procName, ctx->allFuncInfo); - if (funcInfo == nullptr) - printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (int i = 0; i < callStmt->numberOfArgs(); ++i) { SgExpression* callArg = callStmt->arg(i); if (callArg->symbol() == nullptr || !isEqSymbols(callArg->symbol(), ctx->arraySymbol)) continue; - - if (funcInfo->funcParams.isArgOut(i) || // implicit direct usage + + if (funcInfo == nullptr || // no info about function + funcInfo->funcParams.isArgOut(i) || // implicit direct usage callArg->lhs() == nullptr) // reference to whole array { auto mask = getFixedSubscriptsVector((SgArrayRefExp*)callArg, ctx->dimensionsNum); fixedSubscripts.push_back(mask); addMessageUsageInFunctionCall(ctx->messages, getDimensionVarName(ctx->arraySymbol, mask), - procName, ctx->loop->lineNum, st->lineNumber()); + procName, ctx->loop->lineNum, st->lineNumber()); } } } @@ -1084,24 +1299,29 @@ static string getReducedArrayVarName(SgSymbol* symbol, const vector& subscr name.reserve(name.size() + subscripts.size() * 3); for (int i : subscripts) - name += "_" + std::to_string(i); + { + if (i < 0) + name += "_M" + std::to_string((-1) * i); + else + name += "_" + std::to_string(i); + } return name; } // getReducedArrayVars makes reduced array vars for arrayRefs -static ReducedArrayVars getReducedArrayVars(Context* ctx) +static ReducedArrayVarsMap getReducedArrayVars(Context* ctx) { - ReducedArrayVars reducedArrayVars; + ReducedArrayVarsMap reducedArrayVars; SgType* type = ctx->explicitArrayRefs[0]->type(); SgStatement* scope = ctx->loopStmt->getScopeForDeclare(); - for (SgArrayRefExp* ref : ctx->explicitArrayRefs) + for (SgArrayRefExp* arrayRef : ctx->explicitArrayRefs) { - vector subscripts = getShortFixedSubscriptsVector(ref, ctx->fixedDimensionsMask); + vector subscripts = getShortFixedSubscriptsVector(ctx, arrayRef); if (reducedArrayVars.find(subscripts) == nullptr) { - string name = getReducedArrayVarName(ref->symbol(), subscripts); + string name = getReducedArrayVarName(arrayRef->symbol(), subscripts); int nameNumber = checkSymbNameAndCorrect(name + "__", 0); if (nameNumber != 0) @@ -1127,11 +1347,10 @@ static set getVarsToDependOn(SgForStmt* loopStmt, SgSymbol* var) } // getDefStmtForReducedArray returns DFE statement for reduced array variable -static InsertedStatement getDefStmtForReducedArray(SgArrayRefExp* arrayRef, - const vector& fixedDimensions, - const ReducedArrayVars& reducedArrayVars) +static InsertedStatement getDefStmtForReducedArray(Context* ctx, SgArrayRefExp* arrayRef, + const ReducedArrayVarsMap& reducedArrayVars) { - vector subscriptVector = getShortFixedSubscriptsVector(arrayRef, fixedDimensions); + vector subscriptVector = getShortFixedSubscriptsVector(ctx, arrayRef); SgSymbol* reducedVar = reducedArrayVars.find(subscriptVector); if (reducedVar == nullptr) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); @@ -1145,12 +1364,11 @@ static InsertedStatement getDefStmtForReducedArray(SgArrayRefExp* arrayRef, // getUseStmtForReducedArray returns USE statement for reduced array variable // (assignment to receiverVar) -static InsertedStatement getUseStmtForReducedArray(SgArrayRefExp* arrayRef, - const vector& fixedDimensions, - const ReducedArrayVars& reducedArrayVars, +static InsertedStatement getUseStmtForReducedArray(Context* ctx, SgArrayRefExp* arrayRef, + const ReducedArrayVarsMap& reducedArrayVars, SgSymbol* receiverVar) { - vector subscriptVector = getShortFixedSubscriptsVector(arrayRef, fixedDimensions); + vector subscriptVector = getShortFixedSubscriptsVector(ctx, arrayRef); SgSymbol* reducedVar = reducedArrayVars.find(subscriptVector); if (reducedVar == nullptr) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); @@ -1165,7 +1383,7 @@ static InsertedStatement getUseStmtForReducedArray(SgArrayRefExp* arrayRef, // insertReducedArrayVarStmts inserts in loop assignment statements with reduced vars, // returns vector of inserted statements static vector insertReducedArrayVarStmts(Context* ctx, - const ReducedArrayVars& reducedArrayVars, + const ReducedArrayVarsMap& reducedArrayVars, SgSymbol* receiverVar) { vector insertedStmts; @@ -1182,7 +1400,8 @@ static vector insertReducedArrayVarStmts(Context* ctx, { vector arrayRefs; fillDirectArrayRefs(st->expr(i), ctx->arraySymbol, arrayRefs); - arrayRefs = removeDuplicateArrayRefs(arrayRefs, ctx->fixedDimensionsMask); + arrayRefs = removeDuplicateArrayRefs(arrayRefs, ctx->fixedDimensionsMask, ctx->regime, + ctx->arrayRefToIterationVarsMap); if (!arrayRefs.empty()) isUseStmt = true; @@ -1191,7 +1410,7 @@ static vector insertReducedArrayVarStmts(Context* ctx, if (!isArrayRefInVector(arrayRef, ctx->explicitArrayRefs)) continue; - InsertedStatement useStmt = getUseStmtForReducedArray(arrayRef, ctx->fixedDimensionsMask, + InsertedStatement useStmt = getUseStmtForReducedArray(ctx, arrayRef, reducedArrayVars, receiverVar); useStmt.relatedToStmt = st; st->insertStmtBefore(*useStmt.insertedStmt, *st->controlParent()); @@ -1204,8 +1423,8 @@ static vector insertReducedArrayVarStmts(Context* ctx, isEqSymbols(st->expr(0)->symbol(), ctx->arraySymbol) && // assignment to array - DEF stmt isArrayRefInVector((SgArrayRefExp*)st->expr(0), ctx->explicitArrayRefs)) { - InsertedStatement defStmt = getDefStmtForReducedArray((SgArrayRefExp*)st->expr(0), - ctx->fixedDimensionsMask, reducedArrayVars); + InsertedStatement defStmt = getDefStmtForReducedArray(ctx, (SgArrayRefExp*)st->expr(0), + reducedArrayVars); defStmt.relatedToStmt = st; defStmt.isRecursive = isUseStmt; st->insertStmtBefore(*defStmt.insertedStmt, *st->controlParent()); @@ -1233,6 +1452,7 @@ static vector buildDefUsePairs(Context* ctx, const CFG_Type& CF { vector defUsePairs; + string arrayName = ctx->arraySymbol->identifier(); for (const InsertedStatement& useInsertedStmt : insertedStmts) { if (useInsertedStmt.type != TypeOfInsertedStmt::USE) // analysis for USE stmt @@ -1248,7 +1468,7 @@ static vector buildDefUsePairs(Context* ctx, const CFG_Type& CF const auto& RD_forUseArg = RD_In.find(useArg); if (RD_forUseArg == RD_In.end()) // cannot find reaching definitions for argument { - addMessageCannotFindRD(ctx->messages, ctx->arraySymbol->identifier(), useLineNum); + addMessageCannotFindRD(ctx->messages, arrayName, useLineNum); continue; } @@ -1275,19 +1495,21 @@ static vector buildDefUsePairs(Context* ctx, const CFG_Type& CF if (RD_defArgs.size() == 0) // argument is not initialized { - addMessageCannotFindRD(ctx->messages, ctx->arraySymbol->identifier(), useLineNum); + addMessageCannotFindRD(ctx->messages, arrayName, useLineNum); continue; } - if (RD_defArgs.find(SAPFOR::CFG_VAL::UNINIT) != RD_defArgs.end()) // argument is not initialized - { - bool uninitArgIsOk = false; - if (RD_defArgs.size() == 2) - { - RD_defArgs.erase(SAPFOR::CFG_VAL::UNINIT); - int defArgNum = *RD_defArgs.begin(); + SgStatement* defStmt = nullptr; - auto defInsAndBlock = getInstructionAndBlockByNumber(CFGraph, defArgNum); + if (RD_defArgs.size() > 1) + { + bool defIsFound = false; + for (int defArg : RD_defArgs) // try to find the real definition from RD_defArgs + { + if (defArg == SAPFOR::CFG_VAL::UNINIT) + continue; + + auto defInsAndBlock = getInstructionAndBlockByNumber(CFGraph, defArg); if (defInsAndBlock.first == nullptr) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); @@ -1295,38 +1517,54 @@ static vector buildDefUsePairs(Context* ctx, const CFG_Type& CF if (defInsertedStmt->relatedToStmt->lineNumber() < useLineNum && useInsAndBlock.second->getNumber() == defInsAndBlock.second->getNumber()) { - uninitArgIsOk = true; // argument isn't really uninitialized + defIsFound = true; + auto defInsAndBlock = getInstructionAndBlockByNumber(CFGraph, defArg); + defStmt = defInsAndBlock.first->getOperator(); + break; } } - - if (!uninitArgIsOk) + + if (!defIsFound) { - addMessageCannotFindRD(ctx->messages, ctx->arraySymbol->identifier(), useLineNum); + // try to find definition not from RD_defArgs: + string defVarName = useInsertedStmt.insertedStmt->expr(1)->symbol()->identifier(); + SgStatement* blockStart = useInsAndBlock.second->getInstructions().front()->getInstruction()->getOperator(); + SgStatement* blockEnd = useInsAndBlock.second->getInstructions().back()->getInstruction()->getOperator(); + for (SgStatement* st = blockStart; st != blockEnd; st = st->lexNext()) + { + if (st->variant() == ASSIGN_STAT && st->expr(0)->symbol()->identifier() == defVarName && + !isVarChangedBetween(defVarName, st, useInsertedStmt.insertedStmt)) + { + defIsFound = true; + defStmt = st; + break; + } + } + } + + if (!defIsFound) + { + addMessageCannotFindRD(ctx->messages, arrayName, useLineNum); continue; } } - - if (RD_defArgs.size() > 1) // more than one reaching definition + else { - addMessageMoreThanOneRD(ctx->messages, ctx->arraySymbol->identifier(), useLineNum); - continue; + auto defInsAndBlock = getInstructionAndBlockByNumber(CFGraph, *RD_defArgs.begin()); + defStmt = defInsAndBlock.first->getOperator(); } - int defArgNum = *RD_defArgs.begin(); - - auto defInsAndBlock = getInstructionAndBlockByNumber(CFGraph, defArgNum); - SgStatement* defStmt = defInsAndBlock.first->getOperator(); auto defInsertedStmt = findInsertedStmt(insertedStmts, defStmt); if (defInsertedStmt == insertedStmts.end()) { - addMessageCannotFindRD(ctx->messages, ctx->arraySymbol->identifier(), useLineNum); + addMessageCannotFindRD(ctx->messages, arrayName, useLineNum); continue; } //don't substitute def stmt into use, if def is recursive if (defInsertedStmt->isRecursive) { - addMessageRecursiveDependency(ctx->messages, ctx->arraySymbol->identifier(), useLineNum); + addMessageRecursiveDependency(ctx->messages, arrayName, useLineNum); continue; } @@ -1347,18 +1585,6 @@ static SgForStmt* getScopeLoopStmt(SgStatement* stmt) return (SgForStmt*)stmt; } -static int getDimension(SgSymbol* arraySym) -{ - SgExpression* declExpr = arraySym->makeDeclExpr(); - if (declExpr == nullptr) - printInternalError(convertFileName(__FILE__).c_str(), __LINE__); - - int dimensionNum = ((SgExprListExp*)declExpr->lhs())->length(); - delete declExpr; - - return dimensionNum; -} - // findChildLoop returns LoopGraph for provided loop statement static LoopGraph* findLoop(LoopGraph* outerLoop, SgForStmt* loopStmt) { @@ -1489,20 +1715,6 @@ pair> findVarInRDSet(map return make_pair(nullptr, set{}); } -// fillIterationVariables fill vars set with iteration variables of all loops -// from stmt to outerLoopStmt -static void fillIterationVars(SgStatement *stmt, SgStatement* outerLoopStmt, set& vars) -{ - if (stmt == nullptr) - return; - - if (stmt->variant() == FOR_NODE) - vars.insert(((SgForStmt*)stmt)->doName()->identifier()); - - if (stmt->id() != outerLoopStmt->id()) - fillIterationVars(stmt->controlParent(), outerLoopStmt, vars); -} - // 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) @@ -1514,7 +1726,7 @@ static bool checkDefUsePair(Context* ctx, DefUseStmtsPair defUse, const CFG_Type vector>> dependOnVars; SgArrayRefExp* defRef = (SgArrayRefExp*)defUse.first->expr(0); - vector arrayUseRefs = getDirectArrayRefs(defUse.second, ctx->arraySymbol); + vector arrayUseRefs = getDirectArrayRefsFromSingleStmt(defUse.second, ctx->arraySymbol); for (auto useRef : arrayUseRefs) { map varToExpMap = getVarToExpMap(defRef, useRef, ctx->fixedDimensionsMask); @@ -1524,7 +1736,7 @@ static bool checkDefUsePair(Context* ctx, DefUseStmtsPair defUse, const CFG_Type fillFixedSubscriptsVectorsOfAllVars(expToSubst, dependOnVars); } - set iterationVars{}; + vector iterationVars{}; fillIterationVars(defUse.second, ctx->loopStmt, iterationVars); auto defInsAndBlock = getInstructionAndBlockByStatement(CFGraph, defUse.first); @@ -1536,7 +1748,17 @@ static bool checkDefUsePair(Context* ctx, DefUseStmtsPair defUse, const CFG_Type if (var.second.size() == 0) // check scalar vars { // iteration var doesn't obstruct the removing: - if (iterationVars.find(var.first) != iterationVars.end()) + bool isIterationVar = false; + for (auto iterationVar : iterationVars) + { + if (iterationVar->identifier() == var.first) + { + isIterationVar = true; + break; + } + } + + if (isIterationVar) continue; auto defArg = findVarInRDSet(defRD_In, var.first); @@ -1547,6 +1769,10 @@ static bool checkDefUsePair(Context* ctx, DefUseStmtsPair defUse, const CFG_Type if (defArg.second.size() != 1 || useArg.second.size() != 1 || *defArg.second.begin() != *useArg.second.begin()) { + if (defInsAndBlock.second->getNumber() == useInsAndBlock.second->getNumber()) + if (!isVarChangedBetween(var.first, defUse.first, defUse.second)) + continue; + addMessageDependOnNonInvariant(ctx->messages, arrayName, var.first, defUse.first->lineNumber()); return false; @@ -1656,6 +1882,55 @@ static set getPrivateArraysForLoop(LoopGraph* loop, const UsersDirect return privateArrays; } +void removePrivateAnalyze(Context *ctx) +{ + // inserting assignment to reduced array variables for getting reaching definitions analysis: + auto reducedArrayVars = getReducedArrayVars(ctx); + SgSymbol* receiverVar = makeTmpVar(ctx); + auto insertedStmts = insertReducedArrayVarStmts(ctx, reducedArrayVars, receiverVar); + + // declare reduced array variables and receiver: + insertedStmts.push_back(InsertedStatement( + TypeOfInsertedStmt::DECLARATION, + makeDeclaration(ctx->loopStmt, reducedArrayVars.getAllVars(), nullptr) + )); + insertedStmts.push_back(InsertedStatement( + TypeOfInsertedStmt::DECLARATION, + makeDeclaration(ctx->loopStmt, vector {receiverVar}, nullptr) + )); + + CFG_Type CFG_ForFunc = buildCFGforCurrentFunc(ctx->loopStmt, + SAPFOR::CFG_Settings(true, true), + ctx->commonBlocks, ctx->allFuncInfo); + if (CFG_ForFunc.empty()) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + auto defUseStmtsPairs = buildDefUsePairs(ctx, CFG_ForFunc, insertedStmts); + if (!defUseStmtsPairs.empty()) // DEF-USE pairs were build successfully + { + vector resultDefUsePairs; + for (auto& pair : defUseStmtsPairs) + if (checkDefUsePair(ctx, pair, CFG_ForFunc)) + resultDefUsePairs.push_back(pair); + + PrivateToRemove newPrivateToRemove; + newPrivateToRemove.loop = ctx->loop; + newPrivateToRemove.varSymbol = ctx->arraySymbol; + newPrivateToRemove.regime = ctx->regime; + newPrivateToRemove.defUseStmtsPairs.swap(resultDefUsePairs); + newPrivateToRemove.fixedDimensions.swap(ctx->fixedDimensionsMask); + newPrivateToRemove.arrayRefToIterationVarsMap = ctx->arrayRefToIterationVarsMap; + + privatesToRemoveGlobal.push_back(newPrivateToRemove); + } + + // delete inserted statements: + for (auto& stmt : insertedStmts) + stmt.insertedStmt->deleteStmt(); + + deleteCFG(CFG_ForFunc); +} + void removePrivatesAnalysis(vector& loopGraphs, vector& messages, const UsersDirectives& usersDirectives, @@ -1704,9 +1979,10 @@ void removePrivatesAnalysis(vector& loopGraphs, break; Context context = Context{allFuncInfo, commonBlocks, messages}; + context.regime = Regime::DEFLT; context.loop = loop; context.loopStmt = loopStmt; - context.dimensionsNum = getDimension(arrayToRemove); + context.dimensionsNum = ((SgArrayType*)arrayToRemove->type())->dimension(); context.arraySymbol = arrayToRemove; auto filterMasks = checkImplicitAndIndirectUsage(&context); @@ -1718,60 +1994,26 @@ void removePrivatesAnalysis(vector& loopGraphs, context.fixedDimensionsMask = getFixedDimensionsMask(&context); - if (context.fixedDimensionsMask.empty() || - !checkFixedDimensionsMaskMatching(&context) || - !checkDefStmtRefsMatchesMask(&context)) + if (!context.fixedDimensionsMask.empty() && + checkFixedDimensionsMaskMatching(&context) && + checkDefStmtRefsMatchesMask(&context)) { - addMessageDoesNotMatchMask(messages, context.arraySymbol->identifier(), context.loop->lineNum); - continue; + removePrivateAnalyze(&context); } - - // inserting assignment to reduced array variables for getting reaching definitions analysis: - auto reducedArrayVars = getReducedArrayVars(&context); - SgSymbol* receiverVar = makeTmpVar(&context); - auto insertedStmts = insertReducedArrayVarStmts(&context, reducedArrayVars, receiverVar); - - // declare reduced array variables and receiver: - insertedStmts.push_back(InsertedStatement( - TypeOfInsertedStmt::DECLARATION, - makeDeclaration(context.loopStmt, reducedArrayVars.getAllVars(), nullptr) - )); - insertedStmts.push_back(InsertedStatement( - TypeOfInsertedStmt::DECLARATION, - makeDeclaration(context.loopStmt, vector {receiverVar}, nullptr) - )); - - CFG_Type CFG_ForFunc = buildCFGforCurrentFunc(context.loopStmt, - SAPFOR::CFG_Settings(true, true), - commonBlocks, context.allFuncInfo); - if (CFG_ForFunc.empty()) - printInternalError(convertFileName(__FILE__).c_str(), __LINE__); - - auto defUseStmtsPairs = buildDefUsePairs(&context, CFG_ForFunc, insertedStmts); - if (!defUseStmtsPairs.empty()) // DEF-USE pairs were build successfully + else { - vector resultDefUsePairs; - for (auto& pair : defUseStmtsPairs) - if (checkDefUsePair(&context, pair, CFG_ForFunc)) - resultDefUsePairs.push_back(pair); - - PrivateToRemove newPrivateToRemove; - newPrivateToRemove.loop = context.loop; - newPrivateToRemove.varSymbol = context.arraySymbol; - newPrivateToRemove.defUseStmtsPairs.swap(resultDefUsePairs); - newPrivateToRemove.fixedDimensions.swap(context.fixedDimensionsMask); - - privatesToRemoveGlobal.push_back(newPrivateToRemove); + if (checkRegularIndexRefs(&context)) + { + context.regime = Regime::REGULAR_INDEXES; + context.fixedDimensionsMask = vector{}; + removePrivateAnalyze(&context); + } + else + addMessageDoesNotMatchMask(messages, context.arraySymbol->identifier(), context.loop->lineNum); } - - // delete inserted statements: - for (auto& stmt : insertedStmts) - stmt.insertedStmt->deleteStmt(); - - deleteCFG(CFG_ForFunc); } } for (LoopGraph* loop : loopGraphs) removePrivatesAnalysis(loop->children, messages, usersDirectives, commonBlocks, allFuncInfo); -} \ No newline at end of file +} diff --git a/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.h b/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.h index 395375e..84c0584 100644 --- a/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.h +++ b/sapfor/experts/Sapfor_2017/_src/Transformations/private_removing.h @@ -5,14 +5,19 @@ #include "../CFGraph/CFGraph.h" #include "../CFGraph/RD_subst.h" +// Regime defines the regime of private removing +enum class Regime { DEFLT = 1, REGULAR_INDEXES }; + // PrivateToRemove represents private variable of loop, that can be removed // by substitution of its definition statements (DEF) into usage statements (USE). // fixedDimensions is used for comparison of DEF and USE statements struct PrivateToRemove { LoopGraph* loop; SgSymbol* varSymbol; + Regime regime; std::vector> defUseStmtsPairs; std::vector fixedDimensions; + std::map> arrayRefToIterationVarsMap; }; // removePrivates removes all privates from vector privatesToRemoveGloval