1560 lines
53 KiB
C++
1560 lines
53 KiB
C++
#include "private_arrays_resizing.h"
|
||
#include "../GraphLoop/graph_loops.h"
|
||
#include "../Utils/SgUtils.h"
|
||
#include "../Utils/utils.h"
|
||
#include "../Utils/errors.h"
|
||
#include "../DirectiveProcessing/directive_parser.h"
|
||
#include "../LoopAnalyzer/loop_analyzer.h"
|
||
|
||
#include <set>
|
||
#include <queue>
|
||
#include <vector>
|
||
|
||
using std::string;
|
||
using std::set;
|
||
using std::map;
|
||
using std::queue;
|
||
using std::vector;
|
||
using std::pair;
|
||
using std::make_pair;
|
||
|
||
static void printExp(SgExpression *exp)
|
||
{
|
||
queue<SgExpression*> qq;
|
||
qq.push(exp);
|
||
printf("Expression: ");
|
||
|
||
while (!qq.empty())
|
||
{
|
||
SgExpression *exp = qq.front();
|
||
qq.pop();
|
||
|
||
printf("[%s]: %s\n", tag[exp->variant()], exp->unparse());
|
||
if (exp->variant() == TYPE_OP)
|
||
if (exp->symbol())
|
||
printf("%s, %s", exp->symbol()->identifier(), tag[exp->symbol()->variant()]);
|
||
|
||
if (exp->lhs())
|
||
qq.push(exp->lhs());
|
||
if (exp->rhs())
|
||
qq.push(exp->rhs());
|
||
}
|
||
}
|
||
|
||
static void printSt(SgStatement *st)
|
||
{
|
||
printf("Statement [%s]: %s\n", tag[st->variant()], st->unparse());
|
||
queue<SgExpression*> qq;
|
||
for (int i = 0; i < 3; ++i)
|
||
{
|
||
if (st->expr(i))
|
||
{
|
||
printf("[%d,%s]: %s\n", i, tag[st->expr(i)->variant()], st->expr(i)->unparse());
|
||
qq.push(st->expr(i));
|
||
}
|
||
}
|
||
while (!qq.empty())
|
||
{
|
||
SgExpression *exp = qq.front();
|
||
qq.pop();
|
||
|
||
printf("[%s]: %s\n", tag[exp->variant()], exp->unparse());
|
||
if (exp->variant() == TYPE_OP)
|
||
if (exp->symbol())
|
||
printf("%s, %s", exp->symbol()->identifier(), tag[exp->symbol()->variant()]);
|
||
|
||
if (exp->lhs())
|
||
qq.push(exp->lhs());
|
||
if (exp->rhs())
|
||
qq.push(exp->rhs());
|
||
}
|
||
}
|
||
|
||
static void fillIterationVariables(const LoopGraph* loop, set<string>& vars, int dimensions = -1)
|
||
{
|
||
if (dimensions == -1)
|
||
{
|
||
vars.insert(loop->loopSymbol);
|
||
for (LoopGraph* child : loop->children)
|
||
fillIterationVariables(child, vars);
|
||
}
|
||
else
|
||
{
|
||
for (int i = 0; i < dimensions; ++i)
|
||
{
|
||
vars.insert(loop->loopSymbol);
|
||
if (i != dimensions - 1)
|
||
loop = loop->children[0];
|
||
}
|
||
}
|
||
}
|
||
|
||
static SgExpression* findSymbol(SgSymbol* symbol, SgExpression* list)
|
||
{
|
||
if (list)
|
||
{
|
||
if (list->variant() == VAR_REF || list->variant() == ARRAY_REF)
|
||
{
|
||
if (isEqSymbols(list->symbol(), symbol))
|
||
return list;
|
||
}
|
||
|
||
auto left = findSymbol(symbol, list->lhs());
|
||
if (left)
|
||
return left;
|
||
|
||
auto right = findSymbol(symbol, list->rhs());
|
||
if (right)
|
||
return right;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
static char* constructNewArrayName(const char *oldName, bool isExpansion)
|
||
{
|
||
string name(oldName), newName;
|
||
name += isExpansion ? "_ex" : "_sh";
|
||
newName = name + std::to_string(1);
|
||
for (int n = 2; ifSymbolExists(current_file, newName); ++n)
|
||
newName = name + std::to_string(n);
|
||
|
||
char* newNameChar = (char*)malloc((newName.size() + 1) * sizeof(char));
|
||
addToCollection(__LINE__, __FILE__, newNameChar, 0);
|
||
if (newNameChar)
|
||
strcpy(newNameChar, newName.c_str());
|
||
else
|
||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||
|
||
return newNameChar;
|
||
}
|
||
|
||
static const string constructNewBoundName(const char *oldName, int loopLineNumber, const char *add)
|
||
{
|
||
string name(oldName), newName;
|
||
name += "_" + std::to_string(loopLineNumber);
|
||
name += add; // start ? "_start" : "_end";
|
||
newName = name;
|
||
for (int n = 0; ifSymbolExists(current_file, newName); ++n)
|
||
newName = name + "_" + std::to_string(n);
|
||
|
||
return newName;
|
||
}
|
||
|
||
static SgSymbol* createNewArrayNameSymbol(SgExpression* declaration, bool isExpansion, bool canBeStatic)
|
||
{
|
||
SgType* type = new SgType(T_ARRAY);
|
||
char* newNameStr = constructNewArrayName(declaration->symbol()->identifier(), isExpansion);
|
||
SgSymbol* newName = new SgSymbol(VARIABLE_NAME, newNameStr, type, NULL);
|
||
|
||
auto attrs = declaration->symbol()->attributes();
|
||
if (!canBeStatic)
|
||
attrs |= ALLOCATABLE_BIT;
|
||
|
||
newName->setAttribute(attrs);
|
||
return newName;
|
||
}
|
||
|
||
static void fillLoopBoundExprs(const LoopGraph* forLoop, int depthOfResize, const vector<SgSymbol*>& indexes, vector<SgExpression*>& bounds)
|
||
{
|
||
const LoopGraph* curLoop = forLoop;
|
||
for (int i = 0; i < depthOfResize; i++)
|
||
{
|
||
SgForStmt* loopStmt = (SgForStmt*)curLoop->loop->GetOriginal();
|
||
for (int j = 0; j < indexes.size(); j++)
|
||
{
|
||
if (indexes[j] && isEqSymbols(loopStmt->doName(), indexes[j]))
|
||
{
|
||
//TODO: add MIN and MAX call for bounds
|
||
if (curLoop->stepVal == 0)
|
||
{
|
||
__spf_print(1, "unknown step sign of loop on line %d\n", curLoop->lineNum);
|
||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||
}
|
||
|
||
if (curLoop->stepVal > 0)
|
||
bounds[j] = new SgExpression(DDOT, loopStmt->start()->copyPtr(), loopStmt->end()->copyPtr(), NULL);
|
||
else
|
||
bounds[j] = new SgExpression(DDOT, loopStmt->end()->copyPtr(), loopStmt->start()->copyPtr(), NULL);
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (i != depthOfResize - 1)
|
||
curLoop = curLoop->children[0];
|
||
}
|
||
}
|
||
|
||
static SgExpression* constructArrayRefTailWithLoopBounds(const LoopGraph* forLoop, int depthOfResize,
|
||
const vector<SgSymbol*>& indexes, SgExpression* oldTail)
|
||
{
|
||
vector<SgExpression*> dims(indexes.size());
|
||
fillLoopBoundExprs(forLoop, depthOfResize, indexes, dims);
|
||
|
||
for (int i = 0; i < indexes.size(); i++)
|
||
{
|
||
if (dims[i] == NULL)
|
||
{
|
||
dims[i] = oldTail->lhs();
|
||
oldTail = oldTail->rhs();
|
||
}
|
||
}
|
||
|
||
SgExpression* newTail = NULL;
|
||
for (int i = indexes.size() - 1; i >= 0; i--)
|
||
newTail = new SgExpression(EXPR_LIST, dims[i], newTail);
|
||
|
||
return newTail;
|
||
}
|
||
|
||
static void extendArrayDeclaration(const LoopGraph* forLoop, bool canBeStatic, const vector<SgSymbol*>& indexes,
|
||
SgExpression*& exprToExtend, SgSymbol* newArraySym)
|
||
{
|
||
exprToExtend->setSymbol(newArraySym);
|
||
|
||
int depthOfResize = 0;
|
||
for (int i = 0; i < indexes.size(); i++)
|
||
if (indexes[i] != NULL)
|
||
depthOfResize++;
|
||
|
||
SgExpression* newTail = NULL;
|
||
if (canBeStatic)
|
||
{
|
||
SgExpression* oldTail = exprToExtend->lhs();
|
||
newTail = constructArrayRefTailWithLoopBounds(forLoop, depthOfResize, indexes, oldTail);
|
||
}
|
||
else
|
||
{
|
||
for (int i = 0; i < indexes.size(); i++)
|
||
{
|
||
SgExpression* ddotExpr = new SgExpression(DDOT);
|
||
newTail = new SgExpression(EXPR_LIST, ddotExpr, newTail);
|
||
}
|
||
}
|
||
|
||
exprToExtend = new SgArrayRefExp(*newArraySym);
|
||
exprToExtend->setLhs(newTail);
|
||
}
|
||
|
||
static void reduceArray(const vector<int> &indexes, SgExpression *expressionToReduce, SgSymbol *newSymbol)
|
||
{
|
||
expressionToReduce->setSymbol(newSymbol);
|
||
|
||
vector<SgExpression*> tailVec(0);
|
||
SgExpression *tail = expressionToReduce->lhs();
|
||
for (int i = 0; i < indexes.size(); ++i)
|
||
{
|
||
if (indexes[i] == 0)
|
||
tailVec.push_back(tail->lhs());
|
||
|
||
tail = tail->rhs();
|
||
}
|
||
|
||
std::reverse(tailVec.begin(), tailVec.end());
|
||
SgExpression *list = makeExprList(tailVec, false);
|
||
|
||
expressionToReduce->setLhs(list);
|
||
}
|
||
|
||
static SgExpression* constructExtendedArrayRefTail(SgExpression* oldTail, const vector<SgSymbol*>& indexes)
|
||
{
|
||
vector<SgExpression*> dims(indexes.size());
|
||
for (int i = 0; i < indexes.size(); i++)
|
||
{
|
||
if (indexes[i] == NULL)
|
||
{
|
||
dims[i] = oldTail->lhs();
|
||
oldTail = oldTail->rhs();
|
||
}
|
||
else
|
||
dims[i] = new SgVarRefExp(indexes[i]);
|
||
}
|
||
|
||
SgExpression* newTail = NULL;
|
||
for (int i = indexes.size() - 1; i >= 0; i--)
|
||
newTail = new SgExpression(EXPR_LIST, dims[i], newTail);
|
||
|
||
return newTail;
|
||
}
|
||
|
||
static void extendArrayRef(const vector<SgSymbol*>& indexes, SgExpression*& expressionToExtend,
|
||
SgSymbol* newSymbol, const vector<SgExpression*>& lowBounds)
|
||
{
|
||
SgExpression* newTail = constructExtendedArrayRefTail(expressionToExtend->lhs(), indexes);
|
||
SgExpression* oldTail = expressionToExtend->lhs();
|
||
if (oldTail == NULL)
|
||
{
|
||
if (expressionToExtend->variant() == VAR_REF) // create array from scalar
|
||
{
|
||
expressionToExtend = new SgArrayRefExp(*newSymbol);
|
||
expressionToExtend->setLhs(newTail);
|
||
}
|
||
else if (isArrayRef(expressionToExtend)) // create array from full array ref
|
||
{
|
||
SgArrayRefExp* curr = (SgArrayRefExp*)expressionToExtend;
|
||
expressionToExtend->setSymbol(newSymbol);
|
||
for (auto& elem : lowBounds) // add low bounds
|
||
curr->addSubscript(*elem);
|
||
curr->addSubscript(*newTail);
|
||
}
|
||
else
|
||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||
}
|
||
else
|
||
{
|
||
expressionToExtend->setLhs(newTail);
|
||
expressionToExtend->setSymbol(newSymbol);
|
||
}
|
||
}
|
||
|
||
static bool isAllocatable(SgSymbol* symbol)
|
||
{
|
||
return (symbol->attributes() & ALLOCATABLE_BIT) != 0;
|
||
}
|
||
|
||
static bool isAllocatable(SgStatement *decl)
|
||
{
|
||
SgExpression *params = decl->expr(2);
|
||
while (params != NULL)
|
||
{
|
||
if (params->lhs()->variant() == ALLOCATABLE_OP)
|
||
return true;
|
||
params = params->rhs();
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
static void setAllocatable(SgStatement *newDecl, SgSymbol *origSymbol)
|
||
{
|
||
if (isAllocatable(origSymbol))
|
||
return;
|
||
|
||
SgExpression *params = newDecl->expr(2);
|
||
SgExpression newParams (EXPR_LIST, new SgExpression(ALLOCATABLE_OP), params, (SgSymbol*)NULL);
|
||
newDecl->setExpression(2, newParams);
|
||
|
||
//объявление с DIMENSION или с ALLOCATABLBE
|
||
if (newDecl->variant() != VAR_DECL)
|
||
{
|
||
newDecl->setVariant(VAR_DECL);
|
||
if (origSymbol->type()->hasBaseType())
|
||
newDecl->setExpression(1, *(new SgTypeExp(*origSymbol->type()->baseType())));
|
||
else
|
||
newDecl->setExpression(1, *(new SgTypeExp(*origSymbol->type())));
|
||
}
|
||
}
|
||
|
||
static SgExpression* checkArrayDecl(SgExpression* array, SgSymbol* arraySymbol, SgStatement* checkedDecl)
|
||
{
|
||
if (array->lhs() == NULL)
|
||
{
|
||
vector<SgStatement*> allDecls;
|
||
auto mainDecl = declaratedInStmt(arraySymbol, &allDecls);
|
||
if (allDecls.size() == 0)
|
||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||
|
||
if (allDecls.size() == 1)
|
||
{
|
||
array = findSymbol(arraySymbol, mainDecl->expr(0));
|
||
checkNull(array, convertFileName(__FILE__).c_str(), __LINE__);
|
||
return array;
|
||
}
|
||
|
||
for (auto& decl : allDecls)
|
||
{
|
||
if (decl == mainDecl)
|
||
continue;
|
||
if (decl == checkedDecl)
|
||
continue;
|
||
|
||
array = findSymbol(arraySymbol, decl->expr(0));
|
||
if (array->lhs())
|
||
break;
|
||
array = NULL;
|
||
}
|
||
|
||
checkNull(array, convertFileName(__FILE__).c_str(), __LINE__);
|
||
}
|
||
|
||
return array;
|
||
}
|
||
|
||
static SgSymbol* alterExtendArrayDeclaration(const LoopGraph* forLoop, SgStatement* declarationStmt, SgSymbol* arraySymbol,
|
||
bool canBeStatic, const vector<SgSymbol*>& indexes)
|
||
{
|
||
SgSymbol* newArraySymbol = NULL;
|
||
SgExpression* array = findSymbol(arraySymbol, declarationStmt->expr(0));
|
||
array = checkArrayDecl(array, arraySymbol, declarationStmt);
|
||
|
||
SgExpression* newArray = array->copyPtr();
|
||
newArraySymbol = createNewArrayNameSymbol(newArray, true, canBeStatic);
|
||
if (newArraySymbol == NULL)
|
||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||
|
||
extendArrayDeclaration(forLoop, canBeStatic, indexes, newArray, newArraySymbol);
|
||
|
||
SgExpression newExprList(EXPR_LIST, newArray, (SgExpression*)NULL, (SgSymbol*)NULL);
|
||
declarationStmt->setExpression(0, newExprList);
|
||
|
||
if (!canBeStatic)
|
||
setAllocatable(declarationStmt, arraySymbol);
|
||
|
||
return newArraySymbol;
|
||
}
|
||
|
||
static SgSymbol* alterShrinkArrayDeclaration(SgStatement *declarationStatement, SgSymbol *arraySymbol,
|
||
vector<int> &dimensions, bool canBeStatic)
|
||
{
|
||
SgSymbol *newArraySymbol = NULL;
|
||
SgExpression *array = findSymbol(arraySymbol, declarationStatement->expr(0));
|
||
|
||
SgExpression *newArray = array->copyPtr();
|
||
newArraySymbol = createNewArrayNameSymbol(newArray, false, canBeStatic);
|
||
|
||
reduceArray(dimensions, newArray, newArraySymbol);
|
||
|
||
SgExpression newExprList(EXPR_LIST, newArray, (SgExpression*)NULL, (SgSymbol*)NULL);
|
||
declarationStatement->setExpression(0, newExprList);
|
||
|
||
if (newArraySymbol == NULL)
|
||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||
|
||
return newArraySymbol;
|
||
}
|
||
|
||
static void extendArrayRefsInExpr(const vector<SgSymbol*>& indexes, SgExpression*& expr,
|
||
SgSymbol* arraySymbol, SgSymbol* newArraySymbol,
|
||
const vector<SgExpression*>& lowBounds, int line)
|
||
{
|
||
if (expr)
|
||
{
|
||
if (expr->variant() == FUNC_CALL)
|
||
{
|
||
SgFunctionCallExp* call = isSgFunctionCallExp(expr);
|
||
for (int arg = 0; arg < call->numberOfArgs(); ++arg)
|
||
{
|
||
auto argRef = call->arg(arg);
|
||
if ((isArrayRef(argRef) || argRef->variant() == VAR_REF) && isEqSymbols(argRef->symbol(), arraySymbol))
|
||
{
|
||
__spf_print(1, "unsupported private array extension under call on line %d\n", line);
|
||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||
}
|
||
}
|
||
}
|
||
|
||
SgExpression* left = expr->lhs();
|
||
extendArrayRefsInExpr(indexes, left, arraySymbol, newArraySymbol, lowBounds, line);
|
||
if (left != expr->lhs())
|
||
expr->setLhs(left);
|
||
|
||
SgExpression* right = expr->rhs();
|
||
extendArrayRefsInExpr(indexes, right, arraySymbol, newArraySymbol, lowBounds, line);
|
||
if (right != expr->rhs())
|
||
expr->setRhs(right);
|
||
|
||
if (isArrayRef(expr) && isEqSymbols(arraySymbol, expr->symbol()))
|
||
extendArrayRef(indexes, expr, newArraySymbol, lowBounds);
|
||
else if (expr->variant() == VAR_REF && isEqSymbols(arraySymbol, expr->symbol()))
|
||
extendArrayRef(indexes, expr, newArraySymbol, lowBounds);
|
||
}
|
||
}
|
||
|
||
static void extendArrayRefs(const vector<SgSymbol*> &indexes, SgStatement *st, SgSymbol *arraySymbol,
|
||
SgSymbol *newArraySymbol, const vector<SgExpression*> &lowBounds)
|
||
{
|
||
for (int i = 0; i < 3; ++i)
|
||
{
|
||
if (st->variant() == PROC_STAT)
|
||
{
|
||
SgCallStmt* call = isSgCallStmt(st);
|
||
for (int arg = 0; arg < call->numberOfArgs(); ++arg)
|
||
{
|
||
auto argRef = call->arg(arg);
|
||
if ((isArrayRef(argRef) || argRef->variant() == VAR_REF) && isEqSymbols(argRef->symbol(), arraySymbol))
|
||
{
|
||
__spf_print(1, "unsupported private array extension under call on line %d\n", st->lineNumber());
|
||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (st->expr(i))
|
||
{
|
||
SgExpression* ex = st->expr(i);
|
||
extendArrayRefsInExpr(indexes, ex, arraySymbol, newArraySymbol, lowBounds, st->lineNumber());
|
||
if (ex != st->expr(i))
|
||
st->setExpression(i, ex);
|
||
}
|
||
}
|
||
}
|
||
|
||
static SgStatement* createNewDeclarationStatemnet(SgStatement *loop, SgStatement *originalDeclaration, SgSymbol *arraySymbol)
|
||
{
|
||
SgStatement *lastDecl = getFuncStat(loop);
|
||
while (lastDecl)
|
||
{
|
||
if (isSgExecutableStatement(lastDecl))
|
||
break;
|
||
if (lastDecl->variant() == CONTAINS_STMT)
|
||
break;
|
||
lastDecl = lastDecl->lexNext();
|
||
}
|
||
|
||
SgExpression *exprList = originalDeclaration->expr(0);
|
||
while (!isEqSymbols(exprList->lhs()->symbol(), arraySymbol))
|
||
exprList = exprList->rhs();
|
||
|
||
checkNull(exprList, convertFileName(__FILE__).c_str(), __LINE__);
|
||
|
||
SgExpression newExprList(EXPR_LIST, exprList->lhs()->copyPtr(), NULL, NULL);
|
||
SgStatement *newDeclaration = originalDeclaration->copyPtr();
|
||
|
||
newDeclaration->setExpression(0, newExprList);
|
||
lastDecl->insertStmtBefore(*newDeclaration, *lastDecl->controlParent());
|
||
|
||
return newDeclaration;
|
||
}
|
||
|
||
static SgExpression* constructBoundCall(bool upBound, SgSymbol *array, int dim)
|
||
{
|
||
const char *boundName = NULL;
|
||
upBound ? boundName = "ubound" : boundName = "lbound";
|
||
|
||
SgSymbol boundS = SgSymbol(FUNCTION_NAME, boundName);
|
||
|
||
SgExpression *dimParam = new SgExpression(EXPR_LIST, new SgValueExp(dim), NULL, NULL);
|
||
SgExpression params(EXPR_LIST, new SgExpression(ARRAY_REF, NULL, NULL, array), dimParam, NULL);
|
||
|
||
return new SgFunctionCallExp(boundS, params);
|
||
}
|
||
|
||
static SgExpression* constructReducedAllocation(SgExpression *origArray, SgSymbol *arraySymbol, const vector<int> *indexes)
|
||
{
|
||
SgExpression *arrayRef = origArray->copyPtr();
|
||
reduceArray(*indexes, arrayRef, arraySymbol);
|
||
|
||
return new SgExpression(EXPR_LIST, arrayRef, (SgExpression*)NULL, (SgSymbol*)NULL);
|
||
}
|
||
|
||
static SgStatement* getAllocationStmt(const LoopGraph* loop, SgSymbol* symbol)
|
||
{
|
||
SgStatement* originalDeclaration = declaratedInStmt(symbol);
|
||
|
||
if (isAllocatable(symbol))
|
||
{
|
||
SgForStmt* loopStmt = (SgForStmt*)(loop->loop->GetOriginal());
|
||
|
||
SgStatement* allocationStmt = NULL;
|
||
for (auto& alloc : getAttributes<SgStatement*, SgStatement*>(originalDeclaration, set<int>{ ALLOCATE_STMT }))
|
||
{
|
||
if (alloc->variant() != ALLOCATE_STMT)
|
||
continue;
|
||
|
||
if (findSymbol(symbol, alloc->expr(0)) == NULL)
|
||
continue;
|
||
|
||
if (allocationStmt == NULL)
|
||
allocationStmt = alloc;
|
||
else
|
||
if (allocationStmt->lineNumber() < alloc->lineNumber() && alloc->lineNumber() < loopStmt->lineNumber())
|
||
allocationStmt = alloc;
|
||
}
|
||
|
||
return allocationStmt;
|
||
}
|
||
else
|
||
return NULL;
|
||
}
|
||
|
||
static void fillLowBounds(const LoopGraph* forLoop, SgSymbol* origArraySymbol, SgStatement* originalDecl, vector<SgExpression*>& lowBounds)
|
||
{
|
||
SgExpression* origArray = NULL;
|
||
|
||
if (isAllocatable(origArraySymbol))
|
||
{
|
||
SgStatement* allocationStmt = getAllocationStmt(forLoop, origArraySymbol);
|
||
origArray = findSymbol(origArraySymbol, allocationStmt->expr(0));
|
||
}
|
||
else
|
||
origArray = findSymbol(origArraySymbol, originalDecl->expr(0));
|
||
|
||
SgExpression* arrayRef = origArray->copyPtr();
|
||
SgExpression* oldTail = arrayRef->lhs();
|
||
while (oldTail != NULL)
|
||
{
|
||
if (oldTail->lhs()->variant() == DDOT)
|
||
lowBounds.push_back(oldTail->lhs()->lhs());
|
||
else
|
||
lowBounds.push_back(new SgValueExp(1));
|
||
|
||
oldTail = oldTail->rhs();
|
||
}
|
||
}
|
||
|
||
static SgExpression* constructArrayAllocationExp(const LoopGraph* forLoop, SgExpression* origArray, SgSymbol* arraySymbol,
|
||
const vector<SgSymbol*>& indexes, int depthOfResize)
|
||
{
|
||
SgExpression *arrayRef = origArray->copyPtr();
|
||
arrayRef->setSymbol(arraySymbol);
|
||
vector<SgExpression*> dimensions(depthOfResize);
|
||
|
||
SgExpression *oldTail = arrayRef->lhs();
|
||
SgSymbol *origArraySymbol = origArray->symbol();
|
||
int curDim = 0;
|
||
while (oldTail != NULL)
|
||
{
|
||
curDim++;
|
||
if (oldTail->lhs()->variant() == DDOT)
|
||
{
|
||
SgExpression *ddot = oldTail->lhs();
|
||
if (!ddot->lhs())
|
||
ddot->setLhs(constructBoundCall(false, origArraySymbol, curDim));
|
||
if (!ddot->rhs())
|
||
ddot->setRhs(constructBoundCall(true, origArraySymbol, curDim));
|
||
}
|
||
|
||
oldTail = oldTail->rhs();
|
||
}
|
||
|
||
oldTail = arrayRef->lhs();
|
||
SgExpression* newTail = constructArrayRefTailWithLoopBounds(forLoop, depthOfResize, indexes, oldTail);
|
||
|
||
if (arrayRef->variant() == VAR_REF)// create array from scalar
|
||
{
|
||
arrayRef = new SgArrayRefExp(*arrayRef->symbol());
|
||
arrayRef->setLhs(newTail);
|
||
}
|
||
else
|
||
arrayRef->setLhs(newTail);
|
||
|
||
return new SgExpression(EXPR_LIST, arrayRef, (SgExpression*)NULL, (SgSymbol*)NULL);
|
||
}
|
||
|
||
static void insertAllocDealloc(const LoopGraph* forLoop, SgSymbol* origArraySymbol, SgSymbol* arraySymbol, SgSymbol* allocDone,
|
||
bool isExpansion, const vector<SgSymbol*>* indexes = NULL, const vector<int>* shrinkIndexes = NULL)
|
||
{
|
||
SgForStmt *loopStmt = (SgForStmt*)(forLoop->loop->GetOriginal());
|
||
vector<SgExpression*> lowBounds;
|
||
|
||
SgStatement *originalDeclaration = declaratedInStmt(origArraySymbol);
|
||
SgExpression *origArray = NULL;
|
||
|
||
if (isAllocatable(origArraySymbol))
|
||
{
|
||
SgStatement *allocationStmt = getAllocationStmt(forLoop, origArraySymbol);
|
||
origArray = findSymbol(origArraySymbol, allocationStmt->expr(0));
|
||
}
|
||
else
|
||
{
|
||
origArray = findSymbol(origArraySymbol, originalDeclaration->expr(0));
|
||
origArray = checkArrayDecl(origArray, origArraySymbol, originalDeclaration);
|
||
}
|
||
|
||
int depthOfResize = 0;
|
||
if (isExpansion)
|
||
for (int i = 0; i < indexes->size(); i++)
|
||
if ((*indexes)[i] != NULL)
|
||
depthOfResize++;
|
||
|
||
SgExpression* arrayAllocation = isExpansion
|
||
? constructArrayAllocationExp(forLoop, origArray, arraySymbol, *indexes, depthOfResize)
|
||
: constructReducedAllocation(origArray, arraySymbol, shrinkIndexes);
|
||
SgExpression *arrayDeallocation = new SgExpression(EXPR_LIST,
|
||
new SgExpression(ARRAY_REF, (SgExpression*)NULL, (SgExpression*)NULL, arraySymbol),
|
||
(SgExpression*)NULL, (SgSymbol*)NULL);
|
||
|
||
|
||
|
||
SgStatement *allocate = new SgStatement(ALLOCATE_STMT, (SgLabel*)NULL, (SgSymbol*)NULL, arrayAllocation, (SgExpression*)NULL, (SgExpression*)NULL);
|
||
SgIfStmt* ifSt = new SgIfStmt(SgEqOp(*new SgVarRefExp(allocDone), *new SgValueExp(0)), *allocate);
|
||
|
||
loopStmt->insertStmtBefore(*ifSt, *loopStmt->controlParent());
|
||
|
||
|
||
// insert allocates as save
|
||
//SgStatement* deallocate = new SgStatement(DEALLOCATE_STMT, (SgLabel*)NULL, (SgSymbol*)NULL, arrayDeallocation, (SgExpression*)NULL, (SgExpression*)NULL);
|
||
//loopStmt->lastNodeOfStmt()->insertStmtAfter(*deallocate, *loopStmt->controlParent());
|
||
}
|
||
|
||
static bool containsFunctionCall(SgExpression* exp)
|
||
{
|
||
bool retVal = false;
|
||
|
||
if (exp)
|
||
{
|
||
if (exp->variant() == FUNC_CALL)
|
||
retVal = true;
|
||
|
||
if (exp->lhs())
|
||
retVal = retVal || containsFunctionCall(exp->lhs());
|
||
if (exp->rhs())
|
||
retVal = retVal || containsFunctionCall(exp->rhs());
|
||
}
|
||
return retVal;
|
||
}
|
||
|
||
static SgSymbol* createVarDeclaration(SgForStmt *loopStmt, const char *add)
|
||
{
|
||
SgSymbol *doName = loopStmt->doName();
|
||
string newNameStr = constructNewBoundName(doName->identifier(), loopStmt->lineNumber(), add);
|
||
SgSymbol *newName = new SgSymbol(VARIABLE_NAME, newNameStr.c_str(), doName->type(), NULL);
|
||
|
||
SgStatement *decl = declaratedInStmt(doName);
|
||
|
||
SgStatement *newDecl = decl->copyPtr();
|
||
newDecl->setExpression(0, new SgExpression(EXPR_LIST, new SgVarRefExp(newName), NULL, NULL));
|
||
decl->insertStmtAfter(*newDecl, *decl->controlParent());
|
||
|
||
return newName;
|
||
}
|
||
|
||
static SgStatement* createBoundVariableAssign(SgSymbol *varName, SgExpression *value)
|
||
{
|
||
SgAssignStmt *assign = new SgAssignStmt(*new SgVarRefExp(varName), *value);
|
||
return assign;
|
||
}
|
||
|
||
static void replaceFunctionBounds(SgExpression *ex, SgForStmt *loopStmt, SgForStmt *topLoopStmt, const string &kind)
|
||
{
|
||
if (containsFunctionCall(ex))
|
||
{
|
||
SgSymbol *newStart = createVarDeclaration(loopStmt, kind.c_str());
|
||
SgStatement *assignment = createBoundVariableAssign(newStart, ex);
|
||
|
||
topLoopStmt->insertStmtBefore(*assignment, *topLoopStmt->controlParent());
|
||
if (kind == "_start")
|
||
loopStmt->setStart(*assignment->expr(0));
|
||
if (kind == "_end")
|
||
loopStmt->setEnd(*assignment->expr(0));
|
||
if (kind == "_step")
|
||
loopStmt->setStep(*assignment->expr(0));
|
||
}
|
||
}
|
||
|
||
static void replaceFunctionBounds(const LoopGraph *forLoop, int depthOfResize)
|
||
{
|
||
const LoopGraph *curLoop = forLoop;
|
||
SgForStmt *topLoopStmt = (SgForStmt*) (curLoop->loop->GetOriginal());
|
||
for (int i = 0; i < depthOfResize; ++i)
|
||
{
|
||
SgForStmt *loopStmt = (SgForStmt*) (curLoop->loop->GetOriginal());
|
||
|
||
replaceFunctionBounds(loopStmt->start(), loopStmt, topLoopStmt, "_start");
|
||
replaceFunctionBounds(loopStmt->end(), loopStmt, topLoopStmt, "_end");
|
||
replaceFunctionBounds(loopStmt->step(), loopStmt, topLoopStmt, "_step");
|
||
|
||
if (i + 1 != depthOfResize)
|
||
curLoop = curLoop->children[0];
|
||
}
|
||
}
|
||
|
||
static SgSymbol* createReducedToVariableArray(SgStatement *copiedDeclaration, int lineNumber, SgSymbol *arraySymbol)
|
||
{
|
||
SgType *type = copiedDeclaration->expr(1)->type();
|
||
string newNameStr = constructNewBoundName(arraySymbol->identifier(), lineNumber, "_sh");
|
||
SgSymbol *newName = new SgSymbol(VARIABLE_NAME, newNameStr.c_str(), type, NULL);
|
||
|
||
copiedDeclaration->setExpression(0, new SgExpression(EXPR_LIST, new SgVarRefExp(newName), NULL, NULL));
|
||
return newName;
|
||
}
|
||
|
||
static void reduceArrayRefsInExpr(SgExpression *expr, SgSymbol *arraySymbol, SgSymbol *newSymbol, bool reduceToVariable, vector<int> &indexes)
|
||
{
|
||
if (expr == NULL)
|
||
return;
|
||
|
||
SgExpression *lhs = expr->lhs(), *rhs = expr->rhs();
|
||
|
||
if (lhs)
|
||
{
|
||
if (isArrayRef(lhs) && isEqSymbols(arraySymbol, lhs->symbol()))
|
||
{
|
||
if (reduceToVariable)
|
||
expr->setLhs(new SgVarRefExp(newSymbol));
|
||
else
|
||
reduceArray(indexes, lhs, newSymbol);
|
||
}
|
||
else
|
||
reduceArrayRefsInExpr(lhs, arraySymbol, newSymbol, reduceToVariable, indexes);
|
||
}
|
||
|
||
if (rhs)
|
||
{
|
||
if (isArrayRef(rhs) && isEqSymbols(arraySymbol, rhs->symbol()))
|
||
{
|
||
if (reduceToVariable)
|
||
expr->setRhs(new SgVarRefExp(newSymbol));
|
||
else
|
||
reduceArray(indexes, rhs, newSymbol);
|
||
}
|
||
else
|
||
reduceArrayRefsInExpr(rhs, arraySymbol, newSymbol, reduceToVariable, indexes);
|
||
}
|
||
}
|
||
|
||
static void reduceArrayRefs(SgStatement *st, SgSymbol *arraySymbol, SgSymbol *newSymbol, bool reduceToVariable, vector<int> &indexes)
|
||
{
|
||
for (int i = 0; i < 3; ++i)
|
||
{
|
||
if (st->expr(i))
|
||
{
|
||
SgExpression* expr = st->expr(i);
|
||
if (isArrayRef(expr) && isEqSymbols(arraySymbol, expr->symbol()))
|
||
{
|
||
if (reduceToVariable)
|
||
st->setExpression(i, new SgVarRefExp(newSymbol));
|
||
else
|
||
reduceArray(indexes, expr, newSymbol);
|
||
}
|
||
else
|
||
reduceArrayRefsInExpr(expr, arraySymbol, newSymbol, reduceToVariable, indexes);
|
||
}
|
||
}
|
||
}
|
||
|
||
static void fillIndexesToShrink(SgSymbol* arr, SgExprListExp* listExp, vector<int>& indexes)
|
||
{
|
||
SgExpression* sym = findSymbol(arr, listExp);
|
||
if (sym)
|
||
{
|
||
SgExpression* expr = sym->lhs();
|
||
while (expr)
|
||
{
|
||
indexes.push_back(expr->lhs()->valueInteger());
|
||
expr = expr->rhs();
|
||
}
|
||
|
||
bool needShrink = false;
|
||
for (int z = 0; z < indexes.size(); ++z)
|
||
if (indexes[z] == 1)
|
||
needShrink = true;
|
||
|
||
if (!needShrink)
|
||
indexes.clear();
|
||
}
|
||
}
|
||
|
||
static void renamePrivateVarsInAttributes(const vector<SgStatement*>& attrs, const map<SgSymbol*, SgSymbol*>& symbols)
|
||
{
|
||
for (SgStatement* st : attrs)
|
||
{
|
||
if (st->variant() != SPF_ANALYSIS_DIR)
|
||
return;
|
||
|
||
SgExpression* exprList = st->expr(0);
|
||
while (exprList)
|
||
{
|
||
if (exprList->lhs()->variant() == ACC_PRIVATE_OP)
|
||
{
|
||
SgExpression* list = exprList->lhs()->lhs();
|
||
while (list)
|
||
{
|
||
for (auto& pair : symbols)
|
||
if (isEqSymbols(pair.first, list->lhs()->symbol()))
|
||
list->setLhs(new SgExpression(ARRAY_REF, NULL, NULL, pair.second));
|
||
|
||
list = list->rhs();
|
||
}
|
||
}
|
||
exprList = exprList->rhs();
|
||
}
|
||
}
|
||
}
|
||
|
||
static void removePrivateVarsInAttributes(const vector<SgStatement*>& attrs, const map<SgSymbol*, SgSymbol*>& symbols)
|
||
{
|
||
for (SgStatement* st : attrs)
|
||
{
|
||
if (st->variant() != SPF_ANALYSIS_DIR)
|
||
return;
|
||
|
||
SgExpression* exprList = st->expr(0);
|
||
vector<SgExpression*> newL;
|
||
bool remList = false;
|
||
while (exprList)
|
||
{
|
||
if (exprList->lhs()->variant() == ACC_PRIVATE_OP)
|
||
{
|
||
vector<SgExpression*> newL;
|
||
bool removed = false;
|
||
SgExpression* list = exprList->lhs()->lhs();
|
||
while (list)
|
||
{
|
||
bool found = false;
|
||
for (auto& pair : symbols)
|
||
{
|
||
if (isEqSymbols(pair.first, list->lhs()->symbol()))
|
||
found = true;
|
||
if (found)
|
||
break;
|
||
}
|
||
if (!found)
|
||
newL.push_back(list->lhs());
|
||
else
|
||
removed = true;
|
||
list = list->rhs();
|
||
}
|
||
|
||
if (removed)
|
||
{
|
||
if (newL.size() == 0)
|
||
remList = true;
|
||
else
|
||
{
|
||
exprList->lhs()->setLhs(makeExprList(newL));
|
||
newL.push_back(exprList->lhs());
|
||
}
|
||
}
|
||
}
|
||
else
|
||
newL.push_back(exprList->lhs());
|
||
exprList = exprList->rhs();
|
||
}
|
||
|
||
if (remList)
|
||
st->setExpression(0, makeExprList(newL));
|
||
}
|
||
}
|
||
|
||
static int getArrayDimensionality(SgSymbol* array)
|
||
{
|
||
if (array->type()->variant() != T_ARRAY)
|
||
return 0;
|
||
|
||
SgStatement* decl = declaratedInStmt(array);
|
||
DIST::Array* currArray = getArrayFromDeclarated(decl, array->identifier());
|
||
|
||
checkNull(currArray, convertFileName(__FILE__).c_str(), __LINE__);
|
||
|
||
return currArray->GetDimSize();
|
||
}
|
||
|
||
static bool isWellDistributedArray(const LoopGraph* loop, const DIST::Array* array, int depthOfResize, bool fromWrite)
|
||
{
|
||
const LoopGraph* curLoop = loop;
|
||
bool found = true;
|
||
const vector<ArrayOp>* arrayOps = NULL;
|
||
for (int i = 0; i < depthOfResize; i++)
|
||
{
|
||
if (fromWrite)
|
||
{
|
||
for (auto& writeOp : curLoop->writeOps)
|
||
{
|
||
if (isEqSymbols(writeOp.first->GetDeclSymbol(), array->GetDeclSymbol()))
|
||
{
|
||
arrayOps = &writeOp.second;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (auto& readOp : curLoop->readOps)
|
||
{
|
||
if (isEqSymbols(readOp.first->GetDeclSymbol(), array->GetDeclSymbol()))
|
||
{
|
||
arrayOps = &readOp.second.first;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (arrayOps == NULL)
|
||
return false;
|
||
|
||
int counter = 0;
|
||
for (int j = 0; j < arrayOps->size(); j++)
|
||
{
|
||
if (!(*arrayOps)[j].coefficients.empty())
|
||
counter++;
|
||
|
||
for (const auto& elem : (*arrayOps)[j].coefficients)
|
||
{
|
||
if (elem.first.first != 1 || elem.first.second != 0)
|
||
{
|
||
found = false;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (counter != 1)
|
||
found = false;
|
||
|
||
if (!found)
|
||
break;
|
||
|
||
if (i != depthOfResize - 1)
|
||
curLoop = curLoop->children[0];
|
||
}
|
||
|
||
if (found)
|
||
return true;
|
||
|
||
return false;
|
||
}
|
||
|
||
static SgSymbol* findDistributedArrayWrite(const LoopGraph* loop, int origDim, int depthOfResize)
|
||
{
|
||
for (auto& writeOp : loop->writeOps)
|
||
{
|
||
if (writeOp.second.size() != (size_t)origDim + depthOfResize)
|
||
continue;
|
||
|
||
if (isWellDistributedArray(loop, writeOp.first, depthOfResize, true))
|
||
return writeOp.first->GetDeclSymbol();
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
static SgSymbol* findDistributedArrayRead(const LoopGraph* loop, int origDim, int depthOfResize)
|
||
{
|
||
for (auto& readOp : loop->readOps)
|
||
{
|
||
if (readOp.second.first.size() != (size_t)origDim + depthOfResize)
|
||
continue;
|
||
|
||
if (isWellDistributedArray(loop, readOp.first, depthOfResize, false))
|
||
return readOp.first->GetDeclSymbol();
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
static void mapIndexes(const LoopGraph* loop, int depthOfResize, SgSymbol* distributedArray, vector<SgSymbol*>& indexes, bool fromWrite)
|
||
{
|
||
int dim = getArrayDimensionality(distributedArray);
|
||
|
||
vector<bool> mapped(dim);
|
||
for (int i = 0; i < dim; i++)
|
||
mapped[i] = false;
|
||
|
||
const LoopGraph* curLoop = loop;
|
||
int deep = depthOfResize;
|
||
|
||
for (int i = 0; i < deep - 1; i++)
|
||
curLoop = curLoop->children[0];
|
||
|
||
const vector<ArrayOp>* arrayOps = NULL;
|
||
for (int i = 0; i < deep; i++)
|
||
{
|
||
if (fromWrite)
|
||
{
|
||
for (auto& writeOp : curLoop->writeOps)
|
||
{
|
||
if (isEqSymbols(writeOp.first->GetDeclSymbol(), distributedArray))
|
||
{
|
||
arrayOps = &writeOp.second;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (auto& readOp : curLoop->readOps)
|
||
{
|
||
if (isEqSymbols(readOp.first->GetDeclSymbol(), distributedArray))
|
||
{
|
||
arrayOps = &readOp.second.first;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (arrayOps == NULL)
|
||
{
|
||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||
return;
|
||
}
|
||
|
||
for (int j = 0; j < dim; j++)
|
||
{
|
||
if (!(*arrayOps)[j].coefficients.empty())
|
||
{
|
||
if (i == 0 && deep == depthOfResize + 1)
|
||
mapped[j] = true;
|
||
else
|
||
{
|
||
if (!mapped[j])
|
||
{
|
||
indexes[j] = ((SgForStmt*)curLoop->loop->GetOriginal())->doName();
|
||
mapped[j] = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (i != deep - 1)
|
||
curLoop = curLoop->parent;
|
||
}
|
||
}
|
||
|
||
static int fillIndexesToExtend(const LoopGraph* loop, int origDim, int depthOfResize, vector<SgSymbol*>& indexes)
|
||
{
|
||
SgSymbol* distributedArray = NULL;
|
||
distributedArray = findDistributedArrayWrite(loop, origDim, depthOfResize);
|
||
bool fromWrite = true;
|
||
|
||
if (distributedArray == NULL)
|
||
{
|
||
distributedArray = findDistributedArrayRead(loop, origDim, depthOfResize);
|
||
fromWrite = false;
|
||
}
|
||
|
||
if (distributedArray == NULL)
|
||
return -1;
|
||
|
||
mapIndexes(loop, depthOfResize, distributedArray, indexes, fromWrite);
|
||
|
||
return 0;
|
||
}
|
||
|
||
static SgSymbol* shrinkArray(const LoopGraph *forLoop, SgSymbol *arraySymbol, vector<int> &indexes, SgSymbol *allocDone)
|
||
{
|
||
int maxDepth = forLoop->perfectLoop;
|
||
const LoopGraph *curLoop = forLoop;
|
||
|
||
bool reduceToVariable = true;
|
||
for (int i = 0; i < indexes.size(); ++i)
|
||
{
|
||
if (indexes[i] == 0)
|
||
{
|
||
reduceToVariable = false;
|
||
break;
|
||
}
|
||
}
|
||
|
||
for (int i = 0; i < maxDepth; ++i)
|
||
{
|
||
if (curLoop->children.size() == 1)
|
||
curLoop = curLoop->children[0];
|
||
else if (i != maxDepth - 1)
|
||
{
|
||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
replaceFunctionBounds(forLoop, maxDepth);
|
||
SgStatement *originalDeclaration = declaratedInStmt(arraySymbol);
|
||
SgStatement *copiedDeclaration = createNewDeclarationStatemnet(forLoop->loop->GetOriginal(), originalDeclaration, arraySymbol);
|
||
|
||
bool canBeStatic = !(!reduceToVariable && isAllocatable(arraySymbol));
|
||
SgSymbol *newSymbol = reduceToVariable
|
||
? createReducedToVariableArray(copiedDeclaration, forLoop->lineNum, arraySymbol)
|
||
: alterShrinkArrayDeclaration(copiedDeclaration, arraySymbol, indexes, canBeStatic);
|
||
|
||
if (newSymbol)
|
||
{
|
||
SgForStmt *loopStmt = (SgForStmt*)(forLoop->loop->GetOriginal());
|
||
|
||
if (!reduceToVariable && isAllocatable(arraySymbol))
|
||
insertAllocDealloc(forLoop, arraySymbol, newSymbol, allocDone, false, NULL, &indexes);
|
||
|
||
for (SgStatement *st = loopStmt->lexNext(); st != loopStmt->lastNodeOfStmt()->lexNext(); st = st->lexNext())
|
||
if (st->variant() != ALLOCATE_STMT && st->variant() != DEALLOCATE_STMT)
|
||
reduceArrayRefs(st, arraySymbol, newSymbol, reduceToVariable, indexes);
|
||
|
||
return newSymbol;
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
static SgSymbol* resizeArray(const LoopGraph *forLoop, SgSymbol *arraySymbol, int depthOfResize, SgSymbol *allocDone)
|
||
{
|
||
if (depthOfResize < 0 || depthOfResize > forLoop->perfectLoop)
|
||
depthOfResize = forLoop->perfectLoop;
|
||
|
||
int arrayDim = getArrayDimensionality(arraySymbol);
|
||
vector<SgSymbol*> indexes((size_t)depthOfResize + arrayDim);
|
||
|
||
int areIndexesFilled = fillIndexesToExtend(forLoop, arrayDim, depthOfResize, indexes);
|
||
|
||
const LoopGraph* curLoop = forLoop;
|
||
bool canBeStatic = true;
|
||
if (isAllocatable(arraySymbol))
|
||
canBeStatic = false;
|
||
|
||
for (int i = 0; i < depthOfResize; ++i)
|
||
{
|
||
//TODO: add checking for PARAMETER
|
||
//if (curLoop->calculatedCountOfIters == 0)
|
||
canBeStatic = false;
|
||
|
||
if (areIndexesFilled != 0)
|
||
{
|
||
SgForStmt* loopStmt = (SgForStmt*)curLoop->loop->GetOriginal();
|
||
indexes[(size_t)depthOfResize + arrayDim - 1 - i] = loopStmt->doName();
|
||
}
|
||
|
||
if (curLoop->children.size() == 1)
|
||
curLoop = curLoop->children[0];
|
||
else if (i != depthOfResize - 1)
|
||
{
|
||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
replaceFunctionBounds(forLoop, depthOfResize);
|
||
|
||
SgStatement* originalDeclaration = declaratedInStmt(arraySymbol);
|
||
SgStatement *copiedOriginalDecl = createNewDeclarationStatemnet(forLoop->loop->GetOriginal(), originalDeclaration, arraySymbol);
|
||
SgSymbol *newArraySymbol = alterExtendArrayDeclaration(forLoop, copiedOriginalDecl, arraySymbol, canBeStatic, indexes);
|
||
|
||
vector<SgExpression*> lowBounds(depthOfResize);
|
||
fillLowBounds(forLoop, arraySymbol, originalDeclaration, lowBounds);
|
||
|
||
if (newArraySymbol)
|
||
{
|
||
SgForStmt *loopStmt = (SgForStmt*)(forLoop->loop->GetOriginal());
|
||
if (!canBeStatic || isAllocatable(newArraySymbol))
|
||
insertAllocDealloc(forLoop, arraySymbol, newArraySymbol, allocDone, true, &indexes, NULL);
|
||
|
||
for (SgStatement *st = loopStmt->lexNext(); st != loopStmt->lastNodeOfStmt()->lexNext(); st = st->lexNext())
|
||
if (st->variant() != ALLOCATE_STMT && st->variant() != DEALLOCATE_STMT)
|
||
extendArrayRefs(indexes, st, arraySymbol, newArraySymbol, lowBounds);
|
||
|
||
return newArraySymbol;
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
//for testing
|
||
static SgSymbol* findSymbol(LoopGraph *forLoop, const char *arrayName)
|
||
{
|
||
SgForStmt *loopStmt = (SgForStmt*)forLoop->loop->GetOriginal();
|
||
if (loopStmt)
|
||
{
|
||
for (SgStatement *st = loopStmt->lexNext(); st != loopStmt->lastNodeOfStmt()->lexNext(); st = st->lexNext())
|
||
{
|
||
queue<SgExpression*> toCheck = queue<SgExpression*>();
|
||
|
||
for (int i = 0; i < 3; ++i)
|
||
if (st->expr(i))
|
||
toCheck.push(st->expr(i));
|
||
|
||
while (!toCheck.empty())
|
||
{
|
||
SgExpression *curExp = toCheck.front();
|
||
toCheck.pop();
|
||
|
||
if ((isArrayRef(curExp) || curExp->variant() == VAR_REF) && !strcmp(arrayName, curExp->symbol()->identifier()))
|
||
return curExp->symbol();
|
||
else
|
||
{
|
||
if (curExp->lhs())
|
||
toCheck.push(curExp->lhs());
|
||
if (curExp->rhs())
|
||
toCheck.push(curExp->rhs());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
static set<SgSymbol*> fillPrivates(const map<pair<string, int>, set<SgStatement*>>& usersDirectives,
|
||
LoopGraph *loop)
|
||
{
|
||
set<SgStatement*> attrsPriv;
|
||
auto itPriv = usersDirectives.find(make_pair(loop->loop->fileName(), loop->loop->lineNumber()));
|
||
if (itPriv != usersDirectives.end())
|
||
attrsPriv = itPriv->second;
|
||
|
||
set<Symbol*> privates;
|
||
for (auto& spf : attrsPriv)
|
||
if (spf->variant() == SPF_ANALYSIS_DIR)
|
||
fillPrivatesFromComment(new Statement(spf), privates);
|
||
|
||
set<SgSymbol*> arrayPrivates;
|
||
set<string> iterationVars;
|
||
fillIterationVariables(loop, iterationVars);
|
||
for (Symbol* sym : privates)
|
||
if (sym->variant() == VARIABLE_NAME)
|
||
if (iterationVars.find(sym->identifier()) == iterationVars.end())
|
||
arrayPrivates.insert(sym->GetOriginal());
|
||
|
||
return arrayPrivates;
|
||
}
|
||
|
||
static map<LoopGraph*, set<string>> doNotShrink;
|
||
|
||
static void analyzeExpr(SgExpression* ex, const string& arr, const vector<int>& indexes, vector<string>& exprs, int& err)
|
||
{
|
||
if (ex && err == 0)
|
||
{
|
||
if (ex->variant() == ARRAY_REF && ex->symbol()->identifier() == arr)
|
||
{
|
||
SgArrayRefExp* ref = isSgArrayRefExp(ex);
|
||
if (ex == NULL)
|
||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||
|
||
if (ref->numberOfSubscripts() == 0)
|
||
err = 1;
|
||
else
|
||
{
|
||
if (ref->numberOfSubscripts() != exprs.size())
|
||
err = 2;
|
||
else
|
||
{
|
||
for (int z = 0; z < indexes.size(); z++)
|
||
{
|
||
if (indexes[z] == 1)
|
||
{
|
||
string cur = ref->subscript(z)->unparse();
|
||
if (exprs[z] == "")
|
||
exprs[z] = cur;
|
||
else if (exprs[z] != cur)
|
||
{
|
||
err = 3;
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
analyzeExpr(ex->lhs(), arr, indexes, exprs, err);
|
||
analyzeExpr(ex->rhs(), arr, indexes, exprs, err);
|
||
}
|
||
}
|
||
}
|
||
|
||
static bool isNeedSkip(SgStatement* start, const string& arr, const vector<int>& indexes)
|
||
{
|
||
vector<string> exprs(indexes.size());
|
||
for (int z = 0; z < indexes.size(); ++z)
|
||
exprs[z] = "";
|
||
|
||
for (auto st = start; st != start->lastNodeOfStmt(); st = st->lexNext())
|
||
{
|
||
int err = 0;
|
||
for (int z = 0; z < 3; ++z)
|
||
{
|
||
analyzeExpr(st->expr(z), arr, indexes, exprs, err);
|
||
if (err != 0)
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
//TODO: need to add messages
|
||
void analyzeShrinking(SgFile* file, const vector<LoopGraph*>& loopGraphs, vector<Messages>& messages,
|
||
const map<pair<string, int>, set<SgStatement*>>& usersDirectives)
|
||
{
|
||
map<int, LoopGraph*> mapLoopGraph;
|
||
createMapLoopGraph(loopGraphs, mapLoopGraph);
|
||
|
||
for (auto& loopPair : mapLoopGraph)
|
||
{
|
||
LoopGraph* loop = loopPair.second;
|
||
auto loopSt = loop->loop->GetOriginal();
|
||
auto attrsTr = getAttributes<SgStatement*, SgStatement*>(loopSt, set<int>{ SPF_TRANSFORM_DIR });
|
||
auto attrPrivInCode = getAttributes<SgStatement*, SgStatement*>(loopSt, set<int>{ SPF_ANALYSIS_DIR });
|
||
|
||
auto arrayPrivates = fillPrivates(usersDirectives, loop);
|
||
|
||
if (arrayPrivates.size() != 0)
|
||
{
|
||
for (auto attr : attrsTr)
|
||
{
|
||
SgExpression* list = attr->expr(0);
|
||
|
||
while (list)
|
||
{
|
||
if (list->lhs()->variant() == SPF_SHRINK_OP)
|
||
{
|
||
SgExprListExp* listExp = isSgExprListExp(list->lhs()->lhs());
|
||
checkNull(listExp, convertFileName(__FILE__).c_str(), __LINE__);
|
||
|
||
for (SgSymbol* privArr : arrayPrivates)
|
||
{
|
||
vector<int> indexes;
|
||
fillIndexesToShrink(privArr, listExp, indexes);
|
||
|
||
if (!indexes.empty())
|
||
{
|
||
string array = privArr->identifier();
|
||
if (isNeedSkip(loop->loop, array, indexes))
|
||
doNotShrink[loop].insert(array);
|
||
}
|
||
}
|
||
}
|
||
list = list->rhs();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
static void createAllocDoneSymbol(map<SgStatement*, SgSymbol*>& allocDoneByFunc, SgStatement* func)
|
||
{
|
||
if (allocDoneByFunc.find(func) == allocDoneByFunc.end())
|
||
{
|
||
auto newName = (string("spf_") + string(func->symbol()->identifier()) + "_alloc_");
|
||
allocDoneByFunc[func] = new SgSymbol(VARIABLE_NAME, newName.c_str(), SgTypeInt(), func);
|
||
}
|
||
}
|
||
|
||
//Вычислять размер массива с учётом шага цикла - //TODO
|
||
void privateArraysResizing(SgFile *file, const vector<LoopGraph*> &loopGraphs, vector<Messages> &messages, int& countOfTransform,
|
||
const map<pair<string, int>, set<SgStatement*>>& usersDirectives, bool isExpand)
|
||
{
|
||
map<int, LoopGraph*> mapLoopGraph;
|
||
createMapLoopGraph(loopGraphs, mapLoopGraph);
|
||
|
||
map<SgStatement*, SgSymbol*> allocDoneByFunc;
|
||
map<SgStatement*, SgSymbol*> usedAllocDoneByFunc;
|
||
|
||
map<SgStatement*, vector<SgExpression*>> saveDecls;
|
||
|
||
for (auto &loopPair : mapLoopGraph)
|
||
{
|
||
LoopGraph *loop = loopPair.second;
|
||
|
||
auto itSh = doNotShrink.find(loop);
|
||
|
||
auto loopSt = loop->loop->GetOriginal();
|
||
auto attrsTr = getAttributes<SgStatement*, SgStatement*>(loopSt, set<int>{ SPF_TRANSFORM_DIR });
|
||
auto attrPrivInCode = getAttributes<SgStatement*, SgStatement*>(loopSt, set<int>{ SPF_ANALYSIS_DIR });
|
||
|
||
auto arrayPrivates = fillPrivates(usersDirectives, loop);
|
||
auto func = getFuncStat(loopSt);
|
||
|
||
set<SgSymbol*> symbolsToDecl;
|
||
|
||
if (arrayPrivates.size() == 0)
|
||
{
|
||
string str;
|
||
if (isExpand)
|
||
__spf_printToBuf(str, "Can not do PRIVATE EXPANSION for this loop - privates not found");
|
||
else
|
||
__spf_printToBuf(str, "Can not do PRIVATE SHRINK for this loop - privates not found");
|
||
|
||
__spf_print(0, "%s on line %d\n", str.c_str(), loop->lineNum);
|
||
}
|
||
else
|
||
{
|
||
for (auto attr : attrsTr)
|
||
{
|
||
SgExpression *list = attr->expr(0);
|
||
vector<SgExpression*> newL;
|
||
map<SgSymbol*, SgSymbol*> symbols;
|
||
|
||
while (list)
|
||
{
|
||
symbols.clear();
|
||
|
||
if (list->lhs()->variant() == SPF_EXPAND_OP && isExpand)
|
||
{
|
||
createAllocDoneSymbol(allocDoneByFunc, func);
|
||
|
||
int deep = -1;
|
||
if (list->lhs()->lhs() != NULL)
|
||
{
|
||
SgExprListExp* listExp = isSgExprListExp(list->lhs()->lhs());
|
||
checkNull(listExp, convertFileName(__FILE__).c_str(), __LINE__);
|
||
deep = listExp->length();
|
||
}
|
||
|
||
for (SgSymbol* privArr : arrayPrivates)
|
||
{
|
||
SgSymbol* newSymbol = resizeArray(loop, privArr, deep, allocDoneByFunc[func]);
|
||
|
||
if (newSymbol)
|
||
{
|
||
symbols.insert(std::make_pair(privArr, newSymbol));
|
||
usedAllocDoneByFunc[func] = allocDoneByFunc[func];
|
||
countOfTransform++;
|
||
|
||
if (isAllocatable(newSymbol))
|
||
symbolsToDecl.insert(newSymbol);
|
||
}
|
||
}
|
||
removePrivateVarsInAttributes(attrPrivInCode, symbols);
|
||
}
|
||
else if (list->lhs()->variant() == SPF_SHRINK_OP && !isExpand)
|
||
{
|
||
createAllocDoneSymbol(allocDoneByFunc, func);
|
||
|
||
SgExprListExp* listExp = isSgExprListExp(list->lhs()->lhs());
|
||
checkNull(listExp, convertFileName(__FILE__).c_str(), __LINE__);
|
||
|
||
for (SgSymbol* privArr : arrayPrivates)
|
||
{
|
||
vector<int> indexes;
|
||
fillIndexesToShrink(privArr, listExp, indexes);
|
||
|
||
bool skip = false;
|
||
if (itSh != doNotShrink.end())
|
||
if (itSh->second.find(privArr->identifier()) != itSh->second.end())
|
||
skip = true;
|
||
|
||
if (!indexes.empty() && !skip)
|
||
{
|
||
SgSymbol* newSymbol = shrinkArray(loop, privArr, indexes, allocDoneByFunc[func]);
|
||
|
||
if (newSymbol)
|
||
{
|
||
symbols.insert(std::make_pair(privArr, newSymbol));
|
||
usedAllocDoneByFunc[func] = allocDoneByFunc[func];
|
||
countOfTransform++;
|
||
|
||
if (isAllocatable(newSymbol))
|
||
symbolsToDecl.insert(newSymbol);
|
||
}
|
||
}
|
||
}
|
||
renamePrivateVarsInAttributes(attrPrivInCode, symbols);
|
||
}
|
||
else
|
||
newL.push_back(list);
|
||
|
||
list = list->rhs();
|
||
}
|
||
|
||
attr->setExpression(0, makeExprList(newL, false));
|
||
//__spf_print(1, "set new %d attributes to line %d\n", newL.size(), loop->lineNum);
|
||
}
|
||
}
|
||
|
||
for (auto& elem : symbolsToDecl)
|
||
saveDecls[func].push_back(new SgVarRefExp(elem));
|
||
}
|
||
|
||
for (auto& funcPair : saveDecls)
|
||
{
|
||
auto func = funcPair.first;
|
||
if (usedAllocDoneByFunc.find(func) == usedAllocDoneByFunc.end())
|
||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||
|
||
SgSymbol* allocVar = usedAllocDoneByFunc[func];
|
||
auto list = makeExprList(funcPair.second);
|
||
SgStatement* save = new SgStatement(SAVE_DECL, NULL, NULL, list);
|
||
|
||
SgStatement* st = func->lexNext();
|
||
while (!isSgExecutableStatement(st))
|
||
{
|
||
if (st->variant() == CONTAINS_STMT)
|
||
break;
|
||
st = st->lexNext();
|
||
}
|
||
|
||
vector<SgExpression*> init = { new SgValueExp(-1) };
|
||
makeDeclaration(func, { allocVar }, &init);
|
||
|
||
st->insertStmtBefore(*save, *func);
|
||
|
||
SgAssignStmt* assign = new SgAssignStmt(*new SgVarRefExp(allocVar), *new SgVarRefExp(allocVar) + *new SgValueExp(1));
|
||
st->insertStmtBefore(*assign, *func);
|
||
}
|
||
}
|