#include "leak_detector.h" #if _WIN32 && NDEBUG && __SPF && __BOOST #include #endif extern int passDone; #include "dvm.h" #include #include #include #include #include #include #include #include #include #include #include "../ParallelizationRegions/ParRegions.h" #include "../ParallelizationRegions/ParRegions_func.h" #include "graph_loops.h" #include "graph_calls.h" #include "graph_calls_func.h" #include "utils.h" #include "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 key is a file, where replacements take place * map > 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>> replacementsOfConstsInFiles; static map>> replacementsInFiles; static map>* curFileReplacements; static set 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 &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> getReachingDefinitionsExt(SgStatement* stmt) { CBasicBlock* b = GraphsKeeper::getGraphsKeeper()->findBlock(stmt); if(!b) return map>(); return b->getReachedDefinitionsExt(stmt); } static void revertReplacements(map> &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 getCoefsOfSubscript(SgExpression *exp, SgSymbol *doName, int &err) { pair result; pair 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 err = make_pair(-1, -1); pair 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 &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())); 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 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>* 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> &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(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(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(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(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(high_resolution_clock::now() - time).count() / 1000.); } } void BuildUnfilteredReachingDefinitions(ControlFlowGraph* CGraph, map> &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> &defUseByFunctions, const map &commonBlocks, const map> &allFuncInfo) { vector 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 killerFuncs = queue(); set processed = set(); 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>())); auto last = st->lastNodeOfStmt(); for (SgStatement *currS = st; currS != last; currS = currS->lexNext()) { if (currS->variant() == CONTAINS_STMT) break; if (isSgExecutableStatement(currS)) { vector toRepl = { NULL, NULL, NULL }; vector 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 ®ions) { 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> createHeaderInDefs(SgStatement *header) { map> 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())) .first->second.insert(emptyValue); return inDefs; } void expressionAnalyzer(SgFile *file, const map> &defUseByFunctions, const map &commonBlocks, const map> &allFuncInfo, const vector ®ions) { 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>())); 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; } }