diff --git a/sapfor/experts/Sapfor_2017/_src/CFGraph/CFGraph.cpp b/sapfor/experts/Sapfor_2017/_src/CFGraph/CFGraph.cpp index d98dc14..b00a2b1 100644 --- a/sapfor/experts/Sapfor_2017/_src/CFGraph/CFGraph.cpp +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/CFGraph.cpp @@ -56,6 +56,22 @@ void BBlock::addInstruction(IR_Block* item) item->setBasicBlock(this); } +int BBlock::removePrev(BBlock* removed) +{ + auto it = std::remove(prev.begin(), prev.end(), removed); + auto r = prev.end() - it; + prev.erase(it, prev.end()); + return r; +} + +int BBlock::removeNext(BBlock* removed) +{ + auto it = std::remove(next.begin(), next.end(), removed); + auto r = next.end() - it; + next.erase(it, next.end()); + return r; +} + BBlock::~BasicBlock() { for (auto& instr : instructions) diff --git a/sapfor/experts/Sapfor_2017/_src/CFGraph/CFGraph.h b/sapfor/experts/Sapfor_2017/_src/CFGraph/CFGraph.h index e47447c..319b420 100644 --- a/sapfor/experts/Sapfor_2017/_src/CFGraph/CFGraph.h +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/CFGraph.h @@ -42,6 +42,9 @@ namespace SAPFOR void addInstruction(IR_Block* item); void addPrev(BasicBlock* prev_) { prev.push_back(prev_); } void addNext(BasicBlock* next_) { next.push_back(next_); } + + int removePrev(BasicBlock* removed); + int removeNext(BasicBlock* removed); void replacePrevNext(const std::map& oldToNew) { diff --git a/sapfor/experts/Sapfor_2017/_src/CFGraph/RD_subst.cpp b/sapfor/experts/Sapfor_2017/_src/CFGraph/RD_subst.cpp index a99bf77..387b142 100644 --- a/sapfor/experts/Sapfor_2017/_src/CFGraph/RD_subst.cpp +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/RD_subst.cpp @@ -321,38 +321,6 @@ static bool getDependencies(SAPFOR::Argument* var, SAPFOR::Instruction* instr, c return true; } -static bool ifVariableValid(SAPFOR::Argument* var, const set>& defs, - SAPFOR::Argument* processed_var, const pair& def_of_processed_var) -{ - const auto& BB_of_def_of_processed_var = def_of_processed_var.second; - - if (defs.size() == 1) - { - const auto& def = *defs.begin(); - if (def.second == BB_of_def_of_processed_var && def.first->getNumber() < def_of_processed_var.first->getNumber()) - return true; - } - - const auto& RD_In_BB_of_def_of_processed_var = BB_of_def_of_processed_var->getRD_In(); - auto RD_of_var_from_BB_with_processed_var = RD_In_BB_of_def_of_processed_var.find(var); - - if (RD_of_var_from_BB_with_processed_var != RD_In_BB_of_def_of_processed_var.end() - && RD_of_var_from_BB_with_processed_var->second.size() == defs.size()) - { - for (const auto& def : defs) - { - int number_of_istruction_with_decl = def.first ? def.first->getNumber() : CFG_VAL::UNINIT; - - if (RD_of_var_from_BB_with_processed_var->second.count(number_of_istruction_with_decl) == 0) - return false; - } - - return true; - } - - return false; -} - static const set& func_affects(const FuncInfo* func, const vector& blocks) { static map> affects; @@ -1150,7 +1118,7 @@ vector sortCfgNodes(const vector& bloc if (!nodes_added && processing_stack.size() != 0) { //there is some blocks in the stack but no one can be processed //this code should be unreachable -#ifdef DEBUG_CHECKS +#if DEBUG_CHECKS printInternalError(convertFileName(__FILE__).c_str(), __LINE__); #endif // DEBUG_CHECKS auto block = processing_stack.back(); @@ -1167,7 +1135,7 @@ vector sortCfgNodes(const vector& bloc } } -#ifdef DEBUG_CHECKS +#if DEBUG_CHECKS set verify_unique; verify_unique.insert(result.begin(), result.end()); @@ -1176,7 +1144,7 @@ vector sortCfgNodes(const vector& bloc verify_unique.clear(); #endif // DEBUG_CHECKS -#ifdef DEBUG_CHECKS +#if DEBUG_CHECKS set all_blocks, res_blocks; all_blocks.insert(blocks.begin(), blocks.end()); @@ -1267,7 +1235,7 @@ bool isArgReaches(int decl_instr, SAPFOR::BasicBlock* decl_bb, if (RDs_for_arg.size() == 1) { const int rd = *RDs_for_arg.begin(); - if (rd >= decl_bb->getInstructions().front()->getNumber() && rd <= decl_instr) + if (rd >= decl_bb->getInstructions().front()->getNumber() && rd < decl_instr) return true; } @@ -1275,7 +1243,67 @@ bool isArgReaches(int decl_instr, SAPFOR::BasicBlock* decl_bb, if (arg_in_from_decl_it == decl_bb->getRD_In().end()) return false; - return arg_in_from_decl_it->second == RDs_for_arg; + if(arg_in_from_decl_it->second != RDs_for_arg) + return false; + + set reachable = { decl_bb }; + set banned_instructions; + for (int instr_def : arg_in_from_decl_it->second) + if (instr_def >= decl_instr || instr_def < decl_bb->getInstructions().front()->getNumber()) + //try to find way [decl_bb] -> [dest_bb] with redefining of var (that means that var value from decl_bb could be overwrited) + banned_instructions.insert(instr_def); + + set worklist = reachable, banned_blocks; + bool way_found = false; + while (worklist.size() != 0 && banned_instructions.size() != 0) + { + for (SAPFOR::BasicBlock* wl : worklist) + { + int start = wl->getInstructions().front()->getNumber(), end = wl->getInstructions().back()->getNumber(); + + for (auto banned_it = banned_instructions.begin(); banned_it != banned_instructions.end();) + { + if(start <= *banned_it && *banned_it <= end) + { + banned_it = banned_instructions.erase(banned_it); + banned_blocks.insert(wl); + } + else + { + banned_it++; + } + } + } + + set to_insert; + + for (auto b : worklist) + for (auto next : b->getNext()) + if (reachable.insert(next).second) + to_insert.insert(next); + + worklist = to_insert; + } + + reachable = banned_blocks; + worklist = reachable; + while (worklist.size() != 0 || banned_instructions.size() == 0) + { + if(worklist.find(dest_bb) != worklist.end()) + return false; + + set to_insert; + + for (auto b : worklist) + for (auto next : b->getNext()) + if(next != decl_bb) + if (reachable.insert(next).second) + to_insert.insert(next); + + worklist = to_insert; + } + + return true; } // return arg's definition if it really reaches dest_bb @@ -1597,28 +1625,7 @@ void buildSubstitutions(const map>& CFGra for (SAPFOR::Argument* dep : dependencies_of_var->second) { - if (dep->getType() != CFG_ARG_TYPE::VAR) - { - can_use = false; - break; - } - - const auto& RD_In_of_curr_BB = cur_BB->getRD_In(); - auto dep_from_curr_RD_In = RD_In_of_curr_BB.find(dep); - - if (dep_from_curr_RD_In == RD_In_of_curr_BB.end()) - { - can_use = false; - break; - } - - const auto& RDs_for_dep = dep_from_curr_RD_In->second; - - set> defs_of_dep; - for (int def_instruction_num : RDs_for_dep) - defs_of_dep.insert(getInstructionAndBlockByNumber(CFGraph_for_project, def_instruction_num)); - - if (!ifVariableValid(dep, defs_of_dep, in_val.first, instr_and_bb)) + if (!isArgReaches(instr_num, instr_and_bb.second, dep, cur_BB)) { can_use = false; break; diff --git a/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.cpp b/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.cpp index 5f79f52..ad41626 100644 --- a/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.cpp +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.cpp @@ -338,7 +338,7 @@ void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* ins if ((instr_operation == SAPFOR::CFG_OP::F_CALL || instr_operation == SAPFOR::CFG_OP::PARAM) && last_param_ref_index < 0) { auto func_it = funcByName.find(fName); - if (func_it != funcByName.end()) + if (interprocedural && func_it != funcByName.end()) { fcalls.push_back(LiveDeadVarsForCall(func_it->second, block, lastParamRef)); @@ -360,6 +360,18 @@ void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* ins use.insert(make_live.begin(), make_live.end()); def.insert(make_dead.begin(), make_dead.end()); } + else if (func_it != funcByName.end()) + { + int arg_num = lastParamRef.size(); + for (int i = 0; i < arg_num; i++) + { + if(func_it->second->funcParams.isArgOut(i)) + def.insert(lastParamRef[i]); + + if (func_it->second->funcParams.isArgIn(i)) + use.insert(lastParamRef[i]); + } + } else use.insert(lastParamRef.begin(), lastParamRef.end()); diff --git a/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp b/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp index 0590d4e..e09ce14 100644 --- a/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp +++ b/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp @@ -4,35 +4,34 @@ #include #include #include +#include using std::map; using std::string; using std::vector; using std::set; +using std::remove_if; + #define PRINT_USELESS_STATEMENTS 0 static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr, set& use, set& def, vector& formal_parameters, vector& lastParamRef, int& last_param_ref_index, int& last_param_ref_size, - string& fName, + string& fName, const map& funcByName, bool& useful, bool& last_fcall_useful, set& usedByThisBlock) { set res, args; - if (fName == "") - last_fcall_useful = false; - vector fcalls; - getUseDefForInstruction(block, instr, args, res, formal_parameters, fcalls, lastParamRef, last_param_ref_index, last_param_ref_size, - fName, {}, + fName, funcByName, false ); @@ -59,15 +58,18 @@ static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instru SAPFOR::CFG_OP::ENTRY, SAPFOR::CFG_OP::EXIT, SAPFOR::CFG_OP::DVM_DIR, - SAPFOR::CFG_OP::SPF_DIR, - - SAPFOR::CFG_OP::F_CALL //TODO: handle pure functions + SAPFOR::CFG_OP::SPF_DIR }; if (always_useful.find(instr->getOperation()) != always_useful.end()) useful = true; - else if(instr->getOperation() == SAPFOR::CFG_OP::PARAM && last_fcall_useful) - useful = true; + else if (instr->getOperation() == SAPFOR::CFG_OP::F_CALL) + { + auto func_it = funcByName.find(instr->getArg1()->getValue()); + useful |= func_it == funcByName.end() || !(func_it->second->isPure); + } + else if (instr->getOperation() == SAPFOR::CFG_OP::PARAM) + useful |= last_fcall_useful; } if (useful) @@ -89,13 +91,16 @@ static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instru insertIfVar(args.begin(), args.end(), usedByThisBlock); } + + if ((instr->getOperation() == SAPFOR::CFG_OP::F_CALL || instr->getOperation() == SAPFOR::CFG_OP::PARAM) && fName == "") + last_fcall_useful = false; } //Build use and def sets of block. Result are stored in use and def static void buildUseDef(SAPFOR::BasicBlock* block, set& use, set& def, vector& formal_parameters, vector& useful, - set& usedByThisBlock) + set& usedByThisBlock, const map& funcByName) { set use_with_regs = use, def_with_regs = def; @@ -115,7 +120,7 @@ static void buildUseDef(SAPFOR::BasicBlock* block, set& use, use_with_regs, def_with_regs, formal_parameters, lastParamRef, last_param_ref_index, last_param_ref_size, - fName, + fName, funcByName, u, last_fcall_useful, usedByThisBlock ); @@ -136,6 +141,7 @@ private: bool useful_jump = false; vector& formal_parameters; + const map& funcByName; public: bool updateJumpStatus() { @@ -223,7 +229,7 @@ public: use.insert(byArg.first); set usedByThisBlock; - buildUseDef(bb, use, def, this->formal_parameters, useful, usedByThisBlock); + buildUseDef(bb, use, def, this->formal_parameters, useful, usedByThisBlock, funcByName); auto in = bb->getLiveIn(), out = bb->getLiveOut(); @@ -283,15 +289,19 @@ public: return inserted; } - DeadCodeAnalysisNode(SAPFOR::BasicBlock* block, vector& formal_parameters) : - formal_parameters(formal_parameters) + DeadCodeAnalysisNode(SAPFOR::BasicBlock* block, + vector& formal_parameters, + const map& funcByName) + : + formal_parameters(formal_parameters), + funcByName(funcByName) { setBlock(block); useful.resize(block->getInstructions().size(), false); set use, def; set usedByThisBlock; - buildUseDef(getBlock(), use, def, this->formal_parameters, useful, usedByThisBlock); + buildUseDef(getBlock(), use, def, this->formal_parameters, useful, usedByThisBlock, funcByName); for (SAPFOR::Argument* arg : use) getBlock()->addLiveIn({ { arg, { getBlock() } } }); @@ -303,13 +313,16 @@ public: class DeadCodeAnalysis : public BackwardDataFlowAnalysis { protected: vector& formal_parameters; + const map& funcByName; DeadCodeAnalysisNode* createNode(SAPFOR::BasicBlock* block) override { - return new DeadCodeAnalysisNode(block, formal_parameters); + return new DeadCodeAnalysisNode(block, formal_parameters, funcByName); } public: - DeadCodeAnalysis(vector& formal_parameters) : - formal_parameters(formal_parameters) + DeadCodeAnalysis(vector& formal_parameters, const map& funcByName) + : + formal_parameters(formal_parameters), + funcByName(funcByName) { } }; @@ -325,15 +338,67 @@ void removeDeadCode(SgStatement* func, if(cfg.size() != 1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); - const auto& cfg_pair = *(cfg.begin()); + auto& cfg_pair = *(cfg.begin()); + + // delete unreachable blocks + + set reachable; + + for (auto b : cfg_pair.second) + if(b->getInstructions().front()->isHeader()) + reachable.insert(b); + + set worklist = reachable; + while (worklist.size() != 0) + { + set to_insert; + + for(auto b : worklist) + for(auto next: b->getNext()) + if(reachable.insert(next).second) + to_insert.insert(next); + + worklist = to_insert; + } + + auto remove_unreachable_it = remove_if(cfg_pair.second.begin(), cfg_pair.second.end(), + [&reachable](SAPFOR::BasicBlock* b) + { + if (reachable.find(b) == reachable.end()) + { + for(auto next: b->getNext()) + if(reachable.find(next) != reachable.end()) + next->removePrev(b); + + delete b; + return true; + } + + return false; + } + ); + + reachable.clear(); + + cfg_pair.second.erase(remove_unreachable_it, cfg_pair.second.end()); + + // detect useless code vector func_parameters(cfg_pair.first->funcParams.countOfPars, NULL); - DeadCodeAnalysis analysis_object(func_parameters); + map funcByName; + + for (auto& byFile : allFuncs) + for (auto byFunc : byFile.second) + funcByName[byFunc->funcName] = byFunc; + + DeadCodeAnalysis analysis_object(func_parameters, funcByName); analysis_object.fit(cfg_pair.second); analysis_object.analyze(); + // detect dead statements + set useful; for (DeadCodeAnalysisNode* byNode : analysis_object.getNodes()) @@ -358,11 +423,16 @@ void removeDeadCode(SgStatement* func, } } + // remove dead statements + SgStatement* end = func->lastNodeOfStmt(), *st = func; - set removable = + set removable = { - ASSIGN_STAT + ASSIGN_STAT, + PROC_STAT, + WRITE_STAT, + READ_STAT }; while (st != end)