initial version of dead code analysis (dirty)

This commit is contained in:
Михаил Кочармин
2024-01-06 17:26:19 +03:00
parent 48998998d3
commit c3827ed8f6
6 changed files with 195 additions and 315 deletions

View File

@@ -161,6 +161,8 @@ set(PARALLEL_REG _src/ParallelizationRegions/ParRegions.cpp
_src/ParallelizationRegions/resolve_par_reg_conflicts.cpp _src/ParallelizationRegions/resolve_par_reg_conflicts.cpp
_src/ParallelizationRegions/resolve_par_reg_conflicts.h) _src/ParallelizationRegions/resolve_par_reg_conflicts.h)
set(TR_DEAD_CODE _src/Transformations/dead_code.cpp
_src/Transformations/dead_code.h)
set(TR_CP _src/Transformations/checkpoints.cpp set(TR_CP _src/Transformations/checkpoints.cpp
_src/Transformations/checkpoints.h) _src/Transformations/checkpoints.h)
set(TR_VECTOR _src/Transformations/array_assign_to_loop.cpp set(TR_VECTOR _src/Transformations/array_assign_to_loop.cpp
@@ -191,6 +193,7 @@ set(TR_CONV _src/Transformations/convert_to_c.cpp
_src/Transformations/convert_to_c.h) _src/Transformations/convert_to_c.h)
set(TRANSFORMS set(TRANSFORMS
${TR_DEAD_CODE}
${TR_CP} ${TR_CP}
${TR_VECTOR} ${TR_VECTOR}
${TR_ENDDO_LOOP} ${TR_ENDDO_LOOP}
@@ -414,6 +417,7 @@ source_group (CFGraph FILES ${CFG})
source_group (CFGraph\\DataFlow FILES ${DATA_FLOW}) source_group (CFGraph\\DataFlow FILES ${DATA_FLOW})
source_group (Transformations\\ExpressionSubstitution FILES ${EXPR_TRANSFORM}) source_group (Transformations\\ExpressionSubstitution FILES ${EXPR_TRANSFORM})
source_group (Transformations\\DeadCodeRemoving FILES ${TR_DEAD_CODE})
source_group (Transformations\\CheckPoints FILES ${TR_CP}) source_group (Transformations\\CheckPoints FILES ${TR_CP})
source_group (Transformations\\LoopEndDoConverter FILES ${TR_ENDDO_LOOP}) source_group (Transformations\\LoopEndDoConverter FILES ${TR_ENDDO_LOOP})
source_group (Transformations\\LoopNesting FILES ${TR_LOOP_NEST}) source_group (Transformations\\LoopNesting FILES ${TR_LOOP_NEST})

View File

@@ -33,6 +33,7 @@ namespace SAPFOR
bool addLive(const std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>>& to_add, bool in); bool addLive(const std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>>& to_add, bool in);
std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>> getLive(bool in) const; std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>> getLive(bool in) const;
bool removeLive(SAPFOR::Argument* to_remove, bool in);
public: public:
BasicBlock() { num = lastNumBlock++; } BasicBlock() { num = lastNumBlock++; }
BasicBlock(IR_Block* item); BasicBlock(IR_Block* item);
@@ -74,6 +75,10 @@ namespace SAPFOR
std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>> getLiveIn() const { return getLive(true); }; std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>> getLiveIn() const { return getLive(true); };
std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>> getLiveOut() const { return getLive(false); }; std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>> getLiveOut() const { return getLive(false); };
bool removeLiveIn(SAPFOR::Argument* to_remove) { return removeLive(to_remove, true); };
bool removeLiveOut(SAPFOR::Argument* to_remove) { return removeLive(to_remove, false); };
void compressLives(); void compressLives();
/* /*

View File

@@ -1,5 +1,5 @@
#include "live_variable_analysis.h" #include "live_variable_analysis.h"
#include "DataFlow/forward_data_flow.h" #include "DataFlow/backward_data_flow.h"
#include "RD_subst.h" #include "RD_subst.h"
#include <string> #include <string>
@@ -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) {
@@ -112,100 +114,108 @@ namespace SAPFOR
for (auto& byArg : *bySrc) for (auto& byArg : *bySrc)
byArg.second.shrink_to_fit(); byArg.second.shrink_to_fit();
} }
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);
if (!removed) {
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);
}
removed = true;
}
}
return removed;
};
} }
struct fcall bool fcall::tryInsert(set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b)
{ {
private: if (b == block || dest.find(block) == dest.end())
bool tryInsert(set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b)
{ {
if (b == block || dest.find(block) == dest.end()) dest.insert(b);
{ return true;
dest.insert(b);
return true;
}
return false;
} }
public: return false;
FuncInfo* func; }
map<int, set<SAPFOR::BasicBlock*>> live_after; fcall::fcall(FuncInfo* f, SAPFOR::BasicBlock* b, const vector<SAPFOR::Argument*>& p)
set<int> dead_after; {
block = b;
func = f;
map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>> commons_live_after; int param_size = p.size();
set<SAPFOR::Argument*> commons_dead_after; params = vector<SAPFOR::Argument*>(param_size, NULL);
vector<SAPFOR::Argument*> params; for (int i = 0; i < param_size; i++)
SAPFOR::BasicBlock* block; if (f->funcParams.isArgOut(i))
params[i] = p[i];
}
fcall(FuncInfo* f, SAPFOR::BasicBlock* b, const vector<SAPFOR::Argument*>& p) 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_)
{ {
block = b; if (commons_dead_after.find(arg) == commons_dead_after.end())
func = f; tryInsert(commons_live_after[arg], b);
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 make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b) auto it = find(params.begin(), params.end(), arg);
if (it != params.end())
{ {
if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_) int idx = it - params.begin();
{ if (dead_after.find(idx) == dead_after.end())
if (commons_dead_after.find(arg) == commons_dead_after.end()) tryInsert(live_after[idx], b);
tryInsert(commons_live_after[arg], b); }
} }
auto it = find(params.begin(), params.end(), arg); void fcall::make_dead(SAPFOR::Argument* arg)
if (it != params.end()) {
{ if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_)
int idx = it - params.begin(); {
if (dead_after.find(idx) == dead_after.end()) if (commons_live_after.find(arg) == commons_live_after.end())
tryInsert(live_after[idx], b); commons_dead_after.insert(arg);
}
} }
void make_dead(SAPFOR::Argument* arg) auto it = find(params.begin(), params.end(), arg);
if (it != params.end())
{ {
if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_) int idx = it - params.begin();
{ if (live_after.find(idx) == live_after.end())
if (commons_live_after.find(arg) == commons_live_after.end()) dead_after.insert(idx);
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 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);
static void buildUseDef2(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
const map<string, FuncInfo*>& funcByName);
class LiveVarAnalysisNode : public DataFlowAnalysisNode<map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>>> { class LiveVarAnalysisNode : public DataFlowAnalysisNode<map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>>> {
private: private:
@@ -232,7 +242,7 @@ public:
for (const auto& byArg : data) for (const auto& byArg : data)
if (live.find(byArg.first) == live.end() && dead.find(byArg.first) == dead.end()) if (live.find(byArg.first) == live.end() && dead.find(byArg.first) == dead.end())
inserted |= getBlock()->addLiveIn({byArg}); inserted |= getBlock()->addLiveIn({ byArg });
return inserted; return inserted;
}; };
@@ -242,98 +252,7 @@ public:
{ {
setBlock(block); setBlock(block);
set<SAPFOR::Argument*> live1, dead1; buildUseDef(getBlock(), live, dead, formal_parameters, fcalls, funcByName, true);
vector<SAPFOR::Argument*> formal_parameters1 = formal_parameters;
vector<fcall> fcalls1;
buildUseDef(getBlock(), live1, dead1, formal_parameters1, fcalls1, funcByName);
set<SAPFOR::Argument*> live2, dead2;
vector<SAPFOR::Argument*> formal_parameters2 = formal_parameters;
vector<fcall> fcalls2;
buildUseDef2(getBlock(), live2, dead2, formal_parameters2, fcalls2, funcByName);
bool err = false;
for (auto& l1 : live1) {
if (live2.find(l1) == live2.end()) {
__spf_print(1, "bb %d use %s >> 1\n", getBlock()->getNumber(), l1->getValue().c_str());
err = true;
}
}
for (auto& l2 : live2) {
if (live1.find(l2) == live1.end()) {
__spf_print(1, "bb %d use %s >> 2\n", getBlock()->getNumber(), l2->getValue().c_str());
err = true;
}
}
err |= live1.size() != live2.size();
for (auto& l1 : dead1) {
if (dead2.find(l1) == dead2.end()) {
__spf_print(1, "bb %d dead %s >> 1\n", getBlock()->getNumber(), l1->getValue().c_str());
err = true;
}
}
for (auto& l2 : dead2) {
if (dead1.find(l2) == dead1.end()) {
__spf_print(1, "bb %d dead %s >> 2\n", getBlock()->getNumber(), l2->getValue().c_str());
err = true;
}
}
err |= dead1.size() != dead2.size();
if (fcalls1.size() != fcalls2.size()) {
__spf_print(1, "bb %d different fcall sizes: 1: %d, w: %d\n", getBlock()->getNumber(), fcalls1.size(), fcalls2.size());
err = true;
}
else {
for (int i = 0; i < fcalls1.size(); i++) {
auto& c1 = fcalls1[i];
auto& c2 = fcalls2[fcalls1.size() - i - 1];
if (c1.func->funcName != c2.func->funcName) {
__spf_print(1, "different fnames %s, %s\n", c1.func->funcName.c_str(), c2.func->funcName.c_str());
err = true;
}
if (c1.live_after != c2.live_after) {
__spf_print(1, "different live_after\n");
err = true;
}
if (c1.dead_after != c2.dead_after) {
__spf_print(1, "different dead_after\n");
err = true;
}
if (c1.commons_dead_after != c2.commons_dead_after) {
__spf_print(1, "different commons_dead_after\n");
err = true;
}
if (c1.commons_live_after != c2.commons_live_after) {
__spf_print(1, "different commons_live_after\n");
err = true;
}
}
}
if (err)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
live = live1;
dead = dead1;
formal_parameters = formal_parameters1;
for (auto& fc : fcalls1)
fcalls.push_back(fc);
for (SAPFOR::Argument* arg : live) for (SAPFOR::Argument* arg : live)
getBlock()->addLiveIn({ { arg, { getBlock() } } }); getBlock()->addLiveIn({ { arg, { getBlock() } } });
@@ -351,22 +270,20 @@ protected:
}; };
public: public:
LiveVarAnalysis(vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls, LiveVarAnalysis(vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
const map<string, FuncInfo*>& funcByName) : formal_parameters(formal_parameters), fcalls(fcalls), funcByName(funcByName) const map<string, FuncInfo*>& funcByName) : formal_parameters(formal_parameters), fcalls(fcalls), funcByName(funcByName)
{ }; { };
}; };
static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr, void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
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,
vector<SAPFOR::Argument*>& lastParamRef, int& last_param_ref_index, int& last_param_ref_size, vector<SAPFOR::Argument*>& lastParamRef, int& last_param_ref_index, int& last_param_ref_size,
string& fName, string& fName, const map<string, FuncInfo*>& funcByName, bool interprocedural)
const map<string, FuncInfo*>& funcByName)
{ {
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 };
@@ -375,7 +292,7 @@ static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instru
{ {
res_arg = instr->getArg1(); res_arg = instr->getArg1();
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)
{ {
@@ -399,7 +316,7 @@ static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instru
//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
{ {
@@ -416,7 +333,6 @@ static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instru
auto r_it = fcalls.rbegin(); auto r_it = fcalls.rbegin();
auto r_end = fcalls.rend(); auto r_end = fcalls.rend();
for (auto e : def) for (auto e : def)
r_it->make_dead(e); r_it->make_dead(e);
@@ -426,40 +342,65 @@ static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instru
set<SAPFOR::Argument*> make_live, make_dead; set<SAPFOR::Argument*> make_live, make_dead;
if (fName == "_READ") if (fName == "_READ")
res.insert(lastParamRef.begin(), lastParamRef.end()); def.insert(lastParamRef.begin(), lastParamRef.end());
else if (getLiveDead(lastParamRef, fName, make_live, make_dead)) else if (interprocedural && getLiveDead(lastParamRef, fName, make_live, make_dead))
{ {
insertIfVar(make_live.begin(), make_live.end(), args); use.insert(make_live.begin(), make_live.end());
insertIfVar(make_dead.begin(), make_dead.end(), res); def.insert(make_dead.begin(), make_dead.end());
} }
else else
insertIfVar(lastParamRef.begin(), lastParamRef.end(), args); use.insert(lastParamRef.begin(), lastParamRef.end());
last_param_ref_index = 0; last_param_ref_index = 0;
last_param_ref_size = 0; last_param_ref_size = 0;
lastParamRef.clear(); lastParamRef.clear();
fName = "";
} }
if (res_arg && res_arg->getType() == SAPFOR::CFG_ARG_TYPE::VAR) if (res_arg)
res.insert(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) for (auto e : res)
{ {
def.insert(e); if (e && e->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
use.erase(e); {
def.insert(e);
use.erase(e);
}
} }
for (auto e : args) { for (auto e : args)
use.insert(e); {
def.erase(e); 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 //Build use and def sets of block. Result are stored in use and def
static void buildUseDef2(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)
{ {
vector<SAPFOR::Argument*> lastParamRef; vector<SAPFOR::Argument*> lastParamRef;
int last_param_ref_index = 0, last_param_ref_size = 0; int last_param_ref_index = 0, last_param_ref_size = 0;
@@ -474,115 +415,12 @@ static void buildUseDef2(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use,
use, def, use, def,
formal_parameters, fcalls, formal_parameters, fcalls,
lastParamRef, last_param_ref_index, last_param_ref_size, lastParamRef, last_param_ref_index, last_param_ref_size,
fName, funcByName fName, funcByName,
interprocedural
); );
} }
} }
//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)
{
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() })
if (arg && arg->getMemType() == SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_)
formal_parameters[getParamIndex(arg, formal_parameters.size())] = arg;
set<SAPFOR::Argument*> res = {}, args = {};
SAPFOR::Argument* res_arg = NULL;
static const set<SAPFOR::CFG_OP> skip = { SAPFOR::CFG_OP::ENTRY };
SAPFOR::CFG_OP instr_operation = instr->getOperation();
if (hasStoreStructure(instr_operation)) {
res_arg = instr->getArg1();
std::set<SAPFOR::Argument*> instr_args = { instr->getResult(), instr->getArg2()};
insertIfVar(instr_args.begin(), instr_args.end(), args);
}
else if (instr_operation == SAPFOR::CFG_OP::PARAM)
lastParamRef.push_back(instr->getArg1());
else if (instr_operation == SAPFOR::CFG_OP::F_CALL)
{
res_arg = instr->getResult();
int count = 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();
}
else if(skip.find(instr_operation) == skip.end())
{
//default
res_arg = instr->getResult();
std::set<SAPFOR::Argument*> intr_args = { instr->getArg1(), instr->getArg2() };
insertIfVar(intr_args.begin(), intr_args.end(), args);
}
else {
//skip
continue;
}
if (res_arg && res_arg->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
res.insert(res_arg);
for (auto e : args)
if (!tmp_def.count(e))
tmp_use.insert(e);
for(auto e : res)
if (!tmp_use.count(e))
tmp_def.insert(e);
auto r_it = fcalls.rbegin();
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 : args)
r_it->make_live(e, block);
for (auto e : res)
r_it->make_dead(e);
r_it++;
}
}
use = tmp_use;
def = tmp_def;
}
// prints info about live variables // prints info about live variables
void doDumpLive(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph_for_project) void doDumpLive(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph_for_project)
{ {
@@ -598,7 +436,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");
} }
@@ -701,8 +539,8 @@ static void fillLiveDeadArgs(const FuncInfo* func, const vector<SAPFOR::BasicBlo
// unite global arguments and actual parameters with given indexes for function // unite global arguments and actual parameters with given indexes for function
// stores the result in the last argument // stores the result in the last argument
bool joinGlobalsWithParameters(const vector<SAPFOR::Argument*>& params, bool joinGlobalsWithParameters(const vector<SAPFOR::Argument*>& params,
const map<string, pair<set<int>, set<SAPFOR::Argument*>>>& params_and_globals, const map<string, pair<set<int>, set<SAPFOR::Argument*>>>& params_and_globals,
const string& func_name, set<SAPFOR::Argument*>& result) const string& func_name, set<SAPFOR::Argument*>& result)
{ {
auto globals_it = params_and_globals.find(func_name); auto globals_it = params_and_globals.find(func_name);
@@ -717,7 +555,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
@@ -730,10 +568,10 @@ bool joinGlobalsWithParameters(const vector<SAPFOR::Argument*>& params,
// fill sets of arguments wich becomes live or dead after call with parameters params // 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, 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)
{ {
return joinGlobalsWithParameters(params, live_by_func, func_name, live) && return joinGlobalsWithParameters(params, live_by_func, func_name, live) &&
joinGlobalsWithParameters(params, dead_by_func, func_name, dead); joinGlobalsWithParameters(params, dead_by_func, func_name, dead);
} }
// entrypoint for live variable analysis pass // entrypoint for live variable analysis pass
@@ -815,7 +653,7 @@ void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>&
printInternalError(convertFileName(__FILE__).c_str(), __LINE__); printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
auto param_it = func_to_parameters.find(func.first->funcName); auto param_it = func_to_parameters.find(func.first->funcName);
if(param_it == func_to_parameters.end()) if (param_it == func_to_parameters.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__); printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
const vector<SAPFOR::Argument*>& params = param_it->second; const vector<SAPFOR::Argument*>& params = param_it->second;
@@ -852,7 +690,7 @@ void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>&
if (exit->addIn({ byArg })) if (exit->addIn({ byArg }))
{ {
exit->setInCnt(max_cnt); exit->setInCnt(max_cnt);
if(exit->forwardData({ byArg })) if (exit->forwardData({ byArg }))
exit->setOutCnt(max_cnt); exit->setOutCnt(max_cnt);
} }
} }

View File

@@ -1,6 +1,33 @@
#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 +35,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);