2023-09-14 19:43:13 +03:00
|
|
|
#include "live_variable_analysis.h"
|
|
|
|
|
#include "RD_subst.h"
|
2024-01-09 17:28:28 +03:00
|
|
|
#include "DataFlow/backward_data_flow.h"
|
2023-09-14 19:43:13 +03:00
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <map>
|
|
|
|
|
#include <set>
|
|
|
|
|
#include <list>
|
|
|
|
|
#include <unordered_map>
|
2024-04-07 16:38:57 +03:00
|
|
|
#include <algorithm>
|
2023-09-14 19:43:13 +03:00
|
|
|
|
|
|
|
|
using std::string;
|
|
|
|
|
using std::pair;
|
|
|
|
|
using std::vector;
|
|
|
|
|
using std::map;
|
|
|
|
|
using std::set;
|
|
|
|
|
using std::unordered_map;
|
|
|
|
|
using std::list;
|
|
|
|
|
|
2024-01-12 16:11:21 +03:00
|
|
|
using LIVE_VARIABLES::LiveDeadVarsForCall;
|
2024-01-09 18:13:56 +03:00
|
|
|
|
2023-09-14 19:43:13 +03:00
|
|
|
namespace SAPFOR
|
|
|
|
|
{
|
2024-01-10 16:20:48 +03:00
|
|
|
bool BasicBlock::addLive(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& to_add, bool in) {
|
2023-09-14 19:43:13 +03:00
|
|
|
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)
|
|
|
|
|
{
|
2024-01-10 16:20:48 +03:00
|
|
|
const vector<SAPFOR::BasicBlock*>& add_in_live = byNew.second;
|
|
|
|
|
vector<SAPFOR::BasicBlock*> new_in_live = {};
|
2024-01-09 18:13:56 +03:00
|
|
|
|
2023-09-14 19:43:13 +03:00
|
|
|
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;
|
2024-01-14 13:26:21 +03:00
|
|
|
}
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2024-01-09 18:28:50 +03:00
|
|
|
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);
|
|
|
|
|
|
2024-05-22 10:33:58 +03:00
|
|
|
auto it = live_inout.find(to_remove);
|
2024-01-09 18:28:50 +03:00
|
|
|
|
2024-05-22 10:33:58 +03:00
|
|
|
if (it != live_inout.end())
|
|
|
|
|
{
|
|
|
|
|
auto& dest = opposite_set[to_remove];
|
|
|
|
|
for (SAPFOR::BasicBlock* bb : it->second)
|
2024-01-09 18:28:50 +03:00
|
|
|
{
|
2024-05-22 10:33:58 +03:00
|
|
|
auto find_bb_from_dest = std::lower_bound(dest.begin(), dest.end(), bb);
|
2024-01-09 18:28:50 +03:00
|
|
|
|
2024-05-22 10:33:58 +03:00
|
|
|
if (find_bb_from_dest == dest.end() || *find_bb_from_dest != bb)
|
|
|
|
|
dest.insert(find_bb_from_dest, bb);
|
2024-01-09 18:28:50 +03:00
|
|
|
}
|
2024-05-22 10:33:58 +03:00
|
|
|
|
|
|
|
|
live_inout.erase(to_remove);
|
|
|
|
|
removed = true;
|
2024-01-09 18:28:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return removed;
|
2024-01-14 13:26:21 +03:00
|
|
|
}
|
2024-01-09 18:28:50 +03:00
|
|
|
|
2024-01-10 16:20:48 +03:00
|
|
|
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> BasicBlock::getLive(bool in) const {
|
2023-09-14 19:43:13 +03:00
|
|
|
auto& current_set = in ? live_in : live_out;
|
|
|
|
|
|
2024-01-10 16:20:48 +03:00
|
|
|
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> res;
|
2023-09-14 19:43:13 +03:00
|
|
|
|
|
|
|
|
for (auto& by_source : { current_set, live_inout })
|
2024-01-10 16:20:48 +03:00
|
|
|
{
|
2023-09-14 19:43:13 +03:00
|
|
|
for (auto& by_pair : by_source)
|
2024-01-10 16:20:48 +03:00
|
|
|
{
|
|
|
|
|
auto& dest = res[by_pair.first];
|
2024-04-07 16:38:57 +03:00
|
|
|
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());
|
2024-01-10 16:20:48 +03:00
|
|
|
}
|
|
|
|
|
}
|
2023-09-14 19:43:13 +03:00
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
2024-01-09 18:13:56 +03:00
|
|
|
|
2023-09-14 19:43:13 +03:00
|
|
|
void BasicBlock::compressLives() {
|
|
|
|
|
for (auto& bySrc : { &live_in, &live_out, &live_inout })
|
|
|
|
|
for (auto& byArg : *bySrc)
|
|
|
|
|
byArg.second.shrink_to_fit();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-12 16:11:21 +03:00
|
|
|
bool LiveDeadVarsForCall::tryInsert(set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2024-01-09 18:13:56 +03:00
|
|
|
if (b == block || dest.find(block) == dest.end())
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2024-01-09 18:13:56 +03:00
|
|
|
dest.insert(b);
|
|
|
|
|
return true;
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
|
|
|
|
|
2024-01-09 18:13:56 +03:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-12 16:11:21 +03:00
|
|
|
LiveDeadVarsForCall::LiveDeadVarsForCall(FuncInfo* f, SAPFOR::BasicBlock* b, const vector<SAPFOR::Argument*>& p)
|
2024-01-09 18:13:56 +03:00
|
|
|
{
|
|
|
|
|
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];
|
|
|
|
|
}
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2024-01-12 16:11:21 +03:00
|
|
|
void LiveDeadVarsForCall::make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b)
|
2024-01-09 18:13:56 +03:00
|
|
|
{
|
|
|
|
|
if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2024-01-09 18:13:56 +03:00
|
|
|
if (commons_dead_after.find(arg) == commons_dead_after.end())
|
|
|
|
|
tryInsert(commons_live_after[arg], b);
|
|
|
|
|
}
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2024-01-09 18:13:56 +03:00
|
|
|
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);
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
2024-01-09 18:13:56 +03:00
|
|
|
}
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2024-01-12 16:11:21 +03:00
|
|
|
void LiveDeadVarsForCall::make_dead(SAPFOR::Argument* arg)
|
2024-01-09 18:13:56 +03:00
|
|
|
{
|
|
|
|
|
if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2024-01-09 18:13:56 +03:00
|
|
|
if (commons_live_after.find(arg) == commons_live_after.end())
|
2023-09-14 19:43:13 +03:00
|
|
|
commons_dead_after.insert(arg);
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-09 18:13:56 +03:00
|
|
|
auto it = find(params.begin(), params.end(), arg);
|
|
|
|
|
if (it != params.end())
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2024-01-09 18:13:56 +03:00
|
|
|
int idx = it - params.begin();
|
|
|
|
|
if (live_after.find(idx) == live_after.end())
|
|
|
|
|
dead_after.insert(idx);
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
2024-01-09 18:13:56 +03:00
|
|
|
}
|
|
|
|
|
|
2024-01-12 16:11:21 +03:00
|
|
|
void LiveDeadVarsForCall::updateFromOut()
|
2024-01-09 18:13:56 +03:00
|
|
|
{
|
|
|
|
|
for (const auto& p : block->getLiveOut())
|
|
|
|
|
for (auto b : p.second)
|
|
|
|
|
make_live(p.first, b);
|
|
|
|
|
}
|
2023-09-14 19:43:13 +03:00
|
|
|
|
|
|
|
|
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,
|
2024-01-12 16:11:21 +03:00
|
|
|
vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
|
2024-01-09 18:13:56 +03:00
|
|
|
const map<string, FuncInfo*>& funcByName, bool interprocedural);
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2024-01-10 16:20:48 +03:00
|
|
|
class LiveVarAnalysisNode : public DataFlowAnalysisNode<map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>> {
|
2024-01-09 17:28:28 +03:00
|
|
|
private:
|
2023-09-14 19:43:13 +03:00
|
|
|
set<SAPFOR::Argument*> live, dead;
|
2024-01-09 17:28:28 +03:00
|
|
|
public:
|
2024-01-10 16:20:48 +03:00
|
|
|
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> getIn()
|
2024-01-09 17:28:28 +03:00
|
|
|
{
|
|
|
|
|
return getBlock()->getLiveOut();
|
2024-01-14 13:26:21 +03:00
|
|
|
}
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2024-01-10 16:20:48 +03:00
|
|
|
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> getOut()
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2024-01-09 17:28:28 +03:00
|
|
|
return getBlock()->getLiveIn();
|
2024-01-14 13:26:21 +03:00
|
|
|
}
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2024-01-10 16:20:48 +03:00
|
|
|
bool addIn(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
|
2024-01-09 17:28:28 +03:00
|
|
|
{
|
|
|
|
|
return getBlock()->addLiveOut(data);
|
2024-01-14 13:26:21 +03:00
|
|
|
}
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2024-01-10 16:20:48 +03:00
|
|
|
bool addOut(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
|
2024-01-09 17:28:28 +03:00
|
|
|
{
|
|
|
|
|
return getBlock()->addLiveIn(data);
|
2024-01-14 13:26:21 +03:00
|
|
|
}
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2024-05-22 10:33:58 +03:00
|
|
|
DATA_FLOW_UPD_STATUS forwardData(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2024-01-09 17:28:28 +03:00
|
|
|
bool inserted = false;
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2024-01-09 17:28:28 +03:00
|
|
|
for (const auto& byArg : data)
|
|
|
|
|
if (live.find(byArg.first) == live.end() && dead.find(byArg.first) == dead.end())
|
|
|
|
|
inserted |= getBlock()->addLiveIn({ byArg });
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2024-05-22 20:28:13 +03:00
|
|
|
return inserted ? DATA_FLOW_UPD_STATUS::PROPAGATED : DATA_FLOW_UPD_STATUS::NO_CHANGE;
|
2024-01-14 13:26:21 +03:00
|
|
|
}
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2024-01-09 17:28:28 +03:00
|
|
|
LiveVarAnalysisNode(SAPFOR::BasicBlock* block, vector<SAPFOR::Argument*>& formal_parameters,
|
2024-01-12 16:11:21 +03:00
|
|
|
vector<LiveDeadVarsForCall>& fcalls, const map<string, FuncInfo*>& funcByName)
|
2024-01-09 17:28:28 +03:00
|
|
|
{
|
|
|
|
|
setBlock(block);
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2024-01-09 18:13:56 +03:00
|
|
|
buildUseDef(getBlock(), live, dead, formal_parameters, fcalls, funcByName, true);
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2024-01-09 17:28:28 +03:00
|
|
|
for (SAPFOR::Argument* arg : live)
|
|
|
|
|
getBlock()->addLiveIn({ { arg, { getBlock() } } });
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
2024-01-09 17:28:28 +03:00
|
|
|
};
|
|
|
|
|
|
2024-01-12 16:57:02 +03:00
|
|
|
class LiveVarAnalysis : public BackwardDataFlowAnalysis<LiveVarAnalysisNode> {
|
2024-01-09 17:28:28 +03:00
|
|
|
protected:
|
|
|
|
|
vector<SAPFOR::Argument*>& formal_parameters;
|
2024-01-12 16:11:21 +03:00
|
|
|
vector<LiveDeadVarsForCall>& fcalls;
|
2024-01-09 17:28:28 +03:00
|
|
|
const map<string, FuncInfo*>& funcByName;
|
|
|
|
|
|
2024-01-09 18:13:56 +03:00
|
|
|
LiveVarAnalysisNode* createNode(SAPFOR::BasicBlock* block) override {
|
2024-01-09 17:28:28 +03:00
|
|
|
return new LiveVarAnalysisNode(block, formal_parameters, fcalls, funcByName);
|
2024-01-14 13:26:21 +03:00
|
|
|
}
|
2024-01-09 17:28:28 +03:00
|
|
|
public:
|
2024-01-12 16:11:21 +03:00
|
|
|
LiveVarAnalysis(vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
|
2024-01-09 17:28:28 +03:00
|
|
|
const map<string, FuncInfo*>& funcByName) : formal_parameters(formal_parameters), fcalls(fcalls), funcByName(funcByName)
|
2024-01-14 13:26:21 +03:00
|
|
|
{ }
|
2023-09-14 19:43:13 +03:00
|
|
|
};
|
|
|
|
|
|
2024-01-09 18:13:56 +03:00
|
|
|
void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
|
|
|
|
|
set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
|
2024-01-12 16:11:21 +03:00
|
|
|
vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
|
2024-04-10 22:03:27 +03:00
|
|
|
vector<SAPFOR::Argument*>& arg_stack, int& arg_stack_index, int& arg_stack_size,
|
|
|
|
|
bool& last_stack_op,
|
2024-01-09 18:13:56 +03:00
|
|
|
string& fName, const map<string, FuncInfo*>& funcByName, bool interprocedural)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2024-01-09 18:13:56 +03:00
|
|
|
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;
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2024-04-10 22:03:27 +03:00
|
|
|
last_stack_op = false;
|
2024-01-09 18:13:56 +03:00
|
|
|
SAPFOR::Argument* res_arg = NULL;
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2024-01-09 18:13:56 +03:00
|
|
|
static const set<SAPFOR::CFG_OP> skip = { SAPFOR::CFG_OP::ENTRY };
|
|
|
|
|
SAPFOR::CFG_OP instr_operation = instr->getOperation();
|
2024-04-10 22:03:27 +03:00
|
|
|
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))
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2024-01-09 18:13:56 +03:00
|
|
|
res_arg = instr->getArg1();
|
|
|
|
|
set<SAPFOR::Argument*> instr_args = { instr->getResult(), instr->getArg2() };
|
|
|
|
|
use.insert(instr_args.begin(), instr_args.end());
|
|
|
|
|
}
|
2024-04-10 22:03:27 +03:00
|
|
|
else if (instr_operation == SAPFOR::CFG_OP::PARAM || instr_operation == SAPFOR::CFG_OP::REF)
|
2024-01-09 18:13:56 +03:00
|
|
|
{
|
2024-04-10 22:03:27 +03:00
|
|
|
arg_stack[arg_stack_index--] = instr->getArg1();
|
2024-01-09 18:13:56 +03:00
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-10 22:03:27 +03:00
|
|
|
if (arg_stack_index < 0) {
|
|
|
|
|
if(instr_operation == SAPFOR::CFG_OP::PARAM || instr_operation == SAPFOR::CFG_OP::F_CALL)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2024-04-10 22:03:27 +03:00
|
|
|
auto func_it = funcByName.find(fName);
|
|
|
|
|
if (interprocedural && func_it != funcByName.end())
|
|
|
|
|
{
|
|
|
|
|
fcalls.push_back(LiveDeadVarsForCall(func_it->second, block, arg_stack));
|
2024-01-09 18:13:56 +03:00
|
|
|
|
2024-04-10 22:03:27 +03:00
|
|
|
auto r_it = fcalls.rbegin();
|
|
|
|
|
auto r_end = fcalls.rend();
|
2024-01-09 18:13:56 +03:00
|
|
|
|
2024-04-10 22:03:27 +03:00
|
|
|
for (auto e : def)
|
|
|
|
|
r_it->make_dead(e);
|
2024-01-09 18:13:56 +03:00
|
|
|
|
2024-04-10 22:03:27 +03:00
|
|
|
for (auto e : use)
|
|
|
|
|
r_it->make_live(e, block);
|
|
|
|
|
}
|
2024-01-09 18:13:56 +03:00
|
|
|
|
2024-04-10 22:03:27 +03:00
|
|
|
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))
|
2024-02-02 15:52:36 +03:00
|
|
|
{
|
2024-04-10 22:03:27 +03:00
|
|
|
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]);
|
2024-02-02 15:52:36 +03:00
|
|
|
|
2024-04-10 22:03:27 +03:00
|
|
|
if (func_it->second->funcParams.isArgIn(i))
|
|
|
|
|
use.insert(arg_stack[i]);
|
|
|
|
|
}
|
2024-02-02 15:52:36 +03:00
|
|
|
}
|
2024-04-10 22:03:27 +03:00
|
|
|
else
|
|
|
|
|
use.insert(arg_stack.begin(), arg_stack.end());
|
|
|
|
|
|
|
|
|
|
fName = "";
|
2024-02-02 15:52:36 +03:00
|
|
|
}
|
2024-04-10 22:03:27 +03:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
use.insert(arg_stack.begin(), arg_stack.end());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
arg_stack_index = 0;
|
|
|
|
|
arg_stack_size = 0;
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2024-04-10 22:03:27 +03:00
|
|
|
arg_stack.clear();
|
2024-01-09 18:13:56 +03:00
|
|
|
|
2024-04-10 22:03:27 +03:00
|
|
|
last_stack_op = true;
|
2024-01-09 18:13:56 +03:00
|
|
|
}
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2024-01-09 18:13:56 +03:00
|
|
|
if (res_arg)
|
|
|
|
|
def.insert(res_arg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
|
|
|
|
|
set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
|
2024-01-12 16:11:21 +03:00
|
|
|
vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
|
2024-04-10 22:03:27 +03:00
|
|
|
vector<SAPFOR::Argument*>& arg_stack, int& arg_stack_index, int& arg_stack_size,
|
2024-01-09 18:13:56 +03:00
|
|
|
string& fName, const map<string, FuncInfo*>& funcByName, bool interprocedural)
|
|
|
|
|
{
|
|
|
|
|
set<SAPFOR::Argument*> res, args;
|
2024-04-10 22:03:27 +03:00
|
|
|
bool last_stack_op;
|
2024-01-09 18:13:56 +03:00
|
|
|
getUseDefForInstruction(block, instr,
|
|
|
|
|
args, res,
|
|
|
|
|
formal_parameters, fcalls,
|
2024-04-10 22:03:27 +03:00
|
|
|
arg_stack, arg_stack_index, arg_stack_size,
|
|
|
|
|
last_stack_op,
|
2024-01-09 18:13:56 +03:00
|
|
|
fName, funcByName,
|
|
|
|
|
interprocedural
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
for (auto e : res)
|
|
|
|
|
{
|
|
|
|
|
if (e && e->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
|
|
|
|
|
{
|
|
|
|
|
def.insert(e);
|
|
|
|
|
use.erase(e);
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-09 18:13:56 +03:00
|
|
|
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,
|
2024-01-12 16:11:21 +03:00
|
|
|
vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
|
2024-01-09 18:13:56 +03:00
|
|
|
const map<string, FuncInfo*>& funcByName, bool interprocedural)
|
|
|
|
|
{
|
2024-04-10 22:03:27 +03:00
|
|
|
vector<SAPFOR::Argument*> arg_stack;
|
|
|
|
|
int arg_stack_index = 0, arg_stack_size = 0;
|
2024-01-09 18:13:56 +03:00
|
|
|
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,
|
2024-04-10 22:03:27 +03:00
|
|
|
arg_stack, arg_stack_index, arg_stack_size,
|
2024-01-09 18:13:56 +03:00
|
|
|
fName, funcByName,
|
|
|
|
|
interprocedural
|
|
|
|
|
);
|
|
|
|
|
}
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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());
|
2024-01-09 18:13:56 +03:00
|
|
|
for (auto use : live.second)
|
2023-09-14 19:43:13 +03:00
|
|
|
__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,
|
2024-01-09 18:13:56 +03:00
|
|
|
const map<string, pair<set<int>, set<SAPFOR::Argument*>>>& params_and_globals,
|
|
|
|
|
const string& func_name, set<SAPFOR::Argument*>& result)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
|
|
|
|
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) {
|
2024-01-09 18:13:56 +03:00
|
|
|
if (params[idx] && params[idx]->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
|
2023-09-14 19:43:13 +03:00
|
|
|
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
|
2024-01-09 18:13:56 +03:00
|
|
|
static bool getLiveDead(const vector<SAPFOR::Argument*>& params, const string& func_name,
|
|
|
|
|
set<SAPFOR::Argument*>& live, set<SAPFOR::Argument*>& dead)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
|
|
|
|
return joinGlobalsWithParameters(params, live_by_func, func_name, live) &&
|
2024-01-09 18:13:56 +03:00
|
|
|
joinGlobalsWithParameters(params, dead_by_func, func_name, dead);
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
}
|
2024-01-09 17:28:28 +03:00
|
|
|
|
2023-09-14 19:43:13 +03:00
|
|
|
vector<set<FuncInfo*>> scc;
|
|
|
|
|
vector<set<FuncInfo*>> callLvls = groupByCallDependencies(callDeps, scc);
|
|
|
|
|
|
2024-01-09 17:28:28 +03:00
|
|
|
map<string, LiveVarAnalysis*> func_to_analysis_object;
|
2023-09-14 19:43:13 +03:00
|
|
|
map<string, vector<SAPFOR::Argument*>> func_to_parameters;
|
|
|
|
|
|
2024-01-12 16:11:21 +03:00
|
|
|
list<vector<LiveDeadVarsForCall>> live_for_fcalls;
|
2023-09-14 19:43:13 +03:00
|
|
|
|
|
|
|
|
//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);
|
|
|
|
|
|
2024-01-09 17:28:28 +03:00
|
|
|
LiveVarAnalysis* analysis_object = (func_to_analysis_object[byFunc->funcName] = new LiveVarAnalysis(params, curr_fcalls, funcByName));
|
|
|
|
|
analysis_object->fit(itCFG->second);
|
|
|
|
|
analysis_object->analyze();
|
2023-09-14 19:43:13 +03:00
|
|
|
|
|
|
|
|
fillLiveDeadArgs(byFunc, itCFG->second);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// interprocedural analysis
|
|
|
|
|
for (auto& calls_vector : live_for_fcalls)
|
|
|
|
|
{
|
2024-01-12 16:11:21 +03:00
|
|
|
map<FuncInfo*, LiveDeadVarsForCall> assembled_fcalls;
|
2023-09-14 19:43:13 +03:00
|
|
|
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())
|
2024-01-12 16:11:21 +03:00
|
|
|
it = assembled_fcalls.insert({ call.func, LiveDeadVarsForCall(call.func, call.block, {}) }).first;
|
2024-01-09 17:28:28 +03:00
|
|
|
|
2023-09-14 19:43:13 +03:00
|
|
|
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)
|
|
|
|
|
{
|
2024-01-09 17:28:28 +03:00
|
|
|
auto func_it = func_to_analysis_object.find(func.first->funcName);
|
|
|
|
|
if (func_it == func_to_analysis_object.end())
|
2023-09-14 19:43:13 +03:00
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
auto param_it = func_to_parameters.find(func.first->funcName);
|
2024-01-09 17:28:28 +03:00
|
|
|
if (param_it == func_to_parameters.end())
|
2023-09-14 19:43:13 +03:00
|
|
|
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());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-09 17:28:28 +03:00
|
|
|
set<LiveVarAnalysisNode*> exits;
|
2024-01-10 23:53:12 +03:00
|
|
|
int max_cnt = LiveVarAnalysisNode::getStartCounter();
|
2024-01-09 17:28:28 +03:00
|
|
|
for (auto block : func_it->second->getNodes())
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2024-01-09 17:28:28 +03:00
|
|
|
if (block->getBlock()->getNext().size() == 0)
|
2023-09-14 19:43:13 +03:00
|
|
|
exits.insert(block);
|
2024-01-09 17:28:28 +03:00
|
|
|
if (block->getInCnt() > max_cnt)
|
|
|
|
|
max_cnt = block->getInCnt();
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
max_cnt++;
|
|
|
|
|
|
|
|
|
|
for (auto exit : exits)
|
|
|
|
|
{
|
|
|
|
|
for (const auto& byArg : live_after)
|
|
|
|
|
{
|
2024-01-10 16:20:48 +03:00
|
|
|
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> converted;
|
|
|
|
|
converted[byArg.first] = vector<SAPFOR::BasicBlock*>(byArg.second.begin(), byArg.second.end());
|
|
|
|
|
|
|
|
|
|
if (exit->addIn(converted))
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2024-01-09 17:28:28 +03:00
|
|
|
exit->setInCnt(max_cnt);
|
2024-05-22 20:28:13 +03:00
|
|
|
if (exit->forwardData(converted) != DATA_FLOW_UPD_STATUS::NO_CHANGE)
|
2024-01-09 17:28:28 +03:00
|
|
|
exit->setOutCnt(max_cnt);
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-01-09 17:28:28 +03:00
|
|
|
|
2023-09-14 19:43:13 +03:00
|
|
|
// now we can update live sets in all blocks
|
2024-01-09 17:28:28 +03:00
|
|
|
func_it->second->analyze();
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-09 17:28:28 +03:00
|
|
|
for (const auto& byFunc : func_to_analysis_object)
|
|
|
|
|
delete byFunc.second;
|
2023-09-14 19:43:13 +03:00
|
|
|
|
|
|
|
|
for (auto& byFunc : CFGraph_for_project)
|
|
|
|
|
for (auto& byBlock : byFunc.second)
|
|
|
|
|
byBlock->compressLives();
|
|
|
|
|
|
|
|
|
|
live_by_func.clear();
|
|
|
|
|
dead_by_func.clear();
|
|
|
|
|
}
|