diff --git a/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/backward_data_flow.h b/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/backward_data_flow.h index 7f81751..556af90 100644 --- a/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/backward_data_flow.h +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/backward_data_flow.h @@ -10,7 +10,8 @@ #include "../IR.h" template -class BackwardDataFlowAnalysis : public DataFlowAnalysis { +class BackwardDataFlowAnalysis : public DataFlowAnalysis +{ std::vector reorderSequence(const std::vector& blocks, const std::set back_edge_sources); public: diff --git a/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow.h b/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow.h index 8067bd7..561d1b3 100644 --- a/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow.h +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow.h @@ -29,6 +29,7 @@ public: virtual bool addIn(const DataType& data) = 0; virtual bool addOut(const DataType& data) = 0; + virtual bool updateState() { return false; } virtual bool forwardData(const DataType& data) = 0; bool newerThan(const DataFlowAnalysisNode* block) const { return out_cnt > block->in_cnt; } diff --git a/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow_impl.h b/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow_impl.h index 5e74e29..db33e73 100644 --- a/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow_impl.h +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow_impl.h @@ -27,6 +27,8 @@ template void DataFlowAnalysisNode::doStep() { int in_max_cnt = CNT_NOTINIT, out_max_cnt = CNT_NOTINIT; + + bool uniq_change = updateState(); for (auto next : prev_blocks) { if (in_cnt < next->out_cnt) @@ -49,7 +51,7 @@ void DataFlowAnalysisNode::doStep() } } - bool was_notinit = (out_cnt == CNT_NOTINIT); + uniq_change |= (out_cnt == CNT_NOTINIT); if (out_max_cnt != CNT_NOTINIT) out_cnt = out_max_cnt; @@ -58,7 +60,7 @@ void DataFlowAnalysisNode::doStep() in_cnt = in_max_cnt; // TODO: fix counter overflow - if (was_notinit) + if (uniq_change) { out_cnt++; in_cnt++; @@ -68,7 +70,8 @@ void DataFlowAnalysisNode::doStep() /* definitions for DataFlowAnalysis class */ template -void DataFlowAnalysis::analyze() { +void DataFlowAnalysis::analyze() +{ auto curr = 0; auto stop = nodes.size(); diff --git a/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp b/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp index f7493d2..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, @@ -39,7 +73,9 @@ static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instru { 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; break; @@ -88,8 +124,8 @@ static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instru use.insert(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 == "") @@ -128,12 +164,13 @@ 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()); } -class DeadCodeAnalysisNode : public DataFlowAnalysisNode>> { +class DeadCodeAnalysisNode : public DataFlowAnalysisNode>> +{ private: vector useful; bool useful_block = false; @@ -142,6 +179,7 @@ private: vector& formal_parameters; const map& funcByName; + const set& shared_regs; public: bool updateJumpStatus() { @@ -196,30 +234,41 @@ public: return updated; } - map> getIn() { + map> getIn() + { return getBlock()->getLiveOut(); } - map> getOut() { + map> getOut() + { return getBlock()->getLiveIn(); } - bool addIn(const map>& data) { - bool inserted = getBlock()->addLiveOut(data); - - if (!useful_block) - inserted |= updateNextNotEmpty(); - - inserted |= updateJumpStatus(); - - return inserted; + bool addIn(const map>& data) + { + return getBlock()->addLiveOut(data); } - bool addOut(const map>& data) { + bool addOut(const map>& data) + { return getBlock()->addLiveIn(data); } - bool forwardData(const map>& data) { + bool updateState() + { + bool updated = false; + + if (!useful_block) + updated |= updateNextNotEmpty(); + + updated |= updateJumpStatus(); + updated |= this->forwardData({ }); + + return updated; + } + + bool forwardData(const map>& data) + { bool inserted = false; SAPFOR::BasicBlock* bb= getBlock(); @@ -235,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 } } }); } } @@ -291,38 +344,39 @@ 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); - set use, def; - set usedByThisBlock; - - buildUseDef(getBlock(), use, def, this->formal_parameters, useful, usedByThisBlock, funcByName); - - for (SAPFOR::Argument* arg : use) - getBlock()->addLiveIn({ { arg, { getBlock() } } }); } const vector& getResult() { return useful; } }; -class DeadCodeAnalysis : public BackwardDataFlowAnalysis { +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); + DeadCodeAnalysisNode* createNode(SAPFOR::BasicBlock* block) override + { + 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) { } }; @@ -394,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; @@ -403,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(); diff --git a/sapfor/experts/Sapfor_2017/_src/Utils/PassManager.h b/sapfor/experts/Sapfor_2017/_src/Utils/PassManager.h index 0e07092..0f2e0fe 100644 --- a/sapfor/experts/Sapfor_2017/_src/Utils/PassManager.h +++ b/sapfor/experts/Sapfor_2017/_src/Utils/PassManager.h @@ -307,8 +307,8 @@ void InitPassesDependencies(map> &passDepsIn, set Pass(REMOVE_OMP_DIRS) <= Pass(REMOVE_OMP_DIRS_TRANSFORM); - Pass(CALL_GRAPH2) <= 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({ CALL_GRAPH2, REVERT_SUBST_EXPR_RD }) <= Pass(REMOVE_DEAD_CODE); + 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, EXTRACT_SHADOW_DIRS, CREATE_REMOTES, UNPARSE_FILE, REMOVE_AND_CALC_SHADOW,