2023-09-14 19:43:13 +03:00
|
|
|
#include "RD_subst.h"
|
|
|
|
|
#include "IR.h"
|
|
|
|
|
#include "CFGraph.h"
|
|
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdexcept>
|
|
|
|
|
#include <unordered_map>
|
|
|
|
|
#include <unordered_set>
|
|
|
|
|
|
|
|
|
|
#include "../Utils/SgUtils.h"
|
|
|
|
|
#include "../Utils/CommonBlock.h"
|
|
|
|
|
#include "../GraphCall/graph_calls.h"
|
|
|
|
|
#include "../ExpressionTransform/expr_transform.h"
|
|
|
|
|
|
|
|
|
|
#define PRINT_PROF_INFO 0
|
|
|
|
|
#define DEBUG_CHECKS 0
|
|
|
|
|
|
|
|
|
|
using std::string;
|
|
|
|
|
using std::vector;
|
|
|
|
|
using std::list;
|
|
|
|
|
using std::map;
|
|
|
|
|
using std::set;
|
|
|
|
|
using std::pair;
|
|
|
|
|
using std::unordered_map;
|
|
|
|
|
using std::unordered_set;
|
|
|
|
|
using std::cout;
|
|
|
|
|
using std::endl;
|
|
|
|
|
|
|
|
|
|
using SAPFOR::CFG_VAL;
|
|
|
|
|
using SAPFOR::CFG_OP;
|
|
|
|
|
using SAPFOR::CFG_OP_S;
|
|
|
|
|
using SAPFOR::CFG_ARG_TYPE;
|
|
|
|
|
using SAPFOR::CFG_MEM_TYPE;
|
|
|
|
|
|
|
|
|
|
static bool substitutions_were_built = false;
|
|
|
|
|
static bool substitutions_applied = false;
|
|
|
|
|
|
|
|
|
|
static bool wereSubstitutionsBuilt()
|
|
|
|
|
{
|
|
|
|
|
return substitutions_were_built;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void setSubstitutionsWereBuilt(bool new_state)
|
|
|
|
|
{
|
|
|
|
|
substitutions_were_built = new_state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool wereSubstitutionsApplied()
|
|
|
|
|
{
|
|
|
|
|
return substitutions_applied;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void setSubstitutionsApplied(bool new_state)
|
|
|
|
|
{
|
|
|
|
|
substitutions_applied = new_state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static map<string, map<SgStatement*, vector<SgExpression*>>> oldExpressionsInFile;
|
|
|
|
|
static map<string, map<SgStatement*, vector<SgExpression*>>> replacementsInFiles;
|
|
|
|
|
static int substitution_counter = 0;
|
|
|
|
|
|
|
|
|
|
static const map<string, map<SgStatement*, vector<SgExpression*>>>& getReplacementsInFiles()
|
|
|
|
|
{
|
|
|
|
|
return replacementsInFiles;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const map<string, map<SgStatement*, vector<SgExpression*>>>& getOldExpressionsInFile()
|
|
|
|
|
{
|
|
|
|
|
return oldExpressionsInFile;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool storeExpression(map<string, map<SgStatement*, vector<SgExpression*>>>& place,
|
|
|
|
|
const string& filename, SgStatement* stmt, int expr_index, SgExpression* expr, bool override_expr = true)
|
|
|
|
|
{
|
|
|
|
|
auto& by_curr_file = place[filename];
|
|
|
|
|
auto it = by_curr_file.find(stmt);
|
|
|
|
|
if (it == by_curr_file.end())
|
|
|
|
|
it = by_curr_file.insert(it, make_pair(stmt, vector<SgExpression*>(3, NULL)));
|
|
|
|
|
|
|
|
|
|
#if DEBUG_CHECKS
|
|
|
|
|
if(override_expr && it->second[expr_index])
|
|
|
|
|
__spf_print(DEBUG_CHECKS, "lost pointer: %s:%d expr %d %s\n", filename.c_str(), stmt->lineNumber(), expr_index, expr->unparse());
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (override_expr || !(it->second[expr_index]))
|
|
|
|
|
{
|
|
|
|
|
it->second[expr_index] = expr;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool addOldExpression(const string& filename, SgStatement* stmt, int expr_index, SgExpression* old_expr, bool override_expr = true)
|
|
|
|
|
{
|
|
|
|
|
return storeExpression(oldExpressionsInFile, filename, stmt, expr_index, old_expr, override_expr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool addReplacement(const string& filename, SgStatement* stmt, int expr_index, SgExpression* new_expr, bool override_expr = true)
|
|
|
|
|
{
|
|
|
|
|
return storeExpression(replacementsInFiles, filename, stmt, expr_index, new_expr, override_expr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool addReplacementAndBackup(const string& filename, SgStatement* stmt, int expr_index, SgExpression* new_expr)
|
|
|
|
|
{
|
|
|
|
|
addReplacement(filename, stmt, expr_index, new_expr);
|
|
|
|
|
|
|
|
|
|
SgExpression* original = stmt->expr(expr_index);
|
|
|
|
|
|
|
|
|
|
addOldExpression(filename, stmt, expr_index, original, true);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void updateOldExpression()
|
|
|
|
|
{
|
|
|
|
|
for (auto& byFile : oldExpressionsInFile)
|
|
|
|
|
{
|
|
|
|
|
SgFile::switchToFile(byFile.first);
|
|
|
|
|
|
|
|
|
|
for (auto& byStmt : byFile.second)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
auto& expr = byStmt.second[i];
|
|
|
|
|
if (byStmt.second[i] != NULL)
|
|
|
|
|
byStmt.second[i] = byStmt.first->expr(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void applyReplacement(map<string, map<SgStatement*, vector<SgExpression*>>>& replacements)
|
|
|
|
|
{
|
|
|
|
|
for (auto& byFile : replacements)
|
|
|
|
|
{
|
|
|
|
|
SgFile::switchToFile(byFile.first);
|
|
|
|
|
|
|
|
|
|
for (auto& byStmt : byFile.second)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
auto& expr = byStmt.second[i];
|
|
|
|
|
if (expr != NULL)
|
|
|
|
|
byStmt.first->setExpression(i, expr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void removeInfo(map<string, map<SgStatement*, vector<SgExpression*>>>& replacements, string filename, SgStatement* stmt, int i) {
|
|
|
|
|
auto it_file = replacements.find(filename);
|
|
|
|
|
|
|
|
|
|
if (it_file != replacements.end()) {
|
|
|
|
|
auto it_stmt = it_file->second.find(stmt);
|
|
|
|
|
|
|
|
|
|
if (it_stmt != it_file->second.end()) {
|
|
|
|
|
it_stmt->second[i] = NULL;
|
|
|
|
|
|
|
|
|
|
bool all_null = true;
|
|
|
|
|
for (auto e : it_stmt->second)
|
|
|
|
|
{
|
|
|
|
|
if (e != NULL) {
|
|
|
|
|
all_null = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (all_null)
|
|
|
|
|
it_file->second.erase(it_stmt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (it_file->second.size() == 0)
|
|
|
|
|
replacements.erase(it_file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void dump_replacements_for_file(string filename)
|
|
|
|
|
{
|
|
|
|
|
cout << "substitutions for file " << filename << ":" << endl;
|
|
|
|
|
for (auto& byStmt : replacementsInFiles[filename])
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
auto& expr = byStmt.second[i];
|
|
|
|
|
if (expr != NULL)
|
|
|
|
|
cout << " stmt:" << byStmt.first->sunparse() << ", index: " << i << ", expr: " << expr->sunparse() << endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int getSubstitutionCounter()
|
|
|
|
|
{
|
|
|
|
|
return substitution_counter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void incrementSubstitutionCounter()
|
|
|
|
|
{
|
|
|
|
|
++substitution_counter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void resetSubstitutionCounter()
|
|
|
|
|
{
|
|
|
|
|
substitution_counter = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const map<string, SgSymbol*>& getCommonArgsByFunc(FuncInfo* func, map<FuncInfo*, map<string, SgSymbol*>>& cache,
|
|
|
|
|
const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
|
|
|
|
unordered_map<SgSymbol*, string>& globals_cache,
|
|
|
|
|
unordered_map<SgSymbol*, string>& locals_cache)
|
|
|
|
|
{
|
|
|
|
|
auto it = cache.find(func);
|
|
|
|
|
if (it != cache.end())
|
|
|
|
|
return it->second;
|
|
|
|
|
|
|
|
|
|
auto& res = cache[func];
|
|
|
|
|
|
|
|
|
|
for (const auto& byVar : commonVars)
|
|
|
|
|
{
|
|
|
|
|
string file = func->fileName;
|
|
|
|
|
SgSymbol* s = NULL;
|
|
|
|
|
|
|
|
|
|
for (const auto& varUse : byVar.first->getAllUse())
|
|
|
|
|
if (varUse.getFileName() == file && (s = varUse.getUseS()))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (!s)
|
|
|
|
|
s = byVar.first->getSymbol();
|
|
|
|
|
|
|
|
|
|
if (s)
|
|
|
|
|
res[getArgNameBySymbol(commonVars, func, s, globals_cache, locals_cache)] = s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool getDependencies(SAPFOR::Argument* var, SAPFOR::Instruction* instr, const SAPFOR::BasicBlock* curr_BB,
|
|
|
|
|
map<SAPFOR::Argument*, set<SAPFOR::Argument*>>& dependencies)
|
|
|
|
|
{
|
|
|
|
|
map<SAPFOR::Argument*, SAPFOR::Instruction*> process_instr;
|
|
|
|
|
process_instr[var] = instr;
|
|
|
|
|
dependencies[var].clear();
|
|
|
|
|
while (process_instr.size() != 0)
|
|
|
|
|
{
|
|
|
|
|
map<SAPFOR::Argument*, SAPFOR::Instruction*> reg_decl;
|
|
|
|
|
map<SAPFOR::Argument*, SAPFOR::Instruction*> to_add;
|
|
|
|
|
for (const auto& byVar : process_instr)
|
|
|
|
|
{
|
|
|
|
|
if (byVar.second->getOperation() == SAPFOR::CFG_OP::F_CALL)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
auto instr_type = byVar.second->getOperation();
|
|
|
|
|
int instr_num = byVar.second->getNumber();
|
|
|
|
|
set<SAPFOR::Argument*> args;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (instr_type == CFG_OP::LOAD)
|
|
|
|
|
{
|
|
|
|
|
args.insert(byVar.second->getArg1());
|
|
|
|
|
int num_of_params = stoi(byVar.second->getArg2()->getValue());
|
|
|
|
|
|
|
|
|
|
int offset = instr_num - curr_BB->getInstructions().front()->getNumber() - num_of_params;
|
|
|
|
|
auto start = curr_BB->getInstructions().begin() + offset;
|
|
|
|
|
auto end = start + num_of_params;
|
|
|
|
|
|
|
|
|
|
for (; start != end; start++)
|
|
|
|
|
args.insert((*start)->getInstruction()->getArg1());
|
|
|
|
|
}
|
|
|
|
|
else if (hasStoreStructure(instr_type))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
args = { byVar.second->getArg1(), byVar.second->getArg2() };
|
|
|
|
|
}
|
|
|
|
|
catch (std::invalid_argument e)
|
|
|
|
|
{
|
|
|
|
|
//cannot convert number of parameters into integer in LOAD or STORE instruction
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const auto arg : args)
|
|
|
|
|
{
|
|
|
|
|
if (arg != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (arg->getType() == CFG_ARG_TYPE::REG)
|
|
|
|
|
{
|
|
|
|
|
auto reg_decl_it = reg_decl.find(arg);
|
|
|
|
|
if (reg_decl_it != reg_decl.end())
|
|
|
|
|
to_add.insert(*reg_decl_it);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (SAPFOR::IR_Block* byIR : curr_BB->getInstructions())
|
|
|
|
|
{
|
|
|
|
|
auto instruction = byIR->getInstruction();
|
|
|
|
|
auto instr_res = instruction->getResult();
|
|
|
|
|
|
|
|
|
|
if (instr_res && instr_res->getType() == CFG_ARG_TYPE::REG && !hasStoreStructure(instruction->getOperation()))
|
|
|
|
|
reg_decl[instr_res] = instruction;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reg_decl_it = reg_decl.find(arg);
|
|
|
|
|
if (reg_decl_it != reg_decl.end())
|
|
|
|
|
to_add.insert(*reg_decl_it);
|
|
|
|
|
else
|
|
|
|
|
//printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (arg->getType() == CFG_ARG_TYPE::VAR || arg->getType() == CFG_ARG_TYPE::ARRAY)
|
|
|
|
|
dependencies[var].insert(arg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
process_instr = to_add;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const set<SAPFOR::Argument*>& func_affects(const FuncInfo* func, const vector<SAPFOR::BasicBlock*>& blocks)
|
|
|
|
|
{
|
|
|
|
|
static map<const FuncInfo*, set<SAPFOR::Argument*>> affects;
|
|
|
|
|
|
|
|
|
|
auto func_affects_it = affects.find(func);
|
|
|
|
|
if (func_affects_it == affects.end())
|
|
|
|
|
{
|
|
|
|
|
func_affects_it = affects.insert({ func, { } }).first;
|
|
|
|
|
|
|
|
|
|
for (auto block : blocks)
|
|
|
|
|
if (block->getNext().size() == 0)
|
|
|
|
|
for (const auto& out : block->getRD_Out())
|
|
|
|
|
/*
|
|
|
|
|
if a function affects variable, than there is basic block, where
|
|
|
|
|
OUT for that variable contains at least 1 valid index of instruction
|
|
|
|
|
(index < 0 means that this variable has reaching definition otside of this function)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (out.second.size() != 1 || *out.second.begin() >= 0)
|
|
|
|
|
func_affects_it->second.insert(out.first);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return func_affects_it->second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static SgSymbol* findCommon(SgSymbol* symb, const FuncInfo* processed_function, const map<string, CommonBlock*>& commonBlocks)
|
|
|
|
|
{
|
|
|
|
|
for (const auto& cb : processed_function->commonBlocks)
|
|
|
|
|
{
|
|
|
|
|
auto cb_it = commonBlocks.find(cb.first);
|
|
|
|
|
if (cb_it != commonBlocks.end())
|
|
|
|
|
{
|
|
|
|
|
for (auto& var_pos : cb_it->second->getGroupedVars())
|
|
|
|
|
{
|
|
|
|
|
bool this_var = false;
|
|
|
|
|
for (auto& var : var_pos.second)
|
|
|
|
|
{
|
|
|
|
|
for (auto& varUse : var->getAllUse())
|
|
|
|
|
{
|
|
|
|
|
if (varUse.getUseS() == symb)
|
|
|
|
|
{
|
|
|
|
|
this_var = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (this_var)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this_var)
|
|
|
|
|
for (auto& var : var_pos.second)
|
|
|
|
|
for (auto& varUse : var->getAllUse())
|
|
|
|
|
if (varUse.getFunctionName() == processed_function->funcName)
|
|
|
|
|
return varUse.getUseS();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static SgExpression* copyExpr(SgExpression* exp_to_copy, const FuncInfo* processed_function,
|
|
|
|
|
const map<string, CommonBlock*>& commonBlocks, bool only_global = false)
|
|
|
|
|
{
|
|
|
|
|
SgExpression* copy = exp_to_copy->copyPtr();
|
|
|
|
|
|
|
|
|
|
set<SgSymbol*> locals;
|
|
|
|
|
map<SgSymbol*, SgSymbol*> commons; //common symb from expr -> common symb from processed_func
|
|
|
|
|
|
|
|
|
|
set<SgExpression*> exp_to_process = { copy };
|
|
|
|
|
|
|
|
|
|
while (exp_to_process.size() != 0)
|
|
|
|
|
{
|
|
|
|
|
set<SgExpression*> to_add;
|
|
|
|
|
for (auto& exp : exp_to_process)
|
|
|
|
|
{
|
|
|
|
|
if (exp->lhs())
|
|
|
|
|
to_add.insert(exp->lhs());
|
|
|
|
|
|
|
|
|
|
if (exp->rhs())
|
|
|
|
|
to_add.insert(exp->lhs());
|
|
|
|
|
|
|
|
|
|
if (exp->symbol())
|
|
|
|
|
{
|
|
|
|
|
SgSymbol* symb = exp->symbol();
|
|
|
|
|
|
|
|
|
|
if (locals.count(symb))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
auto it = commons.find(symb);
|
|
|
|
|
if (it == commons.end())
|
|
|
|
|
{
|
|
|
|
|
SgSymbol* found = findCommon(symb, processed_function, commonBlocks);
|
|
|
|
|
if (!found)
|
|
|
|
|
{
|
|
|
|
|
if (only_global)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
locals.insert(symb);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
it = commons.insert({ symb, found }).first;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
exp->setSymbol(it->second);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
exp_to_process = to_add;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return copy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool isBBlockFromCurrentFile(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph,
|
|
|
|
|
const SAPFOR::BasicBlock* bb)
|
|
|
|
|
{
|
|
|
|
|
const string curr = current_file->filename();
|
|
|
|
|
for (auto& byFunc : CFGraph)
|
|
|
|
|
{
|
|
|
|
|
if (count(byFunc.second.begin(), byFunc.second.end(), bb))
|
|
|
|
|
return byFunc.first->fileName == curr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool isIfOrLoopFromBB(SgStatement* st, SAPFOR::BasicBlock* bb) {
|
|
|
|
|
SAPFOR::Instruction* last = bb->getInstructions().back()->getInstruction();
|
|
|
|
|
int variant = st->variant();
|
|
|
|
|
|
|
|
|
|
bool if_or_loop_from_BB = last->getOperator() == st;
|
|
|
|
|
switch (variant)
|
|
|
|
|
{
|
|
|
|
|
case IF_NODE:
|
|
|
|
|
case LOGIF_NODE:
|
|
|
|
|
case ELSEIF_NODE:
|
|
|
|
|
return if_or_loop_from_BB && last->getOperation() == CFG_OP::JUMP_IF;
|
|
|
|
|
case FOR_NODE:
|
|
|
|
|
return if_or_loop_from_BB && (last->getOperation() != CFG_OP::JUMP && last->getOperation() != CFG_OP::JUMP_IF);
|
|
|
|
|
case WHILE_NODE:
|
|
|
|
|
return if_or_loop_from_BB && last->getOperation() == CFG_OP::JUMP_IF;
|
|
|
|
|
default:
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static map<SAPFOR::Argument*, SgExpression*>
|
|
|
|
|
func_makes_available(const FuncInfo* func,
|
|
|
|
|
SgProject* project,
|
|
|
|
|
map<const FuncInfo*, map<SAPFOR::Argument*, SgExpression*>>& availableForFunc,
|
|
|
|
|
map<const FuncInfo*, map<SAPFOR::Argument*, set<SAPFOR::Argument*>>>& dependenciesForFunc,
|
|
|
|
|
const vector<SAPFOR::BasicBlock*>& blocks,
|
|
|
|
|
const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph,
|
|
|
|
|
map<SAPFOR::Argument*, set<SAPFOR::Argument*>>& dependencies,
|
|
|
|
|
const FuncInfo* processed_function,
|
|
|
|
|
const map<string, CommonBlock*>& commonBlocks)
|
|
|
|
|
{
|
|
|
|
|
if (string(current_file->filename()) != func->fileName)
|
|
|
|
|
return { };
|
|
|
|
|
|
|
|
|
|
auto available_after_func_it = availableForFunc.find(func);
|
|
|
|
|
|
|
|
|
|
if (available_after_func_it == availableForFunc.end())
|
|
|
|
|
{
|
|
|
|
|
available_after_func_it = availableForFunc.insert({ func, { } }).first;
|
|
|
|
|
auto& availableForCurrentFunc = available_after_func_it->second;
|
|
|
|
|
auto& dependenciesForCurrentFunc = dependenciesForFunc[func];
|
|
|
|
|
|
|
|
|
|
bool first_out_block = true;
|
|
|
|
|
|
|
|
|
|
vector<pair<SAPFOR::Argument*, int>> makes_available;
|
|
|
|
|
for (auto block : blocks)
|
|
|
|
|
{
|
|
|
|
|
if (block->getNext().size() == 0)
|
|
|
|
|
{
|
|
|
|
|
if (first_out_block)
|
|
|
|
|
{
|
|
|
|
|
for (auto& out : block->getRD_Out())
|
|
|
|
|
{
|
|
|
|
|
if ((out.first->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ /* || out.first->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_*/)
|
|
|
|
|
&& out.second.size() == 1 && *(out.second.begin()) >= 0)
|
|
|
|
|
{
|
|
|
|
|
makes_available.push_back(std::make_pair(out.first, *(out.second.begin())));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
first_out_block = false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
makes_available.erase(std::remove_if(makes_available.begin(), makes_available.end(), [&block](const pair<SAPFOR::Argument*, int>& p) {
|
|
|
|
|
auto it = block->getRD_Out().find(p.first);
|
|
|
|
|
|
|
|
|
|
return (it == block->getRD_Out().end())
|
|
|
|
|
|| (it->second.size() != 1)
|
|
|
|
|
|| (*(it->second.begin()) != p.second);
|
|
|
|
|
}),
|
|
|
|
|
makes_available.end()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const auto& p : makes_available)
|
|
|
|
|
{
|
|
|
|
|
auto argument = p.first;
|
|
|
|
|
int instr_number = p.second;
|
|
|
|
|
|
|
|
|
|
pair<SAPFOR::Instruction*, SAPFOR::BasicBlock*> instr_and_bb = getInstructionAndBlockByNumber(CFGraph, instr_number);
|
|
|
|
|
|
|
|
|
|
if (!isBBlockFromCurrentFile(CFGraph, instr_and_bb.second))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (getDependencies(argument, instr_and_bb.first, instr_and_bb.second, dependenciesForCurrentFunc))
|
|
|
|
|
{
|
|
|
|
|
//check if all variables with affect on definition could be used there
|
|
|
|
|
bool can_use = true;
|
|
|
|
|
auto dependencies_of_var = dependenciesForCurrentFunc.find(argument);
|
|
|
|
|
if (dependencies_of_var == dependenciesForCurrentFunc.end())
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
for (SAPFOR::Argument* dep : dependencies_of_var->second)
|
|
|
|
|
{
|
|
|
|
|
if (dep->getMemType() != SAPFOR::CFG_MEM_TYPE::COMMON_/* || dep->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_*/)
|
|
|
|
|
{
|
|
|
|
|
can_use = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (can_use)
|
|
|
|
|
availableForCurrentFunc[argument] = instr_and_bb.first->getOperator()->expr(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto dependencies_after_func_it = dependenciesForFunc.find(func);
|
|
|
|
|
if(dependencies_after_func_it == dependenciesForFunc.end())
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
map<SAPFOR::Argument*, SgExpression*> available;
|
|
|
|
|
|
|
|
|
|
for (const auto& byArgument : available_after_func_it->second) {
|
|
|
|
|
auto dependencies_for_argument_it = dependencies_after_func_it->second.find(byArgument.first);
|
|
|
|
|
if(dependencies_for_argument_it == dependencies_after_func_it->second.end())
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
SgExpression* exp_of_def = copyExpr(byArgument.second, processed_function, commonBlocks, true);
|
|
|
|
|
if (exp_of_def) {
|
|
|
|
|
dependencies[byArgument.first] = dependencies_for_argument_it->second;
|
|
|
|
|
available[byArgument.first] = exp_of_def;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return available;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static unordered_map<SgSymbol*, string> globals, locals;
|
|
|
|
|
const string& getArgNameBySymbol(const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
|
|
|
|
const FuncInfo* func, SgSymbol* s,
|
|
|
|
|
unordered_map<SgSymbol*, string>& globals_cache, unordered_map<SgSymbol*, string>& locals_cache)
|
|
|
|
|
{
|
|
|
|
|
auto local_it = locals_cache.find(s);
|
|
|
|
|
|
|
|
|
|
if (local_it != locals_cache.end())
|
|
|
|
|
return local_it->second;
|
|
|
|
|
|
|
|
|
|
auto global_it = globals_cache.find(s);
|
|
|
|
|
|
|
|
|
|
if (global_it != globals_cache.end())
|
|
|
|
|
return global_it->second;
|
|
|
|
|
|
|
|
|
|
CFG_MEM_TYPE mType = CFG_MEM_TYPE::NONE_;
|
|
|
|
|
|
|
|
|
|
SgStatement* scope = OriginalSymbol(s)->scope();
|
|
|
|
|
|
|
|
|
|
if (!scope)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
string name = createName(commonVars, func, s, scope, mType);
|
|
|
|
|
if (mType == CFG_MEM_TYPE::LOCAL_)
|
|
|
|
|
return locals_cache[s] = name;
|
|
|
|
|
else
|
|
|
|
|
return globals_cache[s] = name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static SgExpression* expandSymbolToExpression(SgExpression* s, const map<string, SgExpression*>& name_to_expr,
|
|
|
|
|
const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
|
|
|
|
const FuncInfo* func)
|
|
|
|
|
{
|
|
|
|
|
while (s->variant() == VAR_REF && s->symbol() && s->symbol()->identifier())
|
|
|
|
|
{
|
|
|
|
|
string argName = getArgNameBySymbol(commonVars, func, s->symbol(), globals, locals);
|
|
|
|
|
auto it = name_to_expr.find(argName);
|
|
|
|
|
|
|
|
|
|
if (it == name_to_expr.end() || it->second->type()->variant() != s->type()->variant())
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
incrementSubstitutionCounter();
|
|
|
|
|
__spf_print(PRINT_PROF_INFO, "%s -> ", s->unparse());
|
|
|
|
|
|
|
|
|
|
s = it->second;
|
|
|
|
|
|
|
|
|
|
__spf_print(PRINT_PROF_INFO, "%s\n", s->unparse());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static SgExpression* performExprSubstAndLink_(SgExpression* cur_exp, bool is_left,
|
|
|
|
|
const map<string, SgExpression*>& name_to_expr,
|
|
|
|
|
const map<SAPFOR::Argument*, SgExpression*>& available,
|
|
|
|
|
const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
|
|
|
|
const FuncInfo* func,
|
|
|
|
|
SgExpression* exp, SgExpression*& backup)
|
|
|
|
|
{
|
|
|
|
|
SgExpression* sub_expr = is_left ? cur_exp->lhs() : cur_exp->rhs();
|
|
|
|
|
|
|
|
|
|
if (sub_expr)
|
|
|
|
|
if (sub_expr->symbol() && sub_expr->variant() != PROC_CALL && sub_expr->variant() != FUNC_CALL)
|
|
|
|
|
{
|
|
|
|
|
SgArrayRefExp* array_expr = isSgArrayRefExp(sub_expr);
|
|
|
|
|
if (array_expr)
|
|
|
|
|
{
|
|
|
|
|
if (array_expr->subscripts())
|
|
|
|
|
return array_expr->subscripts();
|
|
|
|
|
}
|
|
|
|
|
else if (sub_expr->symbol()->identifier())
|
|
|
|
|
{
|
|
|
|
|
SgExpression* replace_by = expandSymbolToExpression(sub_expr, name_to_expr, commonVars, func);
|
|
|
|
|
|
|
|
|
|
if (replace_by != sub_expr)
|
|
|
|
|
{
|
|
|
|
|
if (backup == NULL)
|
|
|
|
|
{
|
|
|
|
|
backup = exp->copyPtr();
|
|
|
|
|
createLinksToCopy(backup, exp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__spf_print(PRINT_PROF_INFO, "%s -> ", sub_expr->unparse());
|
|
|
|
|
is_left ? cur_exp->setLhs(replace_by->copy()) : cur_exp->setRhs(replace_by->copy());
|
|
|
|
|
|
|
|
|
|
sub_expr = is_left ? cur_exp->lhs() : cur_exp->rhs();
|
|
|
|
|
__spf_print(PRINT_PROF_INFO, "%s\n", sub_expr->unparse());
|
|
|
|
|
|
|
|
|
|
incrementSubstitutionCounter();
|
|
|
|
|
|
|
|
|
|
return sub_expr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return sub_expr;
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// iterate over function or procedure call arguments and sustitute if it possible
|
|
|
|
|
static list<SgExpression*> performExprSubstInCall(const char* fname, SgExprListExp* actualArguments,
|
|
|
|
|
const map<string, SgExpression*>& name_to_expr,
|
|
|
|
|
const map<SAPFOR::Argument*, SgExpression*>& available,
|
|
|
|
|
const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
|
|
|
|
const FuncInfo* func, const map<string, FuncInfo*>& funcByName,
|
|
|
|
|
SgExpression* exp, SgExpression*& backup)
|
|
|
|
|
{
|
|
|
|
|
if (!fname || !actualArguments)
|
|
|
|
|
return { };
|
|
|
|
|
|
|
|
|
|
// Step 1. Get indexes of arguments that can be substituted
|
|
|
|
|
set<int> possible_substitution;
|
|
|
|
|
|
|
|
|
|
auto found_func = funcByName.find(fname);
|
|
|
|
|
if (found_func != funcByName.end())
|
|
|
|
|
{
|
|
|
|
|
FuncInfo* called_func = found_func->second;
|
|
|
|
|
|
|
|
|
|
int count_of_params = called_func->funcParams.countOfPars;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < count_of_params; i++)
|
|
|
|
|
if (!called_func->funcParams.isArgOut(i))
|
|
|
|
|
possible_substitution.insert(i);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (isIntrinsicFunctionName(fname))
|
|
|
|
|
return { actualArguments }; // main loop can substitute all arguments indiscriminately
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Step 2. Perform possible substitutions
|
|
|
|
|
list<SgExpression*> res;
|
|
|
|
|
SgExpression* curr = actualArguments;
|
|
|
|
|
int pos = 0;
|
|
|
|
|
|
|
|
|
|
while (curr) {
|
|
|
|
|
SgExpression* actual_param = curr->lhs();
|
|
|
|
|
|
|
|
|
|
if (actual_param)
|
|
|
|
|
{
|
|
|
|
|
if (actual_param->symbol() && actual_param->symbol()->identifier() && actual_param->variant() == VAR_REF)
|
|
|
|
|
{
|
|
|
|
|
if (possible_substitution.find(pos) != possible_substitution.end())
|
|
|
|
|
{
|
|
|
|
|
SgExpression* to_add = performExprSubstAndLink_(curr, true, name_to_expr, available, commonVars, func, exp, backup);
|
|
|
|
|
if (to_add)
|
|
|
|
|
res.push_back(to_add);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
res.push_back(actual_param);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pos++;
|
|
|
|
|
curr = curr->rhs();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if replacement occurs, returns a new expression (the new expression is linked to the original one)
|
|
|
|
|
// if there were no replacements, then returns NULL
|
|
|
|
|
static SgExpression* performExprSubstAndLink(SgStatement* stmt, int i,
|
|
|
|
|
const map<SAPFOR::Argument*, SgExpression*>& available,
|
|
|
|
|
const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
|
|
|
|
const FuncInfo* func, const map<string, FuncInfo*>& funcByName)
|
|
|
|
|
{
|
|
|
|
|
SgExpression* expr_to_subst = stmt->expr(i);
|
|
|
|
|
map<string, SgExpression*> name_to_expr;
|
|
|
|
|
for (const auto& p : available)
|
|
|
|
|
name_to_expr[p.first->getValue()] = p.second;
|
|
|
|
|
|
|
|
|
|
SgExpression* backup = NULL;
|
|
|
|
|
|
|
|
|
|
list<SgExpression*> to_process;
|
|
|
|
|
SgCallStmt* call = isSgCallStmt(stmt);
|
|
|
|
|
if (!call)
|
|
|
|
|
{
|
|
|
|
|
SgExpression* replace_symbol_by = expandSymbolToExpression(expr_to_subst, name_to_expr, commonVars, func);
|
|
|
|
|
|
|
|
|
|
if (replace_symbol_by != expr_to_subst)
|
|
|
|
|
{
|
|
|
|
|
if (backup == NULL)
|
|
|
|
|
{
|
|
|
|
|
backup = expr_to_subst->copyPtr();
|
|
|
|
|
createLinksToCopy(backup, expr_to_subst);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expr_to_subst = replace_symbol_by->copyPtr();
|
|
|
|
|
stmt->setExpression(i, expr_to_subst);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
to_process = { expr_to_subst };
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
auto to_add = performExprSubstInCall(call->name()->identifier(), isSgExprListExp(call->expr(0)),
|
|
|
|
|
name_to_expr, available, commonVars, func, funcByName, expr_to_subst, backup);
|
|
|
|
|
|
|
|
|
|
for (auto e : to_add)
|
|
|
|
|
to_process.push_back(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (to_process.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
SgExpression* cur_exp = to_process.front(), *sub_expr;
|
|
|
|
|
to_process.pop_front();
|
|
|
|
|
|
|
|
|
|
SgFunctionCallExp* fcall = isSgFunctionCallExp(cur_exp);
|
|
|
|
|
if (fcall)
|
|
|
|
|
{
|
|
|
|
|
auto to_add = performExprSubstInCall(fcall->funName()->identifier(), isSgExprListExp(fcall->args()),
|
|
|
|
|
name_to_expr, available, commonVars, func, funcByName, expr_to_subst, backup);
|
|
|
|
|
|
|
|
|
|
for (auto e : to_add)
|
|
|
|
|
to_process.push_back(e);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
sub_expr = performExprSubstAndLink_(cur_exp, true, name_to_expr, available, commonVars, func, expr_to_subst, backup);
|
|
|
|
|
if (sub_expr)
|
|
|
|
|
to_process.push_back(sub_expr);
|
|
|
|
|
|
|
|
|
|
sub_expr = performExprSubstAndLink_(cur_exp, false, name_to_expr, available, commonVars, func, expr_to_subst, backup);
|
|
|
|
|
if (sub_expr)
|
|
|
|
|
to_process.push_back(sub_expr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (backup)
|
|
|
|
|
{
|
|
|
|
|
stmt->setExpression(i, backup);
|
|
|
|
|
return expr_to_subst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// replace argument_to_replace by argument_value in expr.
|
|
|
|
|
// if there were no replacements, then returns expr.
|
|
|
|
|
// if substitution couldn't be applied due to type mismatch, return NULL
|
|
|
|
|
// else returns substituted expression (note that argument_value can be returned)
|
|
|
|
|
// argument value shouldn't contains argument_to_replace
|
|
|
|
|
static SgExpression* substSingleSymb(SgExpression* expr,
|
|
|
|
|
SAPFOR::Argument* argument_to_replace,
|
|
|
|
|
SgExpression* argument_value,
|
|
|
|
|
const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
|
|
|
|
const FuncInfo* func)
|
|
|
|
|
{
|
|
|
|
|
string arg_to_replace_name = argument_to_replace->getValue();
|
|
|
|
|
|
|
|
|
|
if (expr->variant() == VAR_REF && expr->symbol()) {
|
|
|
|
|
string arg_from_expr = getArgNameBySymbol(commonVars, func, expr->symbol(), globals, locals);
|
|
|
|
|
if (arg_from_expr == arg_to_replace_name)
|
|
|
|
|
return argument_value;
|
|
|
|
|
else
|
|
|
|
|
return expr;
|
|
|
|
|
}
|
|
|
|
|
// check if argument in expression
|
|
|
|
|
bool symbol_in_expression = false;
|
|
|
|
|
list<SgExpression*> to_process = { expr };
|
|
|
|
|
|
|
|
|
|
while (to_process.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
SgExpression* cur_exp = to_process.front();
|
|
|
|
|
to_process.pop_front();
|
|
|
|
|
|
|
|
|
|
if (cur_exp && cur_exp->variant() != PROC_CALL && cur_exp->variant() != FUNC_CALL)
|
|
|
|
|
if (cur_exp->symbol())
|
|
|
|
|
{
|
|
|
|
|
SgArrayRefExp* array_expr = isSgArrayRefExp(cur_exp);
|
|
|
|
|
if (array_expr)
|
|
|
|
|
{
|
|
|
|
|
if (array_expr->subscripts())
|
|
|
|
|
to_process.push_back(array_expr->subscripts());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if (cur_exp->variant() == VAR_REF && cur_exp->symbol()->identifier())
|
|
|
|
|
{
|
|
|
|
|
string argName = getArgNameBySymbol(commonVars, func, cur_exp->symbol(), globals, locals);
|
|
|
|
|
if (argName == arg_to_replace_name)
|
|
|
|
|
{
|
|
|
|
|
symbol_in_expression = true;
|
|
|
|
|
to_process.clear();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
to_process.push_back(cur_exp->lhs());
|
|
|
|
|
to_process.push_back(cur_exp->rhs());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!symbol_in_expression)
|
|
|
|
|
return expr;
|
|
|
|
|
|
|
|
|
|
// perform substitution
|
|
|
|
|
SgExpression* copy = expr->copyPtr();
|
|
|
|
|
to_process = { copy };
|
|
|
|
|
|
|
|
|
|
while (to_process.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
SgExpression* cur_exp = to_process.front();
|
|
|
|
|
to_process.pop_front();
|
|
|
|
|
|
|
|
|
|
for (auto is_left : { true, false })
|
|
|
|
|
{
|
|
|
|
|
SgExpression* sub_expr = is_left ? cur_exp->lhs() : cur_exp->rhs();
|
|
|
|
|
|
|
|
|
|
if (sub_expr && sub_expr->variant() != PROC_CALL && sub_expr->variant() != FUNC_CALL)
|
|
|
|
|
if (sub_expr->symbol())
|
|
|
|
|
{
|
|
|
|
|
SgArrayRefExp* array_expr = isSgArrayRefExp(sub_expr);
|
|
|
|
|
if (array_expr)
|
|
|
|
|
{
|
|
|
|
|
if (array_expr->subscripts())
|
|
|
|
|
to_process.push_back(array_expr->subscripts());
|
|
|
|
|
}
|
|
|
|
|
else if (sub_expr->variant() == VAR_REF && sub_expr->symbol()->identifier())
|
|
|
|
|
{
|
|
|
|
|
string argName = getArgNameBySymbol(commonVars, func, sub_expr->symbol(), globals, locals);
|
|
|
|
|
|
|
|
|
|
if (argName == arg_to_replace_name)
|
|
|
|
|
if (sub_expr->type()->variant() == argument_value->type()->variant())
|
|
|
|
|
is_left ? cur_exp->setLhs(argument_value->copy()) : cur_exp->setRhs(argument_value->copy());
|
|
|
|
|
else
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
to_process.push_back(sub_expr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return copy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// replace chains like a->f(arg) by a->f(g()), where arg->g()
|
|
|
|
|
// updates available and dependencies structures
|
|
|
|
|
static bool joinChains(map<SAPFOR::Argument*, SgExpression*>& available,
|
|
|
|
|
map<SAPFOR::Argument*, set<SAPFOR::Argument*>>& dependencies,
|
|
|
|
|
SAPFOR::Argument* arg,
|
|
|
|
|
const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
|
|
|
|
const FuncInfo* func)
|
|
|
|
|
{
|
|
|
|
|
auto arg_in_available = available.find(arg);
|
|
|
|
|
if (arg_in_available == available.end())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
auto arg_in_dependencies = dependencies.find(arg);
|
|
|
|
|
if (arg_in_dependencies == dependencies.end())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
SgExpression* arg_value = arg_in_available->second; // g()
|
|
|
|
|
const auto& arg_dependencies = arg_in_dependencies->second;
|
|
|
|
|
bool joined = false;
|
|
|
|
|
|
|
|
|
|
for (auto& p : dependencies)
|
|
|
|
|
{
|
|
|
|
|
if (p.second.count(arg))
|
|
|
|
|
{
|
|
|
|
|
SAPFOR::Argument* curr_var = p.first; // a variable
|
|
|
|
|
auto available_it = available.find(curr_var);
|
|
|
|
|
if (available_it != available.end())
|
|
|
|
|
{
|
|
|
|
|
SgExpression* new_expr = substSingleSymb(available_it->second, arg, arg_value, commonVars, func); //f(g())
|
|
|
|
|
if (new_expr && new_expr != available_it->second)
|
|
|
|
|
{
|
|
|
|
|
p.second.erase(arg);
|
|
|
|
|
p.second.insert(arg_dependencies.begin(), arg_dependencies.end());
|
|
|
|
|
available[curr_var] = new_expr;
|
|
|
|
|
joined = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return joined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// sorts BasicBlocks from blocks in control flow order
|
|
|
|
|
// pass ignored_edges for saving there back edges (used in live variable analysis)
|
|
|
|
|
vector<SAPFOR::BasicBlock*> sortCfgNodes(const vector<SAPFOR::BasicBlock*>& blocks,
|
|
|
|
|
set<pair<SAPFOR::BasicBlock*, SAPFOR::BasicBlock*>>* ignored_edges)
|
|
|
|
|
{
|
|
|
|
|
list<SAPFOR::BasicBlock*> seq_starts = { };
|
|
|
|
|
for (auto e : blocks)
|
|
|
|
|
if (e->getInstructions().front()->isHeader())
|
|
|
|
|
seq_starts.push_front(e);
|
|
|
|
|
else if(e->getPrev().size() == 0)
|
|
|
|
|
seq_starts.push_back(e);
|
|
|
|
|
|
|
|
|
|
if (blocks.size() == 0)
|
|
|
|
|
return { };
|
|
|
|
|
|
|
|
|
|
// STEP 1: marks all back edges
|
|
|
|
|
set<pair<SAPFOR::BasicBlock*, SAPFOR::BasicBlock*>> to_ignore;
|
|
|
|
|
|
|
|
|
|
unordered_set<SAPFOR::BasicBlock*> in_process = { };
|
|
|
|
|
unordered_set<SAPFOR::BasicBlock*> visited = { }, all_visited = { };
|
|
|
|
|
unordered_set<SAPFOR::BasicBlock*> at_stack = { };
|
|
|
|
|
list<SAPFOR::BasicBlock*> processing_stack, processing_starts = seq_starts;
|
|
|
|
|
|
|
|
|
|
at_stack.insert(seq_starts.begin(), seq_starts.end());
|
|
|
|
|
|
|
|
|
|
while (processing_starts.size() != 0)
|
|
|
|
|
{
|
|
|
|
|
auto start = processing_starts.front();
|
|
|
|
|
processing_starts.pop_front();
|
|
|
|
|
|
|
|
|
|
processing_stack = { start };
|
|
|
|
|
at_stack = { start };
|
|
|
|
|
|
|
|
|
|
while (processing_stack.size() != 0)
|
|
|
|
|
{
|
|
|
|
|
auto curr_it = processing_stack.end();
|
|
|
|
|
curr_it--;
|
|
|
|
|
SAPFOR::BasicBlock* curr = *curr_it;
|
|
|
|
|
in_process.insert(curr);
|
|
|
|
|
bool next_added = false;
|
|
|
|
|
|
|
|
|
|
for (auto next_node : curr->getNext())
|
|
|
|
|
{
|
|
|
|
|
if (!to_ignore.count({ curr, next_node }))
|
|
|
|
|
{
|
|
|
|
|
if (in_process.count(next_node))
|
|
|
|
|
{
|
|
|
|
|
// this is back edge
|
|
|
|
|
to_ignore.insert({ curr, next_node });
|
|
|
|
|
}
|
|
|
|
|
else if (!visited.count(next_node) && at_stack.insert(next_node).second)
|
|
|
|
|
{
|
|
|
|
|
processing_stack.push_back(next_node);
|
|
|
|
|
next_added = true;
|
|
|
|
|
}
|
|
|
|
|
// if next_node has status visited then do nothing
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!next_added) {
|
|
|
|
|
// mark as visited
|
|
|
|
|
in_process.erase(curr);
|
|
|
|
|
visited.insert(curr);
|
|
|
|
|
processing_stack.erase(curr_it);
|
|
|
|
|
at_stack.erase(curr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
in_process.clear();
|
|
|
|
|
|
|
|
|
|
all_visited.insert(visited.begin(), visited.end());
|
|
|
|
|
visited.clear();
|
|
|
|
|
processing_stack.clear();
|
|
|
|
|
at_stack.clear();
|
|
|
|
|
|
|
|
|
|
if (processing_starts.size() == 0 && all_visited.size() < blocks.size())
|
|
|
|
|
{
|
|
|
|
|
//find new entrypoint
|
|
|
|
|
SAPFOR::BasicBlock* new_start = NULL;
|
|
|
|
|
int linenum = 0;
|
|
|
|
|
|
|
|
|
|
for (auto block : blocks)
|
|
|
|
|
{
|
|
|
|
|
if (all_visited.count(block) == 0)
|
|
|
|
|
{
|
|
|
|
|
int curr_line = block->getInstructions().front()->getInstruction()->getOperator()->lineNumber();
|
|
|
|
|
if (new_start == NULL || curr_line < linenum)
|
|
|
|
|
{
|
|
|
|
|
new_start = block;
|
|
|
|
|
linenum = curr_line;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(new_start == NULL)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
seq_starts.push_back(new_start);
|
|
|
|
|
processing_starts.push_back(new_start);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
all_visited.clear();
|
|
|
|
|
|
|
|
|
|
// STEP 2: visit nodes and build sorted array
|
|
|
|
|
vector<SAPFOR::BasicBlock*> result;
|
|
|
|
|
|
|
|
|
|
for (const auto& start : seq_starts)
|
|
|
|
|
processing_stack.push_back(start);
|
|
|
|
|
|
|
|
|
|
in_process.insert(seq_starts.begin(), seq_starts.end());
|
|
|
|
|
|
|
|
|
|
while (processing_stack.size() != 0)
|
|
|
|
|
{
|
|
|
|
|
bool nodes_added = false;
|
|
|
|
|
for (auto block_it = processing_stack.begin(); block_it != processing_stack.end();)
|
|
|
|
|
{
|
|
|
|
|
// check if block could be added to result
|
|
|
|
|
bool add = true;
|
|
|
|
|
auto block = *block_it;
|
|
|
|
|
|
|
|
|
|
for (auto prev : block->getPrev())
|
|
|
|
|
if (!visited.count(prev) && !to_ignore.count({ prev, block }))
|
|
|
|
|
add = false;
|
|
|
|
|
if (add)
|
|
|
|
|
{
|
|
|
|
|
nodes_added = true;
|
|
|
|
|
if (visited.insert(block).second)
|
|
|
|
|
result.push_back(block);
|
|
|
|
|
|
|
|
|
|
in_process.erase(block);
|
|
|
|
|
block_it = processing_stack.erase(block_it);
|
|
|
|
|
bool stack_empty = block_it == processing_stack.end();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (auto next : block->getNext())
|
|
|
|
|
if (!visited.count(next) && in_process.insert(next).second)
|
|
|
|
|
processing_stack.push_back(next);
|
|
|
|
|
|
|
|
|
|
if (stack_empty)
|
|
|
|
|
block_it = processing_stack.begin();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
block_it++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!nodes_added && processing_stack.size() != 0) {
|
|
|
|
|
//there is some blocks in the stack but no one can be processed
|
|
|
|
|
//this code should be unreachable
|
2024-01-30 19:45:27 +03:00
|
|
|
#if DEBUG_CHECKS
|
2023-09-14 19:43:13 +03:00
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
#endif // DEBUG_CHECKS
|
|
|
|
|
auto block = processing_stack.back();
|
|
|
|
|
processing_stack.pop_back();
|
|
|
|
|
in_process.erase(block);
|
|
|
|
|
|
|
|
|
|
result.push_back(block);
|
|
|
|
|
visited.insert(block);
|
|
|
|
|
nodes_added = true;
|
|
|
|
|
|
|
|
|
|
for (auto next : block->getNext())
|
|
|
|
|
if (!visited.count(next) && in_process.insert(next).second)
|
|
|
|
|
processing_stack.push_back(next);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-30 19:45:27 +03:00
|
|
|
#if DEBUG_CHECKS
|
2023-09-14 19:43:13 +03:00
|
|
|
set<SAPFOR::BasicBlock*> verify_unique;
|
|
|
|
|
verify_unique.insert(result.begin(), result.end());
|
|
|
|
|
|
|
|
|
|
if (verify_unique.size() != result.size())
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
verify_unique.clear();
|
|
|
|
|
#endif // DEBUG_CHECKS
|
|
|
|
|
|
2024-01-30 19:45:27 +03:00
|
|
|
#if DEBUG_CHECKS
|
2023-09-14 19:43:13 +03:00
|
|
|
set<SAPFOR::BasicBlock*> all_blocks, res_blocks;
|
|
|
|
|
|
|
|
|
|
all_blocks.insert(blocks.begin(), blocks.end());
|
|
|
|
|
res_blocks.insert(result.begin(), result.end());
|
|
|
|
|
|
|
|
|
|
if(res_blocks != all_blocks)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
#endif // DEBUG_CHECKS
|
|
|
|
|
|
|
|
|
|
if (ignored_edges)
|
|
|
|
|
ignored_edges->insert(to_ignore.begin(), to_ignore.end()); // return back edges if needed
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
map<int, map<SAPFOR::Argument*, SgExpression*>> saved_available;
|
|
|
|
|
map<int, map<SAPFOR::Argument*, set<SAPFOR::Argument*>>> saved_dependencies;
|
|
|
|
|
|
|
|
|
|
// save contents of available and dependencies for specified instruction.
|
|
|
|
|
void save_chains(int instr_num, const map<SAPFOR::Argument*, SgExpression*>& available,
|
|
|
|
|
const map<SAPFOR::Argument*, set<SAPFOR::Argument*>>& dependencies,
|
|
|
|
|
SAPFOR::Argument* arg)
|
|
|
|
|
{
|
|
|
|
|
map<SAPFOR::Argument*, SgExpression*> available_to_save;
|
|
|
|
|
map<SAPFOR::Argument*, set<SAPFOR::Argument*>> dependencies_to_save;
|
|
|
|
|
set<SAPFOR::Argument*> needed_vars, new_needed = { arg };
|
|
|
|
|
|
|
|
|
|
while (new_needed.size() != 0)
|
|
|
|
|
{
|
|
|
|
|
needed_vars = new_needed;
|
|
|
|
|
new_needed = { };
|
|
|
|
|
for (auto e : needed_vars)
|
|
|
|
|
{
|
|
|
|
|
auto it_available = available.find(e);
|
|
|
|
|
if (it_available == available.end())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
auto it_dependencies = dependencies.find(e);
|
|
|
|
|
if (it_dependencies == dependencies.end())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
available_to_save.insert(*it_available);
|
|
|
|
|
dependencies_to_save.insert(*it_dependencies);
|
|
|
|
|
|
|
|
|
|
for (auto dep : it_dependencies->second)
|
|
|
|
|
{
|
|
|
|
|
if (!available_to_save.count(dep))
|
|
|
|
|
new_needed.insert(dep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
saved_available[instr_num] = available_to_save;
|
|
|
|
|
saved_dependencies[instr_num] = dependencies_to_save;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// return number of instructions where we need to save data from available and dependencies
|
|
|
|
|
set<int> save_at_indexes(SAPFOR::BasicBlock* bb)
|
|
|
|
|
{
|
|
|
|
|
if (!bb || bb->getInstructions().size() == 0)
|
|
|
|
|
return { };
|
|
|
|
|
|
|
|
|
|
int bb_start = bb->getInstructions().front()->getNumber();
|
|
|
|
|
int bb_end = bb->getInstructions().back()->getNumber();
|
|
|
|
|
set<int> needed_indexes;
|
|
|
|
|
|
|
|
|
|
for (auto p : bb->getRD_Out())
|
|
|
|
|
if (p.second.size() == 1 && *p.second.begin() >= bb_start && *p.second.begin() <= bb_end)
|
|
|
|
|
needed_indexes.insert(*p.second.begin());
|
|
|
|
|
|
|
|
|
|
return needed_indexes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isArgReaches(int decl_instr, SAPFOR::BasicBlock* decl_bb,
|
|
|
|
|
SAPFOR::Argument* arg, SAPFOR::BasicBlock* dest_bb)
|
|
|
|
|
{
|
|
|
|
|
if (arg->getType() != CFG_ARG_TYPE::VAR)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
const auto& RD_In_of_dest_bb = dest_bb->getRD_In();
|
|
|
|
|
auto dep_from_dest_bb_RD_In = RD_In_of_dest_bb.find(arg);
|
|
|
|
|
|
|
|
|
|
if (dep_from_dest_bb_RD_In == RD_In_of_dest_bb.end())
|
|
|
|
|
return decl_bb->getRD_In().count(arg) == 0;
|
|
|
|
|
|
|
|
|
|
const auto& RDs_for_arg = dep_from_dest_bb_RD_In->second;
|
|
|
|
|
|
|
|
|
|
if (RDs_for_arg.size() == 1)
|
|
|
|
|
{
|
|
|
|
|
const int rd = *RDs_for_arg.begin();
|
2024-05-25 15:37:38 +03:00
|
|
|
if (rd >= decl_bb->getInstructions().front()->getNumber() &&
|
|
|
|
|
rd <= decl_bb->getInstructions().back()->getNumber())
|
|
|
|
|
return rd < decl_instr;
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto arg_in_from_decl_it = decl_bb->getRD_In().find(arg);
|
|
|
|
|
if (arg_in_from_decl_it == decl_bb->getRD_In().end())
|
|
|
|
|
return false;
|
|
|
|
|
|
2024-01-30 19:45:27 +03:00
|
|
|
if(arg_in_from_decl_it->second != RDs_for_arg)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
set<SAPFOR::BasicBlock*> reachable = { decl_bb };
|
|
|
|
|
set<int> banned_instructions;
|
|
|
|
|
for (int instr_def : arg_in_from_decl_it->second)
|
|
|
|
|
if (instr_def >= decl_instr || instr_def < decl_bb->getInstructions().front()->getNumber())
|
|
|
|
|
//try to find way [decl_bb] -> [dest_bb] with redefining of var (that means that var value from decl_bb could be overwrited)
|
|
|
|
|
banned_instructions.insert(instr_def);
|
|
|
|
|
|
|
|
|
|
set<SAPFOR::BasicBlock*> worklist = reachable, banned_blocks;
|
|
|
|
|
bool way_found = false;
|
|
|
|
|
while (worklist.size() != 0 && banned_instructions.size() != 0)
|
|
|
|
|
{
|
|
|
|
|
for (SAPFOR::BasicBlock* wl : worklist)
|
|
|
|
|
{
|
|
|
|
|
int start = wl->getInstructions().front()->getNumber(), end = wl->getInstructions().back()->getNumber();
|
|
|
|
|
|
|
|
|
|
for (auto banned_it = banned_instructions.begin(); banned_it != banned_instructions.end();)
|
|
|
|
|
{
|
|
|
|
|
if(start <= *banned_it && *banned_it <= end)
|
|
|
|
|
{
|
|
|
|
|
banned_it = banned_instructions.erase(banned_it);
|
|
|
|
|
banned_blocks.insert(wl);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
banned_it++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set<SAPFOR::BasicBlock*> to_insert;
|
|
|
|
|
|
|
|
|
|
for (auto b : worklist)
|
|
|
|
|
for (auto next : b->getNext())
|
|
|
|
|
if (reachable.insert(next).second)
|
|
|
|
|
to_insert.insert(next);
|
|
|
|
|
|
|
|
|
|
worklist = to_insert;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reachable = banned_blocks;
|
|
|
|
|
worklist = reachable;
|
2024-02-02 22:43:46 +03:00
|
|
|
while (worklist.size() != 0 && banned_instructions.size() != 0)
|
2024-01-30 19:45:27 +03:00
|
|
|
{
|
|
|
|
|
if(worklist.find(dest_bb) != worklist.end())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
set<SAPFOR::BasicBlock*> to_insert;
|
|
|
|
|
|
|
|
|
|
for (auto b : worklist)
|
|
|
|
|
for (auto next : b->getNext())
|
|
|
|
|
if(next != decl_bb)
|
|
|
|
|
if (reachable.insert(next).second)
|
|
|
|
|
to_insert.insert(next);
|
|
|
|
|
|
|
|
|
|
worklist = to_insert;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// return arg's definition if it really reaches dest_bb
|
|
|
|
|
// else - return NULL.
|
|
|
|
|
// dont alter returned expression. Otherwise Sage tree may change.
|
|
|
|
|
// note: use this function only for decl_bb from the same routine as dest_bb
|
|
|
|
|
SgExpression* getRd(int instr_num, SAPFOR::BasicBlock* decl_bb,
|
|
|
|
|
SAPFOR::Argument* arg, SAPFOR::BasicBlock* dest_bb,
|
|
|
|
|
map<SAPFOR::Argument*, SgExpression*>& available,
|
|
|
|
|
map<SAPFOR::Argument*, set<SAPFOR::Argument*>>& dependencies,
|
|
|
|
|
const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
|
|
|
|
FuncInfo* curr_func,
|
|
|
|
|
const map<string, CommonBlock*>& commonBlocks)
|
|
|
|
|
{
|
|
|
|
|
auto saved_available_it = saved_available.find(instr_num);
|
|
|
|
|
auto saved_dependencies_it = saved_dependencies.find(instr_num);
|
|
|
|
|
|
|
|
|
|
if (saved_available_it == saved_available.end() || saved_dependencies_it == saved_dependencies.end())
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
map<SAPFOR::Argument*, SgExpression*> temp_available = saved_available_it->second;
|
|
|
|
|
map<SAPFOR::Argument*, set<SAPFOR::Argument*>> temp_dependencies = saved_dependencies_it->second;
|
|
|
|
|
|
|
|
|
|
set<SAPFOR::Argument*> arg_rd_dep;
|
|
|
|
|
set<SAPFOR::Argument*> prevents = { };
|
|
|
|
|
|
|
|
|
|
int joined = 0;
|
|
|
|
|
bool all_dep_reaches = false;
|
|
|
|
|
|
|
|
|
|
while (joined == prevents.size())
|
|
|
|
|
{
|
|
|
|
|
prevents = { };
|
|
|
|
|
joined = 0;
|
|
|
|
|
auto arg_rd_it = temp_available.find(arg);
|
|
|
|
|
auto arg_dep_it = temp_dependencies.find(arg);
|
|
|
|
|
|
|
|
|
|
if (arg_rd_it == temp_available.end() || arg_dep_it == temp_dependencies.end())
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
for (auto e : arg_dep_it->second)
|
|
|
|
|
if (!isArgReaches(instr_num, decl_bb, e, dest_bb))
|
|
|
|
|
prevents.insert(e);
|
|
|
|
|
|
|
|
|
|
if (prevents.size() == 0)
|
|
|
|
|
{
|
|
|
|
|
all_dep_reaches = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto e : prevents)
|
|
|
|
|
if (joinChains(temp_available, temp_dependencies, e, commonVars, curr_func))
|
|
|
|
|
joined++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!all_dep_reaches)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
auto arg_rd_it = temp_available.find(arg);
|
|
|
|
|
auto arg_dep_it = temp_dependencies.find(arg);
|
|
|
|
|
|
|
|
|
|
if (arg_rd_it == temp_available.end() || arg_dep_it == temp_dependencies.end())
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
SgExpression* new_exp = copyExpr(arg_rd_it->second, curr_func, commonBlocks);
|
|
|
|
|
if (new_exp)
|
|
|
|
|
{
|
|
|
|
|
dependencies.insert(*arg_dep_it);
|
|
|
|
|
available[arg] = new_exp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new_exp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static SgExpression* replaceSingleConstRef(SgExpression* exp)
|
|
|
|
|
{
|
|
|
|
|
if (exp->variant() != CONST_REF)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
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())
|
|
|
|
|
return new SgValueExp(sign * toCalc->valueInteger());
|
|
|
|
|
else
|
|
|
|
|
return exp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool replaceConstantAndLink_(SgExpression* cur_exp, bool is_left,
|
|
|
|
|
SgExpression* exp, SgExpression*& backup)
|
|
|
|
|
{
|
|
|
|
|
SgExpression* sub_expr = is_left ? cur_exp->lhs() : cur_exp->rhs();
|
|
|
|
|
SgExpression* after_subst;
|
|
|
|
|
|
|
|
|
|
if (sub_expr)
|
|
|
|
|
{
|
|
|
|
|
if (after_subst = replaceSingleConstRef(sub_expr))
|
|
|
|
|
{
|
|
|
|
|
if (after_subst != sub_expr)
|
|
|
|
|
{
|
|
|
|
|
if (backup == NULL)
|
|
|
|
|
{
|
|
|
|
|
backup = exp->copyPtr();
|
|
|
|
|
createLinksToCopy(backup, exp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
is_left ? cur_exp->setLhs(after_subst) : cur_exp->setRhs(after_subst);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool calculateAndLink_(SgExpression* cur_exp, bool is_left,
|
|
|
|
|
SgExpression* exp, SgExpression*& backup)
|
|
|
|
|
{
|
|
|
|
|
int err, res;
|
|
|
|
|
|
|
|
|
|
SgExpression* sub_expr = is_left ? cur_exp->lhs() : cur_exp->rhs();
|
|
|
|
|
|
|
|
|
|
if (sub_expr)
|
|
|
|
|
{
|
|
|
|
|
err = CalculateInteger(sub_expr, res);
|
|
|
|
|
if (err != -1)
|
|
|
|
|
{
|
|
|
|
|
if (backup == NULL)
|
|
|
|
|
{
|
|
|
|
|
backup = exp->copyPtr();
|
|
|
|
|
createLinksToCopy(backup, exp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
is_left ? cur_exp->setLhs(new SgValueExp(res)) : cur_exp->setRhs(new SgValueExp(res));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if replacement occurs, returns a new expression (the new expression is linked to the original one)
|
|
|
|
|
// if there were no replacements, then returns NULL
|
|
|
|
|
static SgExpression* replaceConstantAndLink(SgStatement* stmt, int i)
|
|
|
|
|
{
|
|
|
|
|
SgExpression* exp = stmt->expr(i);
|
|
|
|
|
|
|
|
|
|
SgExpression* is_exp_constant = replaceSingleConstRef(exp);
|
|
|
|
|
|
|
|
|
|
if (is_exp_constant != NULL)
|
|
|
|
|
return is_exp_constant == exp ? NULL : is_exp_constant;
|
|
|
|
|
|
|
|
|
|
SgExpression* backup = NULL;
|
|
|
|
|
list<SgExpression*> to_process = { exp };
|
|
|
|
|
|
|
|
|
|
while (to_process.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
SgExpression* cur_exp = to_process.front();
|
|
|
|
|
to_process.pop_front();
|
|
|
|
|
|
|
|
|
|
if (replaceConstantAndLink_(cur_exp, true, exp, backup))
|
|
|
|
|
to_process.push_back(cur_exp->lhs());
|
|
|
|
|
|
|
|
|
|
if (replaceConstantAndLink_(cur_exp, false, exp, backup))
|
|
|
|
|
to_process.push_back(cur_exp->rhs());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int res;
|
|
|
|
|
if (CalculateInteger(exp, res) != -1)
|
|
|
|
|
{
|
|
|
|
|
if (backup)
|
|
|
|
|
stmt->setExpression(i, backup);
|
|
|
|
|
|
|
|
|
|
return new SgValueExp(res);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
to_process = { exp };
|
|
|
|
|
|
|
|
|
|
while (to_process.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
SgExpression* cur_exp = to_process.front();
|
|
|
|
|
to_process.pop_front();
|
|
|
|
|
|
|
|
|
|
if (calculateAndLink_(cur_exp, true, exp, backup))
|
|
|
|
|
to_process.push_back(cur_exp->lhs());
|
|
|
|
|
|
|
|
|
|
if (calculateAndLink_(cur_exp, false, exp, backup))
|
|
|
|
|
to_process.push_back(cur_exp->rhs());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (backup)
|
|
|
|
|
{
|
|
|
|
|
stmt->setExpression(i, backup);
|
|
|
|
|
return exp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void performExprSubstAndSave(SgStatement* stmt_to_subst, int i,
|
|
|
|
|
const map<SAPFOR::Argument*, SgExpression*>& available,
|
|
|
|
|
const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
|
|
|
|
const FuncInfo* func, const map<string, FuncInfo*>& funcByName)
|
|
|
|
|
{
|
|
|
|
|
SgExpression* expr_to_subst = stmt_to_subst->expr(i);
|
|
|
|
|
SgExpression* expr_with_replacements = NULL;
|
|
|
|
|
|
|
|
|
|
expr_with_replacements = performExprSubstAndLink(stmt_to_subst, i, available, commonVars, func, funcByName);
|
|
|
|
|
|
|
|
|
|
if (expr_with_replacements != NULL)
|
|
|
|
|
{
|
|
|
|
|
replaceConstantRec(expr_with_replacements);
|
|
|
|
|
calculate(expr_with_replacements);
|
|
|
|
|
addReplacementAndBackup(current_file->filename(), stmt_to_subst, i, expr_with_replacements);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
SgExpression* afterReplaceConstants = replaceConstantAndLink(stmt_to_subst, i);
|
|
|
|
|
|
|
|
|
|
if (afterReplaceConstants != NULL)
|
|
|
|
|
addReplacementAndBackup(current_file->filename(), stmt_to_subst, i, afterReplaceConstants);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void buildSubstitutions(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph_for_project,
|
|
|
|
|
const map<string, CommonBlock*>& commonBlocks, SgProject* project)
|
|
|
|
|
{
|
|
|
|
|
if (wereSubstitutionsBuilt())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
resetSubstitutionCounter();
|
|
|
|
|
|
|
|
|
|
map<string, FuncInfo*> funcByName;
|
|
|
|
|
for (const auto& byFunc : CFGraph_for_project)
|
|
|
|
|
funcByName[byFunc.first->funcName] = byFunc.first;
|
|
|
|
|
|
|
|
|
|
map<FuncInfo*, map<string, SgSymbol*>> commonArgsByFunc = { };
|
|
|
|
|
map<const FuncInfo*, map<SAPFOR::Argument*, SgExpression*>> availableForFunc = { };
|
|
|
|
|
map<const FuncInfo*, map<SAPFOR::Argument*, set<SAPFOR::Argument*>>> dependenciesForFunc = { };
|
|
|
|
|
|
|
|
|
|
set<string> analyzedFunctions = {};
|
|
|
|
|
|
|
|
|
|
for (auto& byFunc : CFGraph_for_project)
|
|
|
|
|
{
|
|
|
|
|
SgFile::switchToFile(byFunc.first->fileName);
|
|
|
|
|
|
|
|
|
|
// skip ENTRY, analyze only original functions
|
|
|
|
|
if (!(isSgProgHedrStmt(byFunc.first->funcPointer) || isSgProcHedrStmt(byFunc.first->funcPointer) ||
|
|
|
|
|
isSgFuncHedrStmt(byFunc.first->funcPointer)) || (analyzedFunctions.find(byFunc.first->funcName) != analyzedFunctions.end()))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
analyzedFunctions.insert(byFunc.first->funcName);
|
|
|
|
|
|
|
|
|
|
auto commonVars = getCommonsByFunction(current_file, byFunc.first->funcPointer, commonBlocks);
|
|
|
|
|
const auto& commonArgs = getCommonArgsByFunc(byFunc.first, commonArgsByFunc, commonVars, globals, locals);
|
|
|
|
|
|
|
|
|
|
unordered_set<SgStatement*> analyzedStmt;
|
|
|
|
|
|
|
|
|
|
auto sortedCfgNodes = sortCfgNodes(byFunc.second);
|
|
|
|
|
auto cfg_start_it = sortedCfgNodes.begin();
|
|
|
|
|
auto cfg_end_it = sortedCfgNodes.end();
|
|
|
|
|
|
|
|
|
|
for (auto cfg_it = cfg_start_it; cfg_it < cfg_end_it; cfg_it++)
|
|
|
|
|
{
|
|
|
|
|
SAPFOR::BasicBlock* cur_BB = *cfg_it;
|
|
|
|
|
map<SAPFOR::Argument*, SgExpression*> available; //available definitions
|
|
|
|
|
map<SAPFOR::Argument*, set<SAPFOR::Argument*>> dependencies;
|
|
|
|
|
|
|
|
|
|
set<int> idx_to_save = save_at_indexes(cur_BB);
|
|
|
|
|
auto idx_it = idx_to_save.begin();
|
|
|
|
|
auto idx_end_it = idx_to_save.end();
|
|
|
|
|
|
|
|
|
|
for (const auto& in_val : cur_BB->getRD_In())
|
|
|
|
|
{
|
|
|
|
|
if (in_val.first->getType() == CFG_ARG_TYPE::VAR && in_val.second.size() == 1)
|
|
|
|
|
{
|
|
|
|
|
int instr_num = *(in_val.second.begin());
|
|
|
|
|
if (instr_num < 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
auto cfg_find_bb = cfg_it + 1;
|
|
|
|
|
SAPFOR::BasicBlock* in_val_bb = NULL;
|
|
|
|
|
do {
|
|
|
|
|
cfg_find_bb--;
|
|
|
|
|
if ((*cfg_find_bb)->getInstructions().front()->getNumber() <= instr_num &&
|
|
|
|
|
(*cfg_find_bb)->getInstructions().back()->getNumber() >= instr_num)
|
|
|
|
|
{
|
|
|
|
|
in_val_bb = *cfg_find_bb;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} while (cfg_find_bb > cfg_start_it);
|
|
|
|
|
|
|
|
|
|
if (in_val_bb)
|
|
|
|
|
{
|
|
|
|
|
SgExpression* rd = getRd(instr_num, in_val_bb, in_val.first, cur_BB, available, dependencies, commonVars, byFunc.first, commonBlocks);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
pair<SAPFOR::Instruction*, SAPFOR::BasicBlock*> instr_and_bb = getInstructionAndBlockByNumber(CFGraph_for_project, instr_num);
|
|
|
|
|
if (getDependencies(in_val.first, instr_and_bb.first, instr_and_bb.second, dependencies))
|
|
|
|
|
{
|
|
|
|
|
//check if all variables affecting the definition can be used there
|
|
|
|
|
bool can_use = true;
|
|
|
|
|
auto dependencies_of_var = dependencies.find(in_val.first);
|
|
|
|
|
if (dependencies_of_var == dependencies.end())
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
for (SAPFOR::Argument* dep : dependencies_of_var->second)
|
|
|
|
|
{
|
2024-01-30 19:45:27 +03:00
|
|
|
if (!isArgReaches(instr_num, instr_and_bb.second, dep, cur_BB))
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
|
|
|
|
can_use = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dep->getMemType() == CFG_MEM_TYPE::COMMON_ && commonArgs.find(dep->getValue()) == commonArgs.end())
|
|
|
|
|
{
|
|
|
|
|
can_use = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (can_use && isBBlockFromCurrentFile(CFGraph_for_project, instr_and_bb.second))
|
|
|
|
|
{
|
|
|
|
|
SgExpression* expr_to_subst = copyExpr(instr_and_bb.first->getOperator()->expr(1), byFunc.first, commonBlocks);
|
|
|
|
|
if (expr_to_subst)
|
|
|
|
|
available[in_val.first] = expr_to_subst;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vector<SAPFOR::Argument*> arguments_of_func_call = { };
|
|
|
|
|
SgStatement* prev_stmt = NULL;
|
|
|
|
|
for (SAPFOR::IR_Block* byIR : cur_BB->getInstructions())
|
|
|
|
|
{
|
|
|
|
|
SAPFOR::Instruction* instruction = byIR->getInstruction();
|
|
|
|
|
int instruction_number = instruction->getNumber();
|
|
|
|
|
SAPFOR::CFG_OP instr_type = instruction->getOperation();
|
|
|
|
|
|
|
|
|
|
SAPFOR::Argument* instr_res = hasStoreStructure(instr_type) ? instruction->getArg1() : instruction->getResult();
|
|
|
|
|
|
|
|
|
|
SgStatement* cur_stmt = instruction->getOperator();
|
|
|
|
|
bool stmt_has_result = cur_stmt ? cur_stmt->variant() == ASSIGN_STAT : false;
|
|
|
|
|
|
|
|
|
|
if (cur_stmt && cur_stmt != prev_stmt && isIfOrLoopFromBB(cur_stmt, cur_BB)
|
|
|
|
|
&& cur_stmt->variant() != READ_STAT &&
|
|
|
|
|
analyzedStmt.insert(cur_stmt).second)
|
|
|
|
|
{
|
|
|
|
|
prev_stmt = cur_stmt;
|
|
|
|
|
|
|
|
|
|
int start_with_expression = 0;
|
|
|
|
|
if (stmt_has_result)
|
|
|
|
|
{
|
|
|
|
|
start_with_expression = 1;
|
|
|
|
|
|
|
|
|
|
SgExpression* result_of_stmt = cur_stmt->expr(0);
|
|
|
|
|
SgArrayRefExp* array_ref;
|
|
|
|
|
if (result_of_stmt && (array_ref = isSgArrayRefExp(result_of_stmt)) && array_ref->subscripts())
|
|
|
|
|
performExprSubstAndSave(cur_stmt, 0, available, commonVars, byFunc.first, funcByName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = start_with_expression; i < 3; i++)
|
|
|
|
|
if (cur_stmt->expr(i))
|
|
|
|
|
performExprSubstAndSave(cur_stmt, i, available, commonVars, byFunc.first, funcByName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (instr_res)
|
|
|
|
|
{
|
|
|
|
|
if (instr_res->getType() == CFG_ARG_TYPE::VAR || instr_res->getType() == CFG_ARG_TYPE::ARRAY)
|
|
|
|
|
{
|
|
|
|
|
if (instr_res->getType() == CFG_ARG_TYPE::VAR)
|
|
|
|
|
{
|
|
|
|
|
joinChains(available, dependencies, instr_res, commonVars, byFunc.first);
|
|
|
|
|
SgExpression* prev_expr = NULL;
|
|
|
|
|
set<SAPFOR::Argument*> prev_dep = {};
|
|
|
|
|
|
|
|
|
|
auto available_it = available.find(instr_res);
|
|
|
|
|
if (available_it != available.end())
|
|
|
|
|
{
|
|
|
|
|
prev_expr = available_it->second;
|
|
|
|
|
auto dependencies_it = dependencies.find(instr_res);
|
|
|
|
|
if (dependencies_it != dependencies.end())
|
|
|
|
|
prev_dep = dependencies_it->second;
|
|
|
|
|
else
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
available.erase(available_it);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (cur_stmt && stmt_has_result && getDependencies(instr_res, instruction, cur_BB, dependencies))
|
|
|
|
|
{
|
|
|
|
|
SgExpression* expr_to_subst = copyExpr(cur_stmt->expr(1), byFunc.first, commonBlocks);
|
|
|
|
|
|
|
|
|
|
auto dependencies_it = dependencies.find(instr_res);
|
|
|
|
|
if (dependencies_it != dependencies.end())
|
|
|
|
|
{
|
|
|
|
|
if (dependencies_it->second.count(instr_res) && prev_expr != NULL)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
SgExpression* next_expr_to_subst = substSingleSymb(expr_to_subst, instr_res, prev_expr, commonVars, byFunc.first);
|
|
|
|
|
if (next_expr_to_subst && next_expr_to_subst != expr_to_subst)
|
|
|
|
|
{
|
|
|
|
|
expr_to_subst = next_expr_to_subst;
|
|
|
|
|
|
|
|
|
|
dependencies_it->second.erase(instr_res);
|
|
|
|
|
dependencies_it->second.insert(prev_dep.begin(), prev_dep.end());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (expr_to_subst)
|
|
|
|
|
available[instr_res] = expr_to_subst;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const auto& p : dependencies)
|
|
|
|
|
if (p.second.count(instr_res))
|
|
|
|
|
available.erase(p.first);
|
|
|
|
|
|
|
|
|
|
while (idx_it != idx_end_it && *idx_it < instruction_number)
|
|
|
|
|
idx_it++;
|
|
|
|
|
if (idx_it != idx_end_it && *idx_it == instruction_number)
|
|
|
|
|
save_chains(instruction_number, available, dependencies, instr_res);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (instr_type == CFG_OP::PARAM)
|
|
|
|
|
arguments_of_func_call.push_back(instruction->getArg1());
|
|
|
|
|
|
|
|
|
|
if (instr_type == CFG_OP::F_CALL)
|
|
|
|
|
{
|
|
|
|
|
string func_name = instruction->getArg1()->getValue();
|
|
|
|
|
auto func_to_call_it = CFGraph_for_project.begin();
|
|
|
|
|
auto end_of_CFG = CFGraph_for_project.end();
|
|
|
|
|
for (; func_to_call_it != end_of_CFG; func_to_call_it++)
|
|
|
|
|
{
|
|
|
|
|
const auto& p = func_to_call_it->first;
|
|
|
|
|
if (p->funcName == func_name)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (func_to_call_it != end_of_CFG)
|
|
|
|
|
{
|
|
|
|
|
FuncInfo* func = func_to_call_it->first;
|
|
|
|
|
|
|
|
|
|
int number_of_params = arguments_of_func_call.size();
|
|
|
|
|
for (int i = 0; i < number_of_params; i++)
|
|
|
|
|
{
|
|
|
|
|
if (!func->funcParams.isArgOut(i))
|
|
|
|
|
arguments_of_func_call[i] = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const set<SAPFOR::Argument*>& affected_vars = func_affects(func, func_to_call_it->second);
|
|
|
|
|
|
|
|
|
|
for (auto& affected : affected_vars)
|
|
|
|
|
{
|
|
|
|
|
joinChains(available, dependencies, affected, commonVars, byFunc.first);
|
|
|
|
|
|
|
|
|
|
for (const auto& p : dependencies)
|
|
|
|
|
if (p.second.count(affected))
|
|
|
|
|
available.erase(p.first);
|
|
|
|
|
|
|
|
|
|
if (available.count(affected))
|
|
|
|
|
available.erase(affected);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto add_to_available = func_makes_available(func, project, availableForFunc, dependenciesForFunc, func_to_call_it->second, CFGraph_for_project, dependencies, byFunc.first, commonBlocks);
|
|
|
|
|
available.insert(add_to_available.begin(), add_to_available.end());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto& func_arg : arguments_of_func_call)
|
|
|
|
|
if (func_arg &&
|
|
|
|
|
func_arg->getType() != SAPFOR::CFG_ARG_TYPE::CONST &&
|
|
|
|
|
func_arg->getType() != SAPFOR::CFG_ARG_TYPE::CONST_STR)
|
|
|
|
|
{
|
|
|
|
|
joinChains(available, dependencies, func_arg, commonVars, byFunc.first);
|
|
|
|
|
|
|
|
|
|
for (const auto& p : dependencies)
|
|
|
|
|
if (p.second.count(func_arg))
|
|
|
|
|
available.erase(p.first);
|
|
|
|
|
|
|
|
|
|
available.erase(func_arg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
arguments_of_func_call.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
locals.clear();
|
|
|
|
|
saved_available.clear();
|
|
|
|
|
saved_dependencies.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setSubstitutionsWereBuilt(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void performRDSubst(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph_for_project,
|
|
|
|
|
const map<string, CommonBlock*>& commonBlocks, SgProject* project)
|
|
|
|
|
{
|
|
|
|
|
if (!wereSubstitutionsBuilt())
|
|
|
|
|
buildSubstitutions(CFGraph_for_project, commonBlocks, project);
|
|
|
|
|
else
|
|
|
|
|
updateOldExpression();
|
|
|
|
|
|
|
|
|
|
__spf_print(PRINT_PROF_INFO, "total number of substitutions: %d\n", getSubstitutionCounter());
|
|
|
|
|
|
|
|
|
|
if (!wereSubstitutionsApplied())
|
|
|
|
|
{
|
|
|
|
|
applyReplacement(replacementsInFiles);
|
|
|
|
|
setSubstitutionsApplied(true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void revertSubstitutions()
|
|
|
|
|
{
|
|
|
|
|
if (wereSubstitutionsBuilt() && wereSubstitutionsApplied())
|
|
|
|
|
{
|
|
|
|
|
applyReplacement(oldExpressionsInFile);
|
|
|
|
|
setSubstitutionsApplied(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cancelRevertionForStatement(string filename, SgStatement* stmt, int i) {
|
|
|
|
|
if (i < 0 || i > 2 || !stmt)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
removeInfo(oldExpressionsInFile, filename, stmt, i);
|
|
|
|
|
removeInfo(replacementsInFiles, filename, stmt, i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*void destroyReplacementsInFiles()
|
|
|
|
|
{
|
|
|
|
|
replacementsInFiles.clear();
|
|
|
|
|
setSubstitutionsWereBuilt(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void destroyOldExpressionsInFile()
|
|
|
|
|
{
|
|
|
|
|
oldExpressionsInFile.clear();
|
|
|
|
|
setSubstitutionsWereBuilt(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void destroyAllSubstitutionsData()
|
|
|
|
|
{
|
|
|
|
|
destroyReplacementsInFiles();
|
|
|
|
|
destroyOldExpressionsInFile();
|
|
|
|
|
setSubstitutionsWereBuilt(false);
|
|
|
|
|
setSubstitutionsApplied(false);
|
|
|
|
|
}*/
|