From 5f4bb71dcfb60c032784a15751ee124cf9f9e488 Mon Sep 17 00:00:00 2001 From: Mikhail Kocharmin Date: Fri, 5 Apr 2024 16:03:18 +0300 Subject: [PATCH] dead code: fix for variables from loop headers --- .../_src/Transformations/dead_code.cpp | 110 +++++++++++++----- 1 file changed, 80 insertions(+), 30 deletions(-) diff --git a/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp b/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp index 3535963..52f0458 100644 --- a/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp +++ b/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp @@ -14,6 +14,40 @@ using std::set; using std::remove_if; #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>& cfg, set& shared_regs) +{ + map used_at; + + for (const auto& byFunc : cfg) + { + for (const auto& byBlock : byFunc.second) + { + for (const auto& byIrBlock : byBlock->getInstructions()) + { + auto instr = byIrBlock->getInstruction(); + + set 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, set& use, set& def, @@ -91,7 +125,7 @@ static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instru 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 == "") @@ -130,8 +164,8 @@ static void buildUseDef(SAPFOR::BasicBlock* block, set& use, useful[i] = u; } - insertIfVar(use_with_regs.begin(), use_with_regs.end(), use); - insertIfVar(def_with_regs.begin(), def_with_regs.end(), def); + use.insert(use_with_regs.begin(), use_with_regs.end()); + def.insert(def_with_regs.begin(), def_with_regs.end()); } @@ -145,6 +179,7 @@ private: vector& formal_parameters; const map& funcByName; + const set& shared_regs; public: bool updateJumpStatus() { @@ -249,30 +284,34 @@ public: for (SAPFOR::Argument* arg : use) { - bool this_block = usedByThisBlock.find(arg) != usedByThisBlock.end(); - - if (!this_block) + if(arg && (arg->getType() == SAPFOR::CFG_ARG_TYPE::VAR || + (arg->getType() == SAPFOR::CFG_ARG_TYPE::REG && shared_regs.find(arg) != shared_regs.end()))) { - auto data_it = data.find(arg); + bool this_block = usedByThisBlock.find(arg) != usedByThisBlock.end(); - if (data_it == data.end()) - 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 (!this_block) { - if (in_it->second.size() == 1 && *(in_it->second.begin()) == bb) - skip = true; // nothing to do, inserted = false - else - bb->removeLiveIn(arg); + auto data_it = data.find(arg); + + if (data_it == data.end()) + 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 } } }); } } @@ -305,10 +344,12 @@ public: DeadCodeAnalysisNode(SAPFOR::BasicBlock* block, vector& formal_parameters, - const map& funcByName) + const map& funcByName, + const set& shared_regs) : formal_parameters(formal_parameters), - funcByName(funcByName) + funcByName(funcByName), + shared_regs(shared_regs) { setBlock(block); useful.resize(block->getInstructions().size(), false); @@ -322,16 +363,20 @@ class DeadCodeAnalysis : public BackwardDataFlowAnalysis protected: vector& formal_parameters; const map& funcByName; + const set& shared_regs; DeadCodeAnalysisNode* createNode(SAPFOR::BasicBlock* block) override { - return new DeadCodeAnalysisNode(block, formal_parameters, funcByName); + return new DeadCodeAnalysisNode(block, formal_parameters, funcByName, shared_regs); } public: - DeadCodeAnalysis(vector& formal_parameters, const map& funcByName) + DeadCodeAnalysis(vector& formal_parameters, + const map& funcByName, + const set& shared_regs) : 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()); +#if DEBUG_IR + dumpCFG({ cfg_pair }, false); +#endif // detect useless code - vector func_parameters(cfg_pair.first->funcParams.countOfPars, NULL); map funcByName; @@ -412,8 +459,11 @@ void removeDeadCode(SgStatement* func, for (auto& byFile : allFuncs) for (auto byFunc : byFile.second) funcByName[byFunc->funcName] = byFunc; + + set 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.analyze();