This commit is contained in:
2025-03-12 12:37:19 +03:00
committed by Dudarenko
parent 0c9f0664fd
commit d4fb323f86
428 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,761 @@
#include "live_variable_analysis.h"
#include "RD_subst.h"
#include "DataFlow/backward_data_flow.h"
#include <string>
#include <vector>
#include <map>
#include <set>
#include <list>
#include <unordered_map>
#include <algorithm>
using std::string;
using std::pair;
using std::vector;
using std::map;
using std::set;
using std::unordered_map;
using std::list;
using LIVE_VARIABLES::LiveDeadVarsForCall;
namespace SAPFOR
{
bool BasicBlock::addLive(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& to_add, bool in) {
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& current_set = (in ? live_in : live_out);
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& opposite_set = (!in ? live_in : live_out);
bool inserted = false;
for (const auto& byNew : to_add)
{
const vector<SAPFOR::BasicBlock*>& add_in_live = byNew.second;
vector<SAPFOR::BasicBlock*> new_in_live = {};
auto current_set_iter = current_set.find(byNew.first);
if (current_set_iter == current_set.end())
new_in_live = add_in_live;
else
std::set_difference(add_in_live.begin(), add_in_live.end(), current_set_iter->second.begin(), current_set_iter->second.end(), std::inserter(new_in_live, new_in_live.begin()));
auto opposite_set_iter = opposite_set.find(byNew.first);
auto both_set_iter = live_inout.find(byNew.first);
if (new_in_live.size() != 0)
{
inserted = true;
bool current_set_has_argument = current_set_iter != current_set.end();
bool opposite_set_has_argument = opposite_set_iter != opposite_set.end();
bool both_set_has_argument = both_set_iter != live_inout.end();
for (SAPFOR::BasicBlock* bb : new_in_live)
{
bool insert_to_both = false;
if (opposite_set_has_argument)
{
auto& usages_from_opposite = opposite_set_iter->second;
auto find_bb_from_opposite = std::lower_bound(usages_from_opposite.begin(), usages_from_opposite.end(), bb);
if (find_bb_from_opposite != usages_from_opposite.end() && *find_bb_from_opposite == bb)
{
insert_to_both = true;
usages_from_opposite.erase(find_bb_from_opposite);
if (usages_from_opposite.size() == 0) {
opposite_set.erase(opposite_set_iter);
opposite_set_has_argument = false;
}
}
}
if (insert_to_both)
{
if (!both_set_has_argument) {
both_set_iter = live_inout.insert({ byNew.first, {} }).first;
both_set_has_argument = true;
}
}
else
{
if (!current_set_has_argument) {
current_set_iter = current_set.insert({ byNew.first, {} }).first;
current_set_has_argument = true;
}
}
vector<SAPFOR::BasicBlock*>& dest = insert_to_both ? both_set_iter->second : current_set_iter->second;
auto find_bb_from_dest = std::lower_bound(dest.begin(), dest.end(), bb);
if (find_bb_from_dest == dest.end() || *find_bb_from_dest != bb)
dest.insert(find_bb_from_dest, bb);
}
}
}
return inserted;
}
bool BasicBlock::removeLive(SAPFOR::Argument* to_remove, bool in)
{
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& current_set = (in ? live_in : live_out);
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& opposite_set = (!in ? live_in : live_out);
bool removed = false;
removed |= (current_set.erase(to_remove) != 0);
auto it = live_inout.find(to_remove);
if (it != live_inout.end())
{
auto& dest = opposite_set[to_remove];
for (SAPFOR::BasicBlock* bb : it->second)
{
auto find_bb_from_dest = std::lower_bound(dest.begin(), dest.end(), bb);
if (find_bb_from_dest == dest.end() || *find_bb_from_dest != bb)
dest.insert(find_bb_from_dest, bb);
}
live_inout.erase(to_remove);
removed = true;
}
return removed;
}
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> BasicBlock::getLive(bool in) const {
auto& current_set = in ? live_in : live_out;
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> res;
for (auto& by_source : { current_set, live_inout })
{
for (auto& by_pair : by_source)
{
auto& dest = res[by_pair.first];
auto dest_copy = dest;
dest.resize(dest_copy.size() + by_pair.second.size());
set_union(dest_copy.begin(), dest_copy.end(), by_pair.second.begin(), by_pair.second.end(), dest.begin());
}
}
return res;
}
void BasicBlock::compressLives() {
for (auto& bySrc : { &live_in, &live_out, &live_inout })
for (auto& byArg : *bySrc)
byArg.second.shrink_to_fit();
}
}
bool LiveDeadVarsForCall::tryInsert(set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b)
{
if (b == block || dest.find(block) == dest.end())
{
dest.insert(b);
return true;
}
return false;
}
LiveDeadVarsForCall::LiveDeadVarsForCall(FuncInfo* f, SAPFOR::BasicBlock* b, const vector<SAPFOR::Argument*>& p)
{
block = b;
func = f;
int param_size = p.size();
params = vector<SAPFOR::Argument*>(param_size, NULL);
for (int i = 0; i < param_size; i++)
if (f->funcParams.isArgOut(i))
params[i] = p[i];
}
void LiveDeadVarsForCall::make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b)
{
if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_)
{
if (commons_dead_after.find(arg) == commons_dead_after.end())
tryInsert(commons_live_after[arg], b);
}
auto it = find(params.begin(), params.end(), arg);
if (it != params.end())
{
int idx = it - params.begin();
if (dead_after.find(idx) == dead_after.end())
tryInsert(live_after[idx], b);
}
}
void LiveDeadVarsForCall::make_dead(SAPFOR::Argument* arg)
{
if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_)
{
if (commons_live_after.find(arg) == commons_live_after.end())
commons_dead_after.insert(arg);
}
auto it = find(params.begin(), params.end(), arg);
if (it != params.end())
{
int idx = it - params.begin();
if (live_after.find(idx) == live_after.end())
dead_after.insert(idx);
}
}
void LiveDeadVarsForCall::updateFromOut()
{
for (const auto& p : block->getLiveOut())
for (auto b : p.second)
make_live(p.first, b);
}
static bool getLiveDead(const vector<SAPFOR::Argument*>& params, const string& func_name,
set<SAPFOR::Argument*>& live, set<SAPFOR::Argument*>& dead);
static void buildUseDef(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
const map<string, FuncInfo*>& funcByName, bool interprocedural);
class LiveVarAnalysisNode : public DataFlowAnalysisNode<map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>> {
private:
set<SAPFOR::Argument*> live, dead;
public:
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> getIn()
{
return getBlock()->getLiveOut();
}
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> getOut()
{
return getBlock()->getLiveIn();
}
bool addIn(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
{
return getBlock()->addLiveOut(data);
}
bool addOut(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
{
return getBlock()->addLiveIn(data);
}
DATA_FLOW_UPD_STATUS forwardData(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
{
bool inserted = false;
for (const auto& byArg : data)
if (live.find(byArg.first) == live.end() && dead.find(byArg.first) == dead.end())
inserted |= getBlock()->addLiveIn({ byArg });
return inserted ? DATA_FLOW_UPD_STATUS::PROPAGATED : DATA_FLOW_UPD_STATUS::NO_CHANGE;
}
LiveVarAnalysisNode(SAPFOR::BasicBlock* block, vector<SAPFOR::Argument*>& formal_parameters,
vector<LiveDeadVarsForCall>& fcalls, const map<string, FuncInfo*>& funcByName)
{
setBlock(block);
buildUseDef(getBlock(), live, dead, formal_parameters, fcalls, funcByName, true);
for (SAPFOR::Argument* arg : live)
getBlock()->addLiveIn({ { arg, { getBlock() } } });
}
};
class LiveVarAnalysis : public BackwardDataFlowAnalysis<LiveVarAnalysisNode> {
protected:
vector<SAPFOR::Argument*>& formal_parameters;
vector<LiveDeadVarsForCall>& fcalls;
const map<string, FuncInfo*>& funcByName;
LiveVarAnalysisNode* createNode(SAPFOR::BasicBlock* block) override {
return new LiveVarAnalysisNode(block, formal_parameters, fcalls, funcByName);
}
public:
LiveVarAnalysis(vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
const map<string, FuncInfo*>& funcByName) : formal_parameters(formal_parameters), fcalls(fcalls), funcByName(funcByName)
{ }
};
void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
vector<SAPFOR::Argument*>& arg_stack, int& arg_stack_index, int& arg_stack_size,
bool& last_stack_op,
string& fName, const map<string, FuncInfo*>& funcByName, bool interprocedural)
{
for (auto arg : { instr->getArg1(), instr->getArg2(), instr->getResult() })
if (arg && arg->getMemType() == SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_)
formal_parameters[getParamIndex(arg, formal_parameters.size())] = arg;
last_stack_op = false;
SAPFOR::Argument* res_arg = NULL;
static const set<SAPFOR::CFG_OP> skip = { SAPFOR::CFG_OP::ENTRY };
SAPFOR::CFG_OP instr_operation = instr->getOperation();
if (instr_operation == SAPFOR::CFG_OP::F_CALL ||
instr_operation == SAPFOR::CFG_OP::STORE ||
instr_operation == SAPFOR::CFG_OP::LOAD)
{
res_arg = (instr_operation == SAPFOR::CFG_OP::STORE ? instr->getArg1() : instr->getResult());
if(instr_operation != SAPFOR::CFG_OP::F_CALL)
use.insert(instr_operation != SAPFOR::CFG_OP::STORE ? instr->getArg1() : instr->getResult());
arg_stack_size = stoi(instr->getArg2()->getValue());
arg_stack.clear();
arg_stack.resize(arg_stack_size);
arg_stack_index = arg_stack_size - 1;
if(instr_operation == SAPFOR::CFG_OP::F_CALL)
fName = instr->getArg1()->getValue();
}
else if (hasStoreStructure(instr_operation))
{
res_arg = instr->getArg1();
set<SAPFOR::Argument*> instr_args = { instr->getResult(), instr->getArg2() };
use.insert(instr_args.begin(), instr_args.end());
}
else if (instr_operation == SAPFOR::CFG_OP::PARAM || instr_operation == SAPFOR::CFG_OP::REF)
{
arg_stack[arg_stack_index--] = instr->getArg1();
}
else if (skip.find(instr_operation) == skip.end())
{
//default
res_arg = instr->getResult();
std::set<SAPFOR::Argument*> intr_args = { instr->getArg1(), instr->getArg2() };
use.insert(intr_args.begin(), intr_args.end());
}
else
{
//skip
return;
}
if (arg_stack_index < 0) {
if(instr_operation == SAPFOR::CFG_OP::PARAM || instr_operation == SAPFOR::CFG_OP::F_CALL)
{
auto func_it = funcByName.find(fName);
if (interprocedural && func_it != funcByName.end())
{
fcalls.push_back(LiveDeadVarsForCall(func_it->second, block, arg_stack));
auto r_it = fcalls.rbegin();
auto r_end = fcalls.rend();
for (auto e : def)
r_it->make_dead(e);
for (auto e : use)
r_it->make_live(e, block);
}
set<SAPFOR::Argument*> make_live, make_dead;
if (fName == "_READ")
def.insert(arg_stack.begin(), arg_stack.end());
else if (interprocedural && getLiveDead(arg_stack, fName, make_live, make_dead))
{
use.insert(make_live.begin(), make_live.end());
def.insert(make_dead.begin(), make_dead.end());
}
else if (func_it != funcByName.end())
{
int arg_num = arg_stack.size();
for (int i = 0; i < arg_num; i++)
{
if(func_it->second->funcParams.isArgOut(i))
def.insert(arg_stack[i]);
if (func_it->second->funcParams.isArgIn(i))
use.insert(arg_stack[i]);
}
}
else
use.insert(arg_stack.begin(), arg_stack.end());
fName = "";
}
else
{
use.insert(arg_stack.begin(), arg_stack.end());
}
arg_stack_index = 0;
arg_stack_size = 0;
arg_stack.clear();
last_stack_op = true;
}
if (res_arg)
def.insert(res_arg);
}
static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
vector<SAPFOR::Argument*>& arg_stack, int& arg_stack_index, int& arg_stack_size,
string& fName, const map<string, FuncInfo*>& funcByName, bool interprocedural)
{
set<SAPFOR::Argument*> res, args;
bool last_stack_op;
getUseDefForInstruction(block, instr,
args, res,
formal_parameters, fcalls,
arg_stack, arg_stack_index, arg_stack_size,
last_stack_op,
fName, funcByName,
interprocedural
);
for (auto e : res)
{
if (e && e->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
{
def.insert(e);
use.erase(e);
}
}
for (auto e : args)
{
if (e && e->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
{
use.insert(e);
def.erase(e);
}
}
}
//Build use and def sets of block. Result are stored in use and def
static void buildUseDef(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
const map<string, FuncInfo*>& funcByName, bool interprocedural)
{
vector<SAPFOR::Argument*> arg_stack;
int arg_stack_index = 0, arg_stack_size = 0;
string fName;
const auto& instructions = block->getInstructions();
auto ir_block_it = instructions.rbegin(), ir_block_end = instructions.rend();
for (; ir_block_it != ir_block_end; ir_block_it++)
{
updateUseDefForInstruction(block, (*ir_block_it)->getInstruction(),
use, def,
formal_parameters, fcalls,
arg_stack, arg_stack_index, arg_stack_size,
fName, funcByName,
interprocedural
);
}
}
// prints info about live variables
void doDumpLive(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph_for_project)
{
for (const auto& byFunc : CFGraph_for_project)
{
__spf_print(1, "============================================\n");
__spf_print(1, "Live variables '%s' function\n", byFunc.first->funcName.c_str());
__spf_print(1, "============================================\n");
for (auto byBB : byFunc.second)
{
__spf_print(1, "[BB %d]\n", byBB->getNumber());
__spf_print(1, " IN:\n");
for (const auto& live : byBB->getLiveIn())
{
__spf_print(1, " %s:", live.first->getValue().c_str());
for (auto use : live.second)
__spf_print(1, " %d", use->getNumber());
__spf_print(1, "\n");
}
__spf_print(1, " OUT:\n");
for (const auto& live : byBB->getLiveOut())
{
__spf_print(1, " %s:", live.first->getValue().c_str());
for (auto use : live.second)
__spf_print(1, " %d", use->getNumber());
__spf_print(1, "\n");
}
}
}
}
// sets for the next function
static map<string, pair<set<int>, set<SAPFOR::Argument*>>> live_by_func, dead_by_func;
// fill sets of arguments wich becomes live or dead after call of this function
static void fillLiveDeadArgs(const FuncInfo* func, const vector<SAPFOR::BasicBlock*>& blocks)
{
if (blocks.size() == 0)
return;
SAPFOR::BasicBlock* entrypoint = NULL;
int entrypoint_first_instr = 0;
set<SAPFOR::BasicBlock*> exits = {};
for (auto block : blocks)
{
if (block->getNext().size() == 0)
exits.insert(block);
if (block->getInstructions().front()->isHeader())
{
if (!entrypoint || block->getInstructions()[0]->getNumber() < entrypoint_first_instr)
{
entrypoint_first_instr = block->getInstructions()[0]->getNumber();
entrypoint = block;
}
}
}
if (!entrypoint)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
set<int> live, dead;
set<SAPFOR::Argument*> common_live, common_dead;
for (const auto& arg : entrypoint->getLiveIn())
{
switch (arg.first->getMemType())
{
case SAPFOR::CFG_MEM_TYPE::COMMON_:
case SAPFOR::CFG_MEM_TYPE::MODULE_:
common_live.insert(arg.first);
break;
case SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_:
{
int num = getParamIndex(arg.first, func->funcParams.countOfPars);
if (func->funcParams.isArgIn(num))
live.insert(num);
break;
}
}
}
for (auto byExit : exits)
{
for (const auto& byRd : byExit->getRD_Out())
{
auto out_arg = byRd.first;
if (!(byRd.second.size() == 1 && *(byRd.second.begin()) < 0))
{
switch (out_arg->getMemType())
{
case SAPFOR::CFG_MEM_TYPE::COMMON_:
case SAPFOR::CFG_MEM_TYPE::MODULE_:
if (!common_live.count(out_arg))
common_dead.insert(out_arg);
break;
case SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_:
{
int num = getParamIndex(out_arg, func->funcParams.countOfPars);
if (!live.count(num) && func->funcParams.isArgOut(num))
dead.insert(num);
break;
}
}
}
}
}
live_by_func[func->funcName] = { live, common_live };
dead_by_func[func->funcName] = { dead, common_dead };
}
// unite global arguments and actual parameters with given indexes for function
// stores the result in the last argument
bool joinGlobalsWithParameters(const vector<SAPFOR::Argument*>& params,
const map<string, pair<set<int>, set<SAPFOR::Argument*>>>& params_and_globals,
const string& func_name, set<SAPFOR::Argument*>& result)
{
auto globals_it = params_and_globals.find(func_name);
if (globals_it == params_and_globals.end())
return false;
const auto& param_indexes = globals_it->second.first;
const auto& globals = globals_it->second.second;
int params_size = params.size();
for (int idx : param_indexes)
{
if (idx < params_size) {
if (params[idx] && params[idx]->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
result.insert(params[idx]);
}
else
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
result.insert(globals.begin(), globals.end());
return true;
}
// fill sets of arguments wich becomes live or dead after call with parameters params
static bool getLiveDead(const vector<SAPFOR::Argument*>& params, const string& func_name,
set<SAPFOR::Argument*>& live, set<SAPFOR::Argument*>& dead)
{
return joinGlobalsWithParameters(params, live_by_func, func_name, live) &&
joinGlobalsWithParameters(params, dead_by_func, func_name, dead);
}
// entrypoint for live variable analysis pass
void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph_for_project)
{
/*
Here we assume that there is no recursive (explicit or implicit) calls.
So it is easy to process CALL instruction: just use live_in set of first block
for this function (that has already been built).
*/
map<FuncInfo*, set<FuncInfo*>> callDeps;
map<string, FuncInfo*> funcByName;
for (auto& byFunc : CFGraph_for_project)
{
callDeps[byFunc.first].insert(byFunc.first->callsFromV.begin(), byFunc.first->callsFromV.end());
funcByName[byFunc.first->funcName] = byFunc.first;
}
vector<set<FuncInfo*>> scc;
vector<set<FuncInfo*>> callLvls = groupByCallDependencies(callDeps, scc);
map<string, LiveVarAnalysis*> func_to_analysis_object;
map<string, vector<SAPFOR::Argument*>> func_to_parameters;
list<vector<LiveDeadVarsForCall>> live_for_fcalls;
//TODO: take into account ssc structure
// main stage
for (auto& byLvl : callLvls)
{
live_for_fcalls.push_front({});
auto& curr_fcalls = live_for_fcalls.front();
for (auto& byFunc : byLvl)
{
auto itCFG = CFGraph_for_project.find(byFunc);
if (itCFG == CFGraph_for_project.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
auto& params = func_to_parameters[byFunc->funcName] = vector<SAPFOR::Argument*>(byFunc->funcParams.countOfPars, NULL);
LiveVarAnalysis* analysis_object = (func_to_analysis_object[byFunc->funcName] = new LiveVarAnalysis(params, curr_fcalls, funcByName));
analysis_object->fit(itCFG->second);
analysis_object->analyze();
fillLiveDeadArgs(byFunc, itCFG->second);
}
}
// interprocedural analysis
for (auto& calls_vector : live_for_fcalls)
{
map<FuncInfo*, LiveDeadVarsForCall> assembled_fcalls;
for (auto& call : calls_vector)
{
call.updateFromOut();
call.params.clear();
call.commons_dead_after.clear();
call.dead_after.clear();
auto it = assembled_fcalls.find(call.func);
if (it == assembled_fcalls.end())
it = assembled_fcalls.insert({ call.func, LiveDeadVarsForCall(call.func, call.block, {}) }).first;
for (const auto& p : call.live_after)
it->second.live_after[p.first].insert(p.second.begin(), p.second.end());
for (const auto& p : call.commons_live_after)
it->second.commons_live_after[p.first].insert(p.second.begin(), p.second.end());
}
for (const auto& func : assembled_fcalls)
{
auto func_it = func_to_analysis_object.find(func.first->funcName);
if (func_it == func_to_analysis_object.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
auto param_it = func_to_parameters.find(func.first->funcName);
if (param_it == func_to_parameters.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
const vector<SAPFOR::Argument*>& params = param_it->second;
auto params_begin = params.begin(), params_end = params.end();
map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>> live_after = func.second.commons_live_after;
for (auto curr = params_begin; curr < params_end; curr++)
{
if (*curr)
{
const auto& live_param_it = func.second.live_after.find(curr - params_begin);
if (live_param_it != func.second.live_after.end())
live_after[*curr].insert(live_param_it->second.begin(), live_param_it->second.end());
}
}
set<LiveVarAnalysisNode*> exits;
int max_cnt = LiveVarAnalysisNode::getStartCounter();
for (auto block : func_it->second->getNodes())
{
if (block->getBlock()->getNext().size() == 0)
exits.insert(block);
if (block->getInCnt() > max_cnt)
max_cnt = block->getInCnt();
}
max_cnt++;
for (auto exit : exits)
{
for (const auto& byArg : live_after)
{
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> converted;
converted[byArg.first] = vector<SAPFOR::BasicBlock*>(byArg.second.begin(), byArg.second.end());
if (exit->addIn(converted))
{
exit->setInCnt(max_cnt);
if (exit->forwardData(converted) != DATA_FLOW_UPD_STATUS::NO_CHANGE)
exit->setOutCnt(max_cnt);
}
}
}
// now we can update live sets in all blocks
func_it->second->analyze();
}
}
for (const auto& byFunc : func_to_analysis_object)
delete byFunc.second;
for (auto& byFunc : CFGraph_for_project)
for (auto& byBlock : byFunc.second)
byBlock->compressLives();
live_by_func.clear();
dead_by_func.clear();
}