Files
SAPFOR/src/Transformations/private_removing.cpp

2345 lines
86 KiB
C++
Raw Normal View History

2023-09-14 19:43:13 +03:00
#include "private_removing.h"
#include "../Utils/errors.h"
#include "../Utils/SgUtils.h"
#include "../Utils/utils.h"
#include "../ExpressionTransform/expr_transform.h"
2024-02-24 21:26:05 +03:00
#include "dead_code.h"
2023-09-14 19:43:13 +03:00
using std::make_pair;
using std::map;
using std::pair;
using std::set;
using std::string;
using std::vector;
using std::wstring;
using CFG_Type = map<FuncInfo*, vector<SAPFOR::BasicBlock*>>;
using UsersDirectives = map<pair<string, int>, set<SgStatement*>>;
2024-02-24 21:26:05 +03:00
// RegularExpr represents expressions like ( coefA * I + coefB ),
// where I is a variable and coefA or coefB can be equal to zero
struct RegularExpr {
2024-06-08 21:18:50 +03:00
int coefA;
2024-02-24 21:26:05 +03:00
int coefB;
string var;
2024-06-08 21:18:50 +03:00
SgSymbol* varSymbol;
2024-02-24 21:26:05 +03:00
2024-06-08 21:18:50 +03:00
RegularExpr(): coefA(0), coefB(0), var(""), varSymbol(nullptr) {}
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;
}
2024-02-24 21:26:05 +03:00
};
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;
}
2023-09-14 19:43:13 +03:00
// FixedSubscript represents subscript of array. Subscript is fixed if it is INT_VAL value
2024-03-20 01:24:17 +03:00
struct ArraySubscript {
2023-09-14 19:43:13 +03:00
bool isFixed;
int value;
2024-02-24 21:26:05 +03:00
bool isRegIndex;
RegularExpr regExprStart;
RegularExpr regExprEnd;
ArraySubscript()
{
2024-02-24 21:26:05 +03:00
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();
}
};
2023-09-14 19:43:13 +03:00
// DefUseStmtsPair represents pair of DEF and USE statements for private variable
using DefUseStmtsPair = pair<SgAssignStmt*, SgStatement*>;
2023-09-14 19:43:13 +03:00
// privatesToRemoveGlobal stores the result of PRIVATE_REMOVING_ANALYSIS,
// used in PRIVATE_REMOVING pass - private vars that can be removed
static vector<PrivateToRemove> privatesToRemoveGlobal;
/* ******************************* *
* Block of common used functions: *
* ******************************* */
// fillDirectArrayRefs fills all direct arraySym references in exp into refs
static void fillDirectArrayRefs(SgExpression* exp, SgSymbol* arraySym, vector<SgArrayRefExp*>& refs)
2023-09-14 19:43:13 +03:00
{
if (exp == nullptr)
return;
if (exp->variant() == ARRAY_REF && exp->symbol() != nullptr && isEqSymbols(exp->symbol(), arraySym))
2023-09-14 19:43:13 +03:00
{
refs.push_back((SgArrayRefExp*)exp);
2023-09-14 19:43:13 +03:00
return;
}
fillDirectArrayRefs(exp->lhs(), arraySym, refs);
fillDirectArrayRefs(exp->rhs(), arraySym, refs);
2023-09-14 19:43:13 +03:00
}
// getDirectArrayRefs returns all direct arraySym references in compound stmt,
// except VAR_DECL statements
static vector<SgArrayRefExp*> getDirectArrayRefs(SgStatement* stmt, SgSymbol* arraySym)
2023-09-14 19:43:13 +03:00
{
vector<SgArrayRefExp*> arrayRefs;
if (stmt == nullptr)
return arrayRefs;
SgStatement* st = stmt;
while (true)
{
if (st->variant() != VAR_DECL && st->variant() != VAR_DECL_90) // skip var declaration stmt
for (int i = 0; i < 3; ++i)
fillDirectArrayRefs(st->expr(i), arraySym, arrayRefs);
if (st == stmt->lastNodeOfStmt())
break;
else
st = st->lexNext();
}
2023-09-14 19:43:13 +03:00
return arrayRefs;
}
// getDirectArrayRefs returns all direct arraySym references in single stmt,
// except VAR_DECL statements
static vector<SgArrayRefExp*> getDirectArrayRefsFromSingleStmt(SgStatement* stmt, SgSymbol* arraySym)
{
vector<SgArrayRefExp*> 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<SgArrayRefExp*>& arrayRefs)
{
for (SgArrayRefExp* arrayRef : arrayRefs)
if (arrayRef->id() == ref->id())
return true;
return false;
}
2024-02-24 21:26:05 +03:00
// 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)
{
2024-02-24 21:26:05 +03:00
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<int, int> retCoefs;
getCoefsOfSubscript(retCoefs, expr, iterationVar);
regularExpr.coefA = retCoefs.first;
regularExpr.coefB = retCoefs.second;
2024-02-24 21:26:05 +03:00
if (!deleteTmpVar)
2024-06-08 21:18:50 +03:00
{
2024-02-24 21:26:05 +03:00
regularExpr.var = iterationVar->identifier();
2024-06-08 21:18:50 +03:00
regularExpr.varSymbol = iterationVar;
}
2024-02-24 21:26:05 +03:00
if (deleteTmpVar)
delete iterationVar;
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;
}
2023-09-14 19:43:13 +03:00
// getShortFixedSubscriptsVector returns vector of fixed INT_VAL subscripts of arrayRef
static vector<int> getShortFixedSubscriptsVector(SgArrayRefExp* arrayRef,
const vector<bool>& fixedDimensionsMask,
2024-06-08 21:18:50 +03:00
Regime regime)
2023-09-14 19:43:13 +03:00
{
if (regime == Regime::DEFLT)
{
vector<int> subscriptsVector;
for (int i = 0; i < fixedDimensionsMask.size(); ++i)
if (fixedDimensionsMask[i])
subscriptsVector.push_back(arrayRef->subscript(i)->valueInteger());
2023-09-14 19:43:13 +03:00
return subscriptsVector;
}
else if (regime == Regime::REGULAR_INDEXES)
{
vector<int> subscriptsVector;
SgExprListExp* indexExprList = (SgExprListExp*)arrayRef->lhs();
for (int i = 0; i < indexExprList->length(); ++i)
{
SgExpression* indexExpr = indexExprList->elem(i);
RegularExpr regularExpr;
2024-06-08 21:18:50 +03:00
if (!checkAndFillRegularExpr(indexExpr, regularExpr, nullptr))
return vector<int>{};
subscriptsVector.push_back(regularExpr.coefA);
subscriptsVector.push_back(regularExpr.coefB);
}
return subscriptsVector;
}
return vector<int>{};
2023-09-14 19:43:13 +03:00
}
// removeDuplicateArrayRefs returns unique array refereces in fixed dimensions
static vector<SgArrayRefExp*> removeDuplicateArrayRefs(const vector<SgArrayRefExp*>& arrayRefs,
const vector<bool>& fixedDimensionsMask,
2024-06-08 21:18:50 +03:00
Regime regime)
2023-09-14 19:43:13 +03:00
{
map<vector<int>, SgArrayRefExp*> uniqueRefs;
for (SgArrayRefExp* arrayRef : arrayRefs)
2023-09-14 19:43:13 +03:00
{
2024-06-08 21:18:50 +03:00
vector<int> subscripts = getShortFixedSubscriptsVector(arrayRef, fixedDimensionsMask, regime);
2023-09-14 19:43:13 +03:00
if (uniqueRefs.find(subscripts) == uniqueRefs.end())
uniqueRefs.insert(make_pair(subscripts, arrayRef));
2023-09-14 19:43:13 +03:00
}
vector<SgArrayRefExp*> result;
for (auto& ref : uniqueRefs)
result.push_back(ref.second);
return result;
}
static bool isSymbolInExpression(SgSymbol* symbol, SgExpression* exp)
{
if (exp == nullptr)
return false;
2024-03-20 01:24:17 +03:00
if (exp->symbol() != nullptr &&
(exp->variant() == VAR_REF || exp->variant() == ARRAY_REF) &&
isEqSymbols(exp->symbol(), symbol))
{
2023-09-14 19:43:13 +03:00
return true;
2024-03-20 01:24:17 +03:00
}
2023-09-14 19:43:13 +03:00
return isSymbolInExpression(symbol, exp->lhs()) ||
isSymbolInExpression(symbol, exp->rhs());
}
2024-06-08 21:18:50 +03:00
// findFuncByName searches function by its name among all functions (and subroutines) in program
static FuncInfo* findFuncByName(string funcName, const map<string, vector<FuncInfo*>>& allFuncInfo)
2024-02-24 21:26:05 +03:00
{
for (const auto& fileFuncs : allFuncInfo)
for (auto funcInfo : fileFuncs.second)
if (funcInfo->funcName == funcName)
return funcInfo;
2024-02-24 21:26:05 +03:00
return nullptr;
}
2024-06-08 21:18:50 +03:00
// getCurrentFunc return FuncInfo about current function for stmt
static FuncInfo* getCurrentFunc(SgStatement* stmt, const map<string, vector<FuncInfo*>>& allFuncInfo)
2024-02-24 21:26:05 +03:00
{
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;
}
2024-04-19 17:52:00 +03:00
// fillIterationVariables fills SgSymbol* set with iteration variables of all loops
// from stmt to outerLoopStmt. If outerLoopStmt is nullptr, it fill with iteration variables
// from all outer loops
2024-03-20 01:24:17 +03:00
static void fillIterationVars(SgStatement* stmt, SgStatement* outerLoopStmt, vector<SgSymbol*>& vars)
{
if (stmt == nullptr)
return;
if (stmt->variant() == FOR_NODE)
vars.push_back(((SgForStmt*)stmt)->doName());
2024-04-19 17:52:00 +03:00
if (stmt != outerLoopStmt)
2024-03-20 01:24:17 +03:00
fillIterationVars(stmt->controlParent(), outerLoopStmt, vars);
}
2023-09-14 19:43:13 +03:00
/* ************************************** *
* End of block of common used functions: *
* ************************************** */
/* ************************************* *
* Block of creating messages functions: *
* ************************************* */
static void addMessageVarNotAlignedWithLoop(vector<Messages>& messages, string varName, int loopLineNum)
2023-09-14 19:43:13 +03:00
{
__spf_print(1, "WARR: cannot remove private var '%s' - its references have different alignment with the loop %d\n",
varName.c_str(), loopLineNum);
2023-09-14 19:43:13 +03:00
wstring messageE, messageR;
__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());
2023-09-14 19:43:13 +03:00
messages.push_back(Messages(typeMessage::WARR, loopLineNum, messageR, messageE, 2024));
2023-09-14 19:43:13 +03:00
}
static void addMessageRemovePrivateVar(vector<Messages>& messages, string varName, int loopLineNum)
{
__spf_print(1, "NOTE: private variable '%s' was removed in loop %d\n", varName.c_str(), loopLineNum);
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Private variable '%s' was removed", to_wstring(varName).c_str());
__spf_printToLongBuf(messageR, R191, to_wstring(varName).c_str());
messages.push_back(Messages(typeMessage::NOTE, loopLineNum, messageR, messageE, 2018));
}
static void addMessageRemovePrivateVarPart(vector<Messages>& messages, string varName, int loopLineNum)
{
__spf_print(1, "NOTE: private variable '%s' was partially removed in loop %d\n",
varName.c_str(), loopLineNum);
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Private variable '%s' was partially removed",
to_wstring(varName).c_str());
__spf_printToLongBuf(messageR, R201, to_wstring(varName).c_str());
messages.push_back(Messages(typeMessage::NOTE, loopLineNum, messageR, messageE, 2018));
}
static void addMessageCannotFindRD(vector<Messages>& messages, string varName, int loopLineNum)
{
__spf_print(1, "WARR: cannot remove private var '%s' - cannot find reaching definition for the statement in line %d\n",
varName.c_str(), loopLineNum);
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Cannot remove private var '%s' - cannot find reaching definition for the statement",
to_wstring(varName).c_str());
__spf_printToLongBuf(messageR, R194, to_wstring(varName).c_str());
messages.push_back(Messages(typeMessage::WARR, loopLineNum, messageR, messageE, 2021));
}
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));
}
2023-09-14 19:43:13 +03:00
static void addMessageRecursiveDependency(vector<Messages>& messages, string varName, int lineNum)
{
__spf_print(1, "WARR: cannot remove private var '%s' in line %d - it has recursive dependency\n",
varName.c_str(), lineNum);
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Cannot remove private var '%s' - it has recursive dependency",
2023-09-14 19:43:13 +03:00
to_wstring(varName).c_str());
__spf_printToLongBuf(messageR, R189, to_wstring(varName).c_str());
messages.push_back(Messages(typeMessage::WARR, lineNum, messageR, messageE, 2017));
}
static void addMessageDependOnNonInvariant(vector<Messages>& messages, string varName, string dependOn, int lineNum)
{
__spf_print(1, "WARR: cannot remove private var '%s' in line %d - it depends on non-invariant var '%s'\n",
varName.c_str(), lineNum, dependOn.c_str());
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Cannot remove private var '%s' - it depends on non-invariant var '%s'",
to_wstring(varName).c_str(), to_wstring(dependOn).c_str());
__spf_printToLongBuf(messageR, R190, to_wstring(varName).c_str(), to_wstring(dependOn).c_str());
messages.push_back(Messages(typeMessage::WARR, lineNum, messageR, messageE, 2017));
}
static void addMessageDoesNotMatchMask(vector<Messages>& messages, string varName, int loopLineNum)
2023-09-14 19:43:13 +03:00
{
__spf_print(1, "WARR: cannot remove private var '%s' in loop %d - it doesn't match any fixed dimensions mask\n",
varName.c_str(), loopLineNum);
2023-09-14 19:43:13 +03:00
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Cannot remove private var '%s' - it doesn't match any fixed dimensions mask",
to_wstring(varName).c_str());
__spf_printToLongBuf(messageR, R188, to_wstring(varName).c_str());
messages.push_back(Messages(typeMessage::WARR, loopLineNum, messageR, messageE, 2016));
}
static void addMessageUsageInFunctionCall(vector<Messages>& messages, string varName,
string funcName, int loopLineNum, int stmtLineNum)
{
__spf_print(1, "WARR: cannot remove private var '%s' in loop %d - it is used in the call of function '%s' in line %d\n",
varName.c_str(), loopLineNum, funcName.c_str(), stmtLineNum);
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Cannot remove private var '%s' - it is used in the call of function '%s'",
to_wstring(varName).c_str(), to_wstring(funcName).c_str());
__spf_printToLongBuf(messageR, R203, to_wstring(varName).c_str(), to_wstring(funcName).c_str());
messages.push_back(Messages(typeMessage::WARR, stmtLineNum, messageR, messageE, 2025));
2023-09-14 19:43:13 +03:00
}
/* ****************************************** *
* End of block of creating messages functions: *
* ******************************************** */
/* ************************************ *
* PRIVATE_REMOVING block of functions: *
* ************************************ */
// getDimensionVarName returns var name in style A(1, 2, *)
static string getDimensionVarName(SgSymbol* var, const vector<int>& subscripts,
const vector<bool>& fixedDimensions, Regime regime)
2023-09-14 19:43:13 +03:00
{
string result = var->identifier();
result += "(";
if (regime == Regime::DEFLT)
2023-09-14 19:43:13 +03:00
{
for (int i = 0; i < fixedDimensions.size(); ++i)
{
if (fixedDimensions[i])
result += std::to_string(subscripts[i]);
else
result += "*";
2023-09-14 19:43:13 +03:00
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 += ", ";
}
2023-09-14 19:43:13 +03:00
}
result += ")";
return result;
}
// getDimensionVarName returns var name in style A(1, 2, *)
2024-03-20 01:24:17 +03:00
static string getDimensionVarName(SgSymbol* var, const vector<ArraySubscript>& fixedSubscripts)
{
string result = var->identifier();
result += "(";
for (int i = 0; i < fixedSubscripts.size(); ++i)
{
if (fixedSubscripts[i].isFixed)
result += std::to_string(fixedSubscripts[i].value);
else
result += "*";
if (i != fixedSubscripts.size() - 1)
result += ", ";
}
result += ")";
return result;
}
2023-09-14 19:43:13 +03:00
// findExpByVar returns expression related to var in varToExpMap
static SgExpression* findExpByVar(SgSymbol* var, const map<SgSymbol*, SgExpression*>& varToExpMap)
{
for (const auto& pair : varToExpMap)
if (isEqSymbols(pair.first, var))
return pair.second;
return nullptr;
}
// replaceVarsWithExps changes variables to expressions in exp using varToExpMap,
// returns modified expression
static SgExpression* replaceVarsWithExps(SgExpression* exp,
const map<SgSymbol*, SgExpression*>& varToExpMap)
{
if (exp == nullptr)
return nullptr;
if (exp->variant() == VAR_REF)
{
SgExpression* toReplace = findExpByVar(exp->symbol(), varToExpMap);
if (toReplace != nullptr)
return toReplace;
return exp;
}
exp->setLhs(replaceVarsWithExps(exp->lhs(), varToExpMap));
exp->setRhs(replaceVarsWithExps(exp->rhs(), varToExpMap));
return exp;
}
// substituteExpressions replaces expressions-array references in exp using refToExpMap
static SgExpression* substituteExpressions(SgExpression* exp,
const map<string, SgExpression*>& refToExpMap)
{
if (exp == nullptr)
return nullptr;
if (exp->variant() == ARRAY_REF)
{
const auto& refToExp = refToExpMap.find(exp->unparse());
if (refToExp != refToExpMap.end())
return refToExp->second;
2023-09-14 19:43:13 +03:00
}
exp->setLhs(substituteExpressions(exp->lhs(), refToExpMap));
exp->setRhs(substituteExpressions(exp->rhs(), refToExpMap));
return exp;
}
static bool isVarReadInLoop(SgSymbol* var, SgForStmt* loopStmt)
{
for (SgStatement* st = loopStmt->lexNext(); st != loopStmt->lastNodeOfStmt(); st = st->lexNext())
2023-09-14 19:43:13 +03:00
{
int i = 0;
if (st->variant() == ASSIGN_STAT && isEqSymbols(st->expr(0)->symbol(), var))
i = 1;
for (; i < 3; ++i)
if (st->expr(i) && isSymbolInExpression(var, st->expr(i)))
return true;
}
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;
}
2024-06-08 21:18:50 +03:00
static vector<int> getShortFixedSubscriptsVector(SgArrayRefExp* arrayRef, const PrivateToRemove& varToRemove)
{
return getShortFixedSubscriptsVector(arrayRef, varToRemove.fixedDimensions, varToRemove.regime);
}
2023-09-14 19:43:13 +03:00
// fillReadShortFixedSumscripts fills all short fixed subscripts vectors of array var,
// which are used for reading from array var in exp
static void fillReadShortFixedSubscripts(SgExpression* exp, const PrivateToRemove& var,
2023-09-14 19:43:13 +03:00
set<vector<int>>& fixedSubscripts)
{
if (exp == nullptr)
return;
2024-03-20 01:24:17 +03:00
if (exp->symbol() != nullptr &&
(exp->symbol()->variant() == ARRAY_REF || exp->symbol()->variant() == VARIABLE_NAME) &&
isEqSymbols(exp->symbol(), var.varSymbol))
2023-09-14 19:43:13 +03:00
{
2024-03-20 01:24:17 +03:00
auto subscripts = getShortFixedSubscriptsVector((SgArrayRefExp*)exp, var);
fixedSubscripts.insert(subscripts);
return;
2023-09-14 19:43:13 +03:00
}
fillReadShortFixedSubscripts(exp->lhs(), var, fixedSubscripts);
fillReadShortFixedSubscripts(exp->rhs(), var, fixedSubscripts);
2023-09-14 19:43:13 +03:00
}
// getReadShortFixedSubscripts return set of all short fixed subscripts vectors of array var from loop,
2023-09-14 19:43:13 +03:00
// which are used for reading from array var
static set<vector<int>> getReadShortFixedSubscripts(const PrivateToRemove& var, SgForStmt* loopStmt)
2023-09-14 19:43:13 +03:00
{
set<vector<int>> fixedSubscripts;
for (SgStatement* st = loopStmt->lexNext(); st != loopStmt->lastNodeOfStmt(); st = st->lexNext())
2023-09-14 19:43:13 +03:00
{
int i = 0;
if (st->variant() == ASSIGN_STAT && isEqSymbols(st->expr(0)->symbol(), var.varSymbol))
2023-09-14 19:43:13 +03:00
i = 1;
for (; i < 3; ++i)
fillReadShortFixedSubscripts(st->expr(i), var, fixedSubscripts);
2023-09-14 19:43:13 +03:00
}
return fixedSubscripts;
}
// removeExcessiveDefs removes assignments to var in loop, which are excessive --
// there are no any reading from var with such fixed subscripts vector
static void removeExcessiveDefs(const PrivateToRemove& var)
{
SgForStmt* loopStmt = (SgForStmt*)var.loop->loop->GetOriginal();
set<vector<int>> usedFixedSubscripts = getReadShortFixedSubscripts(var, loopStmt);
2023-09-14 19:43:13 +03:00
vector<SgStatement*> stmtsToRemove;
for (SgStatement* st = loopStmt->lexNext(); st != loopStmt->lastNodeOfStmt(); st = st->lexNext())
2023-09-14 19:43:13 +03:00
{
if (st->variant() != ASSIGN_STAT)
continue;
if (st->expr(0)->symbol() == nullptr || !isEqSymbols(st->expr(0)->symbol(), var.varSymbol))
2023-09-14 19:43:13 +03:00
continue;
auto subscripts = getShortFixedSubscriptsVector((SgArrayRefExp*) st->expr(0), var);
2023-09-14 19:43:13 +03:00
if (usedFixedSubscripts.find(subscripts) == usedFixedSubscripts.end())
stmtsToRemove.push_back(st);
}
for (auto st : stmtsToRemove)
st->deleteStmt();
}
// removeVarFromPrivateAttributes removes var from SPF ANALYSIS PRIVATE attributes of loop
static void removeVarFromPrivateAttributes(SgSymbol* var, LoopGraph* loop)
{
SgStatement* loopStmt = loop->loop->GetOriginal();
for (int i = 0; i < loopStmt->numberOfAttributes(); ++i)
{
SgAttribute* attr = loopStmt->getAttribute(i);
if (attr->getAttributeType() != SPF_ANALYSIS_DIR)
continue;
SgStatement* data = (SgStatement*) attr->getAttributeData();
SgExprListExp* analysisList = (SgExprListExp*) data->expr(0);
if (analysisList == nullptr)
continue;
vector<SgExpression*> newAnalysisList;
for (int i = 0; i < analysisList->length(); ++i)
{
if (analysisList->elem(i)->variant() == ACC_PRIVATE_OP)
{
SgExprListExp* varList = (SgExprListExp*) analysisList->elem(i)->lhs();
vector<SgExpression*> newVarList;
for (int j = 0; j < varList->length(); ++j)
if (!isEqSymbols(var, varList->elem(j)->symbol()))
newVarList.push_back(varList->elem(j)->copyPtr());
if (!newVarList.empty())
newAnalysisList.push_back(new SgExpression(ACC_PRIVATE_OP, makeExprList(newVarList)));
}
else
newAnalysisList.push_back(analysisList->elem(i)->copyPtr());
}
if (!newAnalysisList.empty())
data->setExpression(0, makeExprList(newAnalysisList));
else
loopStmt->deleteAttribute(i);
}
}
// getVarToExpMap returns map SgSymbol* from defRef -> SgExpression* from useRef
static map<SgSymbol*, SgExpression*> getVarToExpMap(SgArrayRefExp* defRef, SgArrayRefExp* useRef,
2024-06-08 21:18:50 +03:00
const vector<bool>& fixedDimensions, Regime regime)
2023-09-14 19:43:13 +03:00
{
map<SgSymbol*, SgExpression*> varToExpMap;
for (int i = 0; i < fixedDimensions.size(); ++i)
2024-06-08 21:18:50 +03:00
{
if (fixedDimensions[i])
continue;
// check not fixed dimension:
if (regime == Regime::REGULAR_INDEXES)
{
RegularExpr useExpr;
checkAndFillRegularExpr(useRef->subscript(i), useExpr, nullptr);
RegularExpr defExpr;
checkAndFillRegularExpr(defRef->subscript(i), defExpr, nullptr);
varToExpMap.insert(make_pair(defExpr.varSymbol, new SgVarRefExp(useExpr.varSymbol)));
}
else
2023-09-14 19:43:13 +03:00
varToExpMap.insert(make_pair(defRef->subscript(i)->symbol(), useRef->subscript(i)));
2024-06-08 21:18:50 +03:00
}
2023-09-14 19:43:13 +03:00
return varToExpMap;
}
// removeArray removes array by substituting it in DEF-USE pairs.
// Returns set of removed fixed subscripts
2024-03-20 01:24:17 +03:00
static set<vector<int>> removeArray(string filename, PrivateToRemove& arrayToRemove)
2023-09-14 19:43:13 +03:00
{
set<vector<int>> removedFixedSubscripts;
auto& fixedDimensions = arrayToRemove.fixedDimensions;
for (auto& defUsePair : arrayToRemove.defUseStmtsPairs)
2023-09-14 19:43:13 +03:00
{
map<string, SgExpression*> refToExpMap;
SgAssignStmt* defStmt = defUsePair.first;
SgStatement* useStmt = defUsePair.second;
2023-09-14 19:43:13 +03:00
SgArrayRefExp* defRef = (SgArrayRefExp*)defStmt->lhs();
vector<int> defFixedSubscripts = getShortFixedSubscriptsVector(defRef, arrayToRemove);
2023-09-14 19:43:13 +03:00
int startIndex = 0;
if (useStmt->variant() == ASSIGN_STAT)
startIndex = 1;
for (int i = startIndex; i < 3; ++i)
2023-09-14 19:43:13 +03:00
{
vector<SgArrayRefExp*> arrayUseRefs;
fillDirectArrayRefs(useStmt->expr(i), arrayToRemove.varSymbol, arrayUseRefs);
if (arrayUseRefs.empty())
continue;
2023-09-14 19:43:13 +03:00
for (SgArrayRefExp* useRef : arrayUseRefs)
{
vector<int> useFixedSubscripts = getShortFixedSubscriptsVector(useRef, arrayToRemove);
if (defFixedSubscripts != useFixedSubscripts)
continue; // because useRef and defRef can be different in subscripts of fixed dimensions
2023-09-14 19:43:13 +03:00
removedFixedSubscripts.insert(useFixedSubscripts);
2023-09-14 19:43:13 +03:00
2024-06-08 21:18:50 +03:00
auto varToExpMap = getVarToExpMap(defRef, useRef, fixedDimensions, arrayToRemove.regime);
2023-09-14 19:43:13 +03:00
SgExpression* expToSubst = defStmt->rhs()->copyPtr();
expToSubst = replaceVarsWithExps(expToSubst, varToExpMap);
refToExpMap.insert(make_pair(useRef->unparse(), expToSubst));
}
2023-09-14 19:43:13 +03:00
SgExpression* substExp = substituteExpressions(useStmt->expr(i), refToExpMap);
useStmt->setExpression(i, *substExp);
}
2023-09-14 19:43:13 +03:00
}
return removedFixedSubscripts;
}
void removePrivates(string filename, vector<Messages>& messages,
2024-02-24 21:26:05 +03:00
const map<string, CommonBlock*>& commonBlocks,
const map<string, vector<FuncInfo*>>& allFuncInfo,
int& countOfTransform)
2023-09-14 19:43:13 +03:00
{
2024-04-01 16:35:26 +03:00
set<LoopGraph*> removeDC;
2023-09-14 19:43:13 +03:00
for (auto& varToRemove : privatesToRemoveGlobal)
{
if (filename != varToRemove.loop->fileName)
2023-09-14 19:43:13 +03:00
continue;
auto removedDimensions = removeArray(filename, varToRemove);
2023-09-14 19:43:13 +03:00
countOfTransform++;
removeExcessiveDefs(varToRemove);
2024-04-01 16:35:26 +03:00
removeDC.insert(varToRemove.loop);
2024-02-24 21:26:05 +03:00
2024-04-01 16:35:26 +03:00
vector<SgArrayRefExp*> varRefs = getDirectArrayRefs(varToRemove.loop->loop, varToRemove.varSymbol);
2023-09-14 19:43:13 +03:00
int loopLineNum = varToRemove.loop->lineNum;
string varName = varToRemove.varSymbol->identifier();
2023-09-14 19:43:13 +03:00
auto& fixedDimensions = varToRemove.fixedDimensions;
if (varRefs.empty())
{
removeVarFromPrivateAttributes(varToRemove.varSymbol, varToRemove.loop);
2023-09-14 19:43:13 +03:00
addMessageRemovePrivateVar(messages, varName, loopLineNum);
}
else
{
2024-06-08 21:18:50 +03:00
varRefs = removeDuplicateArrayRefs(varRefs, fixedDimensions, varToRemove.regime);
2023-09-14 19:43:13 +03:00
for (auto& varRef : varRefs)
{
vector<int> subscripts = getShortFixedSubscriptsVector(varRef, varToRemove);
2023-09-14 19:43:13 +03:00
if (removedDimensions.find(subscripts) != removedDimensions.end())
{
varName = getDimensionVarName(varToRemove.varSymbol, subscripts,
fixedDimensions, varToRemove.regime);
2023-09-14 19:43:13 +03:00
addMessageRemovePrivateVarPart(messages, varName, loopLineNum);
}
removedDimensions.erase(subscripts);
}
for (auto& removedDimension : removedDimensions)
{
varName = getDimensionVarName(varToRemove.varSymbol, removedDimension,
fixedDimensions, varToRemove.regime);
2024-02-24 21:26:05 +03:00
addMessageRemovePrivateVar(messages, varName, loopLineNum);
2023-09-14 19:43:13 +03:00
}
}
}
2024-04-01 16:35:26 +03:00
2024-06-08 21:18:50 +03:00
// remove dead code from loop:
2024-04-01 16:35:26 +03:00
for (auto& dcLoopRem : removeDC)
{
auto loopStmt = dcLoopRem->loop->GetOriginal();
FuncInfo* currFunc = getCurrentFunc(loopStmt, allFuncInfo);
2024-04-01 16:35:26 +03:00
if (currFunc == nullptr)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
removeDeadCode(currFunc->funcPointer, allFuncInfo, commonBlocks,
loopStmt, loopStmt->lastNodeOfStmt());
}
2023-09-14 19:43:13 +03:00
}
/* ****************************************** *
* End of PRIVATE_REMOVING block of functions *
* ****************************************** */
/* ********************************************* *
* PRIVATE_REMOVING_ANALYSIS block of functions: *
* ********************************************* */
// Context stores general info about current loop and array to remove
struct Context {
const map<string, vector<FuncInfo*>>& allFuncInfo;
const map<string, CommonBlock*>& commonBlocks;
vector<Messages>& messages;
string filename;
Regime regime;
LoopGraph* loop;
SgForStmt* loopStmt;
SgSymbol* arraySymbol;
int dimensionsNum;
vector<SgArrayRefExp*> explicitArrayRefs;
vector<bool> fixedDimensionsMask;
};
2023-09-14 19:43:13 +03:00
// ReducedArrayVars represents mapping of array reference to reduced scalar var:
// arr(1, i) -> pair<vector<int>, SgSymbol*>: [1], arr_1
class ReducedArrayVarsMap {
2023-09-14 19:43:13 +03:00
map<vector<int>, SgSymbol*> arrayMap;
public:
void insert(vector<int> subscripts, SgSymbol* var)
{
this->arrayMap.insert(make_pair(subscripts, var));
}
// find looks up for reduced array var with provided subscripts,
// returns this var or nullptr
SgSymbol* find(const vector<int>& subscripts) const
{
const auto& arr = this->arrayMap.find(subscripts);
if (arr == this->arrayMap.end())
return nullptr;
return arr->second;
}
// getAllVars returns all reduced array vars
vector<SgSymbol*> getAllVars() const
{
vector<SgSymbol*> vars;
for (auto& reducedVar : this->arrayMap)
vars.push_back(reducedVar.second);
return vars;
}
};
enum class TypeOfInsertedStmt { DEF = 1, USE, DECLARATION, NONE };
// InsertedStatement represents inserted statement for reaching definition analysis
struct InsertedStatement {
TypeOfInsertedStmt type = TypeOfInsertedStmt::NONE;
SgStatement* insertedStmt = nullptr;
SgStatement* relatedToStmt = nullptr;
bool isRecursive = false; // true for DEF stmt if it is recursive
InsertedStatement() {};
InsertedStatement(TypeOfInsertedStmt type, SgStatement* insertedStmt)
{
this->type = type;
this->insertedStmt = insertedStmt;
}
};
// findInsertedStmt looking for stmt in insertedStmts
static vector<InsertedStatement>::const_iterator findInsertedStmt(const vector<InsertedStatement>& insertedStmts,
SgStatement* stmt)
{
for (auto iter = insertedStmts.begin(); iter != insertedStmts.end(); ++iter)
if (iter->insertedStmt->id() == stmt->id())
return iter;
return insertedStmts.end();
}
static vector<int> getShortFixedSubscriptsVector(Context* ctx, SgArrayRefExp* arrayRef)
{
2024-06-08 21:18:50 +03:00
return getShortFixedSubscriptsVector(arrayRef, ctx->fixedDimensionsMask, ctx->regime);
}
// 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;
}
2023-09-14 19:43:13 +03:00
// matchesFixedDimensionsMask checks if all array references have INT_VAL value in fixed dimension
static bool checkFixedDimensionsMaskMatching(Context* ctx)
2023-09-14 19:43:13 +03:00
{
for (SgArrayRefExp* ref : ctx->explicitArrayRefs)
for (int i = 0; i < ctx->fixedDimensionsMask.size(); ++i)
if (ctx->fixedDimensionsMask[i] && ref->subscript(i)->variant() != INT_VAL)
2023-09-14 19:43:13 +03:00
return false;
return true;
}
// checkDefStmtRefsMatchesMask checks if all DEF array refs have INT_VAL value in fixed dimensions
2023-09-14 19:43:13 +03:00
// and VAR_REF in non-fixed dimensions
static bool checkDefStmtRefsMatchesMask(Context* ctx)
2023-09-14 19:43:13 +03:00
{
for (SgStatement* st = ctx->loopStmt->lexNext(); st != ctx->loopStmt->lastNodeOfStmt(); st = st->lexNext())
2023-09-14 19:43:13 +03:00
{
if (st->variant() != ASSIGN_STAT)
continue;
vector<SgSymbol*> iterationVars;
fillIterationVars(st, ctx->loopStmt, iterationVars);
if (isEqSymbols(st->expr(0)->symbol(), ctx->arraySymbol)) // DEF statement
2023-09-14 19:43:13 +03:00
{
SgArrayRefExp* ref = (SgArrayRefExp*)st->expr(0);
for (int i = 0; i < ctx->fixedDimensionsMask.size(); ++i)
2023-09-14 19:43:13 +03:00
{
if (ctx->fixedDimensionsMask[i] && ref->subscript(i)->variant() == INT_VAL)
2023-09-14 19:43:13 +03:00
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;
2023-09-14 19:43:13 +03:00
continue;
}
2023-09-14 19:43:13 +03:00
return false;
}
}
}
return true;
}
// getFixedDimensionsVector returns vector of fixed dimensions for arrayRef.
// dimension is fixed, when the value of subsctipt is INT_VAL
static vector<bool> getFixedDimensionsVector(SgArrayRefExp* arrayRef)
{
vector<bool> fixedDimensions(arrayRef->numberOfSubscripts(), false);
for (int i = 0; i < arrayRef->numberOfSubscripts(); ++i)
if (arrayRef->subscript(i)->variant() == INT_VAL)
fixedDimensions[i] = true;
return fixedDimensions;
2023-09-14 19:43:13 +03:00
}
// sunparseFixedDimensionsVector unparses fixed dimensions vector as string
static string sunparseFixedDimensionsVector(const vector<bool>& fixedDimensions)
{
string result = "<";
result.reserve(result.size() + 7 * fixedDimensions.size());
for (int i = 0; i < fixedDimensions.size(); ++i)
{
2023-09-14 19:43:13 +03:00
if (fixedDimensions[i] == true)
result += "true";
else
result += "false";
if (i != fixedDimensions.size() - 1)
result += ", ";
}
result += ">";
return result;
}
static bool checkRegularIndexRefs(Context* ctx)
{
vector<SgArrayRefExp*> newArrayRefsVector;
for (SgStatement* st = ctx->loopStmt->lexNext(); st != ctx->loopStmt->lastNodeOfStmt(); st = st->lexNext())
{
vector<SgSymbol*> iterationVars;
fillIterationVars(st, ctx->loopStmt, iterationVars);
vector<SgArrayRefExp*> arrayRefs = getDirectArrayRefsFromSingleStmt(st, ctx->arraySymbol);
for (auto arrayRef : arrayRefs)
{
if (!isArrayRefInVector(arrayRef, ctx->explicitArrayRefs))
continue;
2024-06-08 21:18:50 +03:00
// check if unfixed dimension index contains iteration var:
SgExprListExp* indexExprList = (SgExprListExp*)arrayRef->lhs();
for (int i = 0; i < indexExprList->length(); ++i)
{
2024-06-08 21:18:50 +03:00
if (ctx->fixedDimensionsMask[i])
continue;
SgExpression* indexExpr = indexExprList->elem(i);
RegularExpr regularExpr;
2024-06-08 21:18:50 +03:00
if (!checkAndFillRegularExpr(indexExpr, regularExpr, nullptr))
return false;
2024-06-08 21:18:50 +03:00
if (regularExpr.coefA == 0)
return false;
bool isIterationVar = false;
for (SgSymbol* iterationVar : iterationVars)
{
if (iterationVar->identifier() == regularExpr.var)
{
isIterationVar = true;
break;
}
}
2024-06-08 21:18:50 +03:00
if (!isIterationVar)
return false;
}
}
}
return true;
}
2023-09-14 19:43:13 +03:00
// getFixedDimensionsMask finds fixed dimensions vector with minimum number of fixed dimensions
// and writes messages if array doesn't have fixed dimensions
static vector<bool> getFixedDimensionsMask(Context* ctx)
2023-09-14 19:43:13 +03:00
{
vector<bool> resultMask(ctx->dimensionsNum, true);
for (const auto arrayRef : ctx->explicitArrayRefs)
{
2023-09-14 19:43:13 +03:00
vector<bool> fixedDimensions = getFixedDimensionsVector(arrayRef);
for (int i = 0; i < ctx->dimensionsNum; ++i)
2023-09-14 19:43:13 +03:00
resultMask[i] = resultMask[i] && fixedDimensions[i];
}
string unparsedFixedDimensions = sunparseFixedDimensionsVector(resultMask);
__spf_print(1, "NOTE: found fixed subsripts mask %s for array '%s' in loop %d\n",
unparsedFixedDimensions.c_str(), ctx->arraySymbol->identifier(), ctx->loop->lineNum);
2023-09-14 19:43:13 +03:00
return resultMask;
}
2024-02-24 21:26:05 +03:00
// getScopeLoopStmt returns least outer scope loop statement
static SgForStmt* getScopeLoopStmt(SgStatement* stmt)
{
2024-02-24 21:26:05 +03:00
while (stmt != nullptr && stmt->variant() != FOR_NODE)
stmt = stmt->controlParent();
2024-02-24 21:26:05 +03:00
return (SgForStmt*)stmt;
}
2024-02-24 21:26:05 +03:00
// getLoopStmtForVar searches for loop with iteration var equal loopVar starting from from stmt
static SgForStmt* getLoopStmtForVar(SgStatement* stmt, string loopVar)
{
2024-02-24 21:26:05 +03:00
while (stmt != nullptr)
{
SgForStmt* loopStmt = getScopeLoopStmt(stmt);
if (loopStmt->doName()->identifier() == loopVar)
return loopStmt;
2024-02-24 21:26:05 +03:00
stmt = stmt->controlParent();
}
return nullptr;
}
2024-02-24 21:26:05 +03:00
// getFixedSubscriptsVector returns vector of fixed INT_VAL subscripts of arrayRef
// true - subscript is fixed, false - it isn't
2024-03-20 01:24:17 +03:00
static vector<ArraySubscript> getFixedSubscriptsVector(SgArrayRefExp* arrayRef, int dimensionsNum = 0,
2024-02-24 21:26:05 +03:00
SgStatement* stmt = nullptr)
{
if (arrayRef == nullptr || arrayRef->numberOfSubscripts() == 0)
2024-03-20 01:24:17 +03:00
return vector<ArraySubscript>(dimensionsNum);
2024-03-20 01:24:17 +03:00
vector<ArraySubscript> subscriptsVector;
2024-02-24 21:26:05 +03:00
for (int i = 0; i < arrayRef->numberOfSubscripts(); ++i)
{
SgExpression* subscriptExpr = arrayRef->subscript(i);
2024-03-20 01:24:17 +03:00
ArraySubscript sub;
2024-02-24 21:26:05 +03:00
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;
}
// 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,
2024-03-20 01:24:17 +03:00
vector<vector<ArraySubscript>>& fixedSubscripts)
{
if (exp == nullptr)
return;
if (exp->variant() == FUNC_CALL)
{
SgFunctionCallExp* funcCallExp = (SgFunctionCallExp*)exp;
string funcName = funcCallExp->funName()->identifier();
FuncInfo* funcInfo = findFuncByName(funcName, ctx->allFuncInfo);
2023-11-05 19:11:24 +03:00
if (funcInfo != nullptr)
{
2023-11-05 19:11:24 +03:00
for (int i = 0; i < funcCallExp->numberOfArgs(); ++i)
{
2023-11-05 19:11:24 +03:00
SgExpression* funcArg = funcCallExp->arg(i);
if (funcArg->symbol() == nullptr || !isEqSymbols(funcArg->symbol(), ctx->arraySymbol))
continue;
if (funcInfo->funcParams.isArgOut(i) || funcArg->lhs() == nullptr)
2023-11-05 19:11:24 +03:00
{
auto fixedVec = getFixedSubscriptsVector((SgArrayRefExp*)funcArg, ctx->dimensionsNum);
fixedSubscripts.push_back(fixedVec);
addMessageUsageInFunctionCall(ctx->messages, getDimensionVarName(ctx->arraySymbol, fixedVec),
funcName, ctx->loop->lineNum, stmtLineNum);
}
}
}
}
checkImplicitDirectUsage(ctx, exp->lhs(), stmtLineNum, fixedSubscripts);
checkImplicitDirectUsage(ctx, exp->rhs(), stmtLineNum, fixedSubscripts);
}
// checkImplicitDirectUsage returns masks of array implicit usage (as out argument)
// and reference to whole array (like fcall(A, 1)) in any function call in loop
// and writes message about each usage
2024-03-20 01:24:17 +03:00
static vector<vector<ArraySubscript>> checkImplicitDirectUsage(Context* ctx)
{
2024-03-20 01:24:17 +03:00
vector<vector<ArraySubscript>> fixedSubscripts;
for (SgStatement* st = ctx->loopStmt->lexNext(); st != ctx->loopStmt->lastNodeOfStmt(); st = st->lexNext())
{
if (st->variant() != PROC_STAT)
{
for (int i = 0; i < 3; ++i)
checkImplicitDirectUsage(ctx, st->expr(i), st->lineNumber(), fixedSubscripts);
continue;
}
// st->variant() == PROC_STAT:
SgCallStmt* callStmt = (SgCallStmt*)st;
string procName = callStmt->name()->identifier();
FuncInfo* funcInfo = findFuncByName(procName, ctx->allFuncInfo);
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 == nullptr || // no info about function
funcInfo->funcParams.isArgOut(i) || // implicit direct usage
callArg->lhs() == nullptr) // reference to whole array
{
2023-10-28 10:29:29 +03:00
auto mask = getFixedSubscriptsVector((SgArrayRefExp*)callArg, ctx->dimensionsNum);
fixedSubscripts.push_back(mask);
addMessageUsageInFunctionCall(ctx->messages, getDimensionVarName(ctx->arraySymbol, mask),
procName, ctx->loop->lineNum, st->lineNumber());
}
}
}
return fixedSubscripts;
}
static vector<Variable*> getCommonBlockGroupedVar(FuncInfo* curFunc, SgSymbol* varSymbol,
const map<string, CommonBlock*>& commonBlocks)
{
for (auto& block : commonBlocks)
{
for (auto& groupedVar : block.second->getGroupedVars())
{
for (Variable* var : groupedVar.second)
{
for (const CommonVariableUse& varUse : var->getAllUse())
{
if (varUse.getFileName() == curFunc->fileName &&
varUse.getFunctionName() == curFunc->funcName &&
isEqSymbols(varUse.getUseS(), varSymbol))
{
return groupedVar.second;
}
}
}
}
}
return vector<Variable*>{};
}
// checkIndirectUsage returns masks of array indirect usage in function
// (indirect usage is usage through common blocks) and writes messages about it
static void checkIndirectUsage(Context* ctx, FuncInfo* calledFunc, vector<Variable*> commonBlockGroupedVar,
2024-03-20 01:24:17 +03:00
set<string>& visitedFuncs, vector<vector<ArraySubscript>>& indirectUsageMasks)
{
if (calledFunc == nullptr)
return;
if (visitedFuncs.find(calledFunc->funcName) != visitedFuncs.end())
return;
visitedFuncs.insert(calledFunc->funcName);
for (Variable* commonBlockVar : commonBlockGroupedVar)
{
for (const CommonVariableUse& varUse : commonBlockVar->getAllUse())
{
if (varUse.getFileName() != calledFunc->fileName || varUse.getFunctionName() != calledFunc->funcName)
continue;
SgStatement* calledFuncStmt = varUse.getFunction();
calledFuncStmt->switchToFile();
vector<SgArrayRefExp*> directArrayRefs = getDirectArrayRefs(calledFuncStmt, varUse.getUseS());
for (auto arrayRef : directArrayRefs)
{
2023-10-28 10:29:29 +03:00
auto mask = getFixedSubscriptsVector(arrayRef, ctx->dimensionsNum);
indirectUsageMasks.push_back(mask);
addMessageUsageInFunctionCall(ctx->messages, getDimensionVarName(ctx->arraySymbol, mask),
calledFunc->funcName, ctx->loop->lineNum, ctx->loop->lineNum);
}
ctx->loopStmt->switchToFile();
}
}
for (FuncInfo* subCalledFunc : calledFunc->callsFromV)
checkIndirectUsage(ctx, subCalledFunc, commonBlockGroupedVar, visitedFuncs, indirectUsageMasks);
}
// checkIndirectUsage returns masks of array indirect usage in any function call in exp
// (indirect usage is usage through common blocks) and writes messages about it
static void checkIndirectUsage(Context* ctx, SgExpression* exp, vector<Variable*> commonBlockGroupedVar,
set<string>& visitedFuncs, vector<vector<ArraySubscript>>& indirectUsageMasks)
{
if (exp == nullptr)
return;
if (exp->variant() == FUNC_CALL)
{
SgFunctionCallExp* funcCallExp = (SgFunctionCallExp*)exp;
string funcName = funcCallExp->funName()->identifier();
FuncInfo* funcInfo = findFuncByName(funcName, ctx->allFuncInfo);
if (funcInfo != nullptr)
checkIndirectUsage(ctx, funcInfo, commonBlockGroupedVar, visitedFuncs, indirectUsageMasks);
}
checkIndirectUsage(ctx, exp->lhs(), commonBlockGroupedVar, visitedFuncs, indirectUsageMasks);
checkIndirectUsage(ctx, exp->rhs(), commonBlockGroupedVar, visitedFuncs, indirectUsageMasks);
}
// checkIndirectUsage returns masks of array indirect usage in any function call in loop
// (indirect usage is usage through common blocks) and writes messages about it
2024-03-20 01:24:17 +03:00
static vector<vector<ArraySubscript>> checkIndirectUsage(Context* ctx)
{
2024-03-20 01:24:17 +03:00
vector<vector<ArraySubscript>> indirectUsageMasks;
FuncInfo* currentFunc = getCurrentFunc(ctx->loopStmt, ctx->allFuncInfo);
if (currentFunc == nullptr)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
2024-06-08 21:18:50 +03:00
const auto& blocks = ctx->commonBlocks;
vector<Variable*> commonBlockGroupedVar = getCommonBlockGroupedVar(currentFunc, ctx->arraySymbol, blocks);
if (commonBlockGroupedVar.empty())
return indirectUsageMasks;
set<string> visitedFunctions = { currentFunc->funcName };
for (SgStatement* st = ctx->loopStmt->lexNext(); st != ctx->loopStmt->lastNodeOfStmt(); st = st->lexNext())
{
if (st->variant() == PROC_STAT)
{
SgCallStmt* callStmt = (SgCallStmt*)st;
string procName = callStmt->name()->identifier();
FuncInfo* calledFunc = findFuncByName(procName, ctx->allFuncInfo);
checkIndirectUsage(ctx, calledFunc, commonBlockGroupedVar, visitedFunctions, indirectUsageMasks);
}
for (int i = 0; i < 3; ++i)
checkIndirectUsage(ctx, st->expr(i), commonBlockGroupedVar, visitedFunctions, indirectUsageMasks);
}
return indirectUsageMasks;
}
// checkImplicitAndIndirectUsage returns masks of implicit or indirect array usage in loop
2024-03-20 01:24:17 +03:00
static vector<vector<ArraySubscript>> checkImplicitAndIndirectUsage(Context* ctx)
{
2024-03-20 01:24:17 +03:00
vector<vector<ArraySubscript>> implicitMasks = checkImplicitDirectUsage(ctx);
vector<vector<ArraySubscript>> indirectMasks = checkIndirectUsage(ctx);
implicitMasks.insert(implicitMasks.end(), indirectMasks.begin(), indirectMasks.end());
return implicitMasks;
}
// filterArrayRefs removes from arrayRefs all refs that are not different from fixedVectors
static void filterArrayRefs(Context* ctx, vector<SgArrayRefExp*>& arrayRefs,
2024-03-20 01:24:17 +03:00
const vector<vector<ArraySubscript>>& masks)
{
if (masks.empty())
return;
vector<SgArrayRefExp*> filteredArrayRefs;
for (auto arrayRef : arrayRefs)
{
2024-03-20 01:24:17 +03:00
vector<ArraySubscript> arrayRefVec = getFixedSubscriptsVector(arrayRef, ctx->dimensionsNum);
bool isDifferent = false;
for (auto& mask : masks)
{
for (int i = 0; i < arrayRefVec.size(); i++)
{
if (arrayRefVec[i].isFixed && mask[i].isFixed && arrayRefVec[i].value != mask[i].value)
{
isDifferent = true;
break;
}
}
if (isDifferent)
break;
}
if (isDifferent)
filteredArrayRefs.push_back(arrayRef);
}
arrayRefs.swap(filteredArrayRefs);
}
2023-09-14 19:43:13 +03:00
// getReducedArrayVarName returns name for new reduced array variable,
// made by symbol and subscripts: arr, [1, 2] -> arr_1_2
static string getReducedArrayVarName(SgSymbol* symbol, const vector<int>& subscripts)
{
string name = OriginalSymbol(symbol)->identifier();
if (subscripts.empty())
return name + "_";
name.reserve(name.size() + subscripts.size() * 3);
for (int i : subscripts)
{
if (i < 0)
name += "_M" + std::to_string((-1) * i);
else
name += "_" + std::to_string(i);
}
2023-09-14 19:43:13 +03:00
return name;
}
// getReducedArrayVars makes reduced array vars for arrayRefs
static ReducedArrayVarsMap getReducedArrayVars(Context* ctx)
2023-09-14 19:43:13 +03:00
{
ReducedArrayVarsMap reducedArrayVars;
2023-09-14 19:43:13 +03:00
SgType* type = ctx->explicitArrayRefs[0]->type();
SgStatement* scope = ctx->loopStmt->getScopeForDeclare();
for (SgArrayRefExp* arrayRef : ctx->explicitArrayRefs)
2023-09-14 19:43:13 +03:00
{
vector<int> subscripts = getShortFixedSubscriptsVector(ctx, arrayRef);
2023-09-14 19:43:13 +03:00
if (reducedArrayVars.find(subscripts) == nullptr)
{
string name = getReducedArrayVarName(arrayRef->symbol(), subscripts);
2023-09-14 19:43:13 +03:00
2024-06-08 21:18:50 +03:00
if (checkSymbNameAndCorrect(name, "_") != name)
{
int nameNumber = checkSymbNameAndCorrect(name + "__", 0);
2023-09-14 19:43:13 +03:00
name = name + "__" + std::to_string(nameNumber);
2024-06-08 21:18:50 +03:00
}
2023-09-14 19:43:13 +03:00
SgSymbol* newSymbol = new SgSymbol(VARIABLE_NAME, name.c_str(), type, scope);
reducedArrayVars.insert(subscripts, newSymbol);
}
}
return reducedArrayVars;
}
// getVarsToDependOn returns all vars that var depends on
static set<string> getVarsToDependOn(SgForStmt* loopStmt, SgSymbol* var)
{
set<string> dependOn;
for (SgStatement* st = loopStmt->lexNext(); st != loopStmt->lastNodeOfStmt(); st = st->lexNext())
2023-09-14 19:43:13 +03:00
if (st->variant() == ASSIGN_STAT && isEqSymbols(st->expr(0)->symbol(), var))
getVariables(st->expr(1), dependOn, { VAR_REF, ARRAY_REF });
return dependOn;
}
// getDefStmtForReducedArray returns DFE statement for reduced array variable
static InsertedStatement getDefStmtForReducedArray(Context* ctx, SgArrayRefExp* arrayRef,
const ReducedArrayVarsMap& reducedArrayVars)
2023-09-14 19:43:13 +03:00
{
vector<int> subscriptVector = getShortFixedSubscriptsVector(ctx, arrayRef);
2023-09-14 19:43:13 +03:00
SgSymbol* reducedVar = reducedArrayVars.find(subscriptVector);
if (reducedVar == nullptr)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
SgExpression* lhs = new SgVarRefExp(reducedVar);
SgExpression* rhs = new SgValueExp(0);
SgStatement* assignStmt = new SgAssignStmt(*lhs, *rhs);
return InsertedStatement(TypeOfInsertedStmt::DEF, assignStmt);
}
// getUseStmtForReducedArray returns USE statement for reduced array variable
// (assignment to receiverVar)
static InsertedStatement getUseStmtForReducedArray(Context* ctx, SgArrayRefExp* arrayRef,
const ReducedArrayVarsMap& reducedArrayVars,
2023-09-14 19:43:13 +03:00
SgSymbol* receiverVar)
{
vector<int> subscriptVector = getShortFixedSubscriptsVector(ctx, arrayRef);
2023-09-14 19:43:13 +03:00
SgSymbol* reducedVar = reducedArrayVars.find(subscriptVector);
if (reducedVar == nullptr)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
SgExpression* lhs = new SgVarRefExp(receiverVar);
SgExpression* rhs = new SgVarRefExp(reducedVar);
SgStatement* assignStmt = new SgAssignStmt(*lhs, *rhs);
return InsertedStatement(TypeOfInsertedStmt::USE, assignStmt);
}
// insertReducedArrayVarStmts inserts in loop assignment statements with reduced vars,
// returns vector of inserted statements
static vector<InsertedStatement> insertReducedArrayVarStmts(Context* ctx,
const ReducedArrayVarsMap& reducedArrayVars,
2023-09-14 19:43:13 +03:00
SgSymbol* receiverVar)
{
vector<InsertedStatement> insertedStmts;
for (SgStatement* st = ctx->loopStmt->lexNext(); st != ctx->loopStmt->lastNodeOfStmt(); st = st->lexNext())
2023-09-14 19:43:13 +03:00
{
bool isUseStmt = false;
int startIndex = 0;
if (st->variant() == ASSIGN_STAT)
startIndex = 1;
for (int i = startIndex; i < 3; ++i)
{
if (isSymbolInExpression(ctx->arraySymbol, st->expr(i))) // reading from array - USE stmt
2023-09-14 19:43:13 +03:00
{
vector<SgArrayRefExp*> arrayRefs;
fillDirectArrayRefs(st->expr(i), ctx->arraySymbol, arrayRefs);
2024-06-08 21:18:50 +03:00
arrayRefs = removeDuplicateArrayRefs(arrayRefs, ctx->fixedDimensionsMask, ctx->regime);
if (!arrayRefs.empty())
isUseStmt = true;
for (SgArrayRefExp* arrayRef : arrayRefs)
{
if (!isArrayRefInVector(arrayRef, ctx->explicitArrayRefs))
continue;
InsertedStatement useStmt = getUseStmtForReducedArray(ctx, arrayRef,
reducedArrayVars, receiverVar);
useStmt.relatedToStmt = st;
st->insertStmtBefore(*useStmt.insertedStmt, *st->controlParent());
insertedStmts.push_back(useStmt);
}
2023-09-14 19:43:13 +03:00
}
}
if (st->variant() == ASSIGN_STAT &&
isEqSymbols(st->expr(0)->symbol(), ctx->arraySymbol) && // assignment to array - DEF stmt
isArrayRefInVector((SgArrayRefExp*)st->expr(0), ctx->explicitArrayRefs))
2023-09-14 19:43:13 +03:00
{
InsertedStatement defStmt = getDefStmtForReducedArray(ctx, (SgArrayRefExp*)st->expr(0),
reducedArrayVars);
2023-09-14 19:43:13 +03:00
defStmt.relatedToStmt = st;
defStmt.isRecursive = isUseStmt;
st->insertStmtBefore(*defStmt.insertedStmt, *st->controlParent());
insertedStmts.push_back(defStmt);
}
}
return insertedStmts;
}
// makeTmpVar returns new temporary var with name like tmp_N
static SgSymbol* makeTmpVar(Context* ctx)
2023-09-14 19:43:13 +03:00
{
SgStatement* scope = ctx->loopStmt->getScopeForDeclare();
2023-09-14 19:43:13 +03:00
string varName = "tmp_";
int nameNumber = checkSymbNameAndCorrect(varName, 0);
varName = "tmp_" + std::to_string(nameNumber);
return new SgSymbol(VARIABLE_NAME, varName.c_str(), ctx->explicitArrayRefs[0]->type(), scope);
2023-09-14 19:43:13 +03:00
}
// buildDefUsePairs builds pairs of DEF and USE statements for array
static vector<DefUseStmtsPair> buildDefUsePairs(Context* ctx, const CFG_Type& CFGraph,
const vector<InsertedStatement>& insertedStmts)
2023-09-14 19:43:13 +03:00
{
vector<DefUseStmtsPair> defUsePairs;
string arrayName = ctx->arraySymbol->identifier();
2023-11-05 19:11:24 +03:00
for (const InsertedStatement& useInsertedStmt : insertedStmts)
2023-09-14 19:43:13 +03:00
{
2023-11-05 19:11:24 +03:00
if (useInsertedStmt.type != TypeOfInsertedStmt::USE) // analysis for USE stmt
2023-09-14 19:43:13 +03:00
continue;
2023-11-05 19:11:24 +03:00
int useLineNum = useInsertedStmt.relatedToStmt->lineNumber();
2023-09-14 19:43:13 +03:00
// looking for reaching definitions for the current block:
2023-11-05 19:11:24 +03:00
auto useInsAndBlock = getInstructionAndBlockByStatement(CFGraph, useInsertedStmt.insertedStmt);
2023-09-14 19:43:13 +03:00
auto useArg = useInsAndBlock.first->getArg1();
const auto& RD_In = useInsAndBlock.second->getRD_In();
const auto& RD_forUseArg = RD_In.find(useArg);
if (RD_forUseArg == RD_In.end()) // cannot find reaching definitions for argument
{
addMessageCannotFindRD(ctx->messages, arrayName, useLineNum);
2023-09-14 19:43:13 +03:00
continue;
}
set<int> RD_defArgs = RD_forUseArg->second; // make copy
2023-11-05 19:11:24 +03:00
2024-06-08 21:18:50 +03:00
// delete recursive, uninit and definitions that cannot reach use stmt from RD def args:
2024-02-24 18:11:28 +03:00
set<int> tmpRD_defArgs;
2023-09-14 19:43:13 +03:00
for (int defArgNum : RD_defArgs)
{
2023-11-05 19:11:24 +03:00
if (defArgNum == SAPFOR::CFG_VAL::UNINIT)
continue;
2023-09-14 19:43:13 +03:00
auto defInsAndBlock = getInstructionAndBlockByNumber(CFGraph, defArgNum);
2023-11-05 19:11:24 +03:00
if (defInsAndBlock.first == nullptr)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
2023-09-14 19:43:13 +03:00
SgStatement* defStmt = defInsAndBlock.first->getOperator();
auto defInsertedStmt = findInsertedStmt(insertedStmts, defStmt);
2024-06-08 21:18:50 +03:00
if (useLineNum <= defInsertedStmt->relatedToStmt->lineNumber())
2024-02-24 18:11:28 +03:00
continue;
tmpRD_defArgs.insert(defArgNum);
2023-09-14 19:43:13 +03:00
}
2024-02-24 18:11:28 +03:00
RD_defArgs.swap(tmpRD_defArgs);
2023-09-14 19:43:13 +03:00
SgStatement* defStmt = nullptr;
2024-06-08 21:18:50 +03:00
if (RD_defArgs.size() != 1)
2023-11-05 19:11:24 +03:00
{
bool defIsFound = false;
2023-11-05 19:11:24 +03:00
2024-06-08 21:18:50 +03:00
// try to find definition not from RD_defArgs, by search in the block instructions:
string defVarName = useInsertedStmt.insertedStmt->expr(1)->symbol()->identifier();
const auto& blockInstructionsVector = useInsAndBlock.second->getInstructions();
for (auto& instruction : blockInstructionsVector)
{
SgStatement* stmt = instruction->getInstruction()->getOperator();
if (stmt == useInsertedStmt.insertedStmt)
break;
2023-11-05 19:11:24 +03:00
2024-06-08 21:18:50 +03:00
if (stmt->variant() == ASSIGN_STAT
&& stmt->expr(0)->symbol()->identifier() == defVarName
&& !isVarChangedBetween(defVarName, stmt, useInsertedStmt.insertedStmt))
2023-11-05 19:11:24 +03:00
{
defIsFound = true;
2024-06-08 21:18:50 +03:00
defStmt = stmt;
break;
2023-11-05 19:11:24 +03:00
}
}
if (!defIsFound)
2023-11-05 19:11:24 +03:00
{
addMessageCannotFindRD(ctx->messages, arrayName, useLineNum);
2023-11-05 19:11:24 +03:00
continue;
}
}
else
2023-09-14 19:43:13 +03:00
{
auto defInsAndBlock = getInstructionAndBlockByNumber(CFGraph, *RD_defArgs.begin());
2024-02-24 18:11:28 +03:00
if (defInsAndBlock.first == nullptr)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
defStmt = defInsAndBlock.first->getOperator();
2023-09-14 19:43:13 +03:00
}
auto defInsertedStmt = findInsertedStmt(insertedStmts, defStmt);
if (defInsertedStmt == insertedStmts.end())
{
addMessageCannotFindRD(ctx->messages, arrayName, useLineNum);
2023-09-14 19:43:13 +03:00
continue;
}
//don't substitute def stmt into use, if def is recursive
if (defInsertedStmt->isRecursive)
{
addMessageRecursiveDependency(ctx->messages, arrayName, useLineNum);
2023-09-14 19:43:13 +03:00
continue;
}
SgAssignStmt* def = (SgAssignStmt*)defInsertedStmt->relatedToStmt;
2023-11-05 19:11:24 +03:00
SgAssignStmt* use = (SgAssignStmt*)useInsertedStmt.relatedToStmt;
2023-09-14 19:43:13 +03:00
defUsePairs.push_back(make_pair(def, use));
}
return defUsePairs;
}
// findChildLoop returns LoopGraph for provided loop statement
static LoopGraph* findLoop(LoopGraph* outerLoop, SgForStmt* loopStmt)
{
SgStatement* outerLoopStmt = outerLoop->loop->GetOriginal();
if (outerLoopStmt->id() == loopStmt->id())
return outerLoop;
for (auto childLoop : outerLoop->children)
{
auto childLoopGraph = findLoop(childLoop, loopStmt);
if (childLoopGraph != nullptr)
return childLoopGraph;
}
return nullptr;
}
// minCommonAncestor finds least common ancestor of a and b loops in loop graph tree with root parent
static LoopGraph* leastCommonAncestor(LoopGraph* a, LoopGraph* b, LoopGraph* parent)
{
LoopGraph* tmp;
int aDepth = 0;
tmp = a;
while (tmp != parent)
{
aDepth++;
tmp = tmp->parent;
}
int bDepth = 0;
tmp = b;
while (tmp != parent)
{
bDepth++;
tmp = tmp->parent;
}
while (aDepth != bDepth)
{
if (aDepth > bDepth)
{
a = a->parent;
aDepth--;
}
else
{
b = b->parent;
bDepth--;
}
}
while (a->lineNum != b->lineNum)
{
a = a->parent;
b = b->parent;
}
return a;
}
// 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,
2024-03-20 01:24:17 +03:00
vector<pair<string, vector<ArraySubscript>>>& vec,
2024-02-24 21:26:05 +03:00
SgStatement* stmt = nullptr)
2023-09-14 19:43:13 +03:00
{
if (exp == nullptr)
return;
if (exp->symbol() != nullptr)
{
if (exp->variant() == VAR_REF)
{
for (const auto& elem : vec)
if (elem.first == exp->symbol()->identifier())
return;
2024-03-20 01:24:17 +03:00
vec.push_back(make_pair(exp->symbol()->identifier(), vector<ArraySubscript>{}));
}
2023-09-14 19:43:13 +03:00
else if (exp->variant() == ARRAY_REF)
{
2023-09-14 19:43:13 +03:00
vec.push_back(make_pair(exp->symbol()->identifier(),
2024-02-24 21:26:05 +03:00
getFixedSubscriptsVector((SgArrayRefExp*)exp, 0, stmt)));
SgExprListExp* exprList = (SgExprListExp*)exp->lhs();
for (int i = 0; i < exprList->length(); ++i)
2024-02-24 21:26:05 +03:00
fillFixedSubscriptsVectorsOfAllVars(exprList->elem(i), vec, stmt);
}
2023-09-14 19:43:13 +03:00
return;
}
2024-02-24 21:26:05 +03:00
fillFixedSubscriptsVectorsOfAllVars(exp->lhs(), vec, stmt);
fillFixedSubscriptsVectorsOfAllVars(exp->rhs(), vec, stmt);
}
// fixedSubscriptLess checks if left FixedSubscript is less than right
2024-03-20 01:24:17 +03:00
static bool fixedSubscriptLess(const ArraySubscript& left, const ArraySubscript& right)
2024-02-24 21:26:05 +03:00
{
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 arePossibleDifferent(ArraySubscript left, ArraySubscript right)
2024-02-24 21:26:05 +03:00
{
if (left.isFixed && right.isRegIndex && right.regExprStart == right.regExprEnd) {
return true; // in general, this is not true
}
return false;
2023-09-14 19:43:13 +03:00
}
// 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)
2023-09-14 19:43:13 +03:00
{
if (exp->symbol()->identifier() != var.first)
return true;
if (exp->variant() == VAR_REF)
return false;
2024-03-20 01:24:17 +03:00
vector<ArraySubscript> leftVec = getFixedSubscriptsVector((SgArrayRefExp*)exp, 0, stmt);
2024-02-24 21:26:05 +03:00
if (leftVec.size() != var.second.size())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
2023-09-14 19:43:13 +03:00
for (int i = 0; i < leftVec.size(); i++)
2024-02-24 21:26:05 +03:00
{
if (fixedSubscriptLess(leftVec[i], var.second[i])
|| fixedSubscriptLess(var.second[i], leftVec[i]))
{
return true;
}
else if (arePossibleDifferent(leftVec[i], var.second[i]))
2024-02-24 21:26:05 +03:00
{
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());
2023-09-14 19:43:13 +03:00
return true;
2024-02-24 21:26:05 +03:00
}
2024-02-24 21:26:05 +03:00
}
2023-09-14 19:43:13 +03:00
return false;
}
2024-06-08 21:18:50 +03:00
static pair<SAPFOR::Argument*, set<int>> findVarInRDSet(const map<SAPFOR::Argument*, set<int>>& RD_In,
const string& var)
2023-09-14 19:43:13 +03:00
{
for (auto& RD_InElem : RD_In)
{
string elemName = RD_InElem.first->getValue();
size_t pos = elemName.find('%');
if (pos == string::npos)
continue;
if (var == elemName.substr(pos+1, elemName.length() - pos - 1))
return RD_InElem;
}
return make_pair(nullptr, set<int>{});
}
// checkDefUsePair checks if def statement from pair can be substituted into use statement
// and creates messages
2024-02-24 21:26:05 +03:00
static bool checkDefUsePair(Context* ctx, const DefUseStmtsPair& defUse, const CFG_Type& CFGraph)
2023-09-14 19:43:13 +03:00
{
if (defUse.first->lineNumber() > defUse.second->lineNumber())
return false;
string arrayName = ctx->arraySymbol->identifier();
2023-09-14 19:43:13 +03:00
2024-03-20 01:24:17 +03:00
vector<pair<string, vector<ArraySubscript>>> dependOnVars;
2023-09-14 19:43:13 +03:00
SgArrayRefExp* defRef = (SgArrayRefExp*)defUse.first->expr(0);
vector<SgArrayRefExp*> arrayUseRefs = getDirectArrayRefsFromSingleStmt(defUse.second, ctx->arraySymbol);
2023-09-14 19:43:13 +03:00
for (auto useRef : arrayUseRefs)
{
2024-06-08 21:18:50 +03:00
map<SgSymbol*, SgExpression*> varToExpMap;
varToExpMap = getVarToExpMap(defRef, useRef, ctx->fixedDimensionsMask, ctx->regime);
2023-09-14 19:43:13 +03:00
SgExpression* expToSubst = defUse.first->rhs()->copyPtr();
expToSubst = replaceVarsWithExps(expToSubst, varToExpMap);
2024-02-24 21:26:05 +03:00
fillFixedSubscriptsVectorsOfAllVars(expToSubst, dependOnVars, defUse.second);
2023-09-14 19:43:13 +03:00
}
vector<SgSymbol*> iterationVars{};
2024-04-19 17:52:00 +03:00
fillIterationVars(defUse.second, nullptr, iterationVars);
2023-09-14 19:43:13 +03:00
auto defInsAndBlock = getInstructionAndBlockByStatement(CFGraph, defUse.first);
const auto& defRD_In = defInsAndBlock.second->getRD_In();
auto useInsAndBlock = getInstructionAndBlockByStatement(CFGraph, defUse.second);
const auto& useRD_In = useInsAndBlock.second->getRD_In();
for (const auto& var : dependOnVars)
2023-09-14 19:43:13 +03:00
{
if (var.second.size() == 0) // check scalar vars
2023-09-14 19:43:13 +03:00
{
// iteration var doesn't obstruct the removing:
bool isIterationVar = false;
for (auto iterationVar : iterationVars)
{
if (iterationVar->identifier() == var.first)
{
isIterationVar = true;
break;
}
}
if (isIterationVar)
continue;
2023-09-14 19:43:13 +03:00
auto defArg = findVarInRDSet(defRD_In, var.first);
if (defArg.first == nullptr) // there is no any RD for common vars or parameters
continue;
auto useArg = findVarInRDSet(useRD_In, var.first);
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,
2023-09-14 19:43:13 +03:00
var.first, defUse.first->lineNumber());
return false;
}
}
}
// checking arrays:
auto defLoopStmt = getScopeLoopStmt(defUse.first);
auto useLoopStmt = getScopeLoopStmt(defUse.second);
LoopGraph* loop = ctx->loop;
while (loop->perfectLoop != 1)
loop = loop->children[0];
2024-02-24 21:26:05 +03:00
LoopGraph* defLoop = findLoop(loop, defLoopStmt);
LoopGraph* useLoop = findLoop(loop, useLoopStmt);
2023-09-14 19:43:13 +03:00
if (!defLoopStmt || !useLoopStmt || !defLoop || !useLoop)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
int minCommonLoopLine = leastCommonAncestor(defLoop, useLoop, loop)->lineNum;
if (defLoop->lineNum != minCommonLoopLine)
while (defLoop->parent->lineNum != minCommonLoopLine)
defLoop = defLoop->parent;
if (useLoop->lineNum != minCommonLoopLine)
while (useLoop->parent->lineNum != minCommonLoopLine)
useLoop = useLoop->parent;
int defLoopLine = defLoop->lineNum;
int useLoopLine = useLoop->lineNum;
SgStatement *startStmt = nullptr, *endStmt = nullptr;
if (defLoopLine != minCommonLoopLine && useLoopLine != minCommonLoopLine)
{
startStmt = defLoop->loop;
endStmt = useLoop->loop->lastNodeOfStmt();
}
else if (defLoopLine != minCommonLoopLine && useLoopLine == minCommonLoopLine)
{
startStmt = defLoop->loop;
endStmt = defUse.second;
}
else if (defLoopLine == minCommonLoopLine && useLoopLine != minCommonLoopLine)
{
startStmt = defUse.first;
endStmt = useLoop->loop->lastNodeOfStmt();
}
else if (defLoopLine == minCommonLoopLine && useLoopLine == minCommonLoopLine)
{
startStmt = defUse.first;
endStmt = defUse.second;
}
else
return false;
for (const auto& var : dependOnVars)
{
for (SgStatement* st = startStmt; st != endStmt; st = st->lexNext())
{
2024-02-24 21:26:05 +03:00
if (st == defUse.second)
continue;
if (st->variant() == ASSIGN_STAT && !areDifferentRefs(ctx, st->expr(0), var, st))
2023-09-14 19:43:13 +03:00
{
addMessageDependOnNonInvariant(ctx->messages, arrayName,
2023-09-14 19:43:13 +03:00
var.first, defUse.first->lineNumber());
return false;
}
}
}
return true;
}
// getPrivateArraysFromUserDirs returns private arrays from user directives ANALYSIS PRIVATE
static set<SgSymbol*> getPrivateArraysForLoop(LoopGraph* loop, const UsersDirectives& dirs)
2023-09-14 19:43:13 +03:00
{
set<SgSymbol*> privateArrays;
2023-09-14 19:43:13 +03:00
auto loopDirectives = dirs.find(make_pair(loop->fileName.c_str(), loop->lineNum));
if (loopDirectives == dirs.end()) // no directives for loop
return privateArrays;
set<Symbol*> privateVars;
for (SgStatement* dir : loopDirectives->second)
{
Statement* dirStmt = new Statement(dir);
fillPrivatesFromComment(dirStmt, privateVars);
delete dirStmt;
}
for (Symbol* var : privateVars)
if (var->type()->variant() == T_ARRAY)
privateArrays.insert(var->GetOriginal());
2023-09-14 19:43:13 +03:00
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<SgSymbol*> {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<DefUseStmtsPair> resultDefUsePairs;
for (auto& pair : defUseStmtsPairs)
{
if (checkDefUsePair(ctx, pair, CFG_ForFunc))
{
resultDefUsePairs.push_back(pair);
// don't revert substitutions in use and def stmts:
cancelRevertionForStatement(ctx->filename, pair.first, 1);
cancelRevertionForStatement(ctx->filename, pair.second, 0);
cancelRevertionForStatement(ctx->filename, pair.second, 1);
cancelRevertionForStatement(ctx->filename, pair.second, 2);
}
}
PrivateToRemove newPrivateToRemove;
newPrivateToRemove.loop = ctx->loop;
newPrivateToRemove.varSymbol = ctx->arraySymbol;
newPrivateToRemove.regime = ctx->regime;
newPrivateToRemove.defUseStmtsPairs.swap(resultDefUsePairs);
newPrivateToRemove.fixedDimensions.swap(ctx->fixedDimensionsMask);
privatesToRemoveGlobal.push_back(newPrivateToRemove);
}
// delete inserted statements:
for (auto& stmt : insertedStmts)
stmt.insertedStmt->deleteStmt();
deleteCFG(CFG_ForFunc);
}
void removePrivatesAnalysis(string filename,
vector<LoopGraph*>& loopGraphs,
2023-09-14 19:43:13 +03:00
vector<Messages>& messages,
const UsersDirectives& usersDirectives,
const map<string, CommonBlock*>& commonBlocks,
const map<string, vector<FuncInfo*>>& allFuncInfo)
{
for (LoopGraph* loop : loopGraphs)
{
if (!loop->isFor)
continue;
SgForStmt* loopStmt = (SgForStmt*)loop->loop->GetOriginal();
set<SgSymbol*> privateArrays = getPrivateArraysForLoop(loop, usersDirectives);
2023-09-14 19:43:13 +03:00
if (privateArrays.empty())
continue;
while (true)
{
SgSymbol* arrayToRemove = nullptr;
vector<SgArrayRefExp*> arrayRefs;
// choose arrayToRemove:
for (SgSymbol* arrayToCheck : privateArrays)
2023-09-14 19:43:13 +03:00
{
arrayRefs = getDirectArrayRefs(loopStmt, arrayToCheck);
2023-09-14 19:43:13 +03:00
if (arrayRefs.empty()) // no references to array
continue;
set<string> dependOnVars = getVarsToDependOn(loopStmt, arrayToCheck);
bool skip = false;
for (string dependOnVar : dependOnVars)
for (SgSymbol* notChecked : privateArrays)
2023-09-14 19:43:13 +03:00
if (dependOnVar == notChecked->identifier() && !isEqSymbols(arrayToCheck, notChecked))
skip = true;
if (skip) // check this array again later
continue;
privateArrays.erase(arrayToCheck);
2023-09-14 19:43:13 +03:00
arrayToRemove = arrayToCheck;
break; // arrayToRemove is chosen
}
if (arrayToRemove == nullptr) // no array to remove
break;
Context context = Context{allFuncInfo, commonBlocks, messages, filename};
context.regime = Regime::DEFLT;
context.loop = loop;
context.loopStmt = loopStmt;
context.dimensionsNum = ((SgArrayType*)arrayToRemove->type())->dimension();
context.arraySymbol = arrayToRemove;
2024-06-08 21:18:50 +03:00
string arrayName = arrayToRemove->identifier();
2023-10-28 10:29:29 +03:00
auto filterMasks = checkImplicitAndIndirectUsage(&context);
filterArrayRefs(&context, arrayRefs, filterMasks);
context.explicitArrayRefs.swap(arrayRefs);
if (context.explicitArrayRefs.empty())
continue;
2023-09-14 19:43:13 +03:00
if (!checkLoopAlignmentMatching(&context))
{
2024-06-08 21:18:50 +03:00
addMessageVarNotAlignedWithLoop(messages, arrayName, context.loop->lineNum);
continue;
}
context.fixedDimensionsMask = getFixedDimensionsMask(&context);
2024-03-20 01:24:17 +03:00
if (!context.fixedDimensionsMask.empty() &&
checkFixedDimensionsMaskMatching(&context) &&
checkDefStmtRefsMatchesMask(&context))
2023-09-14 19:43:13 +03:00
{
removePrivateAnalyze(&context);
2023-09-14 19:43:13 +03:00
}
else if (checkRegularIndexRefs(&context))
2023-09-14 19:43:13 +03:00
{
context.regime = Regime::REGULAR_INDEXES;
removePrivateAnalyze(&context);
2023-09-14 19:43:13 +03:00
}
else
2024-06-08 21:18:50 +03:00
addMessageDoesNotMatchMask(messages, arrayName, context.loop->lineNum);
2023-09-14 19:43:13 +03:00
}
}
for (LoopGraph* loop : loopGraphs)
{
removePrivatesAnalysis(filename, loop->children, messages,
usersDirectives, commonBlocks, allFuncInfo);
}
}