dead code: fix for variables from loop headers

This commit is contained in:
2024-04-05 16:03:18 +03:00
parent af194134ba
commit 5f4bb71dcf

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,
@@ -91,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 == "")
@@ -130,8 +164,8 @@ 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());
} }
@@ -145,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()
{ {
@@ -248,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();
@@ -275,6 +313,7 @@ public:
inserted |= bb->addLiveIn({ { arg, { bb } } }); inserted |= bb->addLiveIn({ { arg, { bb } } });
} }
} }
}
if(!useful_block) if(!useful_block)
{ {
@@ -305,10 +344,12 @@ 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);
@@ -322,16 +363,20 @@ 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)
{ } { }
}; };
@@ -403,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;
@@ -413,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();