dead_code_removing #36

Merged
Alexander_KS merged 4 commits from dead_code_removing into master 2024-04-05 17:39:56 +00:00
5 changed files with 125 additions and 61 deletions

View File

@@ -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:

View File

@@ -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; }

View File

@@ -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();

View File

@@ -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;
@@ -88,8 +124,8 @@ static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instru
use.insert(e); use.insert(e);
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();
@@ -235,30 +284,34 @@ public:
for (SAPFOR::Argument* arg : use) for (SAPFOR::Argument* arg : use)
{ {
bool this_block = usedByThisBlock.find(arg) != usedByThisBlock.end(); if(arg && (arg->getType() == SAPFOR::CFG_ARG_TYPE::VAR ||
(arg->getType() == SAPFOR::CFG_ARG_TYPE::REG && shared_regs.find(arg) != shared_regs.end())))
if (!this_block)
{ {
auto data_it = data.find(arg); bool this_block = usedByThisBlock.find(arg) != usedByThisBlock.end();
if (data_it == data.end()) if (!this_block)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
inserted |= bb->addLiveIn({ *data_it });
}
else
{
auto in_it = in.find(arg);
bool skip = false;
if (in_it != in.end())
{ {
if (in_it->second.size() == 1 && *(in_it->second.begin()) == bb) auto data_it = data.find(arg);
skip = true; // nothing to do, inserted = false
else if (data_it == data.end())
bb->removeLiveIn(arg); printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
inserted |= bb->addLiveIn({ *data_it });
}
else
{
auto in_it = in.find(arg);
bool skip = false;
if (in_it != in.end())
{
if (in_it->second.size() == 1 && *(in_it->second.begin()) == bb)
skip = true; // nothing to do, inserted = false
else
bb->removeLiveIn(arg);
}
if(!skip)
inserted |= bb->addLiveIn({ { arg, { bb } } });
} }
if(!skip)
inserted |= bb->addLiveIn({ { arg, { bb } } });
} }
} }
@@ -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;
@@ -403,8 +459,11 @@ void removeDeadCode(SgStatement* func,
for (auto& byFile : allFuncs) for (auto& byFile : allFuncs)
for (auto byFunc : byFile.second) for (auto byFunc : byFile.second)
funcByName[byFunc->funcName] = byFunc; funcByName[byFunc->funcName] = byFunc;
set<SAPFOR::Argument*> shared_regs;
fillSharedRegs({ cfg_pair }, shared_regs);
DeadCodeAnalysis analysis_object(func_parameters, funcByName); 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();

View File

@@ -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,