2023-09-14 19:43:13 +03:00
|
|
|
#include "private_removing.h"
|
|
|
|
|
|
|
|
|
|
#include "../Utils/errors.h"
|
|
|
|
|
#include "../Utils/SgUtils.h"
|
|
|
|
|
#include "../Utils/utils.h"
|
2023-12-10 14:39:06 +03:00
|
|
|
#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) {}
|
2024-04-16 00:06:24 +03:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
2024-04-16 00:06:24 +03:00
|
|
|
ArraySubscript()
|
|
|
|
|
{
|
2024-02-24 21:26:05 +03:00
|
|
|
isFixed = false;
|
|
|
|
|
value = 0;
|
|
|
|
|
isRegIndex = false;
|
|
|
|
|
regExprStart = RegularExpr{};
|
|
|
|
|
regExprEnd = RegularExpr{};
|
|
|
|
|
}
|
2024-04-16 00:06:24 +03:00
|
|
|
|
|
|
|
|
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-11-29 14:41:14 +03:00
|
|
|
};
|
|
|
|
|
|
2023-09-14 19:43:13 +03:00
|
|
|
// DefUseStmtsPair represents pair of DEF and USE statements for private variable
|
2023-10-15 15:27:54 +03:00
|
|
|
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: *
|
|
|
|
|
* ******************************* */
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
// 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;
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
if (exp->variant() == ARRAY_REF && exp->symbol() != nullptr && isEqSymbols(exp->symbol(), arraySym))
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-10-15 15:27:54 +03:00
|
|
|
refs.push_back((SgArrayRefExp*)exp);
|
2023-09-14 19:43:13 +03:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
fillDirectArrayRefs(exp->lhs(), arraySym, refs);
|
|
|
|
|
fillDirectArrayRefs(exp->rhs(), arraySym, refs);
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
|
|
|
|
|
2023-12-10 14:39:06 +03:00
|
|
|
// getDirectArrayRefs returns all direct arraySym references in compound stmt,
|
2023-10-15 15:27:54 +03:00
|
|
|
// except VAR_DECL statements
|
|
|
|
|
static vector<SgArrayRefExp*> getDirectArrayRefs(SgStatement* stmt, SgSymbol* arraySym)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
|
|
|
|
vector<SgArrayRefExp*> arrayRefs;
|
2023-10-15 15:27:54 +03:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-10 14:39:06 +03:00
|
|
|
// 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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
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());
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-29 14:41:14 +03:00
|
|
|
// checkAndFillRegularExpr checks if expr is regular and fills regularExpr struct
|
|
|
|
|
// with info about expr
|
2023-12-10 14:39:06 +03:00
|
|
|
static bool checkAndFillRegularExpr(SgExpression* expr, RegularExpr& regularExpr, SgSymbol* iterationVar)
|
2023-11-29 14:41:14 +03:00
|
|
|
{
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-10 14:39:06 +03:00
|
|
|
pair<int, int> retCoefs;
|
|
|
|
|
getCoefsOfSubscript(retCoefs, expr, iterationVar);
|
2023-11-29 14:41:14 +03:00
|
|
|
|
2023-12-10 14:39:06 +03:00
|
|
|
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;
|
2023-11-29 14:41:14 +03:00
|
|
|
|
2023-12-10 14:39:06 +03:00
|
|
|
if (retCoefs.first != 0 || retCoefs.second != 0)
|
2023-11-29 14:41:14 +03:00
|
|
|
return true;
|
|
|
|
|
|
2023-12-10 14:39:06 +03:00
|
|
|
// check if expr is like ( 0 ), because we cannot separate zero const int expr from incorrect expr:
|
|
|
|
|
if (expr->variant() == INT_VAL)
|
|
|
|
|
return true;
|
2023-11-29 14:41:14 +03:00
|
|
|
|
|
|
|
|
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,
|
2023-11-29 14:41:14 +03:00
|
|
|
const vector<bool>& fixedDimensionsMask,
|
2024-06-08 21:18:50 +03:00
|
|
|
Regime regime)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-11-29 14:41:14 +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
|
|
|
|
2023-11-29 14:41:14 +03:00
|
|
|
return subscriptsVector;
|
|
|
|
|
}
|
|
|
|
|
else if (regime == Regime::REGULAR_INDEXES)
|
|
|
|
|
{
|
|
|
|
|
vector<int> subscriptsVector;
|
|
|
|
|
SgExprListExp* indexExprList = (SgExprListExp*)arrayRef->lhs();
|
2023-12-10 14:39:06 +03:00
|
|
|
|
2023-11-29 14:41:14 +03:00
|
|
|
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))
|
2023-11-29 14:41:14 +03:00
|
|
|
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,
|
2023-11-29 14:41:14 +03:00
|
|
|
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;
|
2023-12-10 14:39:06 +03:00
|
|
|
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())
|
2023-12-10 14:39:06 +03:00
|
|
|
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
|
2024-04-07 12:05:39 +03:00
|
|
|
static FuncInfo* findFuncByName(string funcName, const map<string, vector<FuncInfo*>>& allFuncInfo)
|
2024-02-24 21:26:05 +03:00
|
|
|
{
|
2024-04-07 12:05:39 +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
|
2024-04-07 12:05:39 +03:00
|
|
|
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: *
|
|
|
|
|
* ************************************* */
|
|
|
|
|
|
2024-04-16 00:06:24 +03:00
|
|
|
static void addMessageVarNotAlignedWithLoop(vector<Messages>& messages, string varName, int loopLineNum)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2024-04-16 00:06:24 +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;
|
2024-04-16 00:06:24 +03:00
|
|
|
__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
|
|
|
|
2024-04-16 00:06:24 +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));
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-16 00:06:24 +03:00
|
|
|
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;
|
2023-10-15 15:27:54 +03:00
|
|
|
__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));
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
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",
|
2023-10-02 22:43:06 +03:00
|
|
|
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());
|
|
|
|
|
|
2023-10-02 22:43:06 +03:00
|
|
|
messages.push_back(Messages(typeMessage::WARR, loopLineNum, messageR, messageE, 2016));
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
static void addMessageUsageInFunctionCall(vector<Messages>& messages, string varName,
|
|
|
|
|
string funcName, int loopLineNum, int stmtLineNum)
|
2023-10-02 22:43:06 +03:00
|
|
|
{
|
2023-10-15 15:27:54 +03:00
|
|
|
__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);
|
2023-10-02 22:43:06 +03:00
|
|
|
|
|
|
|
|
wstring messageE, messageR;
|
2023-10-15 15:27:54 +03:00
|
|
|
__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());
|
2023-10-02 22:43:06 +03:00
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
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,
|
2023-11-29 14:41:14 +03:00
|
|
|
const vector<bool>& fixedDimensions, Regime regime)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
|
|
|
|
string result = var->identifier();
|
|
|
|
|
|
|
|
|
|
result += "(";
|
2023-11-29 14:41:14 +03:00
|
|
|
if (regime == Regime::DEFLT)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-11-29 14:41:14 +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
|
|
|
|
2023-11-29 14:41:14 +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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
// 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)
|
2023-10-15 15:27:54 +03:00
|
|
|
{
|
|
|
|
|
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());
|
2023-12-11 19:44:01 +03:00
|
|
|
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)
|
|
|
|
|
{
|
2023-10-15 15:27:54 +03:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-29 14:41:14 +03:00
|
|
|
// 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
|
2023-12-10 14:39:06 +03:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2023-11-29 14:41:14 +03:00
|
|
|
fillReadShortFixedSubscripts(exp->lhs(), var, fixedSubscripts);
|
|
|
|
|
fillReadShortFixedSubscripts(exp->rhs(), var, fixedSubscripts);
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
|
|
|
|
|
2023-11-29 14:41:14 +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
|
2023-11-29 14:41:14 +03:00
|
|
|
static set<vector<int>> getReadShortFixedSubscripts(const PrivateToRemove& var, SgForStmt* loopStmt)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
|
|
|
|
set<vector<int>> fixedSubscripts;
|
2023-10-15 15:27:54 +03:00
|
|
|
for (SgStatement* st = loopStmt->lexNext(); st != loopStmt->lastNodeOfStmt(); st = st->lexNext())
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
|
|
|
|
int i = 0;
|
2023-10-15 15:27:54 +03:00
|
|
|
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)
|
2023-11-29 14:41:14 +03:00
|
|
|
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();
|
2023-11-29 14:41:14 +03:00
|
|
|
set<vector<int>> usedFixedSubscripts = getReadShortFixedSubscripts(var, loopStmt);
|
2023-09-14 19:43:13 +03:00
|
|
|
|
|
|
|
|
vector<SgStatement*> stmtsToRemove;
|
2023-10-15 15:27:54 +03:00
|
|
|
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;
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
if (st->expr(0)->symbol() == nullptr || !isEqSymbols(st->expr(0)->symbol(), var.varSymbol))
|
2023-09-14 19:43:13 +03:00
|
|
|
continue;
|
|
|
|
|
|
2023-12-10 14:39:06 +03:00
|
|
|
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;
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
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;
|
2023-10-15 15:27:54 +03:00
|
|
|
SgStatement* useStmt = defUsePair.second;
|
2023-09-14 19:43:13 +03:00
|
|
|
|
|
|
|
|
SgArrayRefExp* defRef = (SgArrayRefExp*)defStmt->lhs();
|
2023-12-10 14:39:06 +03:00
|
|
|
vector<int> defFixedSubscripts = getShortFixedSubscriptsVector(defRef, arrayToRemove);
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2023-10-15 15:27:54 +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
|
|
|
{
|
2023-10-15 15:27:54 +03:00
|
|
|
vector<SgArrayRefExp*> arrayUseRefs;
|
|
|
|
|
fillDirectArrayRefs(useStmt->expr(i), arrayToRemove.varSymbol, arrayUseRefs);
|
|
|
|
|
if (arrayUseRefs.empty())
|
|
|
|
|
continue;
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
for (SgArrayRefExp* useRef : arrayUseRefs)
|
|
|
|
|
{
|
2023-12-10 14:39:06 +03:00
|
|
|
vector<int> useFixedSubscripts = getShortFixedSubscriptsVector(useRef, arrayToRemove);
|
2023-10-15 15:27:54 +03:00
|
|
|
if (defFixedSubscripts != useFixedSubscripts)
|
|
|
|
|
continue; // because useRef and defRef can be different in subscripts of fixed dimensions
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2023-10-15 15:27:54 +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
|
|
|
|
2023-10-15 15:27:54 +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
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
SgExpression* substExp = substituteExpressions(useStmt->expr(i), refToExpMap);
|
|
|
|
|
useStmt->setExpression(i, *substExp);
|
|
|
|
|
}
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return removedFixedSubscripts;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-16 00:10:28 +03:00
|
|
|
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)
|
|
|
|
|
{
|
2024-03-16 00:10:28 +03:00
|
|
|
if (filename != varToRemove.loop->fileName)
|
2023-09-14 19:43:13 +03:00
|
|
|
continue;
|
|
|
|
|
|
2024-03-16 00:10:28 +03:00
|
|
|
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;
|
2023-10-15 15:27:54 +03:00
|
|
|
string varName = varToRemove.varSymbol->identifier();
|
2023-09-14 19:43:13 +03:00
|
|
|
auto& fixedDimensions = varToRemove.fixedDimensions;
|
|
|
|
|
if (varRefs.empty())
|
|
|
|
|
{
|
2023-10-15 15:27:54 +03:00
|
|
|
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)
|
|
|
|
|
{
|
2023-12-10 14:39:06 +03:00
|
|
|
vector<int> subscripts = getShortFixedSubscriptsVector(varRef, varToRemove);
|
2023-09-14 19:43:13 +03:00
|
|
|
if (removedDimensions.find(subscripts) != removedDimensions.end())
|
|
|
|
|
{
|
2023-11-29 14:41:14 +03:00
|
|
|
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)
|
|
|
|
|
{
|
2023-11-29 14:41:14 +03:00
|
|
|
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();
|
2024-04-07 12:05:39 +03:00
|
|
|
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: *
|
|
|
|
|
* ********************************************* */
|
|
|
|
|
|
2023-11-29 14:41:14 +03:00
|
|
|
// 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;
|
2024-03-16 00:10:28 +03:00
|
|
|
string filename;
|
2023-11-29 14:41:14 +03:00
|
|
|
|
|
|
|
|
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
|
2023-11-29 14:41:14 +03:00
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-10 14:39:06 +03:00
|
|
|
static vector<int> getShortFixedSubscriptsVector(Context* ctx, SgArrayRefExp* arrayRef)
|
|
|
|
|
{
|
2024-06-08 21:18:50 +03:00
|
|
|
return getShortFixedSubscriptsVector(arrayRef, ctx->fixedDimensionsMask, ctx->regime);
|
2023-12-10 14:39:06 +03:00
|
|
|
}
|
|
|
|
|
|
2024-04-16 00:06:24 +03:00
|
|
|
// 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-12-10 14:39:06 +03:00
|
|
|
|
2023-09-14 19:43:13 +03:00
|
|
|
// matchesFixedDimensionsMask checks if all array references have INT_VAL value in fixed dimension
|
2023-10-15 15:27:54 +03:00
|
|
|
static bool checkFixedDimensionsMaskMatching(Context* ctx)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-10-15 15:27:54 +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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
// 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
|
2023-10-15 15:27:54 +03:00
|
|
|
static bool checkDefStmtRefsMatchesMask(Context* ctx)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-10-15 15:27:54 +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;
|
|
|
|
|
|
2023-12-10 14:39:06 +03:00
|
|
|
vector<SgSymbol*> iterationVars;
|
|
|
|
|
fillIterationVars(st, ctx->loopStmt, iterationVars);
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
if (isEqSymbols(st->expr(0)->symbol(), ctx->arraySymbol)) // DEF statement
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
|
|
|
|
SgArrayRefExp* ref = (SgArrayRefExp*)st->expr(0);
|
2023-10-15 15:27:54 +03:00
|
|
|
for (int i = 0; i < ctx->fixedDimensionsMask.size(); ++i)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-10-15 15:27:54 +03:00
|
|
|
if (ctx->fixedDimensionsMask[i] && ref->subscript(i)->variant() == INT_VAL)
|
2023-09-14 19:43:13 +03:00
|
|
|
continue;
|
2023-12-10 14:39:06 +03:00
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
if (!ctx->fixedDimensionsMask[i] && ref->subscript(i)->variant() == VAR_REF)
|
2023-12-10 14:39:06 +03:00
|
|
|
{
|
|
|
|
|
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-12-10 14:39:06 +03:00
|
|
|
}
|
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;
|
|
|
|
|
|
2023-11-29 14:41:14 +03:00
|
|
|
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());
|
2023-10-02 22:43:06 +03:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-29 14:41:14 +03:00
|
|
|
static bool checkRegularIndexRefs(Context* ctx)
|
|
|
|
|
{
|
2023-12-10 14:39:06 +03:00
|
|
|
vector<SgArrayRefExp*> newArrayRefsVector;
|
|
|
|
|
for (SgStatement* st = ctx->loopStmt->lexNext(); st != ctx->loopStmt->lastNodeOfStmt(); st = st->lexNext())
|
2023-11-29 14:41:14 +03:00
|
|
|
{
|
2023-12-10 14:39:06 +03:00
|
|
|
vector<SgSymbol*> iterationVars;
|
|
|
|
|
fillIterationVars(st, ctx->loopStmt, iterationVars);
|
|
|
|
|
|
|
|
|
|
vector<SgArrayRefExp*> arrayRefs = getDirectArrayRefsFromSingleStmt(st, ctx->arraySymbol);
|
|
|
|
|
for (auto arrayRef : arrayRefs)
|
2023-11-29 14:41:14 +03:00
|
|
|
{
|
2023-12-10 14:39:06 +03:00
|
|
|
if (!isArrayRefInVector(arrayRef, ctx->explicitArrayRefs))
|
|
|
|
|
continue;
|
|
|
|
|
|
2024-06-08 21:18:50 +03:00
|
|
|
// check if unfixed dimension index contains iteration var:
|
2023-12-10 14:39:06 +03:00
|
|
|
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;
|
|
|
|
|
|
2023-12-10 14:39:06 +03:00
|
|
|
SgExpression* indexExpr = indexExprList->elem(i);
|
|
|
|
|
RegularExpr regularExpr;
|
2024-06-08 21:18:50 +03:00
|
|
|
if (!checkAndFillRegularExpr(indexExpr, regularExpr, nullptr))
|
2023-12-10 14:39:06 +03:00
|
|
|
return false;
|
2023-11-29 14:41:14 +03:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-12-10 14:39:06 +03:00
|
|
|
|
2024-06-08 21:18:50 +03:00
|
|
|
if (!isIterationVar)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2023-12-10 14:39:06 +03:00
|
|
|
}
|
2023-11-29 14:41:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
2023-10-15 15:27:54 +03:00
|
|
|
static vector<bool> getFixedDimensionsMask(Context* ctx)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-10-15 15:27:54 +03:00
|
|
|
vector<bool> resultMask(ctx->dimensionsNum, true);
|
|
|
|
|
for (const auto arrayRef : ctx->explicitArrayRefs)
|
2023-10-02 22:43:06 +03:00
|
|
|
{
|
2023-09-14 19:43:13 +03:00
|
|
|
vector<bool> fixedDimensions = getFixedDimensionsVector(arrayRef);
|
2023-10-15 15:27:54 +03:00
|
|
|
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",
|
2023-10-15 15:27:54 +03:00
|
|
|
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)
|
2023-10-15 15:27:54 +03:00
|
|
|
{
|
2024-02-24 21:26:05 +03:00
|
|
|
while (stmt != nullptr && stmt->variant() != FOR_NODE)
|
|
|
|
|
stmt = stmt->controlParent();
|
2023-10-15 15:27:54 +03:00
|
|
|
|
2024-02-24 21:26:05 +03:00
|
|
|
return (SgForStmt*)stmt;
|
2023-10-15 15:27:54 +03:00
|
|
|
}
|
|
|
|
|
|
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)
|
2023-10-15 15:27:54 +03:00
|
|
|
{
|
2024-02-24 21:26:05 +03:00
|
|
|
while (stmt != nullptr)
|
|
|
|
|
{
|
|
|
|
|
SgForStmt* loopStmt = getScopeLoopStmt(stmt);
|
|
|
|
|
|
|
|
|
|
if (loopStmt->doName()->identifier() == loopVar)
|
|
|
|
|
return loopStmt;
|
2023-10-15 15:27:54 +03:00
|
|
|
|
2024-02-24 21:26:05 +03:00
|
|
|
stmt = stmt->controlParent();
|
|
|
|
|
}
|
2023-10-15 15:27:54 +03:00
|
|
|
|
|
|
|
|
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)
|
2023-10-15 15:27:54 +03:00
|
|
|
{
|
2024-04-07 12:05:39 +03:00
|
|
|
if (arrayRef == nullptr || arrayRef->numberOfSubscripts() == 0)
|
2024-03-20 01:24:17 +03:00
|
|
|
return vector<ArraySubscript>(dimensionsNum);
|
2023-10-15 15:27:54 +03:00
|
|
|
|
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;
|
2023-10-15 15:27:54 +03:00
|
|
|
|
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;
|
2023-10-15 15:27:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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)
|
2023-10-15 15:27:54 +03:00
|
|
|
{
|
|
|
|
|
if (exp == nullptr)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (exp->variant() == FUNC_CALL)
|
|
|
|
|
{
|
|
|
|
|
SgFunctionCallExp* funcCallExp = (SgFunctionCallExp*)exp;
|
|
|
|
|
string funcName = funcCallExp->funName()->identifier();
|
2024-04-07 12:05:39 +03:00
|
|
|
FuncInfo* funcInfo = findFuncByName(funcName, ctx->allFuncInfo);
|
2023-11-05 19:11:24 +03:00
|
|
|
if (funcInfo != nullptr)
|
2023-10-15 15:27:54 +03:00
|
|
|
{
|
2023-11-05 19:11:24 +03:00
|
|
|
for (int i = 0; i < funcCallExp->numberOfArgs(); ++i)
|
2023-10-15 15:27:54 +03:00
|
|
|
{
|
2023-11-05 19:11:24 +03:00
|
|
|
SgExpression* funcArg = funcCallExp->arg(i);
|
2024-04-09 00:37:44 +03:00
|
|
|
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);
|
|
|
|
|
}
|
2023-10-15 15:27:54 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)
|
2023-10-15 15:27:54 +03:00
|
|
|
{
|
2024-03-20 01:24:17 +03:00
|
|
|
vector<vector<ArraySubscript>> fixedSubscripts;
|
2023-10-15 15:27:54 +03:00
|
|
|
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();
|
2024-04-07 12:05:39 +03:00
|
|
|
FuncInfo* funcInfo = findFuncByName(procName, ctx->allFuncInfo);
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
for (int i = 0; i < callStmt->numberOfArgs(); ++i)
|
|
|
|
|
{
|
|
|
|
|
SgExpression* callArg = callStmt->arg(i);
|
|
|
|
|
if (callArg->symbol() == nullptr || !isEqSymbols(callArg->symbol(), ctx->arraySymbol))
|
|
|
|
|
continue;
|
2023-11-29 14:41:14 +03:00
|
|
|
|
|
|
|
|
if (funcInfo == nullptr || // no info about function
|
|
|
|
|
funcInfo->funcParams.isArgOut(i) || // implicit direct usage
|
2023-10-15 15:27:54 +03:00
|
|
|
callArg->lhs() == nullptr) // reference to whole array
|
|
|
|
|
{
|
2023-10-28 10:29:29 +03:00
|
|
|
auto mask = getFixedSubscriptsVector((SgArrayRefExp*)callArg, ctx->dimensionsNum);
|
2023-10-15 15:27:54 +03:00
|
|
|
fixedSubscripts.push_back(mask);
|
|
|
|
|
addMessageUsageInFunctionCall(ctx->messages, getDimensionVarName(ctx->arraySymbol, mask),
|
2023-12-10 14:39:06 +03:00
|
|
|
procName, ctx->loop->lineNum, st->lineNumber());
|
2023-10-15 15:27:54 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
2024-04-07 12:05:39 +03:00
|
|
|
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)
|
2023-10-15 15:27:54 +03:00
|
|
|
{
|
2024-04-09 00:37:44 +03:00
|
|
|
if (calledFunc == nullptr)
|
|
|
|
|
return;
|
|
|
|
|
|
2024-04-07 12:05:39 +03:00
|
|
|
if (visitedFuncs.find(calledFunc->funcName) != visitedFuncs.end())
|
2023-10-15 15:27:54 +03:00
|
|
|
return;
|
|
|
|
|
|
2024-04-07 12:05:39 +03:00
|
|
|
visitedFuncs.insert(calledFunc->funcName);
|
2023-10-15 15:27:54 +03:00
|
|
|
|
|
|
|
|
for (Variable* commonBlockVar : commonBlockGroupedVar)
|
|
|
|
|
{
|
|
|
|
|
for (const CommonVariableUse& varUse : commonBlockVar->getAllUse())
|
|
|
|
|
{
|
2024-04-07 12:05:39 +03:00
|
|
|
if (varUse.getFileName() != calledFunc->fileName || varUse.getFunctionName() != calledFunc->funcName)
|
2023-10-15 15:27:54 +03:00
|
|
|
continue;
|
|
|
|
|
|
2024-04-07 12:05:39 +03:00
|
|
|
SgStatement* calledFuncStmt = varUse.getFunction();
|
|
|
|
|
calledFuncStmt->switchToFile();
|
|
|
|
|
vector<SgArrayRefExp*> directArrayRefs = getDirectArrayRefs(calledFuncStmt, varUse.getUseS());
|
2023-10-15 15:27:54 +03:00
|
|
|
for (auto arrayRef : directArrayRefs)
|
|
|
|
|
{
|
2023-10-28 10:29:29 +03:00
|
|
|
auto mask = getFixedSubscriptsVector(arrayRef, ctx->dimensionsNum);
|
2023-10-15 15:27:54 +03:00
|
|
|
indirectUsageMasks.push_back(mask);
|
|
|
|
|
addMessageUsageInFunctionCall(ctx->messages, getDimensionVarName(ctx->arraySymbol, mask),
|
2024-04-07 12:05:39 +03:00
|
|
|
calledFunc->funcName, ctx->loop->lineNum, ctx->loop->lineNum);
|
2023-10-15 15:27:54 +03:00
|
|
|
}
|
2024-04-07 12:05:39 +03:00
|
|
|
ctx->loopStmt->switchToFile();
|
2023-10-15 15:27:54 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-07 12:05:39 +03:00
|
|
|
for (FuncInfo* subCalledFunc : calledFunc->callsFromV)
|
|
|
|
|
checkIndirectUsage(ctx, subCalledFunc, commonBlockGroupedVar, visitedFuncs, indirectUsageMasks);
|
2023-10-15 15:27:54 +03:00
|
|
|
}
|
|
|
|
|
|
2024-04-09 00:37:44 +03:00
|
|
|
// 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);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
// 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)
|
2023-10-15 15:27:54 +03:00
|
|
|
{
|
2024-03-20 01:24:17 +03:00
|
|
|
vector<vector<ArraySubscript>> indirectUsageMasks;
|
2024-04-07 12:05:39 +03:00
|
|
|
FuncInfo* currentFunc = getCurrentFunc(ctx->loopStmt, ctx->allFuncInfo);
|
2023-10-15 15:27:54 +03:00
|
|
|
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);
|
2023-10-15 15:27:54 +03:00
|
|
|
if (commonBlockGroupedVar.empty())
|
|
|
|
|
return indirectUsageMasks;
|
|
|
|
|
|
|
|
|
|
set<string> visitedFunctions = { currentFunc->funcName };
|
2024-04-07 12:05:39 +03:00
|
|
|
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);
|
|
|
|
|
}
|
2024-04-09 00:37:44 +03:00
|
|
|
|
|
|
|
|
for (int i = 0; i < 3; ++i)
|
|
|
|
|
checkIndirectUsage(ctx, st->expr(i), commonBlockGroupedVar, visitedFunctions, indirectUsageMasks);
|
2024-04-07 12:05:39 +03:00
|
|
|
}
|
2023-10-15 15:27:54 +03:00
|
|
|
|
|
|
|
|
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)
|
2023-10-15 15:27:54 +03:00
|
|
|
{
|
2024-03-20 01:24:17 +03:00
|
|
|
vector<vector<ArraySubscript>> implicitMasks = checkImplicitDirectUsage(ctx);
|
|
|
|
|
vector<vector<ArraySubscript>> indirectMasks = checkIndirectUsage(ctx);
|
2023-10-15 15:27:54 +03:00
|
|
|
|
|
|
|
|
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)
|
2023-10-15 15:27:54 +03:00
|
|
|
{
|
|
|
|
|
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);
|
2023-10-15 15:27:54 +03:00
|
|
|
|
|
|
|
|
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)
|
2023-11-29 14:41:14 +03:00
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
// getReducedArrayVars makes reduced array vars for arrayRefs
|
2023-11-29 14:41:14 +03:00
|
|
|
static ReducedArrayVarsMap getReducedArrayVars(Context* ctx)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-11-29 14:41:14 +03:00
|
|
|
ReducedArrayVarsMap reducedArrayVars;
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
SgType* type = ctx->explicitArrayRefs[0]->type();
|
|
|
|
|
SgStatement* scope = ctx->loopStmt->getScopeForDeclare();
|
2023-12-10 14:39:06 +03:00
|
|
|
for (SgArrayRefExp* arrayRef : ctx->explicitArrayRefs)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-12-10 14:39:06 +03:00
|
|
|
vector<int> subscripts = getShortFixedSubscriptsVector(ctx, arrayRef);
|
2023-09-14 19:43:13 +03:00
|
|
|
if (reducedArrayVars.find(subscripts) == nullptr)
|
|
|
|
|
{
|
2023-12-10 14:39:06 +03:00
|
|
|
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;
|
2023-10-15 15:27:54 +03:00
|
|
|
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
|
2023-11-29 14:41:14 +03:00
|
|
|
static InsertedStatement getDefStmtForReducedArray(Context* ctx, SgArrayRefExp* arrayRef,
|
|
|
|
|
const ReducedArrayVarsMap& reducedArrayVars)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-12-10 14:39:06 +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)
|
2023-11-29 14:41:14 +03:00
|
|
|
static InsertedStatement getUseStmtForReducedArray(Context* ctx, SgArrayRefExp* arrayRef,
|
|
|
|
|
const ReducedArrayVarsMap& reducedArrayVars,
|
2023-09-14 19:43:13 +03:00
|
|
|
SgSymbol* receiverVar)
|
|
|
|
|
{
|
2023-12-10 14:39:06 +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(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
|
2023-10-15 15:27:54 +03:00
|
|
|
static vector<InsertedStatement> insertReducedArrayVarStmts(Context* ctx,
|
2023-11-29 14:41:14 +03:00
|
|
|
const ReducedArrayVarsMap& reducedArrayVars,
|
2023-09-14 19:43:13 +03:00
|
|
|
SgSymbol* receiverVar)
|
|
|
|
|
{
|
|
|
|
|
vector<InsertedStatement> insertedStmts;
|
2023-10-15 15:27:54 +03:00
|
|
|
for (SgStatement* st = ctx->loopStmt->lexNext(); st != ctx->loopStmt->lastNodeOfStmt(); st = st->lexNext())
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
|
|
|
|
bool isUseStmt = false;
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
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
|
|
|
{
|
2023-10-15 15:27:54 +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);
|
2023-10-15 15:27:54 +03:00
|
|
|
if (!arrayRefs.empty())
|
|
|
|
|
isUseStmt = true;
|
|
|
|
|
|
|
|
|
|
for (SgArrayRefExp* arrayRef : arrayRefs)
|
|
|
|
|
{
|
|
|
|
|
if (!isArrayRefInVector(arrayRef, ctx->explicitArrayRefs))
|
|
|
|
|
continue;
|
|
|
|
|
|
2023-11-29 14:41:14 +03:00
|
|
|
InsertedStatement useStmt = getUseStmtForReducedArray(ctx, arrayRef,
|
2023-10-15 15:27:54 +03:00
|
|
|
reducedArrayVars, receiverVar);
|
|
|
|
|
useStmt.relatedToStmt = st;
|
|
|
|
|
st->insertStmtBefore(*useStmt.insertedStmt, *st->controlParent());
|
|
|
|
|
insertedStmts.push_back(useStmt);
|
|
|
|
|
}
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-15 15:27:54 +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
|
|
|
{
|
2023-11-29 14:41:14 +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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
// makeTmpVar returns new temporary var with name like tmp_N
|
|
|
|
|
static SgSymbol* makeTmpVar(Context* ctx)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-10-15 15:27:54 +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);
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
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
|
2023-10-15 15:27:54 +03:00
|
|
|
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;
|
|
|
|
|
|
2023-11-29 14:41:14 +03:00
|
|
|
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
|
|
|
|
|
{
|
2023-11-29 14:41:14 +03:00
|
|
|
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
|
|
|
|
2023-11-29 14:41:14 +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
|
|
|
{
|
2023-11-29 14:41:14 +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
|
|
|
{
|
2023-11-29 14:41:14 +03:00
|
|
|
defIsFound = true;
|
2024-06-08 21:18:50 +03:00
|
|
|
defStmt = stmt;
|
2023-11-29 14:41:14 +03:00
|
|
|
break;
|
2023-11-05 19:11:24 +03:00
|
|
|
}
|
|
|
|
|
}
|
2023-11-29 14:41:14 +03:00
|
|
|
|
|
|
|
|
if (!defIsFound)
|
2023-11-05 19:11:24 +03:00
|
|
|
{
|
2023-11-29 14:41:14 +03:00
|
|
|
addMessageCannotFindRD(ctx->messages, arrayName, useLineNum);
|
2023-11-05 19:11:24 +03:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-11-29 14:41:14 +03:00
|
|
|
else
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-11-29 14:41:14 +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__);
|
|
|
|
|
|
2023-11-29 14:41:14 +03:00
|
|
|
defStmt = defInsAndBlock.first->getOperator();
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto defInsertedStmt = findInsertedStmt(insertedStmts, defStmt);
|
|
|
|
|
if (defInsertedStmt == insertedStmts.end())
|
|
|
|
|
{
|
2023-11-29 14:41:14 +03:00
|
|
|
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)
|
|
|
|
|
{
|
2023-11-29 14:41:14 +03:00
|
|
|
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)
|
2023-10-02 22:43:06 +03:00
|
|
|
{
|
|
|
|
|
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-10-02 22:43:06 +03:00
|
|
|
}
|
2023-09-14 19:43:13 +03:00
|
|
|
else if (exp->variant() == ARRAY_REF)
|
2023-10-02 22:43:06 +03:00
|
|
|
{
|
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)));
|
2023-10-02 22:43:06 +03:00
|
|
|
|
|
|
|
|
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-10-02 22:43:06 +03:00
|
|
|
}
|
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
|
2024-04-16 00:06:24 +03:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2024-04-16 00:06:24 +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])
|
2024-04-16 00:06:24 +03:00
|
|
|
|| fixedSubscriptLess(var.second[i], leftVec[i]))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (arePossibleDifferent(leftVec[i], var.second[i]))
|
2024-02-24 21:26:05 +03:00
|
|
|
{
|
2024-04-16 00:06:24 +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-04-16 00:06:24 +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;
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
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);
|
2023-12-10 14:39:06 +03:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2023-12-10 14:39:06 +03:00
|
|
|
vector<SgSymbol*> iterationVars{};
|
2024-04-19 17:52:00 +03:00
|
|
|
fillIterationVars(defUse.second, nullptr, iterationVars);
|
2023-10-02 22:43:06 +03:00
|
|
|
|
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();
|
2023-10-02 22:43:06 +03:00
|
|
|
for (const auto& var : dependOnVars)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-10-02 22:43:06 +03:00
|
|
|
if (var.second.size() == 0) // check scalar vars
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-10-02 22:43:06 +03:00
|
|
|
// iteration var doesn't obstruct the removing:
|
2023-12-10 14:39:06 +03:00
|
|
|
bool isIterationVar = false;
|
|
|
|
|
for (auto iterationVar : iterationVars)
|
|
|
|
|
{
|
|
|
|
|
if (iterationVar->identifier() == var.first)
|
|
|
|
|
{
|
|
|
|
|
isIterationVar = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isIterationVar)
|
2023-10-02 22:43:06 +03:00
|
|
|
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())
|
|
|
|
|
{
|
2023-11-29 14:41:14 +03:00
|
|
|
if (defInsAndBlock.second->getNumber() == useInsAndBlock.second->getNumber())
|
|
|
|
|
if (!isVarChangedBetween(var.first, defUse.first, defUse.second))
|
|
|
|
|
continue;
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
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);
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
LoopGraph* loop = ctx->loop;
|
2024-04-16 00:06:24 +03:00
|
|
|
while (loop->perfectLoop != 1)
|
2023-10-02 22:43:06 +03:00
|
|
|
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;
|
2024-04-16 00:06:24 +03:00
|
|
|
if (st->variant() == ASSIGN_STAT && !areDifferentRefs(ctx, st->expr(0), var, st))
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-10-15 15:27:54 +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
|
2023-10-15 15:27:54 +03:00
|
|
|
static set<SgSymbol*> getPrivateArraysForLoop(LoopGraph* loop, const UsersDirectives& dirs)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-10-15 15:27:54 +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)
|
2023-10-15 15:27:54 +03:00
|
|
|
privateArrays.insert(var->GetOriginal());
|
2023-09-14 19:43:13 +03:00
|
|
|
|
|
|
|
|
return privateArrays;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-29 14:41:14 +03:00
|
|
|
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)
|
2024-03-16 00:10:28 +03:00
|
|
|
{
|
2023-11-29 14:41:14 +03:00
|
|
|
if (checkDefUsePair(ctx, pair, CFG_ForFunc))
|
2024-03-16 00:10:28 +03:00
|
|
|
{
|
2023-11-29 14:41:14 +03:00
|
|
|
resultDefUsePairs.push_back(pair);
|
|
|
|
|
|
2024-03-16 00:10:28 +03:00
|
|
|
// 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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-29 14:41:14 +03:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-16 00:10:28 +03:00
|
|
|
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();
|
2023-10-15 15:27:54 +03:00
|
|
|
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:
|
2023-10-15 15:27:54 +03:00
|
|
|
for (SgSymbol* arrayToCheck : privateArrays)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-10-15 15:27:54 +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)
|
2023-10-15 15:27:54 +03:00
|
|
|
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;
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
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;
|
|
|
|
|
|
2024-03-16 00:10:28 +03:00
|
|
|
Context context = Context{allFuncInfo, commonBlocks, messages, filename};
|
2023-11-29 14:41:14 +03:00
|
|
|
context.regime = Regime::DEFLT;
|
2023-10-15 15:27:54 +03:00
|
|
|
context.loop = loop;
|
|
|
|
|
context.loopStmt = loopStmt;
|
2023-11-29 14:41:14 +03:00
|
|
|
context.dimensionsNum = ((SgArrayType*)arrayToRemove->type())->dimension();
|
2023-10-15 15:27:54 +03:00
|
|
|
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);
|
2023-10-15 15:27:54 +03:00
|
|
|
filterArrayRefs(&context, arrayRefs, filterMasks);
|
|
|
|
|
|
2024-04-07 12:05:39 +03:00
|
|
|
context.explicitArrayRefs.swap(arrayRefs);
|
2023-10-15 15:27:54 +03:00
|
|
|
if (context.explicitArrayRefs.empty())
|
2023-10-02 22:43:06 +03:00
|
|
|
continue;
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2024-04-16 00:06:24 +03:00
|
|
|
if (!checkLoopAlignmentMatching(&context))
|
|
|
|
|
{
|
2024-06-08 21:18:50 +03:00
|
|
|
addMessageVarNotAlignedWithLoop(messages, arrayName, context.loop->lineNum);
|
2024-04-16 00:06:24 +03:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-15 15:27:54 +03:00
|
|
|
context.fixedDimensionsMask = getFixedDimensionsMask(&context);
|
2024-03-20 01:24:17 +03:00
|
|
|
|
2023-11-29 14:41:14 +03:00
|
|
|
if (!context.fixedDimensionsMask.empty() &&
|
|
|
|
|
checkFixedDimensionsMaskMatching(&context) &&
|
|
|
|
|
checkDefStmtRefsMatchesMask(&context))
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-11-29 14:41:14 +03:00
|
|
|
removePrivateAnalyze(&context);
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
2024-03-16 00:10:28 +03:00
|
|
|
else if (checkRegularIndexRefs(&context))
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2024-03-16 00:10:28 +03:00
|
|
|
context.regime = Regime::REGULAR_INDEXES;
|
|
|
|
|
removePrivateAnalyze(&context);
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
2024-03-16 00:10:28 +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)
|
2024-04-16 00:06:24 +03:00
|
|
|
{
|
|
|
|
|
removePrivatesAnalysis(filename, loop->children, messages,
|
|
|
|
|
usersDirectives, commonBlocks, allFuncInfo);
|
|
|
|
|
}
|
2023-12-10 14:39:06 +03:00
|
|
|
}
|