Files
SAPFOR/src/Transformations/ExpressionSubstitution/expr_transform.cpp

1351 lines
43 KiB
C++
Raw Normal View History

#include "leak_detector.h"
2023-09-14 19:43:13 +03:00
#if _WIN32 && NDEBUG && __SPF && __BOOST
#include <boost/thread.hpp>
#endif
extern int passDone;
#include "dvm.h"
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <iterator>
#include <fstream>
#include <chrono>
#include "../ParallelizationRegions/ParRegions.h"
#include "../ParallelizationRegions/ParRegions_func.h"
#include "../GraphLoop/graph_loops.h"
#include "graph_calls.h"
2023-09-14 19:43:13 +03:00
#include "../GraphCall/graph_calls_func.h"
#include "../Utils/utils.h"
#include "../Utils/SgUtils.h"
#include "../Distribution/Distribution.h"
#include "../VisualizerCalls/get_information.h"
#include "expr_transform.h"
using std::pair;
using std::map;
using std::set;
using std::tuple;
using std::vector;
using std::string;
using std::iterator;
using std::make_pair;
using std::queue;
using std::chrono::high_resolution_clock;
using std::chrono::duration_cast;
using std::chrono::milliseconds;
#define PRINT_SUBSTITUTION_ABORT 1
#define PRINT_PROF_INFO 0
#define PRINT_PROF_INFO_TIME 0
/*
* Contains original SgExpressions.
* map <string, ...> key is a file, where replacements take place
* map <SgStatement*, vector<SgExpression*>> key is a changed SgStetement, value - 3 SgEpression*'s
* [i] SgExpresson* is null, if it has not been changed
*
* NOTE: 2 levels of replacements: first -- replace constant values, second -- replace other expressions with CFG
*/
static map<string, map<SgStatement*, vector<SgExpression*>>> replacementsOfConstsInFiles;
static map<string, map<SgStatement*, vector<SgExpression*>>> replacementsInFiles;
static map<SgStatement*, vector<SgExpression*>>* curFileReplacements;
static set<SgStatement*> visitedStatements;
static CommonVarsOverseer overseer;
static GraphsKeeper *graphsKeeper = NULL;
static unsigned int substitutionsCounter = 0;
static void incrementSubstitutionsCounter(int print_prof_info) {
if(print_prof_info)
substitutionsCounter++;
}
SgStatement* findReplacedExpression(SgExpression *ex)
{
const int id = ex->id();
for (auto& byFile : replacementsInFiles)
{
for (auto& elem : byFile.second)
{
SgStatement* ret = elem.first;
for (int z = 0; z < elem.second.size(); ++z)
if (elem.second[z] == ex)
if (elem.second[z]->id() == id)
return ret;
}
}
return NULL;
}
void GraphsKeeper::deleteGraphsKeeper()
{
if(graphsKeeper)
delete graphsKeeper;
graphsKeeper = NULL;
}
GraphsKeeper* GraphsKeeper::getGraphsKeeper() {
if(graphsKeeper == NULL)
graphsKeeper = new GraphsKeeper();
return graphsKeeper;
}
GraphItem* GraphsKeeper::buildGraph(SgStatement* st)
{
GraphItem* result = new GraphItem();
SetUpVars(&result->commons, &result->calls, result->calls.AddHeader(st, false, st->symbol(), current_file_id), &result->dldl);
result->CGraph = GetControlFlowGraphWithCalls(true, st, &result->calls, &result->commons);
result->calls.AssociateGraphWithHeader(st, result->CGraph);
result->commons.MarkEndOfCommon(GetCurrentProcedure());
result->file_id = current_file_id;
/*std::fstream fs;
fs.open("graph.txt", std::fstream::out);
fs << result->CGraph->GetVisualGraph(&result->calls);
fs.close();*/
auto inserted = graphs.insert(make_pair(st, result));
return inserted.first->second;
}
GraphItem* GraphsKeeper::getGraph(SgStatement *header)
{
auto it = graphs.find(header);
if (it == graphs.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
GraphItem* res = graphs.find(header)->second;
CurrentProject->file(res->file_id);
return res;
}
CBasicBlock* GraphsKeeper::findBlock(SgStatement* stmt)
{
for(auto &graph : graphs) {
if(graph.second->file_id != stmt->getFileId())
continue;
stmt->switchToFile();
CBasicBlock *b = graph.second->CGraph->getFirst();
while(b != NULL)
{
ControlFlowItem *cfi = b->getStart();
ControlFlowItem *till = b->getEnd()->getNext();
while(cfi != till)
{
SgStatement *st = cfi->getStatement();
if(st && st->id() == stmt->id())
return b;
st = cfi->getOriginalStatement();
if(st && st->id() == stmt->id())
return b;
cfi = cfi->getNext();
}
b = b->getLexNext();
}
}
return NULL;
}
bool findCFIsForStmt(SgStatement *stmt, vector <ControlFlowItem*> &cfis) {
CBasicBlock* b = GraphsKeeper::getGraphsKeeper()->findBlock(stmt);
if(!b)
return false;
ControlFlowItem *cfi = b->getStart();
ControlFlowItem *till = b->getEnd()->getNext();
while (cfi != till)
{
SgStatement *st = cfi->getStatement();
if (st && st->id() == stmt->id())
cfis.push_back(cfi);
else {
st = cfi->getOriginalStatement();
if (st && st->id() == stmt->id())
cfis.push_back(cfi);
}
cfi = cfi->getNext();
}
return cfis.size() != 0;
}
const map<SymbolKey, set<ExpressionValue*>> getReachingDefinitionsExt(SgStatement* stmt)
{
CBasicBlock* b = GraphsKeeper::getGraphsKeeper()->findBlock(stmt);
if(!b)
return map<SymbolKey, set<ExpressionValue*>>();
return b->getReachedDefinitionsExt(stmt);
}
static void revertReplacements(map<SgStatement*, vector<SgExpression*>> &toRev, bool constant = false)
{
for (auto &toReplace : toRev)
{
SgStatement *parent = toReplace.first;
for (int i = 0; i < 3; ++i)
{
if (toReplace.second[i] != NULL)
{
SgExpression *replacement = parent->expr(i);
parent->setExpression(i, *(toReplace.second[i]));
toReplace.second[i] = replacement;
}
}
}
}
void revertReplacements(const string &filename, bool back)
{
auto constF = replacementsOfConstsInFiles.find(filename);
auto tmpF = replacementsInFiles.find(filename);
if (back)
{
if (tmpF != replacementsInFiles.end())
revertReplacements(tmpF->second);
if (constF != replacementsOfConstsInFiles.end())
revertReplacements(constF->second, true);
}
else
{
if (constF != replacementsOfConstsInFiles.end())
revertReplacements(constF->second, true);
if (tmpF != replacementsInFiles.end())
revertReplacements(tmpF->second);
}
}
static SgExpression* getFromConstructor(SgExpression *e, int num)
{
int i = 1;
while (e)
{
if (i == num)
return e->lhs();
++i;
e = e->rhs();
}
return NULL;
}
SgExpression* ReplaceParameter_(SgExpression *e)
{
if (!e)
return e;
if (e->variant() == CONST_REF)
{
auto t1 = e->type();
auto t2 = e->symbol()->type();
SgConstantSymb *sc = isSgConstantSymb(e->symbol());
if (!sc->constantValue())
return e;
auto val = sc->constantValue();
auto typeVal = val->type();
//if type of constant does not match type of variable
if (e->symbol()->type()->variant() == T_DOUBLE && val->variant() == FLOAT_VAL && typeVal->variant() == T_FLOAT)
{
char* digit_o = ((SgValueExp*)val)->floatValue();
SgExpression* val = typeVal->selector();
char* digit = new char[strlen(digit_o) + 2];
strcpy(digit, digit_o);
digit[strlen(digit_o)] = 'f';
digit[strlen(digit_o) + 1] = '\0';
SgValueExp* valDouble = new SgValueExp(double(0.0), digit);
delete[]digit;
if (val != NULL)
{
if (val->valueInteger() == 8) // double
return sc->constantValue()->copyPtr();
else if (val->valueInteger() == 4) // float
return valDouble;
else
return valDouble;
}
else
return valDouble;
}
else
return (ReplaceParameter_(&(sc->constantValue()->copy())));
}
else if (e->variant() == ARRAY_REF)
{
SgConstantSymb *sc = isSgConstantSymb(e->symbol());
if (sc)
{
SgExpression *constructor = sc->constantValue();
SgArrayRefExp *ref = isSgArrayRefExp(e);
if (ref->numberOfSubscripts() == 1)
{
auto sub = ref->subscript(0);
if (sub->isInteger())
{
int num = sub->valueInteger();
SgExpression *value = getFromConstructor(constructor->lhs(), num);
if (value && ((value->lhs() == NULL && value->rhs() == NULL) || value->variant() == MINUS_OP))
return (ReplaceParameter_(&(value->copy())));
}
}
}
}
e->setLhs(ReplaceParameter_(e->lhs()));
e->setRhs(ReplaceParameter_(e->rhs()));
return e;
}
SgExpression* ReplaceConstant(SgExpression *e)
{
SgExpression *er;
er = ReplaceParameter_(&(e->copy()));
if (er->isInteger())
return (new SgValueExp(er->valueInteger()));
else
return er;
}
SgExpression* ReplaceArrayBoundSizes(SgExpression *edim)
{
SgSubscriptExp *sbe = NULL;
SgExpression *low = NULL;
if (!edim)
return edim;
if ((sbe = isSgSubscriptExp(edim)) != NULL) //DDOT
{
if (!sbe->ubound())
return edim;
edim = new SgExpression(DDOT);
edim->setLhs(ReplaceArrayBoundSizes(sbe->lbound()));
edim->setRhs(ReplaceArrayBoundSizes(sbe->ubound()));
}
else
edim = ReplaceConstant(edim);
return edim;
}
static pair<int, int> getCoefsOfSubscript(SgExpression *exp, SgSymbol *doName, int &err)
{
pair<int, int> result;
pair<int, int> lRes = make_pair(0, 0), rRes = make_pair(0, 0);
int lErr = 0, rErr = 0;
const int op = exp->variant();
if (exp->lhs())
lRes = getCoefsOfSubscript(exp->lhs(), doName, lErr);
if (exp->rhs())
rRes = getCoefsOfSubscript(exp->rhs(), doName, rErr);
switch (op)
{
case ADD_OP:
if (lErr != -1 && rErr != -1)
result = make_pair(lRes.first + rRes.first, lRes.second + rRes.second);
else
err = -1;
break;
case MINUS_OP:
if (lErr != -1)
result = make_pair(-lRes.first, lRes.second);
else
err = -1;
break;
case UNARY_ADD_OP:
if (lErr != -1)
result = make_pair(+lRes.first, lRes.second);
else
err = -1;
break;
case MULT_OP:
if (lErr != -1 && rErr != -1)
{
if (lRes.first != 0 && rRes.first != 0)
err = -1;
else
result = make_pair(lRes.first * rRes.second + rRes.first * lRes.second, lRes.second * rRes.second);
}
else
err = -1;
break;
case SUBT_OP:
if (lErr != -1 && rErr != -1)
result = make_pair(lRes.first - rRes.first, lRes.second - rRes.second);
else
err = -1;
break;
case DIV_OP:
if (lErr != -1 && rErr != -1)
{
if (rRes.first != 0 || rRes.second == 0)
err = -1;
else
result = make_pair(lRes.first / rRes.second, lRes.second / rRes.second);
}
else
err = -1;
break;
case MOD_OP:
if (lErr != -1 && rErr != -1)
{
if (rRes.first != 0 || rRes.second == 0)
err = -1;
else
result = make_pair(lRes.first % rRes.second, lRes.second % rRes.second);
}
else
err = -1;
break;
case VAR_REF:
if (strcmp(exp->symbol()->identifier(), doName->identifier()) == 0)
result = make_pair(1, 0);
else
err = -1;
break;
case INT_VAL:
result = make_pair(0, exp->valueInteger());
break;
default:
err = -1;
}
if (err != -1)
return result;
else
return make_pair(0, 0);
}
bool replaceConstantRec(SgExpression *&exp)
{
bool changed = false;
if (exp->variant() == CONST_REF)
{
SgExpression *ret = ReplaceParameter_(exp);
int sign = 1;
SgExpression* toCalc = ret;
if (ret->variant() == UNARY_ADD_OP)
toCalc = ret->lhs();
if (ret->variant() == MINUS_OP)
{
toCalc = ret->lhs();
sign = -1;
}
if (toCalc->isInteger())
{
exp = new SgValueExp(sign * toCalc->valueInteger());
changed = true;
}
}
if (exp->lhs())
{
SgExpression *left = exp->lhs();
changed |= replaceConstantRec(left);
exp->setLhs(left);
}
if (exp->rhs())
{
SgExpression *right = exp->rhs();
changed |= replaceConstantRec(right);
exp->setRhs(right);
}
return changed;
}
int CalculateInteger(SgExpression *expr, int &result)
{
if (expr->variant() == INT_VAL)
{
result = expr->valueInteger();
return 0;
}
else
{
pair<int, int> err = make_pair(-1, -1);
pair<int, int> res;
if (expr->lhs())
err.first = CalculateInteger(expr->lhs(), res.first);
if (expr->rhs())
err.second = CalculateInteger(expr->rhs(), res.second);
switch (expr->variant())
{
case ADD_OP:
if (err.first != -1 && err.second != -1)
{
result = res.first + res.second;
return 0;
}
else
return -1;
break;
case MINUS_OP:
if (err.first != -1)
{
result = -res.first;
return 0;
}
else
return -1;
break;
case UNARY_ADD_OP:
if (err.first != -1)
{
result = res.first;
return 0;
}
else
return -1;
break;
case MULT_OP:
if (err.first != -1 && err.second != -1)
{
result = res.first * res.second;
return 0;
}
else if(err.first != -1 && res.first == 0)
{
result = 0;
return 0;
}
else if (err.second != -1 && res.second == 0)
{
result = 0;
return 0;
}
else
return -1;
break;
case SUBT_OP:
if (err.first != -1 && err.second != -1)
{
result = res.first - res.second;
return 0;
}
else
return -1;
break;
case DIV_OP:
if (err.first != -1 && err.second != -1 && res.second != 0)
{
result = res.first / res.second;
return 0;
}
else
return -1;
break;
case MOD_OP:
if (err.first != -1 && err.second != -1 && res.second != 0)
{
result = res.first % res.second;
return 0;
}
else
return -1;
break;
case EXP_OP:
if (err.first != -1 && err.second != -1)
{
result = (int) pow(res.first, res.second);
return 0;
}
else
return -1;
break;
default:
return -1;
}
}
}
SgExpression* CalculateInteger(SgExpression *expr)
{
int value, res;
replaceConstantRec(expr);
res = CalculateInteger(expr, value);
if (res != -1)
return new SgValueExp(value);
else
return expr;
}
bool calculate(SgExpression *&exp)
{
bool changed = false;
SgExpression *left, *right;
int res, err;
if ((left = exp->lhs()) != NULL)
{
err = CalculateInteger(left, res);
if (err != -1)
{
exp->setLhs(new SgValueExp(res));
changed = true;
}
else
changed |= calculate(left);
}
if ((right = exp->rhs()) != NULL)
{
err = CalculateInteger(right, res);
if (err != -1)
{
exp->setRhs(new SgValueExp(res));
changed = true;
}
else
changed |= calculate(right);
}
return changed;
}
static bool isNeedFinishCalc(SgExpression *exp, string doName)
{
bool ret = true;
if (exp->variant() == VAR_REF)
{
if (string(exp->symbol()->identifier()) != doName)
ret = false;
}
if (exp->lhs())
ret &= isNeedFinishCalc(exp->lhs(), doName);
if (exp->rhs())
ret &= isNeedFinishCalc(exp->rhs(), doName);
return ret;
}
static void replaceVarRefToZero(SgExpression *&exp, int &countVarRefs)
{
if (exp->variant() == VAR_REF)
{
exp = new SgValueExp(0);
countVarRefs++;
}
SgExpression *tmp;
if (exp->lhs())
{
tmp = exp->lhs();
replaceVarRefToZero(tmp, countVarRefs);
exp->setLhs(tmp);
}
if (exp->rhs())
{
tmp = exp->rhs();
replaceVarRefToZero(tmp, countVarRefs);
exp->setRhs(tmp);
}
}
void getCoefsOfSubscript(pair<int, int> &retCoefs, SgExpression *exp, SgSymbol *doName)
{
SgExpression *copyExp = &(exp->copy());
replaceConstantRec(copyExp);
calculate(copyExp);
if (isNeedFinishCalc(copyExp, doName->identifier()))
{
int err = 0;
retCoefs = getCoefsOfSubscript(copyExp, doName, err);
}
else
retCoefs = make_pair(0, 0);
}
static SgExpression* valueOfVar(SgExpression *var, CBasicBlock *b)
{
SgExpression *exp = NULL;
//first, check previous defs within block
auto founded = b->getGen()->find(SymbolKey(var->symbol()));
if (founded != b->getGen()->end())
if (!valueWithFunctionCall(founded->second->getExp()))
if (!valueWithRecursion(founded->first, founded->second->getExp()))
if(!valueWithArrayReference(founded->second->getExp(), founded->second->getFrom()))
if(b->expressionIsAvailable(founded->second))
exp = founded->second->getExp();
if (exp == NULL)
{
//second, check defs from previous blocks
auto founded_inDefs = b->getInDefs()->find(SymbolKey(var->symbol()));
if (founded_inDefs != b->getInDefs()->end())
{
//if smth is founded_inDefs, it has single value
//thanks to CorrectInDefs(ControlFlowGraph*) function
ExpressionValue *expVal = *(founded_inDefs->second.begin());
//we have to check if this value was killed inside block
if(b->expressionIsAvailable(expVal))
exp = expVal->getExp();
}
}
return exp;
}
void createLinksToCopy(SgExpression *exOrig, SgExpression *exCopy)
{
if (exOrig && exCopy)
{
if (exOrig->variant() == ARRAY_REF && exCopy->variant() == ARRAY_REF)
{
exOrig->addAttribute(ARRAY_REF, exCopy, sizeof(SgExpression*));
exCopy->addAttribute(ARRAY_REF, exOrig, sizeof(SgExpression*));
}
createLinksToCopy(exOrig->lhs(), exCopy->lhs());
createLinksToCopy(exOrig->rhs(), exCopy->rhs());
}
}
static void createBackup(SgStatement* stmt, int expNumber)
{
SgExpression *exp = stmt->expr(expNumber);
if (exp == NULL) // no backup is required
return;
auto foundedParent = curFileReplacements->find(stmt);
if (foundedParent == curFileReplacements->end())
{
auto inserted = curFileReplacements->insert(make_pair(stmt, vector<SgExpression*>()));
foundedParent = inserted.first;
foundedParent->second.resize(3);
for (int i = 0; i < 3; ++i)
foundedParent->second[i] = NULL;
}
if (foundedParent->second[expNumber] == NULL)
{
SgExpression *expToCopy = exp->copyPtr();
foundedParent->second[expNumber] = expToCopy;
const string orig = string(exp->unparse());
const string copy = string(expToCopy->unparse());
if (orig == copy)
createLinksToCopy(exp, expToCopy);
}
}
static SgExpression* tryMakeInt(SgExpression* exp)
{
if (exp->variant() != INT_VAL)
if (exp->isInteger())
return new SgValueExp(exp->valueInteger());
return exp;
}
static bool typesAreTheSame(SgExpression *oldExp, SgExpression *newExp, int lineNumber)
{
paramType oldType = detectExpressionType(oldExp);
paramType newType = detectExpressionType(newExp);
if(oldType != newType)
{
char* tmp = oldExp->unparse();
__spf_print(PRINT_SUBSTITUTION_ABORT, "%d: Substitution aborted %s -> ", lineNumber, tmp);
__spf_print(PRINT_SUBSTITUTION_ABORT, "%s. Types do not match: %s != %s\n", newExp->unparse(), paramNames[oldType], paramNames[newType]);
return false;
}
return true;
}
static bool setNewSubexpression(SgExpression *parent, bool rightSide, SgExpression *newExp, const int lineNumber)
{
SgExpression *oldExp = rightSide ? parent->rhs() : parent->lhs();
__spf_print(PRINT_PROF_INFO, "%d: %s -> ",lineNumber, oldExp->unparse());
__spf_print(PRINT_PROF_INFO, "%s\n", newExp->unparse());
incrementSubstitutionsCounter(PRINT_PROF_INFO);
SgExpression* expToCopy = newExp->copyPtr();
calculate(expToCopy);
rightSide ? parent->setRhs(tryMakeInt(expToCopy)) : parent->setLhs(tryMakeInt(expToCopy));
return true;
}
static bool replaceVarsInExpression(SgStatement *parent, int expNumber, CBasicBlock *b, bool replaceFirstVar)
{
queue<SgExpression*> toCheck;
bool wereReplacements = false;
SgExpression* exp = parent->expr(expNumber);
if (exp->variant() == VAR_REF && !replaceFirstVar)
return false;
//If SgExpression is a single VAR
if (exp->variant() == VAR_REF)
{
SgExpression* newExp = valueOfVar(exp, b);
if (newExp != NULL && typesAreTheSame(exp, newExp, parent->lineNumber()))
{
createBackup(parent, expNumber);
__spf_print(PRINT_PROF_INFO, "%d: %s -> %s",parent->lineNumber(), exp->unparse(), newExp->unparse());
incrementSubstitutionsCounter(PRINT_PROF_INFO);
SgExpression* expToCopy = newExp->copyPtr();
calculate(expToCopy);
parent->setExpression(expNumber, *(tryMakeInt(expToCopy)));
return true;
}
}//If not
else
{
toCheck.push(exp);
while (!toCheck.empty())
{
exp = toCheck.front();
toCheck.pop();
if (exp->rhs())
{
if (exp->rhs()->variant() == VAR_REF)
{
SgExpression* newExp = valueOfVar(exp->rhs(), b);
if (newExp != NULL && typesAreTheSame(exp->rhs(), newExp, parent->lineNumber()))
{
createBackup(parent, expNumber);
wereReplacements |= setNewSubexpression(exp, true, newExp, parent->lineNumber());
}
}
else
toCheck.push(exp->rhs());
}
if (exp->variant() != FUNC_CALL)// Funcs' arguments are processed in replaceCallArguments
if (exp->lhs())
{
if (exp->lhs()->variant() == VAR_REF)
{
SgExpression* newExp = valueOfVar(exp->lhs(), b);
if (newExp != NULL && typesAreTheSame(exp->lhs(), newExp, parent->lineNumber()))
{
createBackup(parent, expNumber);
wereReplacements |= setNewSubexpression(exp, false, newExp, parent->lineNumber());
}
}
else
toCheck.push(exp->lhs());
}
}
}
return wereReplacements;
}
static bool needReplacements(SgExpression* exp, map<SymbolKey, vector<SgExpression*>>* ins, bool checkVar)
{
if (exp->variant() == VAR_REF)
{
if (checkVar)
for (auto it = ins->begin(); it != ins->end(); ++it)
if (it->first == exp->symbol())
return true;
return false;
}
else
{
bool needReplacement = false;
if (exp->rhs())
needReplacement = needReplacements(exp->rhs(), ins, true);
if (exp->lhs() && !needReplacement)
needReplacement = needReplacements(exp->lhs(), ins, true);
return needReplacement;
}
}
static bool replaceVarsInCallArgument(SgExpression *exp, const int lineNumber, CBasicBlock *b)
{
bool wereReplacements = false;
SgExpression *lhs = exp->lhs(), *rhs = exp->rhs();
if(lhs && lhs->variant() != FUNC_CALL) //We don't want expand arguments of other functions.
{
if(lhs->variant() == VAR_REF)
{
SgExpression* newExp = valueOfVar(lhs, b);
if (newExp != NULL && typesAreTheSame(lhs, newExp, lineNumber))
{
wereReplacements |= setNewSubexpression(exp, false, newExp, lineNumber);
}
}
else
wereReplacements |= replaceVarsInCallArgument(lhs, lineNumber, b);
}
if(rhs && rhs->variant() != FUNC_CALL) //We don't want expand arguments of other functions
{
if(rhs->variant() == VAR_REF)
{
SgExpression* newExp = valueOfVar(rhs, b);
if (newExp != NULL && typesAreTheSame(rhs, newExp, lineNumber))
{
wereReplacements |= setNewSubexpression(exp, true, newExp, lineNumber);
}
}
else
wereReplacements |= replaceVarsInCallArgument(rhs, lineNumber, b);
}
return wereReplacements;
}
static bool replaceCallArguments(ControlFlowItem *cfi, CBasicBlock *b)
{
bool wereReplacements = false;
int numberOfArgs = 0, lineNumber = 0;
SgExpression *args = NULL, *arg = NULL;
SgFunctionCallExp *funcCall = NULL;
SgStatement *st = cfi->getStatement();
AnalysedCallsList *callData = cfi->getCall();
if(callData == NULL)//no info of arguments, can't expand expressions;
return false;
if (st != NULL && st->variant() == PROC_STAT) //procedure call
{
createBackup(st, 0);
SgCallStmt *callStmt = isSgCallStmt(cfi->getStatement());
args = callStmt->expr(0);
numberOfArgs = callStmt->numberOfArgs();
lineNumber = callStmt->lineNumber();
}
else if ((funcCall = cfi->getFunctionCall()) != NULL) //functionCall
{
st = cfi->getOriginalStatement();
for (int i = 0; i < 3; ++i)
if (st->expr(i))// TODO: search for expression?
createBackup(st, i);
args = funcCall->lhs();
lineNumber = st->lineNumber();
numberOfArgs = funcCall->numberOfArgs();
}
if (args)
{
for (int i = 0; i < numberOfArgs; ++i)
{
arg = args->lhs();
if (arg->variant() == VAR_REF && argIsReplaceable(i, callData))
{
SgExpression* newExp = valueOfVar(arg, b);
if (newExp != NULL && typesAreTheSame(arg, newExp, lineNumber))
{
wereReplacements |= setNewSubexpression(args, false, newExp, lineNumber);
}
}
else if (arg->variant() != VAR_REF)
wereReplacements |= replaceVarsInCallArgument(arg, lineNumber, b);
args = args->rhs();
}
}
return wereReplacements;
}
/*
* Have to run b->adjustGenAndKill(cfi) here to track changes inside block.
*/
static bool replaceVarsInBlock(CBasicBlock* b)
{
bool wereReplacements = false;
SgStatement* st;
for (ControlFlowItem* cfi = b->getStart(); cfi != b->getEnd()->getNext(); cfi = cfi->getNext())
{
st = cfi->getStatement();
if(cfi->getFunctionCall())
{
wereReplacements |= replaceCallArguments(cfi, b);
b->checkFuncAndProcCalls(cfi);
}
if (st != NULL)
{
if (isDVM_stat(st))
continue;
if (isSPF_stat(st))
continue;
switch (st->variant())
{
case ASSIGN_STAT:
wereReplacements |= replaceVarsInExpression(st, 0, b, false);
wereReplacements |= replaceVarsInExpression(st, 1, b, true);
b->adjustGenAndKill(cfi);
break;
case PROC_STAT:
wereReplacements |= replaceCallArguments(cfi, b);
b->adjustGenAndKill(cfi);
break;
case READ_STAT:
//TODO вообще-то подставлять нельзя только переменные, а индексы массивов можно, но стоиот ли?
b->adjustGenAndKill(cfi);
break;
case POINTER_ASSIGN_STAT:
b->adjustGenAndKill(cfi);
break;
default:
for (int i = 0; i < 3; ++i)
if (st->expr(i))
wereReplacements |= replaceVarsInExpression(st, i, b, true);
}
}
else if ((st = cfi->getOriginalStatement()) != NULL) //if, loop or funcCall statement condition expressions
{
if(cfi->getFunctionCall())//processed already
continue;
if (visitedStatements.find(st) == visitedStatements.end())
{
visitedStatements.insert(st);
if (st->expr(0))
wereReplacements |= replaceVarsInExpression(st, 0, b, true);
}
}
}
return wereReplacements;
}
void ExpandExpressions(ControlFlowGraph* CGraph, map<SymbolKey, set<ExpressionValue*>> &inDefs)
{
bool wereReplacements = true;
while (wereReplacements)
{
createNeededException();
__spf_print(PRINT_PROF_INFO_TIME, "New substitution iteration\n");
auto time = high_resolution_clock::now();
wereReplacements = false;
visitedStatements.clear();
__spf_print(PRINT_PROF_INFO_TIME, " clear vis %f\n",
duration_cast<milliseconds>(high_resolution_clock::now() - time).count() / 1000.);
time = high_resolution_clock::now();
ClearCFGInsAndOutsDefs(CGraph);
__spf_print(PRINT_PROF_INFO_TIME, " clear CFG %f\n",
duration_cast<milliseconds>(high_resolution_clock::now() - time).count() / 1000.);
time = high_resolution_clock::now();
FillCFGInsAndOutsDefs(CGraph, &inDefs, &overseer);
__spf_print(PRINT_PROF_INFO_TIME, " fill %f\n",
duration_cast<milliseconds>(high_resolution_clock::now() - time).count() / 1000.);
time = high_resolution_clock::now();
CorrectInDefs(CGraph);
__spf_print(PRINT_PROF_INFO_TIME, " correct %f\n",
duration_cast<milliseconds>(high_resolution_clock::now() - time).count() / 1000.);
time = high_resolution_clock::now();
for (CBasicBlock* b = CGraph->getFirst(); b != NULL; b = b->getLexNext())
{
b->clearGenKill(); //Needed for correct expanding within block
if (replaceVarsInBlock(b))
wereReplacements = true;
}
__spf_print(PRINT_PROF_INFO_TIME, " replace %f\n",
duration_cast<milliseconds>(high_resolution_clock::now() - time).count() / 1000.);
}
}
void BuildUnfilteredReachingDefinitions(ControlFlowGraph* CGraph, map<SymbolKey, set<ExpressionValue*>> &inDefs, const string &filename)
{
__spf_print(PRINT_PROF_INFO, "Building unfiltered reaching definitions\n");
visitedStatements.clear();
ClearCFGInsAndOutsDefs(CGraph);
FillCFGInsAndOutsDefs(CGraph, &inDefs, &overseer);
/* Showtime */
// showDefsOfGraph(CGraph);
// debugStructure(CGraph, filename);
}
ControlFlowGraph* BuildUnfilteredReachingDefinitionsFor(SgStatement *header)
{
auto inDefs = createHeaderInDefs(header);
ControlFlowGraph *CGraph = GraphsKeeper::getGraphsKeeper()->getGraph(header)->CGraph;
BuildUnfilteredReachingDefinitions(CGraph, inDefs, header->getFile()->filename());
return CGraph;
}
static void initOverseer(const map<string, vector<DefUseList>> &defUseByFunctions, const map<string, CommonBlock*> &commonBlocks, const map<string, vector<FuncInfo*>> &allFuncInfo)
{
vector<FuncCallSE> funcCalls;
for(auto &file : allFuncInfo)
for(auto& funcInfo : file.second)
funcCalls.push_back(FuncCallSE(funcInfo->funcName, funcInfo->callsFrom));
for (auto& commonBlock : commonBlocks) {
auto grouped = commonBlock.second->getGroupedVars();
for (auto& var : commonBlock.second->getVariables())
if (var->getType() == SCALAR)
for (auto& fun : var->getAllUse())
{
bool deffed = false;
auto func = fun.getFunctionName();
auto foundedDefUse = defUseByFunctions.find(func);
if (foundedDefUse != defUseByFunctions.end())
for (auto& varDefUse : foundedDefUse->second)
if (varDefUse.isDef() && varDefUse.getVar() == var->getName())
{
deffed = true;
break;
}
if (deffed)
{
queue<string> killerFuncs = queue<string>();
set<string> processed = set<string>();
killerFuncs.push(fun.getFunctionName());
while (!killerFuncs.empty())
{
string& curFunc = killerFuncs.front();
processed.insert(curFunc);
killerFuncs.pop();
for (auto& file : allFuncInfo)
for (auto& funcInfo : file.second)
if (funcInfo->callsFrom.find(curFunc) != funcInfo->callsFrom.end() &&
processed.find(funcInfo->funcName) == processed.end())
killerFuncs.push(funcInfo->funcName);
//added all variables at same common position
overseer.addKilledVar(var->getSymbol(), fun.getFunctionName());
auto atPlace = grouped.find(var->getPosition());
if (atPlace == grouped.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (auto& sameVar : atPlace->second)
overseer.addKilledVar(sameVar->getSymbol(), fun.getFunctionName());
}
}
}
}
overseer.riseInited();
}
static bool findConstRef(SgExpression *ex)
{
bool ret = false;
if (ex)
{
if (ex->variant() == CONST_REF)
return true;
ret = ret || findConstRef(ex->lhs());
ret = ret || findConstRef(ex->rhs());
}
return ret;
}
static void replaceOrigFuncSymbols(SgExpression* ex, SgExpression* copy)
{
if (ex && copy)
{
if (ex->variant() == FUNC_CALL)
copy->setSymbol(ex->symbol());
replaceOrigFuncSymbols(ex->lhs(), copy->lhs());
replaceOrigFuncSymbols(ex->rhs(), copy->rhs());
}
}
static void replaceConstants(const string &file, SgStatement *st)
{
auto it = replacementsOfConstsInFiles.find(file);
if (it == replacementsOfConstsInFiles.end())
it = replacementsOfConstsInFiles.insert(it, make_pair(file, map<SgStatement*, vector<SgExpression*>>()));
auto last = st->lastNodeOfStmt();
for (SgStatement *currS = st; currS != last; currS = currS->lexNext())
{
if (currS->variant() == CONTAINS_STMT)
break;
if (isSgExecutableStatement(currS))
{
vector<SgExpression*> toRepl = { NULL, NULL, NULL };
vector<SgExpression*> original = { NULL, NULL, NULL };
for (int i = 0; i < 3; ++i)
{
if (findConstRef(currS->expr(i)))
{
original[i] = currS->expr(i)->copyPtr();
SgExpression *copy = ReplaceConstant(original[i]);
createLinksToCopy(original[i], copy);
calculate(copy);
toRepl[i] = copy;
currS->setExpression(i, *copy);
}
}
if (toRepl[0] || toRepl[1] || toRepl[2])
{
it->second[currS] = original;
for (int z = 0; z < 3; ++z)
replaceOrigFuncSymbols(currS->expr(z), original[z]);
}
}
}
}
static bool isInParallelRegion(SgStatement *func, const vector<ParallelRegion*> &regions)
{
bool ok = false;
auto last = func->lastNodeOfStmt();
for (auto st = func; st != last; st = st->lexNext())
{
if (getAllRegionsByLine(regions, st->fileName(), st->lineNumber()).size())
{
ok = true;
break;
}
}
return ok;
}
map<SymbolKey, set<ExpressionValue*>> createHeaderInDefs(SgStatement *header) {
map<SymbolKey, set<ExpressionValue*>> inDefs;
ExpressionValue* emptyValue = allocateExpressionValue(NULL, NULL);
emptyValue->setFrom(header);
if(header->variant() == PROC_HEDR || header->variant() == FUNC_HEDR)
for(int i=0; i<((SgProcHedrStmt*)header)->numberOfParameters();++i)
inDefs.insert(make_pair(((SgProcHedrStmt*)header)->parameter(i), set<ExpressionValue*>()))
.first->second.insert(emptyValue);
return inDefs;
}
void expressionAnalyzer(SgFile *file, const map<string, vector<DefUseList>> &defUseByFunctions,
const map<string, CommonBlock*> &commonBlocks, const map<string, vector<FuncInfo*>> &allFuncInfo,
const vector<ParallelRegion*> &regions)
{
if(!overseer.isInited())
initOverseer(defUseByFunctions, commonBlocks, allFuncInfo);
int funcNum = file->numberOfFunctions();
__spf_print(PRINT_PROF_INFO, "functions num in file = %d\n", funcNum);
const string filename = file->filename();
auto itRep = replacementsInFiles.find(filename);
if (itRep == replacementsInFiles.end())
itRep = replacementsInFiles.insert(itRep, make_pair(filename, map<SgStatement*, vector<SgExpression*>>()));
else // replecemets are have been made already
{
revertReplacements(filename);
return;
}
curFileReplacements = &(itRep->second);
for (int i = 0; i < funcNum; ++i)
{
SgStatement *st = file->functions(i);
if (isInParallelRegion(st, regions) == false)
{
__spf_print(1, " skip function '%s\n", st->symbol()->identifier());
continue;
}
if (st->variant() == PROG_HEDR)
{
SgProgHedrStmt *progH = (SgProgHedrStmt*) st;
__spf_print(PRINT_PROF_INFO, "*** Program <%s> started at line %d / %s\n", progH->symbol()->identifier(), st->lineNumber(), st->fileName());
}
else if (st->variant() == PROC_HEDR)
{
SgProcHedrStmt *procH = (SgProcHedrStmt*) st;
__spf_print(PRINT_PROF_INFO, "*** Function <%s> started at line %d / %s\n", procH->symbol()->identifier(), st->lineNumber(), st->fileName());
}
else if (st->variant() == FUNC_HEDR)
{
SgFuncHedrStmt *funcH = (SgFuncHedrStmt*) st;
__spf_print(PRINT_PROF_INFO, "*** Function <%s> started at line %d / %s\n", funcH->symbol()->identifier(), st->lineNumber(), st->fileName());
}
GraphsKeeper* gk = GraphsKeeper::getGraphsKeeper();
replaceConstants(filename, st);
ControlFlowGraph* CGraph = gk->buildGraph(st)->CGraph;
auto inDefs = createHeaderInDefs(st);
ExpandExpressions(CGraph, inDefs);
__spf_print(PRINT_PROF_INFO, "%u total substitutions\n", substitutionsCounter);
}
for (auto &stmt : *curFileReplacements)
{
for (int i = 0; i < 3; ++i)
{
auto expr = stmt.first->expr(i);
if (expr)
{
calculate(expr);
stmt.first->setExpression(i, *expr);
}
}
}
const string fileName = file->filename();
int fileId = -1;
for (SgStatement* st = file->firstStatement(); st; st = st->lexNext())
{
if (st->fileName() == fileName)
{
fileId = st->getFileId();
break;
}
}
if (fileId != -1)
deleteAllocatedExpressionValues(fileId);
}
void runPrivateAnalysis(SgStatement *main)
{
if (main->variant() != PROG_HEDR)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
GraphsKeeper *gk = GraphsKeeper::getGraphsKeeper();
GraphItem *gItem = gk->getGraph(main);
ControlFlowGraph *graph = gItem->CGraph;
if (gItem->privateDone == false)
{
graph->privateAnalyzer();
gItem->privateDone = true;
}
}