dead_code_removing #36
@@ -10,7 +10,8 @@
|
|||||||
#include "../IR.h"
|
#include "../IR.h"
|
||||||
|
|
||||||
template <class NodeType>
|
template <class NodeType>
|
||||||
class BackwardDataFlowAnalysis : public DataFlowAnalysis<NodeType> {
|
class BackwardDataFlowAnalysis : public DataFlowAnalysis<NodeType>
|
||||||
|
{
|
||||||
std::vector<SAPFOR::BasicBlock*> reorderSequence(const std::vector<SAPFOR::BasicBlock*>& blocks,
|
std::vector<SAPFOR::BasicBlock*> reorderSequence(const std::vector<SAPFOR::BasicBlock*>& blocks,
|
||||||
const std::set<SAPFOR::BasicBlock*> back_edge_sources);
|
const std::set<SAPFOR::BasicBlock*> back_edge_sources);
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ public:
|
|||||||
virtual bool addIn(const DataType& data) = 0;
|
virtual bool addIn(const DataType& data) = 0;
|
||||||
virtual bool addOut(const DataType& data) = 0;
|
virtual bool addOut(const DataType& data) = 0;
|
||||||
|
|
||||||
|
virtual bool updateState() { return false; }
|
||||||
virtual bool forwardData(const DataType& data) = 0;
|
virtual bool forwardData(const DataType& data) = 0;
|
||||||
|
|
||||||
bool newerThan(const DataFlowAnalysisNode<DataType>* block) const { return out_cnt > block->in_cnt; }
|
bool newerThan(const DataFlowAnalysisNode<DataType>* block) const { return out_cnt > block->in_cnt; }
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ template <class DataType>
|
|||||||
void DataFlowAnalysisNode<DataType>::doStep()
|
void DataFlowAnalysisNode<DataType>::doStep()
|
||||||
{
|
{
|
||||||
int in_max_cnt = CNT_NOTINIT, out_max_cnt = CNT_NOTINIT;
|
int in_max_cnt = CNT_NOTINIT, out_max_cnt = CNT_NOTINIT;
|
||||||
|
|
||||||
|
bool uniq_change = updateState();
|
||||||
for (auto next : prev_blocks)
|
for (auto next : prev_blocks)
|
||||||
{
|
{
|
||||||
if (in_cnt < next->out_cnt)
|
if (in_cnt < next->out_cnt)
|
||||||
@@ -49,7 +51,7 @@ void DataFlowAnalysisNode<DataType>::doStep()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool was_notinit = (out_cnt == CNT_NOTINIT);
|
uniq_change |= (out_cnt == CNT_NOTINIT);
|
||||||
|
|
||||||
if (out_max_cnt != CNT_NOTINIT)
|
if (out_max_cnt != CNT_NOTINIT)
|
||||||
out_cnt = out_max_cnt;
|
out_cnt = out_max_cnt;
|
||||||
@@ -58,7 +60,7 @@ void DataFlowAnalysisNode<DataType>::doStep()
|
|||||||
in_cnt = in_max_cnt;
|
in_cnt = in_max_cnt;
|
||||||
|
|
||||||
// TODO: fix counter overflow
|
// TODO: fix counter overflow
|
||||||
if (was_notinit)
|
if (uniq_change)
|
||||||
{
|
{
|
||||||
out_cnt++;
|
out_cnt++;
|
||||||
in_cnt++;
|
in_cnt++;
|
||||||
@@ -68,7 +70,8 @@ void DataFlowAnalysisNode<DataType>::doStep()
|
|||||||
/* definitions for DataFlowAnalysis class */
|
/* definitions for DataFlowAnalysis class */
|
||||||
|
|
||||||
template <class NodeType>
|
template <class NodeType>
|
||||||
void DataFlowAnalysis<NodeType>::analyze() {
|
void DataFlowAnalysis<NodeType>::analyze()
|
||||||
|
{
|
||||||
auto curr = 0;
|
auto curr = 0;
|
||||||
auto stop = nodes.size();
|
auto stop = nodes.size();
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,40 @@ using std::set;
|
|||||||
using std::remove_if;
|
using std::remove_if;
|
||||||
|
|
||||||
#define PRINT_USELESS_STATEMENTS 1
|
#define PRINT_USELESS_STATEMENTS 1
|
||||||
|
#define DEBUG_IR 0
|
||||||
|
|
||||||
|
// detect wich registers are used at more than one block
|
||||||
|
// such registers should participate in live analysis to spread information about useful instructions
|
||||||
|
// such registers appears at loops
|
||||||
|
static void fillSharedRegs(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& cfg, set<SAPFOR::Argument*>& shared_regs)
|
||||||
|
{
|
||||||
|
map<SAPFOR::Argument*, SAPFOR::BasicBlock*> used_at;
|
||||||
|
|
||||||
|
for (const auto& byFunc : cfg)
|
||||||
|
{
|
||||||
|
for (const auto& byBlock : byFunc.second)
|
||||||
|
{
|
||||||
|
for (const auto& byIrBlock : byBlock->getInstructions())
|
||||||
|
{
|
||||||
|
auto instr = byIrBlock->getInstruction();
|
||||||
|
|
||||||
|
set<SAPFOR::Argument*> used = { instr->getResult(), instr->getArg1(), instr->getArg2() };
|
||||||
|
for (auto arg : used)
|
||||||
|
{
|
||||||
|
if(arg && arg->getType() == SAPFOR::CFG_ARG_TYPE::REG)
|
||||||
|
{
|
||||||
|
auto it = used_at.find(arg);
|
||||||
|
|
||||||
|
if (it == used_at.end())
|
||||||
|
used_at[arg] = byBlock;
|
||||||
|
else if(it->second != byBlock)
|
||||||
|
shared_regs.insert(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
|
static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
|
||||||
set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
|
set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
|
||||||
@@ -39,7 +73,9 @@ static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instru
|
|||||||
{
|
{
|
||||||
for (SAPFOR::Argument* r : res)
|
for (SAPFOR::Argument* r : res)
|
||||||
{
|
{
|
||||||
if (use.find(r) != use.end() || r->getMemType() != SAPFOR::CFG_MEM_TYPE::LOCAL_)
|
if (use.find(r) != use.end() ||
|
||||||
|
r->getMemType() != SAPFOR::CFG_MEM_TYPE::LOCAL_ ||
|
||||||
|
!(r->getType() == SAPFOR::CFG_ARG_TYPE::VAR || r->getType() == SAPFOR::CFG_ARG_TYPE::REG))
|
||||||
{
|
{
|
||||||
useful = true;
|
useful = true;
|
||||||
break;
|
break;
|
||||||
@@ -89,7 +125,7 @@ static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instru
|
|||||||
def.erase(e);
|
def.erase(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
insertIfVar(args.begin(), args.end(), usedByThisBlock);
|
usedByThisBlock.insert(args.begin(), args.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((instr->getOperation() == SAPFOR::CFG_OP::F_CALL || instr->getOperation() == SAPFOR::CFG_OP::PARAM) && fName == "")
|
if ((instr->getOperation() == SAPFOR::CFG_OP::F_CALL || instr->getOperation() == SAPFOR::CFG_OP::PARAM) && fName == "")
|
||||||
@@ -128,12 +164,13 @@ static void buildUseDef(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use,
|
|||||||
useful[i] = u;
|
useful[i] = u;
|
||||||
}
|
}
|
||||||
|
|
||||||
insertIfVar(use_with_regs.begin(), use_with_regs.end(), use);
|
use.insert(use_with_regs.begin(), use_with_regs.end());
|
||||||
insertIfVar(def_with_regs.begin(), def_with_regs.end(), def);
|
def.insert(def_with_regs.begin(), def_with_regs.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class DeadCodeAnalysisNode : public DataFlowAnalysisNode<map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>> {
|
class DeadCodeAnalysisNode : public DataFlowAnalysisNode<map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>>
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
vector<bool> useful;
|
vector<bool> useful;
|
||||||
bool useful_block = false;
|
bool useful_block = false;
|
||||||
@@ -142,6 +179,7 @@ private:
|
|||||||
|
|
||||||
vector<SAPFOR::Argument*>& formal_parameters;
|
vector<SAPFOR::Argument*>& formal_parameters;
|
||||||
const map<string, FuncInfo*>& funcByName;
|
const map<string, FuncInfo*>& funcByName;
|
||||||
|
const set<SAPFOR::Argument*>& shared_regs;
|
||||||
public:
|
public:
|
||||||
bool updateJumpStatus()
|
bool updateJumpStatus()
|
||||||
{
|
{
|
||||||
@@ -196,30 +234,41 @@ public:
|
|||||||
return updated;
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> getIn() {
|
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> getIn()
|
||||||
|
{
|
||||||
return getBlock()->getLiveOut();
|
return getBlock()->getLiveOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> getOut() {
|
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> getOut()
|
||||||
|
{
|
||||||
return getBlock()->getLiveIn();
|
return getBlock()->getLiveIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool addIn(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data) {
|
bool addIn(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
|
||||||
bool inserted = getBlock()->addLiveOut(data);
|
{
|
||||||
|
return getBlock()->addLiveOut(data);
|
||||||
if (!useful_block)
|
|
||||||
inserted |= updateNextNotEmpty();
|
|
||||||
|
|
||||||
inserted |= updateJumpStatus();
|
|
||||||
|
|
||||||
return inserted;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool addOut(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data) {
|
bool addOut(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
|
||||||
|
{
|
||||||
return getBlock()->addLiveIn(data);
|
return getBlock()->addLiveIn(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool forwardData(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data) {
|
bool updateState()
|
||||||
|
{
|
||||||
|
bool updated = false;
|
||||||
|
|
||||||
|
if (!useful_block)
|
||||||
|
updated |= updateNextNotEmpty();
|
||||||
|
|
||||||
|
updated |= updateJumpStatus();
|
||||||
|
updated |= this->forwardData({ });
|
||||||
|
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool forwardData(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
|
||||||
|
{
|
||||||
bool inserted = false;
|
bool inserted = false;
|
||||||
SAPFOR::BasicBlock* bb= getBlock();
|
SAPFOR::BasicBlock* bb= getBlock();
|
||||||
|
|
||||||
@@ -234,6 +283,9 @@ public:
|
|||||||
auto in = bb->getLiveIn(), out = bb->getLiveOut();
|
auto in = bb->getLiveIn(), out = bb->getLiveOut();
|
||||||
|
|
||||||
for (SAPFOR::Argument* arg : use)
|
for (SAPFOR::Argument* arg : use)
|
||||||
|
{
|
||||||
|
if(arg && (arg->getType() == SAPFOR::CFG_ARG_TYPE::VAR ||
|
||||||
|
(arg->getType() == SAPFOR::CFG_ARG_TYPE::REG && shared_regs.find(arg) != shared_regs.end())))
|
||||||
{
|
{
|
||||||
bool this_block = usedByThisBlock.find(arg) != usedByThisBlock.end();
|
bool this_block = usedByThisBlock.find(arg) != usedByThisBlock.end();
|
||||||
|
|
||||||
@@ -261,6 +313,7 @@ public:
|
|||||||
inserted |= bb->addLiveIn({ { arg, { bb } } });
|
inserted |= bb->addLiveIn({ { arg, { bb } } });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!useful_block)
|
if(!useful_block)
|
||||||
{
|
{
|
||||||
@@ -291,38 +344,39 @@ public:
|
|||||||
|
|
||||||
DeadCodeAnalysisNode(SAPFOR::BasicBlock* block,
|
DeadCodeAnalysisNode(SAPFOR::BasicBlock* block,
|
||||||
vector<SAPFOR::Argument*>& formal_parameters,
|
vector<SAPFOR::Argument*>& formal_parameters,
|
||||||
const map<string, FuncInfo*>& funcByName)
|
const map<string, FuncInfo*>& funcByName,
|
||||||
|
const set<SAPFOR::Argument*>& shared_regs)
|
||||||
:
|
:
|
||||||
formal_parameters(formal_parameters),
|
formal_parameters(formal_parameters),
|
||||||
funcByName(funcByName)
|
funcByName(funcByName),
|
||||||
|
shared_regs(shared_regs)
|
||||||
{
|
{
|
||||||
setBlock(block);
|
setBlock(block);
|
||||||
useful.resize(block->getInstructions().size(), false);
|
useful.resize(block->getInstructions().size(), false);
|
||||||
set<SAPFOR::Argument*> use, def;
|
|
||||||
set<SAPFOR::Argument*> usedByThisBlock;
|
|
||||||
|
|
||||||
buildUseDef(getBlock(), use, def, this->formal_parameters, useful, usedByThisBlock, funcByName);
|
|
||||||
|
|
||||||
for (SAPFOR::Argument* arg : use)
|
|
||||||
getBlock()->addLiveIn({ { arg, { getBlock() } } });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const vector<bool>& getResult() { return useful; }
|
const vector<bool>& getResult() { return useful; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class DeadCodeAnalysis : public BackwardDataFlowAnalysis<DeadCodeAnalysisNode> {
|
class DeadCodeAnalysis : public BackwardDataFlowAnalysis<DeadCodeAnalysisNode>
|
||||||
|
{
|
||||||
protected:
|
protected:
|
||||||
vector<SAPFOR::Argument*>& formal_parameters;
|
vector<SAPFOR::Argument*>& formal_parameters;
|
||||||
const map<string, FuncInfo*>& funcByName;
|
const map<string, FuncInfo*>& funcByName;
|
||||||
|
const set<SAPFOR::Argument*>& shared_regs;
|
||||||
|
|
||||||
DeadCodeAnalysisNode* createNode(SAPFOR::BasicBlock* block) override {
|
DeadCodeAnalysisNode* createNode(SAPFOR::BasicBlock* block) override
|
||||||
return new DeadCodeAnalysisNode(block, formal_parameters, funcByName);
|
{
|
||||||
|
return new DeadCodeAnalysisNode(block, formal_parameters, funcByName, shared_regs);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
DeadCodeAnalysis(vector<SAPFOR::Argument*>& formal_parameters, const map<string, FuncInfo*>& funcByName)
|
DeadCodeAnalysis(vector<SAPFOR::Argument*>& formal_parameters,
|
||||||
|
const map<string, FuncInfo*>& funcByName,
|
||||||
|
const set<SAPFOR::Argument*>& shared_regs)
|
||||||
:
|
:
|
||||||
formal_parameters(formal_parameters),
|
formal_parameters(formal_parameters),
|
||||||
funcByName(funcByName)
|
funcByName(funcByName),
|
||||||
|
shared_regs(shared_regs)
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -394,8 +448,10 @@ void removeDeadCode(SgStatement* func,
|
|||||||
|
|
||||||
cfg_pair.second.erase(remove_unreachable_it, cfg_pair.second.end());
|
cfg_pair.second.erase(remove_unreachable_it, cfg_pair.second.end());
|
||||||
|
|
||||||
|
#if DEBUG_IR
|
||||||
|
dumpCFG({ cfg_pair }, false);
|
||||||
|
#endif
|
||||||
// detect useless code
|
// detect useless code
|
||||||
|
|
||||||
vector<SAPFOR::Argument*> func_parameters(cfg_pair.first->funcParams.countOfPars, NULL);
|
vector<SAPFOR::Argument*> func_parameters(cfg_pair.first->funcParams.countOfPars, NULL);
|
||||||
|
|
||||||
map<string, FuncInfo*> funcByName;
|
map<string, FuncInfo*> funcByName;
|
||||||
@@ -404,7 +460,10 @@ void removeDeadCode(SgStatement* func,
|
|||||||
for (auto byFunc : byFile.second)
|
for (auto byFunc : byFile.second)
|
||||||
funcByName[byFunc->funcName] = byFunc;
|
funcByName[byFunc->funcName] = byFunc;
|
||||||
|
|
||||||
DeadCodeAnalysis analysis_object(func_parameters, funcByName);
|
set<SAPFOR::Argument*> shared_regs;
|
||||||
|
fillSharedRegs({ cfg_pair }, shared_regs);
|
||||||
|
|
||||||
|
DeadCodeAnalysis analysis_object(func_parameters, funcByName, shared_regs);
|
||||||
|
|
||||||
analysis_object.fit(cfg_pair.second);
|
analysis_object.fit(cfg_pair.second);
|
||||||
analysis_object.analyze();
|
analysis_object.analyze();
|
||||||
|
|||||||
@@ -307,8 +307,8 @@ void InitPassesDependencies(map<passes, vector<passes>> &passDepsIn, set<passes>
|
|||||||
|
|
||||||
Pass(REMOVE_OMP_DIRS) <= Pass(REMOVE_OMP_DIRS_TRANSFORM);
|
Pass(REMOVE_OMP_DIRS) <= Pass(REMOVE_OMP_DIRS_TRANSFORM);
|
||||||
|
|
||||||
Pass(CALL_GRAPH2) <= Pass(REMOVE_DEAD_CODE);
|
list({ CALL_GRAPH2, REVERT_SUBST_EXPR_RD }) <= Pass(REMOVE_DEAD_CODE);
|
||||||
list({ REMOVE_DEAD_CODE, REVERT_SUBST_EXPR_RD, CONVERT_LOOP_TO_ASSIGN, RESTORE_LOOP_FROM_ASSIGN }) <= Pass(REMOVE_DEAD_CODE_AND_UNPARSE);
|
list({ REMOVE_DEAD_CODE, CONVERT_LOOP_TO_ASSIGN, RESTORE_LOOP_FROM_ASSIGN }) <= Pass(REMOVE_DEAD_CODE_AND_UNPARSE);
|
||||||
|
|
||||||
passesIgnoreStateDone.insert({ CREATE_PARALLEL_DIRS, INSERT_PARALLEL_DIRS, INSERT_SHADOW_DIRS, EXTRACT_PARALLEL_DIRS,
|
passesIgnoreStateDone.insert({ CREATE_PARALLEL_DIRS, INSERT_PARALLEL_DIRS, INSERT_SHADOW_DIRS, EXTRACT_PARALLEL_DIRS,
|
||||||
EXTRACT_SHADOW_DIRS, CREATE_REMOTES, UNPARSE_FILE, REMOVE_AND_CALC_SHADOW,
|
EXTRACT_SHADOW_DIRS, CREATE_REMOTES, UNPARSE_FILE, REMOVE_AND_CALC_SHADOW,
|
||||||
|
|||||||
Reference in New Issue
Block a user