fix FIND_PRIVATE_ARRAYS
This commit is contained in:
301
src/ArrayConstantPropagation/propagation.cpp
Normal file
301
src/ArrayConstantPropagation/propagation.cpp
Normal file
@@ -0,0 +1,301 @@
|
||||
#include "propagation.h"
|
||||
|
||||
#include "../Utils/SgUtils.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
static SgStatement* declPlace = NULL;
|
||||
|
||||
static bool CheckConstIndexes(SgExpression* exp)
|
||||
{
|
||||
if (!exp)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
SgExpression* lhs = exp->lhs();
|
||||
SgExpression* rhs = exp->rhs();
|
||||
do
|
||||
{
|
||||
if (lhs->variant() != INT_VAL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (rhs)
|
||||
{
|
||||
lhs = rhs->lhs();
|
||||
rhs = rhs->rhs();
|
||||
}
|
||||
} while (rhs);
|
||||
return true;
|
||||
}
|
||||
|
||||
static SgExpression* CreateVar(int& variableNumber, SgType* type)
|
||||
{
|
||||
string varName = "__tmp_prop_var";
|
||||
string name = varName + std::to_string(variableNumber) + "__";
|
||||
variableNumber++;
|
||||
|
||||
SgSymbol* varSymbol = new SgSymbol(VARIABLE_NAME, name.c_str(), *type, *declPlace->controlParent());
|
||||
|
||||
const string commonBlockName = "__propagation_common__";
|
||||
|
||||
SgStatement* funcStart = declPlace->controlParent();
|
||||
SgStatement* commonStat = NULL;
|
||||
SgExpression* commonList = NULL;
|
||||
|
||||
SgStatement* funcEnd = funcStart->lastNodeOfStmt();
|
||||
SgStatement* current = funcStart->lexNext();
|
||||
|
||||
while (current != funcEnd && current)
|
||||
{
|
||||
if (current->variant() == COMM_STAT)
|
||||
{
|
||||
for (SgExpression* exp = current->expr(0); exp; exp = exp->rhs())
|
||||
{
|
||||
if (exp->variant() == COMM_LIST)
|
||||
{
|
||||
string existingName = exp->symbol() ?
|
||||
string(exp->symbol()->identifier()) :
|
||||
string("spf_unnamed");
|
||||
if (existingName == commonBlockName)
|
||||
{
|
||||
commonStat = current;
|
||||
commonList = exp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (commonStat)
|
||||
break;
|
||||
}
|
||||
current = current->lexNext();
|
||||
}
|
||||
|
||||
vector<SgExpression*> varRefs;
|
||||
if (commonList)
|
||||
{
|
||||
SgExpression* varList = commonList->lhs();
|
||||
if (varList)
|
||||
{
|
||||
auto extractSymbol = [](SgExpression* exp) -> SgSymbol* {
|
||||
if (!exp)
|
||||
return NULL;
|
||||
if (exp->symbol())
|
||||
return exp->symbol();
|
||||
if (exp->lhs() && exp->lhs()->symbol())
|
||||
return exp->lhs()->symbol();
|
||||
return NULL;
|
||||
};
|
||||
if (varList->variant() == EXPR_LIST)
|
||||
{
|
||||
for (SgExpression* exp = varList; exp; exp = exp->rhs())
|
||||
{
|
||||
SgExpression* varExp = exp->lhs();
|
||||
SgSymbol* sym = extractSymbol(varExp);
|
||||
if (sym)
|
||||
{
|
||||
varRefs.push_back(new SgVarRefExp(sym));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (SgExpression* varExp = varList; varExp; varExp = varExp->rhs())
|
||||
{
|
||||
SgSymbol* sym = extractSymbol(varExp);
|
||||
if (sym)
|
||||
{
|
||||
varRefs.push_back(new SgVarRefExp(sym));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!commonList)
|
||||
{
|
||||
current = funcStart->lexNext();
|
||||
while (current != funcEnd && current)
|
||||
{
|
||||
if (current->variant() == COMM_STAT)
|
||||
{
|
||||
commonStat = current;
|
||||
break;
|
||||
}
|
||||
current = current->lexNext();
|
||||
}
|
||||
|
||||
SgSymbol* commonSymbol = new SgSymbol(COMMON_NAME, commonBlockName.c_str());
|
||||
commonList = new SgExpression(COMM_LIST, NULL, NULL, commonSymbol);
|
||||
|
||||
if (commonStat)
|
||||
{
|
||||
SgExpression* lastCommList = commonStat->expr(0);
|
||||
if (lastCommList)
|
||||
{
|
||||
while (lastCommList->rhs())
|
||||
lastCommList = lastCommList->rhs();
|
||||
lastCommList->setRhs(commonList);
|
||||
}
|
||||
else
|
||||
{
|
||||
commonStat->setExpression(0, commonList);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
commonStat = new SgStatement(COMM_STAT);
|
||||
commonStat->setFileName(declPlace->fileName());
|
||||
commonStat->setFileId(declPlace->getFileId());
|
||||
commonStat->setProject(declPlace->getProject());
|
||||
commonStat->setlineNumber(getNextNegativeLineNumber());
|
||||
commonStat->setExpression(0, commonList);
|
||||
|
||||
declPlace->insertStmtBefore(*commonStat, *declPlace->controlParent());
|
||||
}
|
||||
|
||||
}
|
||||
varRefs.push_back(new SgVarRefExp(varSymbol));
|
||||
|
||||
if (varRefs.size() > 0)
|
||||
{
|
||||
std::reverse(varRefs.begin(), varRefs.end());
|
||||
SgExpression* varList = makeExprList(varRefs, false);
|
||||
|
||||
commonList->setLhs(varList);
|
||||
}
|
||||
|
||||
return new SgExpression(VAR_REF, NULL, NULL, varSymbol, type->copyPtr());
|
||||
}
|
||||
|
||||
static void TransformRightPart(SgStatement* st, SgExpression* exp, unordered_map<string, SgExpression*>& arrayToVariable, int& variableNumber)
|
||||
{
|
||||
if (!exp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vector<SgExpression*> subnodes = { exp->lhs(), exp->rhs() };
|
||||
|
||||
string expUnparsed;
|
||||
SgExpression* toAdd = NULL;
|
||||
if (exp->variant() == ARRAY_REF && CheckConstIndexes(exp->lhs()))
|
||||
{
|
||||
cout << st->unparse() << endl;
|
||||
if (arrayToVariable.find(expUnparsed) == arrayToVariable.end() && exp->symbol()->type()->baseType())
|
||||
{
|
||||
arrayToVariable[expUnparsed] = CreateVar(variableNumber, exp->symbol()->type()->baseType());
|
||||
}
|
||||
st->setExpression(1, arrayToVariable[expUnparsed]->copyPtr());
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (subnodes[i] && subnodes[i]->variant() == ARRAY_REF && subnodes[i]->symbol()->type()->baseType() && CheckConstIndexes(subnodes[i]->lhs()))
|
||||
{
|
||||
expUnparsed = subnodes[i]->unparse();
|
||||
if (arrayToVariable.find(expUnparsed) == arrayToVariable.end())
|
||||
{
|
||||
arrayToVariable[expUnparsed] = CreateVar(variableNumber, subnodes[i]->symbol()->type()->baseType());;
|
||||
}
|
||||
toAdd = arrayToVariable[expUnparsed]->copyPtr();
|
||||
if (toAdd)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
exp->setLhs(toAdd);
|
||||
}
|
||||
else
|
||||
{
|
||||
exp->setRhs(toAdd);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TransformRightPart(st, subnodes[i], arrayToVariable, variableNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void TransformLeftPart(SgStatement* st, SgExpression* exp, unordered_map<string, SgExpression*>& arrayToVariable, int& variableNumber)
|
||||
{
|
||||
if (exp->symbol()->type()->variant() == T_STRING)
|
||||
return;
|
||||
string expUnparsed = exp->unparse();
|
||||
if (arrayToVariable.find(expUnparsed) == arrayToVariable.end() && exp->symbol()->type()->baseType())
|
||||
{
|
||||
arrayToVariable[expUnparsed] = CreateVar(variableNumber, exp->symbol()->type()->baseType());
|
||||
}
|
||||
SgStatement* newStatement = new SgStatement(ASSIGN_STAT, NULL, NULL, arrayToVariable[expUnparsed]->copyPtr(), st->expr(1)->copyPtr(), NULL);
|
||||
|
||||
newStatement->setFileId(st->getFileId());
|
||||
newStatement->setProject(st->getProject());
|
||||
|
||||
newStatement->setlineNumber(getNextNegativeLineNumber());
|
||||
newStatement->setLocalLineNumber(st->lineNumber());
|
||||
st->insertStmtBefore(*newStatement, *st->controlParent());
|
||||
}
|
||||
|
||||
void ArrayConstantPropagation(SgProject& project)
|
||||
{
|
||||
unordered_map<string, SgExpression*> arrayToVariable;
|
||||
int variableNumber = 0;
|
||||
for (int i = 0; i < project.numberOfFiles(); i++)
|
||||
{
|
||||
SgFile* file = &(project.file(i));
|
||||
|
||||
if (!file)
|
||||
continue;
|
||||
|
||||
const int funcNum = file->numberOfFunctions();
|
||||
for (int i = 0; i < funcNum; ++i)
|
||||
{
|
||||
SgStatement* st = file->functions(i);
|
||||
declPlace = st->lexNext();
|
||||
SgStatement* lastNode = st->lastNodeOfStmt();
|
||||
|
||||
for (; st != lastNode; st = st->lexNext())
|
||||
{
|
||||
if (st->variant() == ASSIGN_STAT)
|
||||
{
|
||||
if (st->expr(1))
|
||||
{
|
||||
TransformRightPart(st, st->expr(1), arrayToVariable, variableNumber);
|
||||
}
|
||||
if (st->expr(0) && st->expr(0)->variant() == ARRAY_REF && CheckConstIndexes(st->expr(0)->lhs()))
|
||||
{
|
||||
TransformLeftPart(st, st->expr(0), arrayToVariable, variableNumber);
|
||||
}
|
||||
}
|
||||
else if (st->variant() == FOR_NODE)
|
||||
{
|
||||
SgExpression* lowerBound = st->expr(0)->lhs();
|
||||
SgExpression* upperBound = st->expr(0)->rhs();
|
||||
string lowerBoundUnparsed = lowerBound->unparse(), upperBoundUnparsed = upperBound->unparse();
|
||||
if (upperBound->variant() == ARRAY_REF && upperBound->symbol()->type()->baseType() && CheckConstIndexes(upperBound->lhs()))
|
||||
{
|
||||
if (arrayToVariable.find(upperBoundUnparsed) == arrayToVariable.end())
|
||||
{
|
||||
arrayToVariable[upperBoundUnparsed] = CreateVar(variableNumber, upperBound->symbol()->type()->baseType());
|
||||
}
|
||||
st->expr(0)->setRhs(arrayToVariable[upperBoundUnparsed]->copyPtr());
|
||||
}
|
||||
if (lowerBound->variant() == ARRAY_REF && lowerBound->symbol()->type()->baseType() && CheckConstIndexes(lowerBound->lhs()))
|
||||
{
|
||||
if (arrayToVariable.find(lowerBoundUnparsed) == arrayToVariable.end())
|
||||
{
|
||||
arrayToVariable[lowerBoundUnparsed] = CreateVar(variableNumber, lowerBound->symbol()->type()->baseType());
|
||||
}
|
||||
st->expr(0)->setLhs(arrayToVariable[lowerBoundUnparsed]->copyPtr());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user