Files
SAPFOR/src/Transformations/private_arrays_resizing.cpp
2025-03-12 14:28:04 +03:00

1560 lines
53 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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);
}
}