reorganize live variable analysis to use it's functions further

This commit is contained in:
mkoch
2024-01-09 18:13:56 +03:00
parent 3cd16c9d0f
commit 5f8940f34d
2 changed files with 227 additions and 159 deletions

View File

@@ -17,6 +17,8 @@ using std::set;
using std::unordered_map; using std::unordered_map;
using std::list; using std::list;
using LIVE_VARIABLES::fcall;
namespace SAPFOR namespace SAPFOR
{ {
bool BasicBlock::addLive(const map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>>& to_add, bool in) { bool BasicBlock::addLive(const map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>>& to_add, bool in) {
@@ -114,11 +116,8 @@ namespace SAPFOR
} }
} }
struct fcall bool fcall::tryInsert(set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b)
{ {
private:
bool tryInsert(set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b)
{
if (b == block || dest.find(block) == dest.end()) if (b == block || dest.find(block) == dest.end())
{ {
dest.insert(b); dest.insert(b);
@@ -126,22 +125,10 @@ private:
} }
return false; return false;
} }
public: fcall::fcall(FuncInfo* f, SAPFOR::BasicBlock* b, const vector<SAPFOR::Argument*>& p)
FuncInfo* func; {
map<int, set<SAPFOR::BasicBlock*>> live_after;
set<int> dead_after;
map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>> commons_live_after;
set<SAPFOR::Argument*> commons_dead_after;
vector<SAPFOR::Argument*> params;
SAPFOR::BasicBlock* block;
fcall(FuncInfo* f, SAPFOR::BasicBlock* b, const vector<SAPFOR::Argument*>& p)
{
block = b; block = b;
func = f; func = f;
@@ -151,10 +138,10 @@ public:
for (int i = 0; i < param_size; i++) for (int i = 0; i < param_size; i++)
if (f->funcParams.isArgOut(i)) if (f->funcParams.isArgOut(i))
params[i] = p[i]; params[i] = p[i];
} }
void make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b) void fcall::make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b)
{ {
if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_) 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()) if (commons_dead_after.find(arg) == commons_dead_after.end())
@@ -168,35 +155,38 @@ public:
if (dead_after.find(idx) == dead_after.end()) if (dead_after.find(idx) == dead_after.end())
tryInsert(live_after[idx], b); tryInsert(live_after[idx], b);
} }
} }
void make_dead(SAPFOR::Argument* arg) void fcall::make_dead(SAPFOR::Argument* arg)
{ {
if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_) 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); commons_dead_after.insert(arg);
}
auto it = find(params.begin(), params.end(), arg); auto it = find(params.begin(), params.end(), arg);
if (it != params.end()) if (it != params.end())
{ {
int idx = it - params.begin(); int idx = it - params.begin();
if (live_after.find(idx) == live_after.end())
dead_after.insert(idx); dead_after.insert(idx);
} }
} }
void updateFromOut() void fcall::updateFromOut()
{ {
for (const auto& p : block->getLiveOut()) for (const auto& p : block->getLiveOut())
for (auto b : p.second) for (auto b : p.second)
make_live(p.first, b); make_live(p.first, b);
} }
};
static bool getLiveDead(const vector<SAPFOR::Argument*>& params, const string& func_name, static bool getLiveDead(const vector<SAPFOR::Argument*>& params, const string& func_name,
set<SAPFOR::Argument*>& live, set<SAPFOR::Argument*>& dead); set<SAPFOR::Argument*>& live, set<SAPFOR::Argument*>& dead);
static void buildUseDef(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def, static void buildUseDef(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls, vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
const map<string, FuncInfo*>& funcByName); const map<string, FuncInfo*>& funcByName, bool interprocedural);
class LiveVarAnalysisNode : public DataFlowAnalysisNode<map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>>> { class LiveVarAnalysisNode : public DataFlowAnalysisNode<map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>>> {
private: private:
@@ -238,7 +228,7 @@ public:
{ {
setBlock(block); setBlock(block);
buildUseDef(getBlock(), live, dead, formal_parameters, fcalls, funcByName); buildUseDef(getBlock(), live, dead, formal_parameters, fcalls, funcByName, true);
for (SAPFOR::Argument* arg : live) for (SAPFOR::Argument* arg : live)
getBlock()->addLiveIn({ { arg, { getBlock() } } }); getBlock()->addLiveIn({ { arg, { getBlock() } } });
@@ -251,8 +241,7 @@ protected:
vector<fcall>& fcalls; vector<fcall>& fcalls;
const map<string, FuncInfo*>& funcByName; const map<string, FuncInfo*>& funcByName;
LiveVarAnalysisNode* createNode(SAPFOR::BasicBlock* block) override LiveVarAnalysisNode* createNode(SAPFOR::BasicBlock* block) override {
{
return new LiveVarAnalysisNode(block, formal_parameters, fcalls, funcByName); return new LiveVarAnalysisNode(block, formal_parameters, fcalls, funcByName);
}; };
public: public:
@@ -261,107 +250,151 @@ public:
{ }; { };
}; };
//Build use and def sets of block. Result are stored in use and def void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
static void buildUseDef(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def, set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls, vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
const map<string, FuncInfo*>& funcByName) vector<SAPFOR::Argument*>& lastParamRef, int& last_param_ref_index, int& last_param_ref_size,
string& fName, const map<string, FuncInfo*>& funcByName, bool interprocedural)
{ {
set<SAPFOR::Argument*> tmp_use, tmp_def;
vector<SAPFOR::Argument*> lastParamRef;
bool fcall_added;
for (auto ir_block : block->getInstructions())
{
fcall_added = false;
SAPFOR::Instruction* instr = ir_block->getInstruction();
for (auto arg : { instr->getArg1(), instr->getArg2(), instr->getResult() }) for (auto arg : { instr->getArg1(), instr->getArg2(), instr->getResult() })
if (arg && arg->getMemType() == SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_) if (arg && arg->getMemType() == SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_)
formal_parameters[getParamIndex(arg, formal_parameters.size())] = arg; formal_parameters[getParamIndex(arg, formal_parameters.size())] = arg;
set<SAPFOR::Argument*> res = {}, args = {};
SAPFOR::Argument* res_arg = NULL; SAPFOR::Argument* res_arg = NULL;
static const set<SAPFOR::CFG_OP> skip = { SAPFOR::CFG_OP::ENTRY }; static const set<SAPFOR::CFG_OP> skip = { SAPFOR::CFG_OP::ENTRY };
SAPFOR::CFG_OP instr_operation = instr->getOperation(); SAPFOR::CFG_OP instr_operation = instr->getOperation();
if (hasStoreStructure(instr_operation)) { if (hasStoreStructure(instr_operation))
{
res_arg = instr->getArg1(); res_arg = instr->getArg1();
std::set<SAPFOR::Argument*> instr_args = { instr->getResult(), instr->getArg2()}; set<SAPFOR::Argument*> instr_args = { instr->getResult(), instr->getArg2() };
insertIfVar(instr_args.begin(), instr_args.end(), args); use.insert(instr_args.begin(), instr_args.end());
} }
else if (instr_operation == SAPFOR::CFG_OP::PARAM) else if (instr_operation == SAPFOR::CFG_OP::PARAM)
lastParamRef.push_back(instr->getArg1()); {
lastParamRef[last_param_ref_index--] = instr->getArg1();
}
else if (instr_operation == SAPFOR::CFG_OP::F_CALL) else if (instr_operation == SAPFOR::CFG_OP::F_CALL)
{ {
res_arg = instr->getResult(); res_arg = instr->getResult();
int count = stoi(instr->getArg2()->getValue()); last_param_ref_size = stoi(instr->getArg2()->getValue());
if (lastParamRef.size() != count)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
const string& fName = instr->getArg1()->getValue();
auto func_it = funcByName.find(fName);
if (func_it != funcByName.end())
{
fcalls.push_back(fcall(func_it->second, block, lastParamRef));
fcall_added = true;
}
set<SAPFOR::Argument*> make_live, make_dead;
if (fName == "_READ")
res.insert(lastParamRef.begin(), lastParamRef.end());
else if (getLiveDead(lastParamRef, fName, make_live, make_dead))
{
insertIfVar(make_live.begin(), make_live.end(), args);
insertIfVar(make_dead.begin(), make_dead.end(), res);
}
else
insertIfVar(lastParamRef.begin(), lastParamRef.end(), args);
lastParamRef.clear(); lastParamRef.clear();
lastParamRef.resize(last_param_ref_size);
last_param_ref_index = last_param_ref_size - 1;
fName = instr->getArg1()->getValue();
} }
else if(skip.find(instr_operation) == skip.end()) else if (skip.find(instr_operation) == skip.end())
{ {
//default //default
res_arg = instr->getResult(); res_arg = instr->getResult();
std::set<SAPFOR::Argument*> intr_args = { instr->getArg1(), instr->getArg2() }; std::set<SAPFOR::Argument*> intr_args = { instr->getArg1(), instr->getArg2() };
insertIfVar(intr_args.begin(), intr_args.end(), args); use.insert(intr_args.begin(), intr_args.end());
} }
else { else
{
//skip //skip
continue; return;
} }
if (res_arg && res_arg->getType() == SAPFOR::CFG_ARG_TYPE::VAR) if ((instr_operation == SAPFOR::CFG_OP::F_CALL || instr_operation == SAPFOR::CFG_OP::PARAM) && last_param_ref_index < 0) {
res.insert(res_arg); auto func_it = funcByName.find(fName);
if (func_it != funcByName.end())
for (auto e : args) {
if (!tmp_def.count(e)) fcalls.push_back(fcall(func_it->second, block, lastParamRef));
tmp_use.insert(e);
for(auto e : res)
if (!tmp_use.count(e))
tmp_def.insert(e);
auto r_it = fcalls.rbegin(); auto r_it = fcalls.rbegin();
auto r_end = fcalls.rend(); auto r_end = fcalls.rend();
if (fcall_added && r_it != r_end)
r_it++;
while (r_it != r_end && r_it->block == block) for (auto e : def)
{
for (auto e : args)
r_it->make_live(e, block);
for (auto e : res)
r_it->make_dead(e); r_it->make_dead(e);
r_it++; for (auto e : use)
r_it->make_live(e, block);
}
set<SAPFOR::Argument*> make_live, make_dead;
if (fName == "_READ")
def.insert(lastParamRef.begin(), lastParamRef.end());
else if (interprocedural && getLiveDead(lastParamRef, fName, make_live, make_dead))
{
use.insert(make_live.begin(), make_live.end());
def.insert(make_dead.begin(), make_dead.end());
}
else
use.insert(lastParamRef.begin(), lastParamRef.end());
last_param_ref_index = 0;
last_param_ref_size = 0;
lastParamRef.clear();
fName = "";
}
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<fcall>& fcalls,
vector<SAPFOR::Argument*>& lastParamRef, int& last_param_ref_index, int& last_param_ref_size,
string& fName, const map<string, FuncInfo*>& funcByName, bool interprocedural)
{
set<SAPFOR::Argument*> res, args;
getUseDefForInstruction(block, instr,
args, res,
formal_parameters, fcalls,
lastParamRef, last_param_ref_index, last_param_ref_size,
fName, funcByName,
interprocedural
);
for (auto e : res)
{
if (e && e->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
{
def.insert(e);
use.erase(e);
} }
} }
use = tmp_use; for (auto e : args)
def = tmp_def; {
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<fcall>& fcalls,
const map<string, FuncInfo*>& funcByName, bool interprocedural)
{
vector<SAPFOR::Argument*> lastParamRef;
int last_param_ref_index = 0, last_param_ref_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,
lastParamRef, last_param_ref_index, last_param_ref_size,
fName, funcByName,
interprocedural
);
}
} }
// prints info about live variables // prints info about live variables
@@ -379,7 +412,7 @@ void doDumpLive(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph_for_p
for (const auto& live : byBB->getLiveIn()) for (const auto& live : byBB->getLiveIn())
{ {
__spf_print(1, " %s:", live.first->getValue().c_str()); __spf_print(1, " %s:", live.first->getValue().c_str());
for(auto use : live.second) for (auto use : live.second)
__spf_print(1, " %d", use->getNumber()); __spf_print(1, " %d", use->getNumber());
__spf_print(1, "\n"); __spf_print(1, "\n");
} }
@@ -498,7 +531,7 @@ bool joinGlobalsWithParameters(const vector<SAPFOR::Argument*>& params,
for (int idx : param_indexes) for (int idx : param_indexes)
{ {
if (idx < params_size) { if (idx < params_size) {
if(params[idx] && params[idx]->getType() == SAPFOR::CFG_ARG_TYPE::VAR) if (params[idx] && params[idx]->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
result.insert(params[idx]); result.insert(params[idx]);
} }
else else

View File

@@ -1,6 +1,35 @@
#pragma once
#include "../Utils/SgUtils.h" #include "../Utils/SgUtils.h"
#include "CFGraph.h" #include "CFGraph.h"
namespace LIVE_VARIABLES
{
struct fcall
{
private:
bool tryInsert(std::set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b);
public:
FuncInfo* func;
std::map<int, std::set<SAPFOR::BasicBlock*>> live_after;
std::set<int> dead_after;
std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>> commons_live_after;
std::set<SAPFOR::Argument*> commons_dead_after;
std::vector<SAPFOR::Argument*> params;
SAPFOR::BasicBlock* block;
fcall(FuncInfo* f, SAPFOR::BasicBlock* b, const std::vector<SAPFOR::Argument*>& p);
void make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b);
void make_dead(SAPFOR::Argument* arg);
void updateFromOut();
};
}
template <class IT, class DEST> template <class IT, class DEST>
void insertIfVar(IT begin, IT end, DEST& to) { void insertIfVar(IT begin, IT end, DEST& to) {
for (auto it = begin; it != end; it++) for (auto it = begin; it != end; it++)
@@ -8,6 +37,12 @@ void insertIfVar(IT begin, IT end, DEST& to) {
to.insert(*it); to.insert(*it);
}; };
void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
std::set<SAPFOR::Argument*>& use, std::set<SAPFOR::Argument*>& def,
std::vector<SAPFOR::Argument*>& formal_parameters, std::vector<LIVE_VARIABLES::fcall>& fcalls,
std::vector<SAPFOR::Argument*>& lastParamRef, int& last_param_ref_index, int& last_param_ref_size,
std::string& fName, const std::map<std::string, FuncInfo*>& funcByName, bool interprocedural);
void runLiveVariableAnalysis(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project); void runLiveVariableAnalysis(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project);
void doDumpLive(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project); void doDumpLive(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project);