initial version of dead code analysis (dirty)
This commit is contained in:
@@ -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})
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -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,12 +114,38 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fcall
|
removed = true;
|
||||||
{
|
}
|
||||||
private:
|
}
|
||||||
bool tryInsert(set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b)
|
|
||||||
|
return removed;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fcall::tryInsert(set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b)
|
||||||
{
|
{
|
||||||
if (b == block || dest.find(block) == dest.end())
|
if (b == block || dest.find(block) == dest.end())
|
||||||
{
|
{
|
||||||
@@ -128,19 +156,7 @@ 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;
|
||||||
@@ -153,7 +169,7 @@ public:
|
|||||||
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_)
|
||||||
{
|
{
|
||||||
@@ -170,7 +186,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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_)
|
||||||
{
|
{
|
||||||
@@ -187,25 +203,19 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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:
|
||||||
@@ -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() } } });
|
||||||
@@ -355,18 +274,16 @@ public:
|
|||||||
{ };
|
{ };
|
||||||
};
|
};
|
||||||
|
|
||||||
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)
|
||||||
|
{
|
||||||
|
if (e && e->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
|
||||||
{
|
{
|
||||||
def.insert(e);
|
def.insert(e);
|
||||||
use.erase(e);
|
use.erase(e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto e : args) {
|
for (auto e : args)
|
||||||
|
{
|
||||||
|
if (e && e->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
|
||||||
|
{
|
||||||
use.insert(e);
|
use.insert(e);
|
||||||
def.erase(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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
BIN
sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp
Normal file
BIN
sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp
Normal file
Binary file not shown.
BIN
sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.h
Normal file
BIN
sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.h
Normal file
Binary file not shown.
Reference in New Issue
Block a user