Files
SAPFOR/src/ExpressionTransform/control_flow_graph_part.cpp

1571 lines
49 KiB
C++
Raw Normal View History

2023-09-14 19:43:13 +03:00
#include "../Utils/leak_detector.h"
#include "dvm.h"
#include "acc_analyzer.h"
#include "expr_transform.h"
#include <stack>
#include <chrono>
#define PRINT_PROF_INFO 0
using std::string;
using std::vector;
using std::map;
using std::list;
using std::make_pair;
using std::set;
using std::pair;
using std::stack;
using std::chrono::high_resolution_clock;
using std::chrono::duration_cast;
using std::chrono::milliseconds;
void showDefs(set<ExpressionValue*> *defs);
void showDefs(map<SymbolKey, ExpressionValue*> *defs);
void showDefs(map<SymbolKey, set<ExpressionValue*>> *defs);
void showDefs(map<SymbolKey, SgExpression*> *defs);
static void showDefs(map <SymbolKey, set<SgExpression*>> *defs);
static CommonVarsOverseer *overseerPtr = NULL;
//static map<string, ExpressionValue*> allocated;
static map<int, set<ExpressionValue*>> allocated2;
static const char* unknownValueChars = "unknownValue";
static set<ExpressionValue> usedVariablesInStatement(SgStatement *st, set<string> &privates) {
stack<SgExpression*> toCheck;
set<ExpressionValue> result;
for(int i=0;i<3;++i)
if(st->expr(i))
toCheck.push(st->expr(i));
while(!toCheck.empty()) {
SgExpression* top = toCheck.top();
toCheck.pop();
if(top->variant() == VAR_REF)
result.insert(ExpressionValue(top, top->unparse()));
if(top->variant() == ARRAY_REF) {
if(privates.find(top->symbol()->identifier()) != privates.end())
result.insert(ExpressionValue(top, top->unparse()));
}
if (top->rhs())
toCheck.push(top->rhs());
if (top->lhs())
toCheck.push(top->lhs());
}
return result;
}
static void addDefinitionReachesStatement(map<SgStatement*, pair<set<SgStatement*>, set<SgStatement*>>>& result, SgStatement* definition, SgStatement* reachesHere)
{
//this depends on
auto found_r = result.find(reachesHere);
if (found_r == result.end())
{
pair<set<SgStatement*>, set<SgStatement*>> newPair;
newPair.first = set<SgStatement*>();
newPair.second = set<SgStatement*>();
newPair.first.insert(definition);
result.insert(found_r, make_pair(reachesHere, newPair));
}
else
found_r->second.first.insert(definition);
//this used in
auto found_d = result.find(definition);
if(found_d == result.end())
{
pair<set<SgStatement*>, set<SgStatement*>> newPair;
newPair.first = set<SgStatement*>();
newPair.second = set<SgStatement*>();
newPair.second.insert(reachesHere);
result.insert(found_d, make_pair(definition, newPair));
}
else
found_d->second.second.insert(reachesHere);
}
static bool checkSymbolUsedByProcsAndFuncs(SgStatement *st, const ExpressionValue &symbol, map<SymbolKey, set<ExpressionValue>> &arraysAssingments, vector <ControlFlowItem*> &cfis) {
if(cfis.size() == 0)
findCFIsForStmt(st, cfis);
for(ControlFlowItem *cfi : cfis) {
AnalysedCallsList *callData = cfi->getCall();
SgFunctionCallExp *funcCall = NULL;
if (((st = cfi->getStatement()) != NULL) && (st->variant() == PROC_STAT))
{
SgCallStmt *callStmt = isSgCallStmt(st);
for (int i = 0; i < callStmt->numberOfArgs(); ++i)
{
SgExpression *arg = callStmt->arg(i);
if ((arg->variant() == VAR_REF /*|| arg->variant() == ARRAY_REF*/) && argIsUsed(i, callData)) {
if(strcmp(symbol.getExp()->symbol()->identifier(), arg->symbol()->identifier())) {
// printf("in %d ", st->lineNumber());
// printf(" %s is required\n", arg->unparse());
return true;
}
}
}
}
else if ((funcCall = cfi->getFunctionCall()) != NULL)
{
for (int i = 0; i < funcCall->numberOfArgs(); ++i)
{
SgExpression *arg = funcCall->arg(i);
if ((arg->variant() == VAR_REF /*|| arg->variant() == ARRAY_REF*/) && argIsUsed(i, callData)) {
if(strcmp(symbol.getExp()->symbol()->identifier(), arg->symbol()->identifier())) {
// printf("in %d ", st->lineNumber());
// printf(" %s is required\n", arg->unparse());
return true;
}
}
}
}
}
return false;
}
/**
* symbol упоминается в st. Нужно проверить, что значение symbol действительно важно в st.
* Например для оператора x = 7; значение x не важно, а для x = x + 2 - важно
* symbol - это ExpressionValue из SgExpression у которого есть symbol()
*/
static bool symbolIsUsed(SgStatement *st, const ExpressionValue &symbol, map<SymbolKey, set<ExpressionValue>> &arraysAssingments, vector <ControlFlowItem*> &cfis) {
stack<SgExpression*> toCheck;
if(checkSymbolUsedByProcsAndFuncs(st, symbol, arraysAssingments, cfis)) {
// if(st->lineNumber() == 345/* || st->lineNumber() == 301*/)
// printf("from func true\n");
return true;
}
SgExpression *lval = st->expr(0);
if(lval)
{
if(st->variant() == ASSIGN_STAT)
{
if(lval->rhs())
toCheck.push(lval->rhs());
if(lval->lhs())
toCheck.push(lval->lhs());
}
else
toCheck.push(lval);
}
for(int i=1;i<3;++i)
if(st->expr(i))
toCheck.push(st->expr(i));
while(!toCheck.empty()) {
SgExpression* top = toCheck.top();
toCheck.pop();
if(top->variant() == VAR_REF)
if(symbol.getUnparsed() == top->symbol()->identifier()) {
// if(st->lineNumber() == 345 || st->lineNumber() == 301)
// printf("%s == %s is true\n", symbol.getUnparsed().c_str(), top->symbol()->identifier());
return true;
}
//TODO arraysAssignments
/*
if(top->variant() == ARRAY_REF) {
if(symbol.getUnparsed() == top->unparse())
return true;
}*/
//Не лезть проверять индексы массивов
if(top->variant() != ARRAY_REF) {
SgExpression *rhs = top->rhs();
SgExpression *lhs = top->lhs();
if (rhs && rhs->variant() != FUNC_CALL)
toCheck.push(rhs);
if (lhs && lhs->variant() != FUNC_CALL)
toCheck.push(lhs);
}
}
return false;
}
static void updateArraysAssingments(map<SymbolKey, set<ExpressionValue>> &arraysAssingments, map<SymbolKey, set<ExpressionValue*>> &definitions, SgStatement* cur)
{
for(auto it : definitions)
for(auto itt : it.second)
if(itt->getUnparsed() == unknownValueChars)
{
auto founded = arraysAssingments.find(it.first);
if(founded != arraysAssingments.end()) {
// for(auto fit : founded->second)
// delete fit;
arraysAssingments.erase(it.first);
}
}
if(cur->variant() == ASSIGN_STAT)
{
SgExpression *var = cur->expr(0);
if(var->variant() == ARRAY_REF)
{
auto founded = arraysAssingments.find(var->symbol());
string unp = var->unparse();
ExpressionValue expVal = ExpressionValue(var, unp);
if(founded == arraysAssingments.end())
arraysAssingments.insert(founded, make_pair(var->symbol(), set<ExpressionValue>()))->second.insert(expVal );
else
founded->second.insert(expVal);
}
}
}
/**
* Построить мап с зависимостями:
* <Оператор от Х : пара<сет зависящих от Х операторов : сет используюемых в Х операторов>>
* с since включительно, по till не включительно
*/
map<SgStatement*, pair<set<SgStatement*>, set<SgStatement*>>> buildRequireReachMapForLoop(SgStatement *since, SgStatement *till, set<string> &privates) {
int sinceLine = since->lineNumber();
int tillLine = till->lineNumber();
map<SgStatement*, pair<set<SgStatement*>, set<SgStatement*>>> result;
map<SymbolKey, set<ExpressionValue>> arraysAssingments;
for(SgStatement* cur = since; cur != till; cur = cur->lexNext())
{
auto definitions = getReachingDefinitionsExt(cur);
updateArraysAssingments(arraysAssingments, definitions, cur);
auto usedVariables = usedVariablesInStatement(cur, privates);
vector <ControlFlowItem*> cfis;
/*
printf("after %d:\n", cur->lineNumber());
for(auto it : arraysAssingments)
{
printf(" %s: ", it.first.getVarName().c_str());
for(auto itt : it.second)
printf("%s, ", itt.getUnparsed().c_str());
printf("\n");
}
*/
for(auto& var : usedVariables)
{
/* if(cur->lineNumber() == 127) {
printf("checking %d for %s %s\n",cur->lineNumber(), var.getUnparsed().c_str(), cur->unparse());
}*/
if(symbolIsUsed(cur, var, arraysAssingments, cfis))
{
/* if(cur->lineNumber() == 127) {
printf("%s is used\n", var.getUnparsed().c_str());
}*/
auto expressions = definitions.find(var.getExp()->symbol());
if (expressions != definitions.end())
{
for (ExpressionValue* expValue : expressions->second)
{
SgStatement *def = expValue->getFrom();
if (def->lineNumber() >= sinceLine && def->lineNumber() <= tillLine && def->lineNumber() != cur->lineNumber()) {
addDefinitionReachesStatement(result, def, cur);
/* if(cur->lineNumber() == 127)
printf("connected to %s\n", def->unparse());*/
}
}
}
}
}
}
/*
for(auto& it : result) {
printf("st: %d:\n",it.first->lineNumber());
printf("Depends on:\n");
for(auto& itt : it.second.first)
printf("%d ", itt->lineNumber());
printf("\n");
printf("Used in:\n");
for(auto& itt : it.second.second)
printf("%d ", itt->lineNumber());
printf("\n");
printf("\n");
}*/
return result;
}
bool symbolInExpression(const SymbolKey &symbol, SgExpression *exp)
{
bool result = false;
if (exp)
{
if (exp->variant() == VAR_REF)
return (symbol == exp->symbol());
if(exp->variant() == ARRAY_REF && symbol == exp->symbol())
return true;
bool hasSymbol = false;
if (exp->rhs())
hasSymbol |= symbolInExpression(symbol, exp->rhs());
if (exp->lhs())
hasSymbol |= symbolInExpression(symbol, exp->lhs());
result |= hasSymbol;
}
return result;
}
ExpressionValue* allocateExpressionValue(SgExpression* newExp, SgStatement* from)
{
string unp = (newExp == NULL) ? unknownValueChars : string(newExp->unparse());
int file_id = from == NULL ? current_file_id : from->getFileId();
auto allocatedMap = allocated2.find(file_id);
if(allocatedMap == allocated2.end())
allocatedMap = allocated2.insert(allocatedMap, make_pair(file_id, set<ExpressionValue*>()));
for(ExpressionValue* expVal : allocatedMap->second)
if(expVal->getUnparsed() == unp && expVal->getFrom() == from)
return expVal;
ExpressionValue* newExpVal = new ExpressionValue(newExp, unp, from);
allocatedMap->second.insert(newExpVal);
return newExpVal;
/* auto alloc = allocatedMap->second.find(unp);
if (alloc == allocatedMap->second.end())
newExpVal = allocatedMap->second.insert(alloc, make_pair(unp, new ExpressionValue(newExp, unp, from)))->second;
else
newExpVal = alloc->second;
*/
/* auto alloc = allocated.find(unp);
if (alloc == allocated.end())
newExpVal = allocated.insert(alloc, make_pair(unp, new ExpressionValue(newExp, unp, from)))->second;
else
newExpVal = alloc->second;
*/
// return newExpVal;//new ExpressionValue(newExp, unp, from);
}
void CBasicBlock::addVarToGen(SymbolKey var, SgExpression *value, SgStatement *defSt)
{
addVarToKill(var);
ExpressionValue* expVal = allocateExpressionValue(value, defSt);
e_gen.insert(expVal);
gen.insert(make_pair(var, expVal));
// saveDefinitionStatement(var, expVal, defSt);
}
void CBasicBlock::addVarUnknownToGen(SymbolKey var, SgStatement *defSt) {
addVarToKill(var);
ExpressionValue* expVal = allocateExpressionValue(NULL, defSt);
gen.insert(make_pair(var, expVal));
// saveDefinitionStatement(var, expVal, defSt);
}
void CBasicBlock::addVarToKill(const SymbolKey &key)
{
kill.insert(key);
for (auto it = gen.begin(); it != gen.end();)
if (it->first == key)
it = gen.erase(it);
else
++it;
for (auto it = e_gen.begin(); it != e_gen.end();)
if (symbolInExpression(key, (*it)->getExp()))
it = e_gen.erase(it);
else
++it;
}
bool argIsUsed(int i, AnalysedCallsList *callData)
{
// AnalysedCallsList == -1 or -2 if no user procedure/subroutine found
if (callData == NULL || (AnalysedCallsList*)(-1) == callData || (AnalysedCallsList*)(-2) == callData)
return true;
int stored = SwitchFile(callData->file_id);
SgProcHedrStmt *header = isSgProcHedrStmt(callData->header);
SgSymbol *currPar = NULL;
if (header)
currPar = header->parameter(i);
SwitchFile(stored);
if (header == NULL)
return false;
if (header->parameter(i) == NULL)
return false;
int attr = currPar->attributes();
bool isArgOut = callData->isArgOut(i, NULL);
bool isArgIn = callData->isArgIn(i, NULL);
if(((attr & (IN_BIT)) || (attr & (INOUT_BIT))) || isArgIn) //argument used in procedure
return true;
else
return false;
}
bool argIsReplaceable(int i, AnalysedCallsList *callData)
{
// AnalysedCallsList == -1 or -2 if no user procedure/subroutine found
if (callData == NULL || (AnalysedCallsList*)(-1) == callData || (AnalysedCallsList*)(-2) == callData)
return false;
int stored = SwitchFile(callData->file_id);
SgProcHedrStmt *header = isSgProcHedrStmt(callData->header);
SgSymbol *currPar = NULL;
if (header)
currPar = header->parameter(i);
SwitchFile(stored);
if (header == NULL)
return false;
if (header->parameter(i) == NULL)
return false;
int attr = currPar->attributes();
bool isArgOut = callData->isArgOut(i, NULL);
bool isArgIn = callData->isArgIn(i, NULL);
if ((attr & (OUT_BIT)) || (attr & (INOUT_BIT)) || isArgOut) //argument modified inside procedure
return false;
else if (!((attr & (IN_BIT)) || isArgIn)) // no information, assume that argument is "inout"
return false;
else
return true;
}
void CBasicBlock::checkFuncAndProcCalls(ControlFlowItem *cfi)
{
SgStatement *st = NULL;
AnalysedCallsList *callData = cfi->getCall();
SgFunctionCallExp *funcCall = NULL;
set<SgSymbol*> *varsToKill = NULL;
if (((st = cfi->getStatement()) != NULL) && (st->variant() == PROC_STAT))
{
SgCallStmt *callStmt = isSgCallStmt(st);
for (int i = 0; i < callStmt->numberOfArgs(); ++i)
{
SgExpression *arg = callStmt->arg(i);
if ((arg->variant() == VAR_REF || arg->variant() == ARRAY_REF) && (!argIsReplaceable(i, callData)))
addVarUnknownToGen(arg->symbol(), st);
}
varsToKill = overseerPtr->killedVars(callStmt->symbol()->identifier());
}
else if ((funcCall = cfi->getFunctionCall()) != NULL)
{
for (int i = 0; i < funcCall->numberOfArgs(); ++i)
{
SgExpression *arg = funcCall->arg(i);
if ((arg->variant() == VAR_REF || arg->variant() == ARRAY_REF) && (!argIsReplaceable(i, callData)))
addVarUnknownToGen(arg->symbol(), cfi->getOriginalStatement());
}
varsToKill = overseerPtr->killedVars(funcCall->symbol()->identifier());
}
if (varsToKill)
for (auto var : *varsToKill)
addVarUnknownToGen(var, cfi->getStatement());
}
set<SymbolKey>* CBasicBlock::getOutVars()
{
set<SymbolKey> *outVars = new set<SymbolKey>();
for (auto elem : out_defs)
outVars->insert(elem.first);
return outVars;
}
bool CBasicBlock::varIsPointer(SgSymbol *symbol)
{
if (symbol == NULL)
return false;
auto found = parent->getPointers()->find(symbol);
if(found != parent->getPointers()->end())
return true;
return false;
}
void CBasicBlock::processAssignThroughPointer(SgSymbol *symbol, SgExpression *right, SgStatement* st)
{
//printf("processAssignThroughPointer REBUILD?!\n");
auto found = gen.find(symbol);
if (found != gen.end())
{
addVarToGen(found->second->getExp()->symbol(), right, st);
return;
}
auto found_inDefs = in_defs.find(symbol);
if (found_inDefs != in_defs.end())
{
for (auto& value : found_inDefs->second)
addVarUnknownToGen(value->getExp()->symbol(), st);
}
}
void CBasicBlock::processPointerAssignment(SgSymbol *symbol, SgExpression *right, SgStatement* st)
{
//TODO: Record_Ref
if (symbol == NULL)
return;
//right is a single VAR_REF
SgSymbol *rSymbol = right->symbol();
parent->getPointers()->insert(SymbolKey(symbol, true));
if(varIsPointer(rSymbol))
{
auto found = gen.find(rSymbol);
//auto found_inDefsP = in_defs_p.find(rSymbol);
if(found != gen.end())
addVarToGen(SymbolKey(symbol, true), found->second->getExp(), st);
//else if(found_inDefsP != in_defs_p.end())
//addVarToGenP(SymbolKey(symbol, true), found_inDefsP->second);
}
else
addVarToGen(SymbolKey(symbol, true), right, st);
}
void CBasicBlock::adjustGenAndKillP(ControlFlowItem *cfi)
{
SgStatement *st = cfi->getStatement();
if (st != NULL)
{
SgExpression *left = st->expr(0);
SgExpression *right = st->expr(1);
if (st->variant() == POINTER_ASSIGN_STAT)
processPointerAssignment(left->symbol(), right, st);
}
//checkFuncAndProcCalls(cfi);
}
void CBasicBlock::processReadStat(SgStatement *readSt)
{
SgExpression *input = readSt->expr(0);
std::stack<SgExpression*> toCheck;
if (input)
toCheck.push(input);
while (!toCheck.empty())
{
SgExpression *exp = toCheck.top();
toCheck.pop();
if (exp->variant() == VAR_REF || exp->variant() == ARRAY_REF)
addVarToGen(exp->symbol(), NULL, readSt);
//addVarToKill(exp->symbol());
else
{
if (exp->rhs())
toCheck.push(exp->rhs());
if (exp->lhs())
toCheck.push(exp->lhs());
}
}
}
void CBasicBlock::adjustGenAndKill(ControlFlowItem *cfi)
{
SgStatement *st = cfi->getStatement();
if (st != NULL)
{
SgExpression *left = st->expr(0);
SgExpression *right = st->expr(1);
if (st->variant() == ASSIGN_STAT)
{
if (left->variant() == VAR_REF) // x = ...
{
if (varIsPointer(left->symbol()))
processAssignThroughPointer(left->symbol(), right, st);
else
addVarToGen(left->symbol(), right, st);
}
else if (left->variant() == ARRAY_REF) // a(...) = ...
addVarToGen(left->symbol(), right, st);
}
else if(st->variant() == READ_STAT)
processReadStat(st);
else if (st->variant() == POINTER_ASSIGN_STAT)
processPointerAssignment(left->symbol(), right, st);
}
checkFuncAndProcCalls(cfi);
}
bool CBasicBlock::expressionIsAvailable(ExpressionValue* expValue) {
for(auto it = e_gen.begin(); it != e_gen.end(); ++it)
if(**it == *expValue)
return true;
for(auto it = e_in.begin(); it != e_in.end(); ++it)
if(**it == *expValue)
{
bool killed = false;
for(auto killIt = kill.begin(); killIt != kill.end(); ++killIt)
if(symbolInExpression(*killIt, expValue->getExp()))
{
killed = true;
break;
}
if(!killed)
return true;
}
return false;
}
const map<SymbolKey, set<ExpressionValue*>> CBasicBlock::getReachedDefinitionsExt(SgStatement *stmt)
{
ControlFlowItem *cfi = getStart();
ControlFlowItem *till = getEnd()->getNext();
clearGenKill();
bool founded = false;
while (cfi != till)
{
if (cfi->getStatement() == stmt || cfi->getOriginalStatement() == stmt)
{
founded = true;
break;
}
adjustGenAndKill(cfi);
cfi = cfi->getNext();
}
map<SymbolKey, set<ExpressionValue*>> defs;
if (founded)
{
for (auto &it : in_defs)
{
if (kill.find(it.first) == kill.end())
{
auto founded = defs.find(it.first);
if (founded == defs.end())
founded = defs.insert(founded, make_pair(it.first, set<ExpressionValue*>()));
for (auto &exp : it.second)
founded->second.insert(exp);
}
}
for(auto &it : gen)
defs.insert(make_pair(it.first, set<ExpressionValue*>())).first->second.insert(it.second);
}
/*
for(auto it : defs) {
printf("%s: ", it.first.getVarName().c_str());
for(auto itt : it.second)
printf("%s, ", itt->getUnparsed().c_str());
printf("\n");
}
*/
return defs;
}
size_t max1 = 0;
size_t min1 = 0;
size_t max2 = 0;
size_t min2 = 0;
size_t countMerge = 0;
static bool mergeExpressionMaps(set<ExpressionValue*> &main, set<ExpressionValue*> &term)
{
#if PRINT_PROF_INFO
++countMerge;
max1 = std::max(max1, main.size());
max2 = std::max(max2, term.size());
min1 = std::min(min1, main.size());
min2 = std::min(min2, term.size());
#endif
size_t mainSize = main.size();
main.insert(term.begin(), term.end());
if(main.size() != mainSize)
return true;
return false;
}
static void mergeDefs(map<SymbolKey, set<ExpressionValue*>> *main, map<SymbolKey, set<ExpressionValue*>> *term, set<SymbolKey> *allowedVars)
{
for (auto &toCheck : *term)
{
if (!allowedVars || (allowedVars && allowedVars->find(toCheck.first) != allowedVars->end()))
{
auto founded = main->find(toCheck.first);
if (founded == main->end())
main->insert(founded, toCheck);
else if (founded != main->end())
mergeExpressionMaps(founded->second, toCheck.second);
}
}
}
void CBasicBlock::initializeOut()
{
for (auto &elem : gen)
{
SgExpression *newExp = NULL;
if (elem.second)
{
auto inserted = out_defs.find(elem.first);
if (inserted == out_defs.end())
inserted = out_defs.insert(inserted, make_pair(elem.first, set<ExpressionValue*>()));
inserted->second.insert(elem.second);
}
}
}
void CBasicBlock::initializeEOut(set<ExpressionValue*>& allEDefs)
{
e_in.insert(allEDefs.begin(), allEDefs.end()); //чтобы потом только уменьшать при пересечении
if(getPrev() != NULL) //OUT[first] = empty
e_out.insert(allEDefs.begin(), allEDefs.end());
}
bool CBasicBlock::updateEDefs()
{
//IN == intersection of all prev OUT
for (BasicBlockItem *prev = getPrev(); prev != NULL; prev = prev->next)
{
CBasicBlock *b = prev->block;
for(auto it = e_in.begin(); it != e_in.end();)
if(b->e_out.find(*it) == b->e_out.end())
it = e_in.erase(it);
else
++it;
}
int out_size = e_out.size();
//OUT = e_gen обеъденить c (IN - kill)
e_out.clear();
e_out.insert(e_gen.begin(), e_gen.end());
for(auto it = e_in.begin(); it != e_in.end(); ++it)
{
bool killed = false;
for(auto killIt = kill.begin(); killIt != kill.end(); ++killIt)
if(symbolInExpression(*killIt, (*it)->getExp()))
{
killed = true;
break;
}
if(!killed)
e_out.insert(*it);
}
if(out_size != e_out.size())
return true;
return false;
}
static bool addDefsFilteredByKill(map<SymbolKey, set<ExpressionValue*>> *main,
map<SymbolKey, set<ExpressionValue*>> *defs, set<SymbolKey> *kill)
{
bool mainChanged = false;
for (auto it = defs->begin(); it != defs->end(); ++it)
{
SymbolKey key = it->first;
if (kill->find(key) != kill->end())
continue;
auto founded = main->find(key);
if (founded == main->end())
{
main->insert(make_pair(key, it->second));
mainChanged = true;
}
else
mainChanged |= mergeExpressionMaps(founded->second, it->second);
}
return mainChanged;
}
void showDefs(map<SymbolKey, set<ExpressionValue*>> *defs)
{
printf("Defs: %d\n", (int)defs->size());
for (auto it = defs->begin(); it != defs->end(); ++it)
{
if (it->first.isPointer())
printf("--- %s => ", it->first.getVarName().c_str());
else
printf("--- %s = ", it->first.getVarName().c_str());
for (auto iter = it->second.begin(); iter != it->second.end(); ++iter)
{
printf("%s", (*iter)->getUnparsed().c_str());
if (iter != it->second.end())
printf(", ");
}
printf("\n");
}
printf("\n");
}
void showDefs(set<ExpressionValue*> *defs)
{
printf("Defs: %d\n", (int)defs->size());
printf(" ");
for (auto it = defs->begin(); it != defs->end(); ++it)
{
printf("%s, ", (*it)->getUnparsed().c_str());
}
printf("\n");
}
void showDefs(map<SymbolKey, ExpressionValue*> *defs)
{
printf("Defs: %d\n", (int)defs->size());
for (auto it = defs->begin(); it != defs->end(); ++it)
{
if(it->first.isPointer())
printf("--- %s => %s", it->first.getVarName().c_str(), it->second->getUnparsed().c_str());
else
printf("--- %s = %s", it->first.getVarName().c_str(), it->second->getUnparsed().c_str());
printf("\n");
}
printf("\n");
}
void showDefs(map<SymbolKey, SgExpression*> *defs)
{
printf("Defs: %d\n", (int)defs->size());
for (auto it = defs->begin(); it != defs->end(); ++it)
{
if(it->first.isPointer())
printf("--- %s => %s", it->first.getVarName().c_str(), it->second == NULL ? "value is undefined" : it->second->unparse());
else
printf("--- %s = %s", it->first.getVarName().c_str(), it->second == NULL ? "value is undefined" : it->second->unparse());
printf("\n");
}
printf("\n");
}
static void showDefs(map <SymbolKey, set<SgExpression*>> *defs)
{
printf("Defs: %d\n", (int)defs->size());
for(auto it = defs->begin(); it != defs->end(); ++it)
{
printf("--- %s = ", it->first.getVarName().c_str());
for(auto itt = it->second.begin(); itt != it->second.end(); ++itt)
printf("%s, ", (*itt)->unparse());
printf("\n");
}
printf("\n");
}
void debugStructure(ControlFlowGraph *CGraph, const string &filename)
{
CBasicBlock *b = CGraph->getFirst();
printf("strict digraph {\n");
while (b != NULL)
{
printf("\"%s_%d\" [shape = box, label = \"%s_%d\n", b->getProc()->funName, b->getNum(), b->getProc()->funName, b->getNum());
bool printed = false;
ControlFlowItem *cfi = b->getStart();
ControlFlowItem *till = b->getEnd()->getNext();
while (cfi != till)
{
if (cfi->getStatement())
{
printed = true;
printf("%d ", cfi->getStatement()->lineNumber());
printf("%s\n", cfi->getStatement()->unparse());
}
else if(cfi->getOriginalStatement())
{
SgStatement *origSt = cfi->getOriginalStatement();
if(origSt->variant() == IF_NODE)
{
printed = true;
printf("%d ", origSt->lineNumber());
printf("If: (%s)\n", ((SgIfStmt*) origSt)->conditional()->unparse());
}
}
cfi = cfi->getNext();
}
if (!printed)
{
SgStatement* origStmt = NULL;
cfi = b->getStart();
while (cfi != till)
{
if ((origStmt = cfi->getOriginalStatement()) != NULL)
{
printed = true;
printf("Original: %s\n", origStmt->unparse());
}
cfi = cfi->getNext();
}
}
printf("\"];\n");
for (BasicBlockItem *prev = b->getPrev(); prev != NULL; prev = prev->next)
printf("\"%s_%d\" -> \"%s_%d\";\n", prev->block->getProc()->funName, prev->block->getNum(), b->getProc()->funName, b->getNum());
printf("\n");
b = b->getLexNext();
}
printf("}\n");
}
void showDefsOfGraph(ControlFlowGraph *CGraph)
{
CBasicBlock *b = CGraph->getFirst();
while (b != NULL)
{
printf("\n\nBlock %d, prev: ", b->getNum());
for (BasicBlockItem *prev = b->getPrev(); prev != NULL; prev = prev->next)
printf("%d, ", prev->block->getNum());
printf("\n");
bool printed = false;
ControlFlowItem *cfi = b->getStart();
ControlFlowItem *till = b->getEnd()->getNext();
while (cfi != till)
{
if (cfi->getStatement())
{
printed = true;
printf("%d ", cfi->getStatement()->lineNumber());
cfi->getStatement()->unparsestdout();
}
else if(cfi->getOriginalStatement())
{
SgStatement *origSt = cfi->getOriginalStatement();
if(origSt->variant() == IF_NODE)
{
printed = true;
printf("%d ", origSt->lineNumber());
printf("If: (%s)\n", ((SgIfStmt*) origSt)->conditional()->unparse());
}
}
cfi = cfi->getNext();
}
if (!printed)
{
SgStatement* origStmt = NULL;
cfi = b->getStart();
while (cfi != till)
{
if ((origStmt = cfi->getOriginalStatement()) != NULL)
{
printed = true;
printf("Original: ");
origStmt->unparsestdout();
}
cfi = cfi->getNext();
}
}
if (printed)
{
printf("\n In ");
showDefs(b->getInDefs());
printf("\n Gen");
showDefs(b->getGen());
printf("\n E Gen");
showDefs(b->getEGen());
printf("\n Kill %d\n ", (int)b->getKill()->size());
for (auto it = b->getKill()->begin(); it != b->getKill()->end(); ++it)
printf("%s ", it->getVarName().c_str());
printf("\n");
printf("\n Out ");
showDefs(b->getOutDefs());
printf("\n E In ");
showDefs(b->getEIn());
printf("\n E Out ");
showDefs(b->getEOut());
}
b = b->getLexNext();
}
}
void ClearCFGInsAndOutsDefs(ControlFlowGraph *CGraph)
{
int64_t memCount = 0;
int64_t elemCount = 0;
int64_t elemCount1 = 0;
CBasicBlock *b = CGraph->getFirst();
while (b != NULL)
{
#if PRINT_PROF_INFO
auto gen = b->getGen();
for (auto &elem : *gen)
{
memCount += elem.first.getVarName().size() + sizeof(SgExpression*);
++elemCount;
elemCount1 += 2;
}
auto in_def = b->getInDefs();
for (auto &elem : *in_def)
{
memCount += elem.first.getVarName().size() + elem.second.size() * sizeof(ExpressionValue*);
++elemCount;
elemCount1 = elemCount1 + 1 + elem.second.size();
}
auto out_def = b->getOutDefs();
for (auto &elem : *out_def)
{
memCount += elem.first.getVarName().size() + elem.second.size() * sizeof(ExpressionValue*);
++elemCount;
elemCount1 = elemCount1 + 1 + elem.second.size();
}
#endif
b->clearGenKill();
b->clearDefs();
b = b->getLexNext();
}
/*int64_t countS = 0;
for (auto &elem : allocated)
{
#if PRINT_PROF_INFO
countS += elem.second->getUnparsed().size();
#endif
if (elem.second->getUnparsed() != "")
delete elem.second;
}
#if PRINT_PROF_INFO
if (allocated.size())
__spf_print(1, " count of elem %lld, in MB %f, info %lld in MB %f, elemCount = %d, elemCount1 = %d\n",
countS, (double)countS / 1024. / 1024., memCount, double(memCount) / 1024./1024., elemCount, elemCount1);
#endif
*/
//allocated.clear();
}
void deleteAllocatedExpressionValues(int file_id) {
auto fa = allocated2.find(file_id);
if(fa != allocated2.end())
for(auto &elem : fa->second)
delete elem;
// delete elem.second;0
allocated2.clear();
}
//TODO
//TODO
//TODO вернуть true если GEN изменился
bool BuildGenKillAndUpdateOutP(ControlFlowGraph* CGraph)
{
CBasicBlock* b = CGraph->getFirst();
while (b != NULL)
{
ControlFlowItem *cfi = b->getStart();
ControlFlowItem *till = b->getEnd()->getNext();
while (cfi != till)
{
b->adjustGenAndKillP(cfi);
cfi = cfi->getNext();
}
b = b->getLexNext();
//Обновить OUT
b->getOutDefsP();
}
return false;
}
/*
* Отдельная подготовка достигающих определений для указателей.
* Она не может быть проведена вместе с быной т.к. GEN для указателей зависит от IN.
* Всё также, только GEN обновляется на каждой итерации.
*/
void PreparePointers(ControlFlowGraph *CGraph)
{
bool setsChanged = true;
while (setsChanged)
{
setsChanged = false;
//Вычисление KILL и GEN, GEN могло измениться
setsChanged |= BuildGenKillAndUpdateOutP(CGraph);
CBasicBlock* b = CGraph->getFirst();
while (b != NULL)
{
/*Updating IN for pointers*/
for (BasicBlockItem* prev = b->getPrev(); prev != NULL; prev = prev->next)
mergeDefs(b->getInDefsP(), prev->block->getOutDefsP(), NULL);
/*Updating OUT for pointers, true, if OUT has been changed*/
setsChanged |= addDefsFilteredByKill(b->getOutDefsP(), b->getInDefsP(), b->getKillP());
b = b->getLexNext();
}
}
}
void FillCFGInsAndOutsDefs(ControlFlowGraph *CGraph, map<SymbolKey, set<ExpressionValue*>> *inDefs, CommonVarsOverseer *overseer_Ptr)
{
overseerPtr = overseer_Ptr;
CBasicBlock *b = CGraph->getFirst();
PreparePointers(CGraph);
b = CGraph->getFirst();
#if PRINT_PROF_INFO
auto time = high_resolution_clock::now();
#endif
set<ExpressionValue*> availableExpressions;
while (b != NULL)
{
ControlFlowItem *cfi = b->getStart();
ControlFlowItem *till = b->getEnd()->getNext();
while (cfi != till)
{
b->adjustGenAndKill(cfi);
cfi = cfi->getNext();
}
availableExpressions.insert(b->getEGen()->begin(), b->getEGen()->end());
/*Initialization of OUT, it equals to GEN */
b->initializeOut();
b = b->getLexNext();
}
b = CGraph->getFirst();
while(b != NULL)
{
b->initializeEOut(availableExpressions);
b = b->getLexNext();
}
#if PRINT_PROF_INFO
__spf_print(PRINT_PROF_INFO, " block 1 %f\n",
duration_cast<milliseconds>(high_resolution_clock::now() - time).count() / 1000.);
time = high_resolution_clock::now();
#endif
if (inDefs != NULL)
CGraph->getFirst()->setInDefs(inDefs);
double timeMerge = 0;
double timeAdd = 0;
bool setsChanged = true;
size_t countIn1 = 0;
countMerge = 0;
size_t countSet1 = 0;
size_t countSet2 = 0;
while (setsChanged)
{
setsChanged = false;
b = CGraph->getFirst();
while (b != NULL)
{
#if PRINT_PROF_INFO
auto locT = high_resolution_clock::now();
#endif
/*Updating IN*/
for (BasicBlockItem *prev = b->getPrev(); prev != NULL; prev = prev->next)
{
#if PRINT_PROF_INFO
countSet1 = std::max(countSet1, b->getInDefs()->size());
countSet2 = std::max(countSet2, prev->block->getOutDefs()->size());
countIn1++;
#endif
mergeDefs(b->getInDefs(), prev->block->getOutDefs(), NULL);
}
#if PRINT_PROF_INFO
timeMerge += (duration_cast<milliseconds>(high_resolution_clock::now() - locT).count() / 1000.);
locT = high_resolution_clock::now();
#endif
/*Updating OUT, true, if OUT has been changed*/
setsChanged |= addDefsFilteredByKill(b->getOutDefs(), b->getInDefs(), b->getKill());
#if PRINT_PROF_INFO
timeAdd += (duration_cast<milliseconds>(high_resolution_clock::now() - locT).count() / 1000.);
#endif
b = b->getLexNext();
}
}
#if PRINT_PROF_INFO
__spf_print(PRINT_PROF_INFO, " block 2 %f\n",
duration_cast<milliseconds>(high_resolution_clock::now() - time).count() / 1000.);
__spf_print(PRINT_PROF_INFO, " merge %f, count %d, MM [%lld, %lld] [%lld, %lld], merge call %lld, %lld %lld\n",
timeMerge, countIn1, min1, max1, min2, max2, countMerge, countSet1, countSet2);
__spf_print(PRINT_PROF_INFO, " add %f\n", timeAdd);
#endif
setsChanged = true;
while (setsChanged)
{
setsChanged = false;
b = CGraph->getFirst();
while (b != NULL)
{
setsChanged |= b->updateEDefs();
b = b->getLexNext();
}
}
//printf("[%s]: %s\n", tag[newDeclaration->variant()], newDeclaration->unparse());
/*Showtime*/
//showDefsOfGraph(CGraph);
}
bool valueWithRecursion(const SymbolKey &var, SgExpression *exp)
{
if (!exp)
return false;
if (exp->variant() == VAR_REF)
return var == exp->symbol();
bool recursionFounded = false;
if (exp->rhs())
recursionFounded = valueWithRecursion(var, exp->rhs());
if (exp->lhs() && !recursionFounded)
recursionFounded = valueWithRecursion(var, exp->lhs());
return recursionFounded;
}
bool valueWithFunctionCall(SgExpression *exp)
{
if (!exp)
return false;
if (exp->variant() == FUNC_CALL)
return true;
bool funcFounded = false;
if (exp->rhs())
funcFounded = valueWithFunctionCall(exp->rhs());
if (exp->lhs() && !funcFounded)
funcFounded = valueWithFunctionCall(exp->lhs());
return funcFounded;
}
static bool ifExprExist(SgExpression *curr, const int toFind)
{
if (curr)
{
if (curr->id() == toFind)
return true;
else
return ifExprExist(curr->lhs(), toFind) || ifExprExist(curr->rhs(), toFind);
}
return false;
}
static SgStatement* getStatmentByExpression(SgStatement* begin, SgExpression* ex)
{
SgStatement* start = begin ? begin : current_file->firstStatement();
SgStatement* end = NULL;
if (begin)
end = getFuncStat(begin, { MODULE_STMT })->lastNodeOfStmt();
for (auto st = start; st != end; st = st->lexNext())
{
for (int z = 0; z < 3; ++z)
if (ifExprExist(st->expr(z), ex->id()))
return st;
}
// if NULL found, try to find across full file
if (begin)
{
for (auto st = current_file->firstStatement()->lexNext(); st; st = st->lexNext())
for (int z = 0; z < 3; ++z)
if (ifExprExist(st->expr(z), ex->id()))
return st;
}
return NULL;
}
static void findFuncCall(SgExpression* ex, vector<SgExpression*>& calls)
{
if (ex)
{
if (ex->variant() == FUNC_CALL)
if (!isIntrinsicFunctionName(ex->symbol()->identifier()))
calls.push_back(ex);
findFuncCall(ex->rhs(), calls);
findFuncCall(ex->lhs(), calls);
}
}
static bool hasArrayRef(SgExpression* ex, const string& arrName)
{
bool retVal = false;
if (ex)
{
if (ex->variant() == ARRAY_REF && ex->symbol()->identifier() == arrName)
return true;
retVal |= hasArrayRef(ex->lhs(), arrName);
retVal |= hasArrayRef(ex->rhs(), arrName);
}
return retVal;
}
static bool checkRange(SgStatement *start, SgStatement *end, const DIST::Array* array)
{
const string arrName = array->GetShortName();
for (auto st = start; st != end; st = st->lexNext())
{
if (st->variant() == ASSIGN_STAT)
{
auto ex = st->expr(0);
if (ex->variant() == ARRAY_REF && ex->symbol()->identifier() == arrName)
return false;
}
else if (st->variant() == READ_STAT || st->variant() == WRITE_STAT || st->variant() == PRINT_STAT)
{
SgInputOutputStmt* s = isSgInputOutputStmt(st);
if (s)
if (hasArrayRef(s->itemList(), arrName))
return false;
}
else if (st->variant() == PROC_STAT)
{
for (auto args = st->expr(0); args; args = args->rhs())
{
if (args->lhs()->variant() == ARRAY_REF)
if (args->lhs()->symbol()->identifier() == arrName)
return false;
}
}
else
{
//TODO:
}
//find func call
vector<SgExpression*> calls;
for (int z = 0; z < 3; ++z)
if (st->expr(z))
findFuncCall(st->expr(z), calls);
for (auto& elem : calls)
{
for (auto args = elem->lhs(); args; args = args->rhs())
{
if (args->lhs()->variant() == ARRAY_REF)
if (args->lhs()->symbol()->identifier() == arrName)
return false;
}
}
if (calls.size())
{
if (array->GetLocation().first == DIST::l_MODULE || array->GetLocation().first == DIST::l_COMMON)
{
//TODO: need to add IP analysis
}
}
}
return true;
}
static map<SgSymbol*, pair<SgStatement*, DIST::Array*>> cache;
//TODO: improve for MODULE
static bool allowedArrayReference(SgExpression *exp, SgStatement* from)
{
//Must return false if exp is not allowed to be substituted
SgSymbol* arr = OriginalSymbol(exp->symbol());
checkNull(arr, convertFileName(__FILE__).c_str(), __LINE__);
SgStatement* decl = NULL;
DIST::Array* array = NULL;
auto it = cache.find(arr);
if (it != cache.end())
{
decl = it->second.first;
array = it->second.second;
}
if (!decl)
{
decl = declaratedInStmt(arr);
checkNull(decl, convertFileName(__FILE__).c_str(), __LINE__);
}
if (!array)
{
array = getArrayFromDeclarated(decl, arr->identifier());
checkNull(array, convertFileName(__FILE__).c_str(), __LINE__);
}
if (it == cache.end())
cache.insert(it, make_pair(arr, make_pair(decl, array)));
if (array->GetDistributeFlagVal() == DIST::SPF_PRIV)
return false;
SgStatement* st = NULL;
for (int z = 0; z < 3; ++z)
{
if (ifExprExist(from->expr(z), exp->id()))
{
st = from;
break;
}
}
if (st == NULL)
st = getStatmentByExpression(decl, exp);
checkNull(st, convertFileName(__FILE__).c_str(), __LINE__);
SgStatement* cp = st->controlParent();
SgStatement* prev = st;
while (isSgProgHedrStmt(cp) == NULL)
{
prev = cp;
cp = cp->controlParent();
}
auto last = prev->lastNodeOfStmt();
auto retVal = checkRange(cp, last, array);
return retVal;
}
bool valueWithArrayReference(SgExpression *exp, SgStatement* from)
{
if (!exp)
return false;
if (isArrayRef(exp))
return !allowedArrayReference(exp, from);
bool arrayFounded = false;
if (exp->rhs())
arrayFounded = valueWithArrayReference(exp->rhs(), from);
if (exp->lhs() && !arrayFounded)
arrayFounded = valueWithArrayReference(exp->lhs(), from);
return arrayFounded;
}
/*
* Can't expand var if:
* 1. it has multiple values
* 2. it is a NULL value
* 3. value has function call
* 4. value has itself within (recursion)
* 5. value has array reference
*/
void CBasicBlock::correctInDefsSimple()
{
for (auto it = in_defs.begin(); it != in_defs.end();)
{
if (it->second.size() != 1) //1
it = in_defs.erase(it);
else if((*(it->second.begin()))->getExp() == NULL)
it = in_defs.erase(it);
else if (valueWithFunctionCall((*(it->second.begin()))->getExp())) //3
it = in_defs.erase(it);
else if (valueWithRecursion(it->first, (*(it->second.begin()))->getExp())) //4
it = in_defs.erase(it);
else if(valueWithArrayReference((*(it->second.begin()))->getExp(), (*(it->second.begin()))->getFrom()))
it = in_defs.erase(it);
else
it++;
}
}
/*
* Can't expand var if
* value is not present in one of previous block
*/
bool CBasicBlock::correctInDefsIterative()
{
bool changed = false;
BasicBlockItem *bi = getPrev();
if (bi)
{
set<SymbolKey> *allowedVars = bi->block->getOutVars();
for (bi = bi->next; bi != NULL; bi = bi->next)
{
set<SymbolKey> *nextAllowedVars = bi->block->getOutVars();
for (auto it = allowedVars->begin(); it != allowedVars->end();)
{
if (nextAllowedVars->find(*it) == nextAllowedVars->end())
it = allowedVars->erase(it);
else
++it;
}
delete nextAllowedVars;
}
//Clean inDefs
for (auto it = in_defs.begin(); it != in_defs.end();)
if (allowedVars->find(it->first) == allowedVars->end())
it = in_defs.erase(it);
else
it++;
//Clean outDefs
vector<map<SymbolKey, set<ExpressionValue*>>::const_iterator> toDel;
for (auto it = out_defs.begin(); it != out_defs.end(); ++it)
if (allowedVars->find(it->first) == allowedVars->end()
&& gen.find(it->first) == gen.end())
toDel.push_back(it);
for (int i = 0; i < toDel.size(); ++i)
out_defs.erase(toDel[i]);
if (toDel.size() != 0)
changed = true;
delete allowedVars;
}
return changed;
}
void CorrectInDefs(ControlFlowGraph *CGraph)
{
CBasicBlock *b = CGraph->getFirst();
while (b != NULL)
{
b->correctInDefsSimple();
b = b->getLexNext();
}
/* bool changes = true;
while (changes)
{
changes = false;
b = CGraph->getFirst();
while (b != NULL)
{
changes |= b->correctInDefsIterative();
b = b->getLexNext();
}
}*/
}